Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
0446f449
Commit
0446f449
authored
8 years ago
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add auth and permission backends
parent
a62a2178
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
68 additions
and
18 deletions
+68
-18
settings.py
apps/jumpserver/settings.py
+3
-2
api.py
apps/users/api.py
+7
-2
backends.py
apps/users/backends.py
+44
-10
models.py
apps/users/models.py
+14
-4
No files found.
apps/jumpserver/settings.py
View file @
0446f449
...
...
@@ -68,7 +68,6 @@ INSTALLED_APPS = [
'django.contrib.sessions'
,
'django.contrib.messages'
,
'django.contrib.staticfiles'
,
'ws4redis'
,
]
...
...
@@ -264,12 +263,14 @@ REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES'
:
(
'rest_framework.permissions.IsAdminUser'
,
# 'rest_framework.permissions.IsAuthenticated',
'users.backends.IsValidUser'
,
),
'DEFAULT_AUTHENTICATION_CLASSES'
:
(
'rest_framework.authentication.BasicAuthentication'
,
'rest_framework.authentication.SessionAuthentication'
,
'rest_framework.authentication.TokenAuthentication'
,
'users.backends.AppSignAuthentication'
,
),
}
# This setting is required to override the Django's main loop, when running in
...
...
This diff is collapsed.
Click to expand it.
apps/users/api.py
View file @
0446f449
...
...
@@ -7,11 +7,12 @@ from rest_framework import generics, status
from
rest_framework.response
import
Response
from
rest_framework_bulk
import
ListBulkCreateUpdateDestroyAPIView
from
common.mixins
import
BulkDeleteApiMixin
from
common.utils
import
get_logger
from
.models
import
User
,
UserGroup
from
.serializers
import
UserDetailSerializer
,
UserAndGroupSerializer
,
\
GroupDetailSerializer
,
UserPKUpdateSerializer
,
UserBulkUpdateSerializer
,
GroupBulkUpdateSerializer
from
common.mixins
import
BulkDeleteApiMixin
from
common.utils
import
get_logger
from
.backends
import
IsSuperUser
,
IsAppUser
,
IsValidUser
,
IsSuperUserOrAppUser
logger
=
get_logger
(
__name__
)
...
...
@@ -84,6 +85,10 @@ class GroupDetailApi(generics.RetrieveUpdateDestroyAPIView):
class
UserListUpdateApi
(
BulkDeleteApiMixin
,
ListBulkCreateUpdateDestroyAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserBulkUpdateSerializer
permission_classes
=
(
IsSuperUserOrAppUser
,)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
return
super
(
UserListUpdateApi
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
class
GroupListUpdateApi
(
BulkDeleteApiMixin
,
ListBulkCreateUpdateDestroyAPIView
):
...
...
This diff is collapsed.
Click to expand it.
apps/users/backends.py
View file @
0446f449
# -*- coding: utf-8 -*-
#
from
rest_framework
import
authentication
,
exceptions
from
rest_framework
import
authentication
,
exceptions
,
permissions
from
rest_framework.compat
import
is_authenticated
from
django.utils.translation
import
ugettext
as
_
from
common.utils
import
unsign
from
common.utils
import
unsign
,
get_object_or_none
from
.models
import
User
class
A
PP
SignAuthentication
(
authentication
.
BaseAuthentication
):
class
A
pp
SignAuthentication
(
authentication
.
BaseAuthentication
):
keyword
=
'Sign'
model
=
User
...
...
@@ -30,17 +31,50 @@ class APPSignAuthentication(authentication.BaseAuthentication):
except
UnicodeError
:
msg
=
_
(
'Invalid token header. Sign string should not contain invalid characters.'
)
raise
exceptions
.
AuthenticationFailed
(
msg
)
return
self
.
authenticate_credentials
(
sign
)
def
authenticate_credentials
(
self
,
key
):
try
:
token
=
self
.
model
.
objects
.
select_related
(
'user'
)
.
get
(
key
=
key
)
except
self
.
model
.
DoesNotExist
:
raise
exceptions
.
AuthenticationFailed
(
_
(
'Invalid token.'
))
def
authenticate_credentials
(
self
,
sign
):
app
=
unsign
(
sign
,
max_age
=
300
)
if
app
:
user
=
get_object_or_none
(
self
.
model
,
username
=
app
,
role
=
'App'
)
else
:
raise
exceptions
.
AuthenticationFailed
(
_
(
'Invalid sign.'
))
if
not
token
.
user
.
is_active
:
if
not
user
.
is_active
:
raise
exceptions
.
AuthenticationFailed
(
_
(
'User inactive or deleted.'
))
return
user
,
None
class
IsValidUser
(
permissions
.
IsAuthenticated
,
permissions
.
BasePermission
):
"""Allows access to valid user, is active and not expired"""
def
has_permission
(
self
,
request
,
view
):
return
super
(
IsValidUser
,
self
)
.
has_permission
(
request
,
view
)
\
and
request
.
user
.
is_valid
class
IsAppUser
(
IsValidUser
,
permissions
.
BasePermission
):
"""Allows access only to app user """
def
has_permission
(
self
,
request
,
view
):
return
super
(
IsAppUser
,
self
)
.
has_permission
(
request
,
view
)
\
and
request
.
user
.
is_app_user
class
IsSuperUser
(
IsValidUser
,
permissions
.
BasePermission
):
"""Allows access only to superuser"""
def
has_permission
(
self
,
request
,
view
):
return
super
(
IsSuperUser
,
self
)
.
has_permission
(
request
,
view
)
\
and
request
.
user
.
is_superuser
class
IsSuperUserOrAppUser
(
IsValidUser
,
permissions
.
BasePermission
):
"""Allows access between superuser and app user"""
def
has_permission
(
self
,
request
,
view
):
return
super
(
IsSuperUserOrAppUser
,
self
)
.
has_permission
(
request
,
view
)
\
and
(
request
.
user
.
is_superuser
or
request
.
user
.
is_app_user
)
if
__name__
==
'__main__'
:
...
...
This diff is collapsed.
Click to expand it.
apps/users/models.py
View file @
0446f449
...
...
@@ -69,6 +69,7 @@ class User(AbstractUser):
ROLE_CHOICES
=
(
(
'Admin'
,
_
(
'Administrator'
)),
(
'User'
,
_
(
'User'
)),
(
'App'
,
_
(
'Application'
)),
)
username
=
models
.
CharField
(
max_length
=
20
,
unique
=
True
,
verbose_name
=
_
(
'Username'
))
...
...
@@ -148,9 +149,18 @@ class User(AbstractUser):
else
:
self
.
role
=
'User'
is_admin
=
is_superuser
@property
def
is_app_user
(
self
):
if
self
.
role
==
'App'
:
return
True
else
:
return
False
@property
def
is_staff
(
self
):
if
self
.
is_authenticated
and
self
.
is_
active
and
not
self
.
is_expired
and
self
.
is_superuser
:
if
self
.
is_authenticated
and
self
.
is_
valid
:
return
True
else
:
return
False
...
...
@@ -185,14 +195,14 @@ class User(AbstractUser):
Token
.
objects
.
filter
(
user
=
self
)
.
delete
()
return
Token
.
objects
.
create
(
user
=
self
)
def
generate_reset_token
(
self
):
return
signing
.
dumps
({
'reset'
:
self
.
id
,
'email'
:
self
.
email
})
def
is_member_of
(
self
,
user_group
):
if
user_group
in
self
.
groups
.
all
():
return
True
return
False
def
generate_reset_token
(
self
):
return
signing
.
dumps
({
'reset'
:
self
.
id
,
'email'
:
self
.
email
})
@classmethod
def
validate_reset_token
(
cls
,
token
,
max_age
=
3600
):
try
:
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment