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
b45b3338
Unverified
Commit
b45b3338
authored
Mar 11, 2019
by
老广
Committed by
GitHub
Mar 11, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Monitor (#2485)
* [Update] * [Update] 修改fields
parent
c86a036a
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
227 additions
and
73 deletions
+227
-73
tasks.py
apps/authentication/tasks.py
+11
-0
__init__.py
apps/common/fields/__init__.py
+6
-0
form.py
apps/common/fields/form.py
+8
-51
model.py
apps/common/fields/model.py
+132
-0
serializer.py
apps/common/fields/serializer.py
+41
-0
urls.py
apps/jumpserver/urls.py
+25
-19
signals_handler.py
apps/orgs/signals_handler.py
+1
-1
echarts.min.js
apps/static/js/plugins/echarts/echarts.min.js
+0
-0
user.py
apps/users/api/user.py
+3
-2
No files found.
apps/authentication/tasks.py
View file @
b45b3338
...
...
@@ -2,6 +2,9 @@
#
from
celery
import
shared_task
from
ops.celery.decorator
import
register_as_period_task
from
django.contrib.sessions.models
import
Session
from
django.utils
import
timezone
from
.utils
import
write_login_log
...
...
@@ -9,3 +12,11 @@ from .utils import write_login_log
@shared_task
def
write_login_log_async
(
*
args
,
**
kwargs
):
write_login_log
(
*
args
,
**
kwargs
)
@register_as_period_task
(
interval
=
3600
*
24
)
@shared_task
def
clean_django_sessions
():
Session
.
objects
.
filter
(
expire_date__lt
=
timezone
.
now
())
.
delete
()
apps/common/fields/__init__.py
0 → 100644
View file @
b45b3338
# -*- coding: utf-8 -*-
#
from
.form
import
*
from
.model
import
*
from
.serializer
import
*
apps/common/fields.py
→
apps/common/fields
/form
.py
View file @
b45b3338
...
...
@@ -2,16 +2,19 @@
#
import
json
from
django.db
import
models
from
django
import
forms
from
django.utils
import
six
from
django.core.exceptions
import
ValidationError
from
django.utils.translation
import
ugettext
as
_
from
rest_framework
import
serializers
from
.utils
import
get_signer
from
..utils
import
get_signer
signer
=
get_signer
()
__all__
=
[
'FormDictField'
,
'FormEncryptCharField'
,
'FormEncryptDictField'
,
'FormEncryptMixin'
,
]
class
FormDictField
(
forms
.
Field
):
widget
=
forms
.
Textarea
...
...
@@ -44,38 +47,6 @@ class FormDictField(forms.Field):
return
self
.
to_python
(
initial
)
!=
self
.
to_python
(
data
)
class
StringIDField
(
serializers
.
Field
):
def
to_representation
(
self
,
value
):
return
{
"pk"
:
value
.
pk
,
"name"
:
value
.
__str__
()}
class
StringManyToManyField
(
serializers
.
RelatedField
):
def
to_representation
(
self
,
value
):
return
value
.
__str__
()
class
EncryptMixin
:
def
from_db_value
(
self
,
value
,
expression
,
connection
,
context
):
if
value
is
not
None
:
return
signer
.
unsign
(
value
)
return
super
()
.
from_db_value
(
self
,
value
,
expression
,
connection
,
context
)
def
get_prep_value
(
self
,
value
):
if
value
is
None
:
return
value
return
signer
.
sign
(
value
)
class
EncryptTextField
(
EncryptMixin
,
models
.
TextField
):
description
=
_
(
"Encrypt field using Secret Key"
)
class
EncryptCharField
(
EncryptMixin
,
models
.
CharField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
kwargs
[
'max_length'
]
=
2048
super
()
.
__init__
(
*
args
,
**
kwargs
)
class
FormEncryptMixin
:
pass
...
...
@@ -88,19 +59,5 @@ class FormEncryptDictField(FormEncryptMixin, FormDictField):
pass
class
ChoiceDisplayField
(
serializers
.
ChoiceField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
ChoiceDisplayField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
choice_strings_to_display
=
{
six
.
text_type
(
key
):
value
for
key
,
value
in
self
.
choices
.
items
()
}
def
to_representation
(
self
,
value
):
if
value
is
None
:
return
value
return
{
'value'
:
self
.
choice_strings_to_values
.
get
(
six
.
text_type
(
value
),
value
),
'display'
:
self
.
choice_strings_to_display
.
get
(
six
.
text_type
(
value
),
value
),
}
apps/common/fields/model.py
0 → 100644
View file @
b45b3338
# -*- coding: utf-8 -*-
#
import
json
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
from
..utils
import
get_signer
__all__
=
[
'JsonMixin'
,
'JsonDictMixin'
,
'JsonListMixin'
,
'JsonTypeMixin'
,
'JsonCharField'
,
'JsonTextField'
,
'JsonListCharField'
,
'JsonListTextField'
,
'JsonDictCharField'
,
'JsonDictTextField'
,
'EncryptCharField'
,
'EncryptTextField'
,
'EncryptMixin'
,
]
signer
=
get_signer
()
class
JsonMixin
:
tp
=
None
@staticmethod
def
json_decode
(
data
):
try
:
return
json
.
loads
(
data
)
except
(
TypeError
,
json
.
JSONDecodeError
):
return
None
@staticmethod
def
json_encode
(
data
):
return
json
.
dumps
(
data
)
def
from_db_value
(
self
,
value
,
expression
,
connection
,
context
):
if
value
is
None
:
return
value
return
self
.
json_decode
(
value
)
def
to_python
(
self
,
value
):
if
value
is
None
:
return
value
if
not
isinstance
(
value
,
str
)
or
not
value
.
startswith
(
'"'
):
return
value
else
:
return
self
.
json_decode
(
value
)
def
get_prep_value
(
self
,
value
):
if
value
is
None
:
return
value
return
self
.
json_encode
(
value
)
class
JsonTypeMixin
(
JsonMixin
):
tp
=
dict
def
from_db_value
(
self
,
value
,
expression
,
connection
,
context
):
value
=
super
()
.
from_db_value
(
value
,
expression
,
connection
,
context
)
if
not
isinstance
(
value
,
self
.
tp
):
value
=
self
.
tp
()
return
value
def
to_python
(
self
,
value
):
data
=
super
()
.
to_python
(
value
)
if
not
isinstance
(
data
,
self
.
tp
):
data
=
self
.
tp
()
return
data
def
get_prep_value
(
self
,
value
):
if
not
isinstance
(
value
,
self
.
tp
):
value
=
self
.
tp
()
return
self
.
json_encode
(
value
)
class
JsonDictMixin
(
JsonTypeMixin
):
tp
=
dict
class
JsonDictCharField
(
JsonDictMixin
,
models
.
CharField
):
description
=
_
(
"Marshal dict data to char field"
)
class
JsonDictTextField
(
JsonDictMixin
,
models
.
TextField
):
description
=
_
(
"Marshal dict data to text field"
)
class
JsonListMixin
(
JsonTypeMixin
):
tp
=
list
class
JsonStrListMixin
(
JsonListMixin
):
pass
class
JsonListCharField
(
JsonListMixin
,
models
.
CharField
):
description
=
_
(
"Marshal list data to char field"
)
class
JsonListTextField
(
JsonListMixin
,
models
.
TextField
):
description
=
_
(
"Marshal list data to text field"
)
class
JsonCharField
(
JsonMixin
,
models
.
CharField
):
description
=
_
(
"Marshal data to char field"
)
class
JsonTextField
(
JsonMixin
,
models
.
TextField
):
description
=
_
(
"Marshal data to text field"
)
class
EncryptMixin
:
def
from_db_value
(
self
,
value
,
expression
,
connection
,
context
):
if
value
is
not
None
:
return
signer
.
unsign
(
value
)
return
None
def
get_prep_value
(
self
,
value
):
if
value
is
None
:
return
value
return
signer
.
sign
(
value
)
class
EncryptTextField
(
EncryptMixin
,
models
.
TextField
):
description
=
_
(
"Encrypt field using Secret Key"
)
class
EncryptCharField
(
EncryptMixin
,
models
.
CharField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
kwargs
[
'max_length'
]
=
2048
super
()
.
__init__
(
*
args
,
**
kwargs
)
apps/common/fields/serializer.py
0 → 100644
View file @
b45b3338
# -*- coding: utf-8 -*-
#
from
rest_framework
import
serializers
from
django.utils
import
six
__all__
=
[
'StringIDField'
,
'StringManyToManyField'
,
'ChoiceDisplayField'
]
class
StringIDField
(
serializers
.
Field
):
def
to_representation
(
self
,
value
):
return
{
"pk"
:
value
.
pk
,
"name"
:
value
.
__str__
()}
class
StringManyToManyField
(
serializers
.
RelatedField
):
def
to_representation
(
self
,
value
):
return
value
.
__str__
()
class
ChoiceDisplayField
(
serializers
.
ChoiceField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
ChoiceDisplayField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
choice_strings_to_display
=
{
six
.
text_type
(
key
):
value
for
key
,
value
in
self
.
choices
.
items
()
}
def
to_representation
(
self
,
value
):
if
value
is
None
:
return
value
return
{
'value'
:
self
.
choice_strings_to_values
.
get
(
six
.
text_type
(
value
),
value
),
'display'
:
self
.
choice_strings_to_display
.
get
(
six
.
text_type
(
value
),
value
),
}
class
DictField
(
serializers
.
DictField
):
def
to_representation
(
self
,
value
):
if
not
value
or
not
isinstance
(
value
,
dict
):
value
=
{}
return
super
()
.
to_representation
(
value
)
apps/jumpserver/urls.py
View file @
b45b3338
...
...
@@ -10,28 +10,24 @@ from django.views.i18n import JavaScriptCatalog
from
.views
import
IndexView
,
LunaView
,
I18NView
from
.swagger
import
get_swagger_view
api_v1_patterns
=
[
path
(
'api/'
,
include
([
path
(
'users/v1/'
,
include
(
'users.urls.api_urls'
,
namespace
=
'api-users'
)),
path
(
'assets/v1/'
,
include
(
'assets.urls.api_urls'
,
namespace
=
'api-assets'
)),
path
(
'perms/v1/'
,
include
(
'perms.urls.api_urls'
,
namespace
=
'api-perms'
)),
path
(
'terminal/v1/'
,
include
(
'terminal.urls.api_urls'
,
namespace
=
'api-terminal'
)),
path
(
'ops/v1/'
,
include
(
'ops.urls.api_urls'
,
namespace
=
'api-ops'
)),
path
(
'audits/v1/'
,
include
(
'audits.urls.api_urls'
,
namespace
=
'api-audits'
)),
path
(
'orgs/v1/'
,
include
(
'orgs.urls.api_urls'
,
namespace
=
'api-orgs'
)),
path
(
'settings/v1/'
,
include
(
'settings.urls.api_urls'
,
namespace
=
'api-settings'
)),
path
(
'authentication/v1/'
,
include
(
'authentication.urls.api_urls'
,
namespace
=
'api-auth'
)),
]))
api_v1
=
[
path
(
'users/v1/'
,
include
(
'users.urls.api_urls'
,
namespace
=
'api-users'
)),
path
(
'assets/v1/'
,
include
(
'assets.urls.api_urls'
,
namespace
=
'api-assets'
)),
path
(
'perms/v1/'
,
include
(
'perms.urls.api_urls'
,
namespace
=
'api-perms'
)),
path
(
'terminal/v1/'
,
include
(
'terminal.urls.api_urls'
,
namespace
=
'api-terminal'
)),
path
(
'ops/v1/'
,
include
(
'ops.urls.api_urls'
,
namespace
=
'api-ops'
)),
path
(
'audits/v1/'
,
include
(
'audits.urls.api_urls'
,
namespace
=
'api-audits'
)),
path
(
'orgs/v1/'
,
include
(
'orgs.urls.api_urls'
,
namespace
=
'api-orgs'
)),
path
(
'settings/v1/'
,
include
(
'settings.urls.api_urls'
,
namespace
=
'api-settings'
)),
path
(
'authentication/v1/'
,
include
(
'authentication.urls.api_urls'
,
namespace
=
'api-auth'
)),
]
api_v2_patterns
=
[
path
(
'api/'
,
include
([
path
(
'terminal/v2/'
,
include
(
'terminal.urls.api_urls_v2'
,
namespace
=
'api-terminal-v2'
)),
path
(
'users/v2/'
,
include
(
'users.urls.api_urls_v2'
,
namespace
=
'api-users-v2'
)),
]))
api_v2
=
[
path
(
'terminal/v2/'
,
include
(
'terminal.urls.api_urls_v2'
,
namespace
=
'api-terminal-v2'
)),
path
(
'users/v2/'
,
include
(
'users.urls.api_urls_v2'
,
namespace
=
'api-users-v2'
)),
]
app_view_patterns
=
[
path
(
'users/'
,
include
(
'users.urls.views_urls'
,
namespace
=
'users'
)),
path
(
'assets/'
,
include
(
'assets.urls.views_urls'
,
namespace
=
'assets'
)),
...
...
@@ -45,12 +41,21 @@ app_view_patterns = [
if
settings
.
XPACK_ENABLED
:
app_view_patterns
.
append
(
path
(
'xpack/'
,
include
(
'xpack.urls'
,
namespace
=
'xpack'
)))
app_view_patterns
.
append
(
path
(
'xpack/'
,
include
(
'xpack.urls.view_urls'
,
namespace
=
'xpack'
)))
api_v1
.
append
(
path
(
'xpack/v1/'
,
include
(
'xpack.urls.api_urls'
,
namespace
=
'api-xpack'
)))
js_i18n_patterns
=
i18n_patterns
(
path
(
'jsi18n/'
,
JavaScriptCatalog
.
as_view
(),
name
=
'javascript-catalog'
),
)
api_v1_patterns
=
[
path
(
'api/'
,
include
(
api_v1
))
]
api_v2_patterns
=
[
path
(
'api/'
,
include
(
api_v2
))
]
urlpatterns
=
[
path
(
''
,
IndexView
.
as_view
(),
name
=
'index'
),
path
(
''
,
include
(
api_v2_patterns
)),
...
...
@@ -63,6 +68,7 @@ urlpatterns = [
# External apps url
path
(
'captcha/'
,
include
(
'captcha.urls'
)),
]
urlpatterns
+=
app_view_patterns
urlpatterns
+=
static
(
settings
.
MEDIA_URL
,
document_root
=
settings
.
MEDIA_ROOT
)
\
+
static
(
settings
.
STATIC_URL
,
document_root
=
settings
.
STATIC_ROOT
)
...
...
apps/orgs/signals_handler.py
View file @
b45b3338
...
...
@@ -23,7 +23,7 @@ def on_org_create_or_update(sender, instance=None, created=False, **kwargs):
set_current_org
(
old_org
)
if
instance
and
not
created
:
instance
.
expire_
user_
cache
()
instance
.
expire_cache
()
@receiver
(
m2m_changed
,
sender
=
Organization
.
users
.
through
)
...
...
apps/static/js/plugins/echarts/echarts.min.js
0 → 100644
View file @
b45b3338
This diff is collapsed.
Click to expand it.
apps/users/api/user.py
View file @
b45b3338
...
...
@@ -11,8 +11,9 @@ from rest_framework.permissions import IsAuthenticated
from
rest_framework_bulk
import
BulkModelViewSet
from
rest_framework.pagination
import
LimitOffsetPagination
from
common.permissions
import
IsOrgAdmin
,
IsCurrentUserOrReadOnly
,
\
IsOrgAdminOrAppUser
from
common.permissions
import
(
IsOrgAdmin
,
IsCurrentUserOrReadOnly
,
IsOrgAdminOrAppUser
)
from
common.mixins
import
IDInFilterMixin
from
common.utils
import
get_logger
from
orgs.utils
import
current_org
...
...
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