kopia lustrzana https://github.com/OpenDroneMap/WebODM
Added django-guardian, set owner permissions on post save, testing, CSS fixes
rodzic
d686e63c40
commit
90cc52ff2d
|
@ -1 +1,8 @@
|
|||
from django.contrib import admin
|
||||
from guardian.admin import GuardedModelAdmin
|
||||
from .models import Project
|
||||
|
||||
class ProjectAdmin(GuardedModelAdmin):
|
||||
pass
|
||||
|
||||
admin.site.register(Project, ProjectAdmin)
|
|
@ -11,7 +11,7 @@ class ProjectSerializer(serializers.HyperlinkedModelSerializer):
|
|||
|
||||
class ProjectViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
Projects the current user has access to, including the ability to create new ones.
|
||||
Projects the current user has access to.
|
||||
"""
|
||||
queryset = models.Project.objects.all()
|
||||
serializer_class = ProjectSerializer
|
|
@ -1,7 +1,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
import .signals
|
||||
|
||||
class MainConfig(AppConfig):
|
||||
name = 'main'
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# password: test1234
|
||||
password: pbkdf2_sha256$30000$pFwIz88hEEZ4$siNaZefZB3bb0DlemWNOkj6+tCq3I3LW+IgVw5VsRmE=
|
||||
last_login: null
|
||||
is_superuser: true
|
||||
is_superuser: false
|
||||
username: testuser2
|
||||
first_name: ''
|
||||
last_name: ''
|
||||
|
@ -29,4 +29,20 @@
|
|||
is_active: true
|
||||
date_joined: '2016-09-11T22:26:52.582858+00:00'
|
||||
groups: []
|
||||
user_permissions: []
|
||||
- model: auth.user
|
||||
pk: 3
|
||||
fields:
|
||||
# password: test1234
|
||||
password: pbkdf2_sha256$30000$pFwIz88hEEZ4$siNaZefZB3bb0DlemWNOkj6+tCq3I3LW+IgVw5VsRmE=
|
||||
last_login: null
|
||||
is_superuser: false
|
||||
username: testuser3
|
||||
first_name: ''
|
||||
last_name: ''
|
||||
email: test2@mail.com
|
||||
is_staff: true
|
||||
is_active: true
|
||||
date_joined: '2016-09-11T22:26:52.582858+00:00'
|
||||
groups: []
|
||||
user_permissions: []
|
|
@ -1,10 +1,15 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.postgres import fields
|
||||
from nodeodm.models import ProcessingNode
|
||||
from django.dispatch import receiver
|
||||
from guardian.shortcuts import get_perms_for_model, assign_perm
|
||||
from guardian.models import UserObjectPermissionBase
|
||||
from guardian.models import GroupObjectPermissionBase
|
||||
|
||||
def assets_directory_path(taskId, projectId, filename):
|
||||
# files will be uploaded to MEDIA_ROOT/project_<id>/task_<id>/<filename>
|
||||
|
@ -14,12 +19,37 @@ def assets_directory_path(taskId, projectId, filename):
|
|||
class Project(models.Model):
|
||||
owner = models.ForeignKey(User, on_delete=models.PROTECT, help_text="The person who created the project")
|
||||
name = models.CharField(max_length=255, help_text="A label used to describe the project")
|
||||
description = models.TextField(null=True, help_text="More in-depth description of the project")
|
||||
description = models.TextField(null=True, blank=True, help_text="More in-depth description of the project")
|
||||
created_at = models.DateTimeField(default=timezone.now, help_text="Creation date")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
permissions = (
|
||||
('view_project', 'Can view project'),
|
||||
)
|
||||
|
||||
|
||||
@receiver(signals.post_save, sender=Project, dispatch_uid="project_post_save")
|
||||
def project_post_save(sender, instance, created, **kwargs):
|
||||
"""
|
||||
Automatically assigns all permissions to the owner. If the owner changes
|
||||
it's up to the user/developer to remove the previous owner's permissions.
|
||||
"""
|
||||
for perm in get_perms_for_model(sender).all():
|
||||
assign_perm(perm.codename, instance.owner, instance)
|
||||
|
||||
|
||||
class ProjectUserObjectPermission(UserObjectPermissionBase):
|
||||
content_object = models.ForeignKey(Project)
|
||||
|
||||
class ProjectGroupObjectPermission(GroupObjectPermissionBase):
|
||||
content_object = models.ForeignKey(Project)
|
||||
|
||||
# from guardian.shortcuts import get_objects_for_user
|
||||
# ...
|
||||
# videos = get_objects_for_user(request.user, "view_video", Video.objects.all())
|
||||
|
||||
def gcp_directory_path(task, filename):
|
||||
return assets_directory_path(task.id, task.project.id, filename)
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
/* HEADER */
|
||||
/* SIDEBAR */
|
||||
/* POPUP */ }
|
||||
.admin-area #changelist-filter {
|
||||
display: none; }
|
||||
.admin-area a:link, .admin-area a:visited {
|
||||
color: #447e9b;
|
||||
text-decoration: none; }
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3,6 +3,10 @@
|
|||
*/
|
||||
|
||||
.admin-area{
|
||||
#changelist-filter{
|
||||
display: none;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
color: #447e9b;
|
||||
text-decoration: none;
|
||||
|
|
|
@ -72,8 +72,8 @@
|
|||
.admin-area .colMS .aligned .vLargeTextField, .admin-area .colMS .aligned .vXMLLargeTextField {
|
||||
width: 350px; }
|
||||
.admin-area form .aligned ul {
|
||||
margin-left: 160px;
|
||||
padding-left: 10px; }
|
||||
margin-left: 6px;
|
||||
padding-left: 3px; }
|
||||
.admin-area form .aligned ul.radiolist {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
|
@ -302,8 +302,8 @@
|
|||
background-image: url(../img/search.svg); }
|
||||
.admin-area form .related-widget-wrapper ul {
|
||||
display: inline-block;
|
||||
margin-left: 0;
|
||||
padding-left: 0; }
|
||||
margin-left: 6px;
|
||||
padding-left: 3px; }
|
||||
.admin-area .clearable-file-input input {
|
||||
margin-top: 0; }
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -105,8 +105,8 @@
|
|||
}
|
||||
|
||||
form .aligned ul {
|
||||
margin-left: 160px;
|
||||
padding-left: 10px;
|
||||
margin-left: 6px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
form .aligned ul.radiolist {
|
||||
|
@ -489,8 +489,8 @@
|
|||
|
||||
form .related-widget-wrapper ul {
|
||||
display: inline-block;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
margin-left: 6px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.clearable-file-input input {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
{% block extra-headers %}{% endblock %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'app/css/main.css' %}" />
|
||||
<script src="{% static 'app/js/vendor/modernizr-2.8.3.min.js' %}"></script>
|
||||
<script src="{% static 'app/js/vendor/knockout-3.4.0.js' %}"></script>
|
||||
<script src="{% static 'app/js/vendor/jquery-1.11.2.min.js' %}"></script>
|
||||
<title>{{title|default:"Login"}} - WebODM</title>
|
||||
</head>
|
||||
|
|
29
app/tests.py
29
app/tests.py
|
@ -84,3 +84,32 @@ class TestApp(TestCase):
|
|||
|
||||
res = c.get('/processingnode/abc/')
|
||||
self.assertTrue(res.status_code == 404)
|
||||
|
||||
def test_projects(self):
|
||||
# Get a normal user
|
||||
user = User.objects.get(pk=2)
|
||||
self.assertFalse(user.is_superuser)
|
||||
|
||||
# Create a new project
|
||||
p = Project(owner=user, name="test")
|
||||
p.save()
|
||||
|
||||
# Have the proper permissions been set?
|
||||
self.assertTrue(user.has_perm("view_project", p))
|
||||
self.assertTrue(user.has_perm("add_project", p))
|
||||
self.assertTrue(user.has_perm("change_project", p))
|
||||
self.assertTrue(user.has_perm("delete_project", p))
|
||||
|
||||
# Get a superuser
|
||||
superUser = User.objects.get(pk=1)
|
||||
self.assertTrue(superUser.is_superuser)
|
||||
|
||||
# He should also have permissions, although not explicitly set
|
||||
self.assertTrue(superUser.has_perm("delete_project", p))
|
||||
|
||||
# Get another user
|
||||
anotherUser = User.objects.get(pk=3)
|
||||
self.assertFalse(anotherUser.is_superuser)
|
||||
|
||||
# Should not have permission
|
||||
self.assertFalse(anotherUser.has_perm("delete_project", p))
|
||||
|
|
|
@ -15,7 +15,7 @@ def dashboard(request):
|
|||
no_processingnodes = ProcessingNode.objects.count() == 0
|
||||
|
||||
# Create first project automatically
|
||||
if Project.objects.count() == 0:
|
||||
if Project.objects.filter(owner=request.user).count() == 0:
|
||||
proj = Project(owner=request.user, name=_("First Project"))
|
||||
proj.save()
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ cryptography==1.5
|
|||
Django==1.10
|
||||
django-common-helpers==0.8.0
|
||||
django-filter==0.15.2
|
||||
django-guardian==1.4.6
|
||||
django-knockout==0.3.2
|
||||
djangorestframework==3.4.7
|
||||
enum34==1.1.6
|
||||
fido==3.2.0
|
||||
|
|
|
@ -38,6 +38,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'guardian',
|
||||
'rest_framework',
|
||||
'app',
|
||||
'nodeodm',
|
||||
|
@ -111,6 +112,11 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
},
|
||||
]
|
||||
|
||||
# Hook guardian
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'django.contrib.auth.backends.ModelBackend', # this is default
|
||||
'guardian.backends.ObjectPermissionBackend',
|
||||
)
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.10/topics/i18n/
|
||||
|
|
Ładowanie…
Reference in New Issue