Commit 759760e7 authored by ibuler's avatar ibuler

[Update] 服务器可以生成用户密钥

parent 6f29cf5d
This diff is collapsed.
...@@ -26,6 +26,11 @@ class UserCreateUpdateForm(forms.ModelForm): ...@@ -26,6 +26,11 @@ class UserCreateUpdateForm(forms.ModelForm):
max_length=128, strip=False, required=False, max_length=128, strip=False, required=False,
) )
role = forms.ChoiceField(choices=role_choices, required=True, initial=User.ROLE_USER, label=_("Role")) role = forms.ChoiceField(choices=role_choices, required=True, initial=User.ROLE_USER, label=_("Role"))
public_key = forms.CharField(
label=_('ssh public key'), max_length=5000,
widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}),
help_text=_('Paste user id_rsa.pub here.')
)
class Meta: class Meta:
model = User model = User
...@@ -47,12 +52,26 @@ class UserCreateUpdateForm(forms.ModelForm): ...@@ -47,12 +52,26 @@ class UserCreateUpdateForm(forms.ModelForm):
), ),
} }
def clean_public_key(self):
public_key = self.cleaned_data['public_key']
if self.instance.public_key and public_key == self.instance.public_key:
msg = _('Public key should not be the same as your old one.')
raise forms.ValidationError(msg)
if not validate_ssh_public_key(public_key):
raise forms.ValidationError(_('Not a valid ssh public key'))
return public_key
def save(self, commit=True): def save(self, commit=True):
password = self.cleaned_data.get('password') password = self.cleaned_data.get('password')
public_key = self.cleaned_data.get('public_key')
user = super().save(commit=commit) user = super().save(commit=commit)
if password: if password:
user.set_password(password) user.set_password(password)
user.save() user.save()
if public_key:
user.public_key = public_key
user.save()
return user return user
...@@ -70,6 +89,9 @@ class UserProfileForm(forms.ModelForm): ...@@ -70,6 +89,9 @@ class UserProfileForm(forms.ModelForm):
} }
UserProfileForm.verbose_name = _("Profile")
class UserPasswordForm(forms.Form): class UserPasswordForm(forms.Form):
old_password = forms.CharField( old_password = forms.CharField(
max_length=128, widget=forms.PasswordInput, max_length=128, widget=forms.PasswordInput,
...@@ -113,7 +135,7 @@ class UserPasswordForm(forms.Form): ...@@ -113,7 +135,7 @@ class UserPasswordForm(forms.Form):
class UserPublicKeyForm(forms.Form): class UserPublicKeyForm(forms.Form):
public_key = forms.CharField( public_key = forms.CharField(
label=_('ssh public key'), max_length=5000, label=_('ssh public key'), max_length=5000, required=False,
widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}), widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}),
help_text=_('Paste your id_rsa.pub here.') help_text=_('Paste your id_rsa.pub here.')
) )
...@@ -131,17 +153,21 @@ class UserPublicKeyForm(forms.Form): ...@@ -131,17 +153,21 @@ class UserPublicKeyForm(forms.Form):
msg = _('Public key should not be the same as your old one.') msg = _('Public key should not be the same as your old one.')
raise forms.ValidationError(msg) raise forms.ValidationError(msg)
if not validate_ssh_public_key(public_key): if public_key and not validate_ssh_public_key(public_key):
raise forms.ValidationError(_('Not a valid ssh public key')) raise forms.ValidationError(_('Not a valid ssh public key'))
return public_key return public_key
def save(self): def save(self):
public_key = self.cleaned_data['public_key'] public_key = self.cleaned_data['public_key']
self.instance.public_key = public_key if public_key:
self.instance.save() self.instance.public_key = public_key
self.instance.save()
return self.instance return self.instance
UserPublicKeyForm.verbose_name = _("Public key")
class UserBulkUpdateForm(forms.ModelForm): class UserBulkUpdateForm(forms.ModelForm):
users = forms.ModelMultipleChoiceField( users = forms.ModelMultipleChoiceField(
required=True, required=True,
......
...@@ -115,7 +115,7 @@ class User(AbstractUser): ...@@ -115,7 +115,7 @@ class User(AbstractUser):
import sshpubkeys import sshpubkeys
try: try:
return sshpubkeys.SSHKey(self.public_key) return sshpubkeys.SSHKey(self.public_key)
except TabError: except (TabError, TypeError):
pass pass
return PubKey() return PubKey()
......
...@@ -45,10 +45,8 @@ ...@@ -45,10 +45,8 @@
{{ wizard.form.management_form }} {{ wizard.form.management_form }}
{% for form in wizard.form.forms %} {% for form in wizard.form.forms %}
{% bootstrap_form form %} {% bootstrap_form form %}
{# {{ form|bootstrap }}#}
{% endfor %} {% endfor %}
{% else %} {% else %}
{# {{ wizard.form|bootstrap }}#}
{% bootstrap_form wizard.form %} {% bootstrap_form wizard.form %}
{% endif %} {% endif %}
</form> </form>
...@@ -56,8 +54,10 @@ ...@@ -56,8 +54,10 @@
<div class="actions clearfix"> <div class="actions clearfix">
<ul> <ul>
{% if wizard.steps.prev %} {% if wizard.steps.prev %}
<li><a class="fl_goto" data-goto="{{ wizard.steps.first }}">{% trans "First step" %}</a></li> <li><a class="fl_goto" name="wizard_goto_step" data-goto="{{ wizard.steps.prev }}">{% trans "Previous" %}</a></li>
<li><a class="fl_goto" name="wizard_goto_step" data-goto="{{ wizard.steps.prev }}">{% trans "Prev step" %}</a></li> {% endif %}
{% if wizard.steps.next %}
<li><a class="fl_goto" name="wizard_goto_step" data-goto="{{ wizard.steps.next }}">{% trans "Next" %}</a></li>
{% endif %} {% endif %}
<li><a id="fl_submit">{% trans "Submit" %}</a></li> <li><a id="fl_submit">{% trans "Submit" %}</a></li>
</ul> </ul>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
</ul> </ul>
</div> </div>
<div class="tab-content"> <div class="tab-content">
<div class="col-sm-7" style="padding-left: 0;"> <div class="col-sm-8" style="padding-left: 0;">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-primary"><b>{{ user.name }}</b></span> <span class="label label-primary"><b>{{ user.name }}</b></span>
...@@ -120,7 +120,7 @@ ...@@ -120,7 +120,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-5" style="padding-left: 0;padding-right: 0"> <div class="col-sm-4" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary"> <div class="panel panel-primary">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Quick modify' %} <i class="fa fa-info-circle"></i> {% trans 'Quick modify' %}
...@@ -129,18 +129,26 @@ ...@@ -129,18 +129,26 @@
<table class="table"> <table class="table">
<tbody> <tbody>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td>{% trans 'Reset password' %}:</td> <td>{% trans 'Update password' %}:</td>
<td> <td>
<span class="pull-right"> <span class="pull-right">
<a type="button" class="btn btn-primary btn-xs" style="width: 54px" href="{% url 'users:user-password-update' %}">{% trans 'Reset' %}</a> <a type="button" class="btn btn-primary btn-xs" style="width: 54px" href="{% url 'users:user-password-update' %}">{% trans 'Update' %}</a>
</span> </span>
</td> </td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Reset SSH public key' %}:</td> <td>{% trans 'Update SSH public key' %}:</td>
<td> <td>
<span class="pull-right"> <span class="pull-right">
<a type="button" class="btn btn-primary btn-xs" style="width: 54px" href="{% url 'users:user-pubkey-update' %}">{% trans 'Reset' %}</a> <a type="button" class="btn btn-primary btn-xs" style="width: 54px" href="{% url 'users:user-pubkey-update' %}">{% trans 'Update' %}</a>
</span>
</td>
</tr>
<tr>
<td>{% trans 'Reset public key and download' %}:</td>
<td>
<span class="pull-right">
<a type="button" class="btn btn-primary btn-xs btn-reset-pubkey" style="width: 54px">{% trans 'Reset' %}</a>
</span> </span>
</td> </td>
</tr> </tr>
...@@ -180,8 +188,11 @@ $(document).on('click', '#btn_update_pk', function() { ...@@ -180,8 +188,11 @@ $(document).on('click', '#btn_update_pk', function() {
$('#txt_pk').focus(); $('#txt_pk').focus();
} }
); );
} };
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail}); APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
}).on('click', '.btn-reset-pubkey', function () {
var the_url = '{% url "users:user-pubkey-generate" %}';
window.open(the_url, "_blank")
}) })
</script> </script>
{% endblock %} {% endblock %}
...@@ -64,6 +64,12 @@ ...@@ -64,6 +64,12 @@
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans 'Update public key' %}</h3> <h3>{% trans 'Update public key' %}</h3>
{% bootstrap_field form.public_key layout="horizontal" %} {% bootstrap_field form.public_key layout="horizontal" %}
<div class="form-group">
<label class="control-label col-sm-2 col-lg-2" style="padding-top: 0">{% trans 'Or reset by server' %}</label>
<div class=" col-sm-9 col-lg-9 ">
<a href="{% url 'users:user-pubkey-generate' %}">{% trans 'Reset' %}</a>
</div>
</div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <div class="col-sm-4 col-sm-offset-2">
......
...@@ -5,4 +5,5 @@ ...@@ -5,4 +5,5 @@
{% block password %} {% block password %}
<h3>{% trans 'Auth' %}</h3> <h3>{% trans 'Auth' %}</h3>
{% bootstrap_field form.password layout="horizontal" %} {% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.public_key layout="horizontal" %}
{% endblock %} {% endblock %}
...@@ -20,6 +20,7 @@ urlpatterns = [ ...@@ -20,6 +20,7 @@ urlpatterns = [
url(r'^profile/update/$', views.UserProfileUpdateView.as_view(), name='user-profile-update'), 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/password/update/$', views.UserPasswordUpdateView.as_view(), name='user-password-update'),
url(r'^profile/pubkey/update/$', views.UserPublicKeyUpdateView.as_view(), name='user-pubkey-update'), url(r'^profile/pubkey/update/$', views.UserPublicKeyUpdateView.as_view(), name='user-pubkey-update'),
url(r'^profile/pubkey/generate/$', views.UserPublicKeyGenerateView.as_view(), name='user-pubkey-generate'),
# User view # User view
url(r'^user$', views.UserListView.as_view(), name='user-list'), url(r'^user$', views.UserListView.as_view(), name='user-list'),
......
...@@ -31,7 +31,7 @@ from django.contrib.auth import logout as auth_logout ...@@ -31,7 +31,7 @@ from django.contrib.auth import logout as auth_logout
from common.const import create_success_msg, update_success_msg from common.const import create_success_msg, update_success_msg
from common.mixins import JSONResponseMixin from common.mixins import JSONResponseMixin
from common.utils import get_logger, get_object_or_none, is_uuid from common.utils import get_logger, get_object_or_none, is_uuid, ssh_key_gen
from .. import forms from .. import forms
from ..models import User, UserGroup from ..models import User, UserGroup
from ..utils import AdminUserRequiredMixin from ..utils import AdminUserRequiredMixin
...@@ -45,6 +45,7 @@ __all__ = [ ...@@ -45,6 +45,7 @@ __all__ = [
'UserExportView', 'UserBulkImportView', 'UserProfileView', 'UserExportView', 'UserBulkImportView', 'UserProfileView',
'UserProfileUpdateView', 'UserPasswordUpdateView', 'UserProfileUpdateView', 'UserPasswordUpdateView',
'UserPublicKeyUpdateView', 'UserBulkUpdateView', 'UserPublicKeyUpdateView', 'UserBulkUpdateView',
'UserPublicKeyGenerateView',
] ]
logger = get_logger(__name__) logger = get_logger(__name__)
...@@ -375,3 +376,15 @@ class UserPublicKeyUpdateView(LoginRequiredMixin, UpdateView): ...@@ -375,3 +376,15 @@ class UserPublicKeyUpdateView(LoginRequiredMixin, UpdateView):
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class UserPublicKeyGenerateView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
private, public = ssh_key_gen(username=request.user.username, hostname='jumpserver')
request.user.public_key = public
request.user.save()
response = HttpResponse(private, content_type='text/plain')
filename = "{0}-jumpserver.pem".format(request.user.username)
response['Content-Disposition'] = 'attachment; filename={}'.format(filename)
return response
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment