mirror of https://github.com/jumpserver/jumpserver
fix #14
parent
8cdc4674d7
commit
8a5a4f3362
|
@ -1,5 +1,5 @@
|
|||
@import url("https://fonts.useso.com/css?family=Open+Sans:300,400,600,700");
|
||||
@import url("https://fonts.useso.com/css?family=Roboto:400,300,500,700");
|
||||
@import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700");
|
||||
@import url("https://fonts.googleapis.com/css?family=Roboto:400,300,500,700");
|
||||
/*
|
||||
*
|
||||
* INSPINIA - Responsive Admin Theme
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
{% load static %}
|
||||
{% load static i18n %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
@ -20,6 +20,25 @@
|
|||
<div id="page-wrapper" class="gray-bg">
|
||||
{% include '_header_bar.html' %}
|
||||
{% include '_message.html' %}
|
||||
{% block first_login_message %}
|
||||
{% if user.is_authenticated and user.is_first_login %}
|
||||
<div class="alert alert-danger" style="margin: 20px auto 0px">
|
||||
{% url 'users:user-first-login' as the_url %}
|
||||
{% blocktrans %}
|
||||
Your information was incomplete. Please click <a href="{{ the_url }}"> this link </a>to complete your information.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block update_public_key_message %}
|
||||
{% if user.is_authenticated and not user.is_public_key_valid %}
|
||||
<div class="alert alert-danger" style="margin: 20px auto 0px">
|
||||
{% blocktrans %}
|
||||
Your ssh-public-key has been expired. Please click <a href="#"> this link </a>to update your ssh-public-key.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content %}{% endblock %}
|
||||
{% include '_footer.html' %}
|
||||
</div>
|
||||
|
@ -28,4 +47,4 @@
|
|||
</body>
|
||||
{% include '_foot_js.html' %}
|
||||
{% block custom_foot_js %} {% endblock %}
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -5,7 +5,8 @@ import logging
|
|||
|
||||
from rest_framework import generics
|
||||
|
||||
from .serializers import UserSerializer, UserGroupSerializer, UserAttributeSerializer, UserGroupEditSerializer
|
||||
from .serializers import UserSerializer, UserGroupSerializer, UserAttributeSerializer, UserGroupEditSerializer, \
|
||||
UserPKUpdateSerializer
|
||||
from .models import User, UserGroup
|
||||
|
||||
|
||||
|
@ -72,7 +73,17 @@ class UserResetPKApi(generics.UpdateAPIView):
|
|||
|
||||
def perform_update(self, serializer):
|
||||
user = self.get_object()
|
||||
user._public_key = ''
|
||||
user.is_public_key_valid = False
|
||||
user.save()
|
||||
from .utils import send_reset_ssh_key_mail
|
||||
send_reset_ssh_key_mail(user)
|
||||
|
||||
|
||||
class UserUpdatePKApi(generics.UpdateAPIView):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserPKUpdateSerializer
|
||||
|
||||
def perform_update(self, serializer):
|
||||
user = self.get_object()
|
||||
user.private_key = serializer.validated_data['_public_key']
|
||||
user.save()
|
||||
|
|
|
@ -79,9 +79,11 @@ class UserKeyForm(forms.Form):
|
|||
help_text=_('Paste your id_ras.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.'))
|
||||
from sshpubkeys import SSHKey
|
||||
from sshpubkeys.exceptions import InvalidKeyException
|
||||
public_key = self.cleaned_data['public_key']
|
||||
ssh = SSHKey(public_key)
|
||||
try:
|
||||
ssh.parse()
|
||||
|
|
|
@ -80,6 +80,7 @@ class User(AbstractUser):
|
|||
date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True,
|
||||
verbose_name=_('Date expired'))
|
||||
created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by'))
|
||||
is_public_key_valid = models.BooleanField(default=False)
|
||||
|
||||
@property
|
||||
def password_raw(self):
|
||||
|
|
|
@ -46,11 +46,18 @@ class UserPKUpdateSerializer(serializers.ModelSerializer):
|
|||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['id', '_private_key']
|
||||
fields = ['id', '_public_key']
|
||||
|
||||
def validate__private_key(self, value):
|
||||
from users.utils import validate_ssh_pk
|
||||
checked, reason = validate_ssh_pk(value)
|
||||
if not checked:
|
||||
raise serializers.ValidationError(_('Not a valid ssh private key.'))
|
||||
def validate__public_key(self, value):
|
||||
from sshpubkeys import SSHKey
|
||||
from sshpubkeys.exceptions import InvalidKeyException
|
||||
ssh = SSHKey(value)
|
||||
try:
|
||||
ssh.parse()
|
||||
except InvalidKeyException as e:
|
||||
print e
|
||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||
except NotImplementedError as e:
|
||||
print e
|
||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||
return value
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{% extends '_modal.html' %}
|
||||
{% load i18n %}
|
||||
{% block modal_id %}user_reset_pk_modal{% endblock %}
|
||||
{% block modal_title%}{% trans 'Reset User SSH Private Key' %}{% endblock %}
|
||||
{% block modal_body %}
|
||||
<textarea id="txt_pk" class="form-control" cols="30" rows="10" placeholder="-----BEGIN RSA PRIVATE KEY-----"></textarea>
|
||||
{% endblock %}
|
||||
{% block modal_confirm_id %}btn_user_reset_pk{% endblock %}
|
|
@ -0,0 +1,8 @@
|
|||
{% extends '_modal.html' %}
|
||||
{% load i18n %}
|
||||
{% block modal_id %}user_update_pk_modal{% endblock %}
|
||||
{% block modal_title%}{% trans "Update User SSH Public Key" %}{% endblock %}
|
||||
{% block modal_body %}
|
||||
<textarea id="txt_pk" class="form-control" cols="30" rows="10" placeholder="ssh-rsa AAAAB3NzaC1yc2EAA....."></textarea>
|
||||
{% endblock %}
|
||||
{% block modal_confirm_id %}btn_user_update_pk{% endblock %}
|
|
@ -3,10 +3,12 @@
|
|||
{% load i18n %}
|
||||
{% load bootstrap %}
|
||||
|
||||
|
||||
{% block custom_head_css_js %}
|
||||
{{ wizard.form.media }}
|
||||
<link href="{% static 'css/plugins/steps/jquery.steps.css' %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block first_login_message %}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
|
|
|
@ -160,6 +160,14 @@
|
|||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Update ssh key' %}:</td>
|
||||
<td>
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-primary btn-xs" id="btn_update_pk" style="width: 54px;" data-toggle="modal" data-target="#user_update_pk_modal">{% trans 'Update' %}</button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -207,6 +215,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'users/_user_update_pk_modal.html' %}
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
|
@ -352,6 +361,33 @@ $(document).ready(function() {
|
|||
}, function() {
|
||||
doReset();
|
||||
});
|
||||
}).on('click', '#btn_user_update_pk', function(){
|
||||
var $this = $(this);
|
||||
var pk = $('#txt_pk').val();
|
||||
var the_url = '{% url "users:user-update-pk-api" pk=user_object.id %}';
|
||||
var body = {'_public_key': pk};
|
||||
var success = function() {
|
||||
$('#txt_pk').val('');
|
||||
$this.closest('.modal').modal('hide');
|
||||
var msg = "{% trans 'Successfully updated the SSH public key.' %}";
|
||||
swal("{% trans 'User SSH Public Key Update' %}", msg, "success");
|
||||
};
|
||||
var fail = function() {
|
||||
var msg = "{% trans 'Failed to update the user\'s SSH public key.' %}";
|
||||
swal({
|
||||
title: "{% trans 'User SSH Public Key Update' %}",
|
||||
text: msg,
|
||||
type: "error",
|
||||
showCancelButton: false,
|
||||
confirmButtonColor: "#DD6B55",
|
||||
confirmButtonText: "{% trans 'Confirm' %}",
|
||||
closeOnConfirm: true
|
||||
}, function () {
|
||||
$('#txt_pk').focus();
|
||||
}
|
||||
);
|
||||
}
|
||||
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -43,6 +43,7 @@ urlpatterns += [
|
|||
api.UserAttributeApi.as_view(), name='user-patch-api'),
|
||||
url(r'^v1/users/(?P<pk>\d+)/reset-password/$', api.UserResetPasswordApi.as_view(), name='user-reset-password-api'),
|
||||
url(r'^v1/users/(?P<pk>\d+)/reset-pk/$', api.UserResetPKApi.as_view(), name='user-reset-pk-api'),
|
||||
url(r'^v1/users/(?P<pk>\d+)/update-pk/$', api.UserUpdatePKApi.as_view(), name='user-update-pk-api'),
|
||||
url(r'^v1/user-groups$', api.UserGroupListAddApi.as_view(), name='user-group-list-api'),
|
||||
url(r'^v1/user-groups/(?P<pk>[0-9]+)$',
|
||||
api.UserGroupDetailDeleteUpdateApi.as_view(), name='user-group-detail-api'),
|
||||
|
|
|
@ -19,7 +19,7 @@ from django.views.decorators.debug import sensitive_post_parameters
|
|||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic.list import ListView
|
||||
from django.views.generic.edit import CreateView, DeleteView, UpdateView, FormView, SingleObjectMixin, \
|
||||
FormMixin, ModelFormMixin, ProcessFormView, BaseCreateView
|
||||
FormMixin
|
||||
from django.views.generic.detail import DetailView
|
||||
from formtools.wizard.views import SessionWizardView
|
||||
|
||||
|
@ -332,6 +332,7 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
|
|||
if field.name == 'enable_otp':
|
||||
user.enable_otp = field.value()
|
||||
user.is_first_login = False
|
||||
user.is_public_key_valid = True
|
||||
user.save()
|
||||
return redirect(reverse('index'))
|
||||
|
||||
|
@ -351,6 +352,16 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
|
|||
}
|
||||
return super(UserFirstLoginView, self).get_form_initial(step)
|
||||
|
||||
def get_form(self, step=None, data=None, files=None):
|
||||
form = super(UserFirstLoginView, self).get_form(step, data, files)
|
||||
|
||||
if step is None:
|
||||
step = self.steps.current
|
||||
|
||||
if step == '1':
|
||||
form.user = self.request.user
|
||||
return form
|
||||
|
||||
|
||||
class UserAssetPermissionView(AdminUserRequiredMixin, FormMixin, SingleObjectMixin, ListView):
|
||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||
|
@ -376,7 +387,7 @@ class UserAssetPermissionView(AdminUserRequiredMixin, FormMixin, SingleObjectMix
|
|||
|
||||
def get_queryset(self):
|
||||
asset_permissions = set(self.object.asset_permissions.all()) \
|
||||
| self.get_asset_permission_inherit_from_user_group()
|
||||
| self.get_asset_permission_inherit_from_user_group()
|
||||
return list(asset_permissions)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
|
Loading…
Reference in New Issue