[Fixture] 添加用户信息更改

pull/417/head
ibuler 8 years ago
parent 0983f294b7
commit 3fa5ce5404

@ -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">

@ -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)

@ -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):

@ -0,0 +1,75 @@
{% 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 %}

@ -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>

@ -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 }}

@ -0,0 +1,86 @@
{% 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 %}

@ -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'),

@ -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.UserPublicKeyForm]
file_storage = default_storage
def dispatch(self, request, *args, **kwargs):

@ -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)
return super(UserPublicKeyUpdateView, self).get_context_data(**kwargs)

Loading…
Cancel
Save