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
3fa5ce54
Commit
3fa5ce54
authored
Mar 30, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Fixture] 添加用户信息更改
parent
0983f294
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
306 additions
and
55 deletions
+306
-55
_user_profile.html
apps/templates/_user_profile.html
+1
-1
forms.py
apps/users/forms.py
+62
-18
user.py
apps/users/models/user.py
+6
-3
user_password_update.html
apps/users/templates/users/user_password_update.html
+75
-0
user_profile.html
apps/users/templates/users/user_profile.html
+17
-21
user_profile_update.html
apps/users/templates/users/user_profile_update.html
+7
-4
user_pubkey_update.html
apps/users/templates/users/user_pubkey_update.html
+86
-0
views_urls.py
apps/users/urls/views_urls.py
+6
-0
login.py
apps/users/views/login.py
+1
-1
user.py
apps/users/views/user.py
+45
-7
No files found.
apps/templates/_user_profile.html
View file @
3fa5ce54
...
...
@@ -3,7 +3,7 @@
<li
class=
"nav-header"
>
<div
class=
"dropdown profile-element"
>
<span>
<img
alt=
"image"
class=
"img-circle"
width=
"48"
height=
"48"
src=
"{
% static "
img
/
root
.
png
"
%
}"
/>
<img
alt=
"image"
class=
"img-circle"
width=
"48"
height=
"48"
src=
"{
{ user.avatar_url }
}"
/>
</span>
<a
data-toggle=
"dropdown"
class=
"dropdown-toggle"
href=
"#"
>
<span
class=
"clear"
>
...
...
apps/users/forms.py
View file @
3fa5ce54
...
...
@@ -41,8 +41,8 @@ class UserProfileForm(forms.ModelForm):
class
Meta
:
model
=
User
fields
=
[
'username'
,
'name'
,
'email'
,
'groups'
,
'wechat'
,
'phone'
,
'username'
,
'name'
,
'email'
,
'
wechat'
,
'
phone'
,
]
help_texts
=
{
'username'
:
'* required'
,
...
...
@@ -51,6 +51,66 @@ class UserProfileForm(forms.ModelForm):
}
class
UserPasswordForm
(
forms
.
Form
):
old_password
=
forms
.
CharField
(
min_length
=
5
,
max_length
=
128
,
widget
=
forms
.
PasswordInput
)
new_password
=
forms
.
CharField
(
min_length
=
5
,
max_length
=
128
,
widget
=
forms
.
PasswordInput
)
confirm_password
=
forms
.
CharField
(
min_length
=
5
,
max_length
=
128
,
widget
=
forms
.
PasswordInput
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
instance
=
kwargs
.
pop
(
'instance'
)
super
(
UserPasswordForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
clean_old_password
(
self
):
old_password
=
self
.
cleaned_data
[
'old_password'
]
if
not
self
.
instance
.
check_password
(
old_password
):
raise
forms
.
ValidationError
(
_
(
'Old password error'
))
return
old_password
def
clean_confirm_password
(
self
):
new_password
=
self
.
cleaned_data
[
'new_password'
]
confirm_password
=
self
.
cleaned_data
[
'confirm_password'
]
if
new_password
!=
confirm_password
:
raise
forms
.
ValidationError
(
_
(
'Password does not match'
))
return
confirm_password
def
save
(
self
):
password
=
self
.
cleaned_data
[
'new_password'
]
self
.
instance
.
set_password
(
password
)
self
.
instance
.
save
()
return
self
.
instance
class
UserPublicKeyForm
(
forms
.
Form
):
public_key
=
forms
.
CharField
(
label
=
_
(
'ssh public key'
),
max_length
=
5000
,
widget
=
forms
.
Textarea
(
attrs
=
{
'placeholder'
:
_
(
'ssh-rsa AAAA...'
)}),
help_text
=
_
(
'Paste your id_rsa.pub here.'
))
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
instance
=
kwargs
.
pop
(
'instance'
)
super
(
UserPublicKeyForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
clean_public_key
(
self
):
public_key
=
self
.
cleaned_data
[
'public_key'
]
if
self
.
instance
.
public_key
and
public_key
==
self
.
instance
.
public_key
:
raise
forms
.
ValidationError
(
_
(
'Public key should not be the '
'same as your old one.'
))
if
not
validate_ssh_public_key
(
public_key
):
raise
forms
.
ValidationError
(
_
(
'Not a valid ssh public key'
))
return
public_key
def
save
(
self
):
public_key
=
self
.
cleaned_data
[
'public_key'
]
self
.
instance
.
public_key
=
public_key
self
.
instance
.
save
()
return
self
.
instance
class
UserBulkImportForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
User
...
...
@@ -76,25 +136,10 @@ class UserInfoForm(forms.Form):
enable_otp
=
forms
.
BooleanField
(
required
=
False
,
label
=
_
(
'enable otp'
))
class
UserKeyForm
(
forms
.
Form
):
public_key
=
forms
.
CharField
(
label
=
_
(
'ssh public key'
),
max_length
=
5000
,
widget
=
forms
.
Textarea
(
attrs
=
{
'placeholder'
:
_
(
'ssh-rsa AAAA...'
)}),
help_text
=
_
(
'Paste your id_rsa.pub here.'
))
def
clean_public_key
(
self
):
public_key
=
self
.
cleaned_data
[
'public_key'
]
if
self
.
user
.
public_key
and
public_key
==
self
.
user
.
public_key
:
raise
forms
.
ValidationError
(
_
(
'Public key should not be the '
'same as your old one.'
))
if
not
validate_ssh_public_key
(
public_key
):
raise
forms
.
ValidationError
(
_
(
'Not a valid ssh public key'
))
return
public_key
class
UserPrivateAssetPermissionForm
(
forms
.
ModelForm
):
def
save
(
self
,
commit
=
True
):
self
.
instance
=
super
(
UserPrivateAssetPermissionForm
,
self
)
\
.
save
(
commit
=
commit
)
...
...
@@ -121,7 +166,6 @@ class UserPrivateAssetPermissionForm(forms.ModelForm):
class
UserGroupPrivateAssetPermissionForm
(
forms
.
ModelForm
):
def
save
(
self
,
commit
=
True
):
self
.
instance
=
super
(
UserGroupPrivateAssetPermissionForm
,
self
)
\
.
save
(
commit
=
commit
)
...
...
apps/users/models/user.py
View file @
3fa5ce54
...
...
@@ -101,14 +101,17 @@ class User(AbstractUser):
self
.
_public_key
=
signer
.
sign
(
public_key_raw
)
@property
def
public_key_hash
(
self
):
def
public_key_obj
(
self
):
class
PubKey
(
object
):
def
__getattr__
(
self
,
item
):
return
''
if
self
.
public_key
:
import
sshpubkeys
try
:
return
sshpubkeys
.
SSHKey
(
self
.
public_key
)
.
hash_md5
()
return
sshpubkeys
.
SSHKey
(
self
.
public_key
)
except
TabError
:
pass
return
'None'
return
PubKey
()
@property
def
is_superuser
(
self
):
...
...
apps/users/templates/users/user_password_update.html
0 → 100644
View file @
3fa5ce54
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
cropper
/
cropper
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
<style>
.crop
{
width
:
200px
;
height
:
150px
;
overflow
:
hidden
;
}
.img-preview-sm
img
{
width
:
64px
;
height
:
64px
;
margin
:
-75px
0
0
-100px
;
}
img
{
max-width
:
100%
;
/* This rule is very important, please do not ignore this! */
}
</style>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-12"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"panel-options"
>
<ul
class=
"nav nav-tabs"
>
<li>
<a
href=
"{% url 'users:user-profile-update' %}"
class=
"text-center"
>
{% trans 'Profile' %}
</a>
</li>
<li
class=
"active"
>
<a
href=
"{% url 'users:user-password-update' %}"
class=
"text-center"
>
{% trans 'Password' %}
</a>
</li>
<li>
<a
href=
"{% url 'users:user-pubkey-update' %}"
class=
"text-center"
>
{% trans 'Public key' %}
</a>
</li>
</ul>
</div>
<div
class=
"tab-content"
style=
"background-color: #ffffff"
>
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<form
method=
"post"
class=
"form-horizontal"
action=
""
enctype=
"multipart/form-data"
>
{% csrf_token %}
{{ form.old_password|bootstrap_horizontal}}
{{ form.new_password|bootstrap_horizontal }}
{{ form.confirm_password|bootstrap_horizontal }}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script
src=
"{% static 'js/plugins/cropper/cropper.min.js' %}"
></script>
<script>
</script>
{% endblock %}
apps/users/templates/users/user_profile.html
View file @
3fa5ce54
...
...
@@ -68,8 +68,21 @@
<td>
{{ user.enable_otp|yesno:"Yes,No,Unkown" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
{% trans 'Public key fingerprint' %}
</td>
<td>
{{ user.public_key_hash }}
</td>
<td
class=
"text-navy"
>
{% trans 'Public key' %}
</td>
<td>
<table>
<tr>
<td>
{{ user.public_key_obj.comment }}
</td>
</tr>
<tr>
<td>
{{ user.public_key_obj.hash_md5 }}
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
{% trans 'Date joined' %}
</td>
...
...
@@ -123,7 +136,7 @@
<td>
{% trans 'Reset password' %}:
</td>
<td>
<span
class=
"pull-right"
>
<
button
type=
"button"
class=
"btn btn-primary btn-xs"
style=
"width: 54px"
>
{% trans 'Reset' %}
</button
>
<
a
type=
"button"
class=
"btn btn-primary btn-xs"
style=
"width: 54px"
href=
"{% url 'users:user-password-update' %}"
>
{% trans 'Reset' %}
</a
>
</span>
</td>
</tr>
...
...
@@ -131,27 +144,10 @@
<td>
{% trans 'Reset public key' %}:
</td>
<td>
<span
class=
"pull-right"
>
<
button
type=
"button"
class=
"btn btn-primary btn-xs"
style=
"width: 54px"
>
{% trans 'Reset' %}
</button
>
<
a
type=
"button"
class=
"btn btn-primary btn-xs"
style=
"width: 54px"
href=
"{% url 'users:user-pubkey-update' %}"
>
{% trans 'Reset' %}
</a
>
</span>
</td>
</tr>
<tr>
<td>
{% trans 'Test admin user' %}:
</td>
<td>
<span
class=
"pull-right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn_reset_pk"
style=
"width: 54px;"
>
{% trans 'Test' %}
</button>
</span>
</td>
</tr>
<tr>
<td>
{% trans 'Test system pingpong' %}:
</td>
<td>
<span
class=
"pull-right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn_reset_pk"
style=
"width: 54px;"
>
{% trans 'Test' %}
</button>
</span>
</td>
</tr>
</tbody>
</table>
</div>
...
...
apps/users/templates/users/user_profile_update.html
View file @
3fa5ce54
...
...
@@ -20,6 +20,10 @@
height
:
64px
;
margin
:
-75px
0
0
-100px
;
}
img
{
max-width
:
100%
;
/* This rule is very important, please do not ignore this! */
}
</style>
{% endblock %}
{% block content %}
...
...
@@ -30,13 +34,13 @@
<div
class=
"panel-options"
>
<ul
class=
"nav nav-tabs"
>
<li
class=
"active"
>
<a
href=
""
class=
"text-center"
>
{% trans 'Profile' %}
</a>
<a
href=
"
{% url 'users:user-profile-update' %}
"
class=
"text-center"
>
{% trans 'Profile' %}
</a>
</li>
<li>
<a
href=
""
class=
"text-center"
>
{% trans 'Password' %}
</a>
<a
href=
"
{% url 'users:user-password-update' %}
"
class=
"text-center"
>
{% trans 'Password' %}
</a>
</li>
<li>
<a
href=
""
class=
"text-center"
>
{% trans 'Public key' %}
</a>
<a
href=
"
{% url 'users:user-pubkey-update' %}
"
class=
"text-center"
>
{% trans 'Public key' %}
</a>
</li>
</ul>
</div>
...
...
@@ -45,7 +49,6 @@
<form
method=
"post"
class=
"form-horizontal"
action=
""
enctype=
"multipart/form-data"
>
{% csrf_token %}
<h3>
{% trans 'Account' %}
</h3>
{# {{ form.avatar|bootstrap_horizontal }}#}
{{ form.username|bootstrap_horizontal }}
{{ form.name|bootstrap_horizontal }}
{{ form.email|bootstrap_horizontal }}
...
...
apps/users/templates/users/user_pubkey_update.html
0 → 100644
View file @
3fa5ce54
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
cropper
/
cropper
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
<style>
.crop
{
width
:
200px
;
height
:
150px
;
overflow
:
hidden
;
}
.img-preview-sm
img
{
width
:
64px
;
height
:
64px
;
margin
:
-75px
0
0
-100px
;
}
img
{
max-width
:
100%
;
/* This rule is very important, please do not ignore this! */
}
</style>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-12"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"panel-options"
>
<ul
class=
"nav nav-tabs"
>
<li>
<a
href=
"{% url 'users:user-profile-update' %}"
class=
"text-center"
>
{% trans 'Profile' %}
</a>
</li>
<li>
<a
href=
"{% url 'users:user-password-update' %}"
class=
"text-center"
>
{% trans 'Password' %}
</a>
</li>
<li
class=
"active"
>
<a
href=
"{% url 'users:user-pubkey-update' %}"
class=
"text-center"
>
{% trans 'Public key' %}
</a>
</li>
</ul>
</div>
<div
class=
"tab-content"
style=
"background-color: #ffffff"
>
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<form
method=
"post"
class=
"form-horizontal"
action=
""
enctype=
"multipart/form-data"
>
{% csrf_token %}
<h3>
{% trans 'Old public key' %}
</h3>
<div
class=
"form-group"
>
<label
class=
"control-label col-sm-2 col-lg-2"
style=
"padding-top: 0"
>
{% trans 'Name' %}
</label>
<div
class=
" col-sm-9 col-lg-9"
>
<label>
{{ user.public_key_obj.comment }}
</label>
</div>
</div>
<div
class=
"form-group"
>
<label
class=
"control-label col-sm-2 col-lg-2"
style=
"padding-top: 0"
>
{% trans 'Fingerprint' %}
</label>
<div
class=
" col-sm-9 col-lg-9 "
>
<label>
{{ user.public_key_obj.hash_md5 }}
</label>
</div>
</div>
<h3>
{% trans 'Update public key' %}
</h3>
{{ form.public_key|bootstrap_horizontal}}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script
src=
"{% static 'js/plugins/cropper/cropper.min.js' %}"
></script>
<script>
</script>
{% endblock %}
apps/users/urls/views_urls.py
View file @
3fa5ce54
...
...
@@ -28,6 +28,12 @@ urlpatterns = [
url
(
r'^profile/update/$'
,
views
.
UserProfileUpdateView
.
as_view
(),
name
=
'user-profile-update'
),
url
(
r'^profile/password/update/$'
,
views
.
UserPasswordUpdateView
.
as_view
(),
name
=
'user-password-update'
),
url
(
r'^profile/pubkey/update/$'
,
views
.
UserPublicKeyUpdateView
.
as_view
(),
name
=
'user-pubkey-update'
),
# User view
url
(
r'^user$'
,
views
.
UserListView
.
as_view
(),
name
=
'user-list'
),
...
...
apps/users/views/login.py
View file @
3fa5ce54
...
...
@@ -154,7 +154,7 @@ class UserResetPasswordView(TemplateView):
class
UserFirstLoginView
(
LoginRequiredMixin
,
SessionWizardView
):
template_name
=
'users/first_login.html'
form_list
=
[
forms
.
UserInfoForm
,
forms
.
UserKeyForm
]
form_list
=
[
forms
.
UserInfoForm
,
forms
.
User
Public
KeyForm
]
file_storage
=
default_storage
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
apps/users/views/user.py
View file @
3fa5ce54
...
...
@@ -25,6 +25,7 @@ from django.views.generic.edit import (CreateView, UpdateView, FormMixin,
FormView
)
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
django.views.decorators.csrf
import
csrf_exempt
from
django.contrib.auth
import
logout
as
auth_logout
from
..
import
forms
from
..models
import
User
,
UserGroup
...
...
@@ -37,7 +38,8 @@ __all__ = ['UserListView', 'UserCreateView', 'UserDetailView',
'UserUpdateView'
,
'UserAssetPermissionCreateView'
,
'UserAssetPermissionView'
,
'UserGrantedAssetView'
,
'UserExportView'
,
'UserBulkImportView'
,
'UserProfileView'
,
'UserProfileUpdateView'
,
'UserProfileUpdateView'
,
'UserPasswordUpdateView'
,
'UserPublicKeyUpdateView'
,
]
logger
=
get_logger
(
__name__
)
...
...
@@ -341,12 +343,49 @@ class UserProfileUpdateView(LoginRequiredMixin, UpdateView):
)
def
get_context_data
(
self
,
**
kwargs
):
from
perms.utils
import
get_user_granted_assets
assets
=
get_user_granted_assets
(
self
.
request
.
user
)
context
=
{
'app'
:
'User'
,
'action'
:
'User Profile'
,
'assets'
:
assets
,
'action'
:
'Profile update'
,
}
kwargs
.
update
(
context
)
return
super
(
UserProfileUpdateView
,
self
)
.
get_context_data
(
**
kwargs
)
class
UserPasswordUpdateView
(
LoginRequiredMixin
,
UpdateView
):
template_name
=
'users/user_password_update.html'
model
=
User
form_class
=
forms
.
UserPasswordForm
success_url
=
reverse_lazy
(
'users:user-profile'
)
def
get_object
(
self
,
queryset
=
None
):
return
self
.
request
.
user
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
'User'
,
'action'
:
'Password update'
,
}
kwargs
.
update
(
context
)
return
super
(
UserPasswordUpdateView
,
self
)
.
get_context_data
(
**
kwargs
)
def
get_success_url
(
self
):
auth_logout
(
self
.
request
)
return
super
(
UserPasswordUpdateView
,
self
)
.
get_success_url
()
class
UserPublicKeyUpdateView
(
LoginRequiredMixin
,
UpdateView
):
template_name
=
'users/user_pubkey_update.html'
model
=
User
form_class
=
forms
.
UserPublicKeyForm
success_url
=
reverse_lazy
(
'users:user-profile'
)
def
get_object
(
self
,
queryset
=
None
):
return
self
.
request
.
user
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
'User'
,
'action'
:
'Public key update'
,
}
kwargs
.
update
(
context
)
return
super
(
UserProfileUpdateView
,
self
)
.
get_context_data
(
**
kwargs
)
\ No newline at end of file
return
super
(
UserPublicKeyUpdateView
,
self
)
.
get_context_data
(
**
kwargs
)
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