feat: Add permissions to subscriptions to only exposed user's
This commit is contained in:
parent
6bddcea475
commit
75baf561a8
@ -5,10 +5,54 @@ stages:
|
|||||||
- test
|
- test
|
||||||
- release
|
- release
|
||||||
|
|
||||||
|
variables:
|
||||||
|
SIB_PROJECT_NAME: "sib_test"
|
||||||
|
SIB_PROJECT_DIR: "/builds/$SIB_PROJECT_NAME"
|
||||||
|
DJANGO_SETTINGS_MODULE: "$SIB_PROJECT_NAME.settings"
|
||||||
|
SIB_PACKAGE_CONTENT: >
|
||||||
|
{
|
||||||
|
"ldppackages": {
|
||||||
|
"djangoldp_project": "djangoldp_project",
|
||||||
|
"djangoldp_circle": "djangoldp_circle",
|
||||||
|
"djangoldp_notification": "djangoldp_notification",
|
||||||
|
"djangoldp_account": "djangoldp_account",
|
||||||
|
"djangoldp_skill": "djangoldp_skill",
|
||||||
|
"djangoldp_joboffer": "djangoldp_joboffer",
|
||||||
|
"djangoldp_conversation": "djangoldp_conversation",
|
||||||
|
"djangoldp_profile": "djangoldp_profile",
|
||||||
|
"oidc_provider": "git+https://github.com/jblemee/django-oidc-provider.git@develop"
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"site_url": "http://localhost:8000",
|
||||||
|
"allowed_hosts": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"db_host": "localhost",
|
||||||
|
"db_name": "database",
|
||||||
|
"db_user": "me",
|
||||||
|
"db_pass": "changeit",
|
||||||
|
"smtp_host": "locahost",
|
||||||
|
"smtp_user": "user",
|
||||||
|
"smtp_pass": "changeit",
|
||||||
|
"admin_email": "admin@example.org",
|
||||||
|
"admin_name": "admin",
|
||||||
|
"admin_pass": "admin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test:
|
test:
|
||||||
stage: test
|
stage: test
|
||||||
|
before_script:
|
||||||
|
- export PATH="$PATH:/root/.local/bin" PYTHONPATH="$SIB_PROJECT_DIR"
|
||||||
|
- pip install git+https://git.happy-dev.fr/startinblox/devops/sib.git
|
||||||
|
- cd /builds && DJANGO_SETTINGS_MODULE="" sib startproject $SIB_PROJECT_NAME
|
||||||
|
- echo $SIB_PACKAGE_CONTENT > $SIB_PROJECT_DIR/packages.yml
|
||||||
|
- cd $SIB_PROJECT_DIR
|
||||||
|
- sib install $SIB_PROJECT_NAME
|
||||||
|
- cd $CI_PROJECT_DIR
|
||||||
|
- pip install -e .[dev]
|
||||||
script:
|
script:
|
||||||
- echo 'Make your tests here !'
|
- pytest
|
||||||
except:
|
except:
|
||||||
- master
|
- master
|
||||||
tags:
|
tags:
|
||||||
|
@ -1,25 +1,20 @@
|
|||||||
import logging
|
import logging
|
||||||
from threading import Thread
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.admin.models import LogEntry
|
|
||||||
from django.contrib.sessions.models import Session
|
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from oidc_provider.models import Token
|
from django.template import loader
|
||||||
from django.urls import NoReverseMatch
|
from django.urls import NoReverseMatch
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from djangoldp.fields import LDPUrlField
|
from djangoldp.fields import LDPUrlField
|
||||||
from djangoldp.models import Model
|
from djangoldp.models import Model
|
||||||
|
from threading import Thread
|
||||||
from django.template import loader
|
|
||||||
|
|
||||||
from djangoldp_notification.middlewares import MODEL_MODIFICATION_USER_FIELD
|
from djangoldp_notification.middlewares import MODEL_MODIFICATION_USER_FIELD
|
||||||
from .permissions import InboxPermissions
|
from djangoldp_notification.permissions import InboxPermissions, SubscriptionsPermissions
|
||||||
|
|
||||||
|
|
||||||
class Notification(Model):
|
class Notification(Model):
|
||||||
@ -50,6 +45,11 @@ class Subscription(Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}'.format(self.object)
|
return '{}'.format(self.object)
|
||||||
|
|
||||||
|
class Meta(Model.Meta):
|
||||||
|
anonymous_perms = []
|
||||||
|
authenticated_perms = ["add", "view", "delete"]
|
||||||
|
permission_classes = [SubscriptionsPermissions]
|
||||||
|
|
||||||
# --- SUBSCRIPTION SYSTEM ---
|
# --- SUBSCRIPTION SYSTEM ---
|
||||||
@receiver(post_save, dispatch_uid="callback_notif")
|
@receiver(post_save, dispatch_uid="callback_notif")
|
||||||
def send_notification(sender, instance, created, **kwargs):
|
def send_notification(sender, instance, created, **kwargs):
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
from django.contrib.auth import get_user_model
|
||||||
from djangoldp.permissions import LDPPermissions
|
from djangoldp.permissions import LDPPermissions
|
||||||
|
from rest_framework.reverse import reverse
|
||||||
|
|
||||||
|
|
||||||
class InboxPermissions(LDPPermissions):
|
class InboxPermissions(LDPPermissions):
|
||||||
@ -36,3 +38,25 @@ class InboxPermissions(LDPPermissions):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class SubscriptionsPermissions(LDPPermissions):
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
if request.user.is_anonymous and not request.method == "OPTIONS":
|
||||||
|
return False
|
||||||
|
|
||||||
|
if request.method in ["GET", "PATCH", "DELETE", "PUT"]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return super().has_permission(request, view)
|
||||||
|
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
if request.user.is_anonymous and not request.method == "OPTIONS":
|
||||||
|
return False
|
||||||
|
|
||||||
|
reverse_path_key = "{}-notification-list".format(get_user_model()._meta.object_name.lower())
|
||||||
|
user_inbox = reverse(reverse_path_key, kwargs={"slug": request.user.slug}, request=request)
|
||||||
|
if obj.inbox == user_inbox:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
15
djangoldp_notification/tests/conftest.py
Normal file
15
djangoldp_notification/tests/conftest.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from importlib import import_module
|
||||||
|
from os import environ
|
||||||
|
|
||||||
|
from pytest import fail
|
||||||
|
|
||||||
|
settings_module = environ.get("DJANGO_SETTINGS_MODULE")
|
||||||
|
if settings_module is None or len(settings_module) == 0:
|
||||||
|
fail("DJANGO_SETTINGS_MODULE needs to be defined and point to your SIB app installation settings")
|
||||||
|
|
||||||
|
try:
|
||||||
|
import_module(settings_module)
|
||||||
|
except ImportError:
|
||||||
|
initial_module = [token for token in settings_module.split(".") if len(token) > 0][0]
|
||||||
|
fail("Unable to import {}. Try to configure PYTHONPATH to point the "
|
||||||
|
"directory containing the {} module".format(settings_module, initial_module))
|
47
djangoldp_notification/tests/test_models.py
Normal file
47
djangoldp_notification/tests/test_models.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from djangoldp.factories import UserFactory
|
||||||
|
from test_plus import APITestCase
|
||||||
|
|
||||||
|
from djangoldp_notification.models import Subscription
|
||||||
|
|
||||||
|
|
||||||
|
class TestSubscription(APITestCase):
|
||||||
|
user1 = None
|
||||||
|
user2 = None
|
||||||
|
circle_user1_url = "http://localhost:8000/circles/1"
|
||||||
|
circle_user2_url = "http://localhost:8000/circles/2"
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.user1 = UserFactory(username="karl_marx", password="password")
|
||||||
|
Subscription.objects.create(object=self.circle_user1_url, inbox="http://testserver/users/karl_marx/inbox/")
|
||||||
|
|
||||||
|
self.user2 = UserFactory(username="piotr_kropotkine", password="password")
|
||||||
|
Subscription.objects.create(object=self.circle_user2_url,
|
||||||
|
inbox="http://testserver/users/piotr_kropotkine/inbox/")
|
||||||
|
|
||||||
|
def test_not_logged_fails(self):
|
||||||
|
response = self.get("/subscriptions/")
|
||||||
|
self.assert_http_403_forbidden(response)
|
||||||
|
self.assertEqual(response.data.get("detail"), "Authentication credentials were not provided.")
|
||||||
|
|
||||||
|
def test_logged_in_succeeds(self):
|
||||||
|
with self.login(self.user1):
|
||||||
|
result = self.get("/subscriptions/").data.get("ldp:contains")
|
||||||
|
expected = [OrderedDict({
|
||||||
|
"@id": "http://localhost:8000/subscriptions/1/",
|
||||||
|
"object": self.circle_user1_url,
|
||||||
|
"inbox": "http://testserver/users/karl_marx/inbox/",
|
||||||
|
"permissions": [{'mode': {'@type': 'view'}}, {'mode': {'@type': 'delete'}}]
|
||||||
|
})]
|
||||||
|
self.assertSequenceEqual(result, expected)
|
||||||
|
|
||||||
|
with self.login(self.user2):
|
||||||
|
result = self.get("/subscriptions/").data.get("ldp:contains")
|
||||||
|
expected = [OrderedDict({
|
||||||
|
"@id": "http://localhost:8000/subscriptions/2/",
|
||||||
|
"object": self.circle_user2_url,
|
||||||
|
"inbox": "http://testserver/users/piotr_kropotkine/inbox/",
|
||||||
|
"permissions": [{'mode': {'@type': 'view'}}, {'mode': {'@type': 'delete'}}]
|
||||||
|
})]
|
||||||
|
self.assertSequenceEqual(result, expected)
|
@ -15,7 +15,10 @@ install_requires =
|
|||||||
[options.extras_require]
|
[options.extras_require]
|
||||||
include_package_data = True
|
include_package_data = True
|
||||||
dev =
|
dev =
|
||||||
factory_boy>=2.11.0
|
factory_boy>=2.12.0
|
||||||
|
pytest==5.1.1
|
||||||
|
pytest-django==3.7.0
|
||||||
|
django-test-plus==1.4.0
|
||||||
|
|
||||||
[semantic_release]
|
[semantic_release]
|
||||||
version_source = tag
|
version_source = tag
|
||||||
|
Loading…
Reference in New Issue
Block a user