Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Backend
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Analyze
Contributor analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Arkindex
Backend
Commits
189d571f
Commit
189d571f
authored
4 years ago
by
Valentin Rigal
Browse files
Options
Downloads
Patches
Plain Diff
Implement the force approach
parent
da402551
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
arkindex/project/mixins.py
+43
-24
43 additions, 24 deletions
arkindex/project/mixins.py
with
43 additions
and
24 deletions
arkindex/project/mixins.py
+
43
−
24
View file @
189d571f
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.exceptions
import
PermissionDenied
from
django.core.exceptions
import
PermissionDenied
from
django.db.models
import
IntegerField
,
Q
,
Value
,
functions
from
django.db.models
import
Case
,
IntegerField
,
Q
,
Value
,
When
,
functions
from
django.db.models.query_utils
import
DeferredAttribute
from
django.db.models.query_utils
import
DeferredAttribute
from
django.shortcuts
import
get_object_or_404
from
django.shortcuts
import
get_object_or_404
from
django.views.decorators.cache
import
cache_page
from
django.views.decorators.cache
import
cache_page
...
@@ -44,7 +44,7 @@ class ACLMixin(object):
...
@@ -44,7 +44,7 @@ class ACLMixin(object):
.
filter
(
public
=
True
)
\
.
filter
(
public
=
True
)
\
.
annotate
(
max_level
=
Value
(
default_level
,
IntegerField
()))
.
annotate
(
max_level
=
Value
(
default_level
,
IntegerField
()))
def
rights_filter
(
self
,
model
,
level
,
public
=
False
):
def
rights_filter
(
self
,
model
,
level
):
"""
"""
Return a model queryset matching a given access level for this user.
Return a model queryset matching a given access level for this user.
"""
"""
...
@@ -64,33 +64,52 @@ class ACLMixin(object):
...
@@ -64,33 +64,52 @@ class ACLMixin(object):
.
annotate
(
max_level
=
Value
(
Role
.
Admin
.
value
,
IntegerField
()))
\
.
annotate
(
max_level
=
Value
(
Role
.
Admin
.
value
,
IntegerField
()))
\
.
order_by
(
*
self
.
mixin_order_by_fields
,
'
id
'
)
.
order_by
(
*
self
.
mixin_order_by_fields
,
'
id
'
)
# Filter users rights and annotate the resulting level for those rights
qs_filters
=
(
queryset
=
model
.
objects
\
# Filter corpora with a right (direct or via a group)
.
filter
(
Q
(
memberships__user
=
self
.
user
)
# Filter instances with rights concerning this user. This may create duplicates
# Note: in case of direct right, the group level will be skipped (Null value)
Q
(
memberships__user
=
self
.
user
)
|
Q
(
memberships__group__memberships__user
=
self
.
user
)
|
Q
(
memberships__group__memberships__user
=
self
.
user
)
)
)
\
if
include_public
:
.
annotate
(
# Also match public corpora for which this user has no right
# Keep only the lowest level for each right via group
qs_filters
|=
Q
(
max_level
=
functions
.
Least
(
Q
(
public
=
True
)
'
memberships__level
'
,
&
~
Q
(
memberships__user
=
self
.
user
)
# In case of direct right, the group level will be skipped (Null value)
&
~
Q
(
memberships__group__memberships__user
=
self
.
user
)
'
memberships__group__memberships__level
'
)
)
)
#
Order by decreasing max_level to make sure we keep the max among all right
s
#
Annotate instances for each right. This may return duplicated instance
s
queryset
=
queryset
.
filter
(
max_level__gte
=
level
)
\
max_level_annotation
=
functions
.
Least
(
.
order_by
(
*
self
.
mixin_order_by_fields
,
'
id
'
,
'
-max
_level
'
)
\
'
memberships_
_level
'
,
.
distinct
(
*
self
.
mixin_order_by_fields
,
'
id
'
)
# In case of direct right, group level will be skipped (Null value
)
'
memberships__group__memberships__level
'
# Use a join to add public instances as this is the more elegant solution
)
if
include_public
:
if
include_public
:
queryset
=
queryset
.
union
(
self
.
get_public_instances
(
model
,
Role
.
Guest
.
value
))
# Also annotate public instances with no member right
max_level_annotation
=
Case
(
When
(
Q
(
Q
(
public
=
True
)
&
~
Q
(
memberships__user
=
self
.
user
)
&
~
Q
(
memberships__group__memberships__user
=
self
.
user
)
),
# Set the rôle to guest on public instances
then
=
Value
(
Role
.
Guest
.
value
)
),
default
=
max_level_annotation
,
output_field
=
IntegerField
()
)
# Return distinct corpus with the max right level among matching rights
# Return distinct corpus with the max right level among matching rights
return
queryset
.
order_by
(
*
self
.
mixin_order_by_fields
,
'
id
'
)
return
model
.
objects
\
.
filter
(
qs_filters
)
\
.
annotate
(
max_level
=
max_level_annotation
)
\
.
filter
(
max_level__gte
=
level
)
\
.
order_by
(
# Order by decreasing max_level to make sure we keep the max among all rights
*
self
.
mixin_order_by_fields
,
'
id
'
,
'
-max_level
'
)
\
.
distinct
(
*
self
.
mixin_order_by_fields
,
'
id
'
)
def
has_access
(
self
,
instance
,
level
):
def
has_access
(
self
,
instance
,
level
):
self
.
_check_level
(
level
)
self
.
_check_level
(
level
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment