mirror of https://github.com/jumpserver/jumpserver
[Bugfix] 解决下载导入模版时KeyError的问题(数据为空时) (#3017)
* [Bugfix] 解决下载导入模版时KeyError的问题(数据为空时) * [Bugfix] 解决下载导入模版时KeyError的问题(数据为空时)2 * [Bugfix] 解决下载导入模版时KeyError的问题(数据为空时)3 * [Update] 解决LDAP用户禁用后,终端还可以登录成功一次的问题 * [Update] 解决LDAP用户禁用后,终端还可以登录成功一次的问题2 * [Update] LDAP AD Server可以通过UserAccountControl映射is_active字段 * [Update] 限制只有local用户可以更新ssh key * [Update] 限制只有local用户可以更新ssh key 2pull/3024/head
parent
421e98696c
commit
c929c1a87e
|
@ -8,6 +8,7 @@ from django_auth_ldap.backend import _LDAPUser, LDAPBackend
|
||||||
from django_auth_ldap.config import _LDAPConfig, LDAPSearch, LDAPSearchUnion
|
from django_auth_ldap.config import _LDAPConfig, LDAPSearch, LDAPSearchUnion
|
||||||
|
|
||||||
from users.utils import construct_user_email
|
from users.utils import construct_user_email
|
||||||
|
from common.const import LDAP_AD_ACCOUNT_DISABLE
|
||||||
|
|
||||||
logger = _LDAPConfig.get_logger()
|
logger = _LDAPConfig.get_logger()
|
||||||
|
|
||||||
|
@ -17,6 +18,15 @@ class LDAPAuthorizationBackend(LDAPBackend):
|
||||||
Override this class to override _LDAPUser to LDAPUser
|
Override this class to override _LDAPUser to LDAPUser
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def user_can_authenticate(user):
|
||||||
|
"""
|
||||||
|
Reject users with is_active=False. Custom user models that don't have
|
||||||
|
that attribute are allowed.
|
||||||
|
"""
|
||||||
|
is_valid = getattr(user, 'is_valid', None)
|
||||||
|
return is_valid or is_valid is None
|
||||||
|
|
||||||
def authenticate(self, request=None, username=None, password=None, **kwargs):
|
def authenticate(self, request=None, username=None, password=None, **kwargs):
|
||||||
logger.info('Authentication LDAP backend')
|
logger.info('Authentication LDAP backend')
|
||||||
if not username:
|
if not username:
|
||||||
|
@ -25,34 +35,29 @@ class LDAPAuthorizationBackend(LDAPBackend):
|
||||||
ldap_user = LDAPUser(self, username=username.strip(), request=request)
|
ldap_user = LDAPUser(self, username=username.strip(), request=request)
|
||||||
user = self.authenticate_ldap_user(ldap_user, password)
|
user = self.authenticate_ldap_user(ldap_user, password)
|
||||||
logger.info('Authenticate user: {}'.format(user))
|
logger.info('Authenticate user: {}'.format(user))
|
||||||
return user
|
return user if self.user_can_authenticate(user) else None
|
||||||
|
|
||||||
def get_user(self, user_id):
|
def get_user(self, user_id):
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = self.get_user_model().objects.get(pk=user_id)
|
user = self.get_user_model().objects.get(pk=user_id)
|
||||||
LDAPUser(self, user=user) # This sets user.ldap_user
|
LDAPUser(self, user=user) # This sets user.ldap_user
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def get_group_permissions(self, user, obj=None):
|
def get_group_permissions(self, user, obj=None):
|
||||||
if not hasattr(user, 'ldap_user') and self.settings.AUTHORIZE_ALL_USERS:
|
if not hasattr(user, 'ldap_user') and self.settings.AUTHORIZE_ALL_USERS:
|
||||||
LDAPUser(self, user=user) # This sets user.ldap_user
|
LDAPUser(self, user=user) # This sets user.ldap_user
|
||||||
|
|
||||||
if hasattr(user, 'ldap_user'):
|
if hasattr(user, 'ldap_user'):
|
||||||
permissions = user.ldap_user.get_group_permissions()
|
permissions = user.ldap_user.get_group_permissions()
|
||||||
else:
|
else:
|
||||||
permissions = set()
|
permissions = set()
|
||||||
|
|
||||||
return permissions
|
return permissions
|
||||||
|
|
||||||
def populate_user(self, username):
|
def populate_user(self, username):
|
||||||
ldap_user = LDAPUser(self, username=username)
|
ldap_user = LDAPUser(self, username=username)
|
||||||
user = ldap_user.populate_user()
|
user = ldap_user.populate_user()
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,13 +96,19 @@ class LDAPUser(_LDAPUser):
|
||||||
for field, attr in self.settings.USER_ATTR_MAP.items():
|
for field, attr in self.settings.USER_ATTR_MAP.items():
|
||||||
try:
|
try:
|
||||||
value = self.attrs[attr][0]
|
value = self.attrs[attr][0]
|
||||||
|
if attr.lower() == 'useraccountcontrol' \
|
||||||
|
and field == 'is_active' and value:
|
||||||
|
value = int(value) & LDAP_AD_ACCOUNT_DISABLE \
|
||||||
|
!= LDAP_AD_ACCOUNT_DISABLE
|
||||||
except LookupError:
|
except LookupError:
|
||||||
logger.warning("{} does not have a value for the attribute {}".format(self.dn, attr))
|
logger.warning("{} does not have a value for the attribute {}".format(self.dn, attr))
|
||||||
else:
|
else:
|
||||||
if not hasattr(self._user, field):
|
if not hasattr(self._user, field):
|
||||||
continue
|
continue
|
||||||
if isinstance(getattr(self._user, field), bool):
|
if isinstance(getattr(self._user, field), bool):
|
||||||
value = value.lower() in ['true', '1']
|
if isinstance(value, str):
|
||||||
|
value = value.lower()
|
||||||
|
value = value in ['true', '1', True]
|
||||||
setattr(self._user, field, value)
|
setattr(self._user, field, value)
|
||||||
|
|
||||||
email = getattr(self._user, 'email', '')
|
email = getattr(self._user, 'email', '')
|
||||||
|
|
|
@ -26,8 +26,8 @@ class BaseOpenIDAuthorizationBackend(object):
|
||||||
Reject users with is_active=False. Custom user models that don't have
|
Reject users with is_active=False. Custom user models that don't have
|
||||||
that attribute are allowed.
|
that attribute are allowed.
|
||||||
"""
|
"""
|
||||||
is_active = getattr(user, 'is_active', None)
|
is_valid = getattr(user, 'is_valid', None)
|
||||||
return is_active or is_active is None
|
return is_valid or is_valid is None
|
||||||
|
|
||||||
def get_user(self, user_id):
|
def get_user(self, user_id):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -8,3 +8,7 @@ update_success_msg = _("%(name)s was updated successfully")
|
||||||
FILE_END_GUARD = ">>> Content End <<<"
|
FILE_END_GUARD = ">>> Content End <<<"
|
||||||
celery_task_pre_key = "CELERY_"
|
celery_task_pre_key = "CELERY_"
|
||||||
KEY_CACHE_RESOURCES_ID = "RESOURCES_ID_{}"
|
KEY_CACHE_RESOURCES_ID = "RESOURCES_ID_{}"
|
||||||
|
|
||||||
|
# AD User AccountDisable
|
||||||
|
# https://blog.csdn.net/bytxl/article/details/17763975
|
||||||
|
LDAP_AD_ACCOUNT_DISABLE = 2
|
||||||
|
|
|
@ -137,6 +137,16 @@ class PermissionsMixin(UserPassesTestMixin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class UserCanUpdatePassword:
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
return request.user.can_update_password()
|
||||||
|
|
||||||
|
|
||||||
|
class UserCanUpdateSSHKey:
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
return request.user.can_update_ssh_key()
|
||||||
|
|
||||||
|
|
||||||
class NeedMFAVerify(permissions.BasePermission):
|
class NeedMFAVerify(permissions.BasePermission):
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
mfa_verify_time = request.session.get('MFA_VERIFY_TIME', 0)
|
mfa_verify_time = request.session.get('MFA_VERIFY_TIME', 0)
|
||||||
|
|
|
@ -58,8 +58,8 @@ class JMSCSVRender(BaseRenderer):
|
||||||
template = request.query_params.get('template', 'export')
|
template = request.query_params.get('template', 'export')
|
||||||
view = renderer_context['view']
|
view = renderer_context['view']
|
||||||
|
|
||||||
if isinstance(data, dict) and data.get("count"):
|
if isinstance(data, dict):
|
||||||
data = data["results"]
|
data = data.get("results", [])
|
||||||
|
|
||||||
if template == 'import':
|
if template == 'import':
|
||||||
data = [data[0]] if data else data
|
data = [data[0]] if data else data
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from users.utils import construct_user_email
|
from users.utils import construct_user_email
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
|
from common.const import LDAP_AD_ACCOUNT_DISABLE
|
||||||
|
|
||||||
from .models import settings
|
from .models import settings
|
||||||
|
|
||||||
|
@ -70,7 +71,12 @@ class LDAPUtil:
|
||||||
for attr, mapping in self.attr_map.items():
|
for attr, mapping in self.attr_map.items():
|
||||||
if not hasattr(entry, mapping):
|
if not hasattr(entry, mapping):
|
||||||
continue
|
continue
|
||||||
user_item[attr] = getattr(entry, mapping).value or ''
|
value = getattr(entry, mapping).value or ''
|
||||||
|
if mapping.lower() == 'useraccountcontrol' and attr == 'is_active'\
|
||||||
|
and value:
|
||||||
|
value = int(value) & LDAP_AD_ACCOUNT_DISABLE \
|
||||||
|
!= LDAP_AD_ACCOUNT_DISABLE
|
||||||
|
user_item[attr] = value
|
||||||
return user_item
|
return user_item
|
||||||
|
|
||||||
def search_user_items(self):
|
def search_user_items(self):
|
||||||
|
@ -102,7 +108,9 @@ class LDAPUtil:
|
||||||
if not hasattr(user, field):
|
if not hasattr(user, field):
|
||||||
continue
|
continue
|
||||||
if isinstance(getattr(user, field), bool):
|
if isinstance(getattr(user, field), bool):
|
||||||
value = value.lower() in ['true', 1]
|
if isinstance(value, str):
|
||||||
|
value = value.lower()
|
||||||
|
value = value in ['true', 1, True]
|
||||||
setattr(user, field, value)
|
setattr(user, field, value)
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ UserProfileForm.verbose_name = _("Profile")
|
||||||
class UserMFAForm(forms.ModelForm):
|
class UserMFAForm(forms.ModelForm):
|
||||||
|
|
||||||
mfa_description = _(
|
mfa_description = _(
|
||||||
'Tip: when enabled, '
|
'When enabled, '
|
||||||
'you will enter the MFA binding process the next time you log in. '
|
'you will enter the MFA binding process the next time you log in. '
|
||||||
'you can also directly bind in '
|
'you can also directly bind in '
|
||||||
'"personal information -> quick modification -> change MFA Settings"!')
|
'"personal information -> quick modification -> change MFA Settings"!')
|
||||||
|
|
|
@ -54,6 +54,9 @@ class AuthMixin:
|
||||||
def can_update_password(self):
|
def can_update_password(self):
|
||||||
return self.is_local
|
return self.is_local
|
||||||
|
|
||||||
|
def can_update_ssh_key(self):
|
||||||
|
return self.is_local
|
||||||
|
|
||||||
def check_otp(self, code):
|
def check_otp(self, code):
|
||||||
from ..utils import check_otp_code
|
from ..utils import check_otp_code
|
||||||
return check_otp_code(self.otp_secret_key, code)
|
return check_otp_code(self.otp_secret_key, code)
|
||||||
|
|
|
@ -73,14 +73,17 @@
|
||||||
<p id="noTerms" class="red-fonts" style="visibility: hidden; font-size: 10px; margin-top: 10px;">* {% trans 'Please choose the terms and conditions.' %}</p>
|
<p id="noTerms" class="red-fonts" style="visibility: hidden; font-size: 10px; margin-top: 10px;">* {% trans 'Please choose the terms and conditions.' %}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if wizard.steps.current == '1' and not request.user.can_update_ssh_key %}
|
||||||
|
<b id="ssh_key_help_text">{% trans 'User auth from {}, ssh key login is not supported' %}</b>
|
||||||
|
{% else %}
|
||||||
{% bootstrap_form wizard.form %}
|
{% bootstrap_form wizard.form %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if form.mfa_description %}
|
{% if form.mfa_description %}
|
||||||
<b>{{ form.mfa_description }}</b>
|
<b>{{ form.mfa_description }}</b>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if form.pubkey_description %}
|
{% if form.pubkey_description and request.user.can_update_ssh_key %}
|
||||||
<span>或者:</span>
|
|
||||||
<a type="button" id="btn-reset-pubkey">{{ form.pubkey_description }}</a>
|
<a type="button" id="btn-reset-pubkey">{{ form.pubkey_description }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -121,12 +124,18 @@
|
||||||
|
|
||||||
{% block custom_foot_js %}
|
{% block custom_foot_js %}
|
||||||
<script>
|
<script>
|
||||||
$(document).on('click', ".fl_goto", function(){
|
$(document).ready(function(){
|
||||||
|
var origin_ssh_key_text = $("#ssh_key_help_text").text();
|
||||||
|
var new_ssh_key_text = origin_ssh_key_text.replace('{}', "{{ request.user.source_display }}");
|
||||||
|
$("#ssh_key_help_text").html(new_ssh_key_text)
|
||||||
|
})
|
||||||
|
.on('click', ".fl_goto", function(){
|
||||||
var $form = $('#fl_form');
|
var $form = $('#fl_form');
|
||||||
$('<input />', {'name': 'wizard_goto_step', 'value': $(this).data('goto'), 'type': 'hidden'}).appendTo($form);
|
$('<input />', {'name': 'wizard_goto_step', 'value': $(this).data('goto'), 'type': 'hidden'}).appendTo($form);
|
||||||
$form.submit();
|
$form.submit();
|
||||||
return false;
|
return false;
|
||||||
}).on('click', '#fl_submit', function(){
|
})
|
||||||
|
.on('click', '#fl_submit', function(){
|
||||||
var isFinish = $('#fl_submit').html() === "{% trans 'Finish' %}";
|
var isFinish = $('#fl_submit').html() === "{% trans 'Finish' %}";
|
||||||
var noChecked = !$('#acceptTerms').prop('checked');
|
var noChecked = !$('#acceptTerms').prop('checked');
|
||||||
if ( isFinish && noChecked){
|
if ( isFinish && noChecked){
|
||||||
|
@ -136,7 +145,8 @@
|
||||||
$('#fl_form').submit();
|
$('#fl_form').submit();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}).on('click', '#btn-reset-pubkey', function () {
|
})
|
||||||
|
.on('click', '#btn-reset-pubkey', function () {
|
||||||
var the_url = '{% url "users:user-pubkey-generate" %}';
|
var the_url = '{% url "users:user-pubkey-generate" %}';
|
||||||
window.open(the_url, "_blank");
|
window.open(the_url, "_blank");
|
||||||
$('#fl_form').submit();
|
$('#fl_form').submit();
|
||||||
|
|
|
@ -119,10 +119,12 @@
|
||||||
<td>{% trans 'Last login' %}:</td>
|
<td>{% trans 'Last login' %}:</td>
|
||||||
<td><b>{{ user_object.last_login|date:"Y-m-j H:i:s" }}</b></td>
|
<td><b>{{ user_object.last_login|date:"Y-m-j H:i:s" }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% if user_object.can_update_password %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans 'Last password updated' %}:</td>
|
<td>{% trans 'Last password updated' %}:</td>
|
||||||
<td><b>{{ user_object.date_password_last_updated|date:"Y-m-j H:i:s" }}</b></td>
|
<td><b>{{ user_object.date_password_last_updated|date:"Y-m-j H:i:s" }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans 'Comment' %}:</td>
|
<td>{% trans 'Comment' %}:</td>
|
||||||
<td><b>{{ user_object.comment }}</b></td>
|
<td><b>{{ user_object.comment }}</b></td>
|
||||||
|
@ -187,6 +189,7 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if user_object.can_update_ssh_key %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans 'Send reset ssh key mail' %}:</td>
|
<td>{% trans 'Send reset ssh key mail' %}:</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -195,6 +198,7 @@
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr style="{% if not unblock %}display:none{% endif %}">
|
<tr style="{% if not unblock %}display:none{% endif %}">
|
||||||
<td>{% trans 'Unblock user' %}</td>
|
<td>{% trans 'Unblock user' %}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -39,12 +39,16 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-profile-update' %}" class="text-center">{% trans 'Profile' %} </a>
|
<a href="{% url 'users:user-profile-update' %}" class="text-center">{% trans 'Profile' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% if request.user.can_update_password %}
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'users:user-password-update' %}" class="text-center">{% trans 'Password' %} </a>
|
<a href="{% url 'users:user-password-update' %}" class="text-center">{% trans 'Password' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if request.user.can_update_ssh_key %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-pubkey-update' %}" class="text-center">{% trans 'Public key' %} </a>
|
<a href="{% url 'users:user-pubkey-update' %}" class="text-center">{% trans 'Public key' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content" style="background-color: #ffffff">
|
<div class="tab-content" style="background-color: #ffffff">
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
<td>{{ user.is_active|yesno:"Yes,No,Unkown" }}</td>
|
<td>{{ user.is_active|yesno:"Yes,No,Unkown" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
{% if user.can_update_ssh_key %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-navy">{% trans 'Public key' %}</td>
|
<td class="text-navy">{% trans 'Public key' %}</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -81,6 +82,7 @@
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-navy">{% trans 'MFA certification' %}</td>
|
<td class="text-navy">{% trans 'MFA certification' %}</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -108,10 +110,12 @@
|
||||||
<td class="text-navy">{% trans 'Last login' %}</td>
|
<td class="text-navy">{% trans 'Last login' %}</td>
|
||||||
<td>{{ user.last_login|date:"Y-m-d H:i:s" }}</td>
|
<td>{{ user.last_login|date:"Y-m-d H:i:s" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% if user.can_update_password %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-navy">{% trans 'Last password updated' %}</td>
|
<td class="text-navy">{% trans 'Last password updated' %}</td>
|
||||||
<td>{{ user.date_password_last_updated|date:"Y-m-d H:i:s" }}</td>
|
<td>{{ user.date_password_last_updated|date:"Y-m-d H:i:s" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-navy">{% trans 'Date expired' %}</td>
|
<td class="text-navy">{% trans 'Date expired' %}</td>
|
||||||
<td>{{ user.date_expired|date:"Y-m-d H:i:s" }}</td>
|
<td>{{ user.date_expired|date:"Y-m-d H:i:s" }}</td>
|
||||||
|
@ -189,6 +193,7 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if request.user.can_update_ssh_key %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans 'Update SSH public key' %}:</td>
|
<td>{% trans 'Update SSH public key' %}:</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -205,6 +210,7 @@
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endif %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -36,12 +36,16 @@
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'users:user-profile-update' %}" class="text-center">{% trans 'Profile' %} </a>
|
<a href="{% url 'users:user-profile-update' %}" class="text-center">{% trans 'Profile' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% if request.user.can_update_password %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-password-update' %}" class="text-center">{% trans 'Password' %} </a>
|
<a href="{% url 'users:user-password-update' %}" class="text-center">{% trans 'Password' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if request.user.can_update_ssh_key %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-pubkey-update' %}" class="text-center">{% trans 'Public key' %} </a>
|
<a href="{% url 'users:user-pubkey-update' %}" class="text-center">{% trans 'Public key' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content" style="background-color: #ffffff">
|
<div class="tab-content" style="background-color: #ffffff">
|
||||||
|
|
|
@ -36,12 +36,16 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-profile-update' %}" class="text-center">{% trans 'Profile' %} </a>
|
<a href="{% url 'users:user-profile-update' %}" class="text-center">{% trans 'Profile' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% if request.user.can_update_password %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-password-update' %}" class="text-center">{% trans 'Password' %} </a>
|
<a href="{% url 'users:user-password-update' %}" class="text-center">{% trans 'Password' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if request.user.can_update_ssh_key %}
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'users:user-pubkey-update' %}" class="text-center">{% trans 'Public key' %} </a>
|
<a href="{% url 'users:user-pubkey-update' %}" class="text-center">{% trans 'Public key' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content" style="background-color: #ffffff">
|
<div class="tab-content" style="background-color: #ffffff">
|
||||||
|
|
|
@ -23,7 +23,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if object.can_update_ssh_key %}
|
||||||
{% bootstrap_field form.public_key layout="horizontal" %}
|
{% bootstrap_field form.public_key layout="horizontal" %}
|
||||||
|
{% else %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">{% trans 'ssh public key' %}</label>
|
||||||
|
<div class="col-sm-8 controls" style="margin-top: 8px;" id="ssh_key_help_text">
|
||||||
|
{% trans 'User auth from {}, ssh key login is not supported' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block custom_foot_js %}
|
{% block custom_foot_js %}
|
||||||
|
@ -77,9 +86,13 @@ function passwordCheck() {
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
passwordCheck();
|
passwordCheck();
|
||||||
|
|
||||||
var origin_text = $("#password_help_text").text();
|
var origin_password_text = $("#password_help_text").text();
|
||||||
var new_text = origin_text.replace('{}', "{{ object.source_display }}");
|
var new_password_text = origin_password_text.replace('{}', "{{ object.source_display }}");
|
||||||
$("#password_help_text").html(new_text);
|
$("#password_help_text").html(new_password_text);
|
||||||
|
|
||||||
|
var origin_ssh_key_text = $("#ssh_key_help_text").text();
|
||||||
|
var new_ssh_key_text = origin_ssh_key_text.replace('{}', "{{ object.source_display }}");
|
||||||
|
$("#ssh_key_help_text").html(new_ssh_key_text)
|
||||||
|
|
||||||
})
|
})
|
||||||
.on("submit", "form", function (evt) {
|
.on("submit", "form", function (evt) {
|
||||||
|
|
|
@ -198,7 +198,7 @@ def check_user_valid(**kwargs):
|
||||||
if password and authenticate(username=username, password=password):
|
if password and authenticate(username=username, password=password):
|
||||||
return user, ''
|
return user, ''
|
||||||
|
|
||||||
if public_key and user.public_key:
|
if public_key and user.public_key and user.is_local:
|
||||||
public_key_saved = user.public_key.split()
|
public_key_saved = user.public_key.split()
|
||||||
if len(public_key_saved) == 1:
|
if len(public_key_saved) == 1:
|
||||||
if public_key == public_key_saved[0]:
|
if public_key == public_key_saved[0]:
|
||||||
|
|
|
@ -2,40 +2,32 @@
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import json
|
|
||||||
import uuid
|
|
||||||
import csv
|
|
||||||
import codecs
|
|
||||||
import chardet
|
|
||||||
from io import StringIO
|
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth import authenticate, login as auth_login
|
from django.contrib.auth import authenticate
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import HttpResponse, JsonResponse
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse_lazy, reverse
|
from django.urls import reverse_lazy, reverse
|
||||||
from django.utils import timezone
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.utils.decorators import method_decorator
|
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from django.db import transaction
|
|
||||||
from django.views.generic.edit import (
|
from django.views.generic.edit import (
|
||||||
CreateView, UpdateView, FormView
|
CreateView, UpdateView, FormView
|
||||||
)
|
)
|
||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
|
||||||
from django.contrib.auth import logout as auth_logout
|
from django.contrib.auth import logout as auth_logout
|
||||||
|
|
||||||
from common.const import (
|
from common.const import (
|
||||||
create_success_msg, update_success_msg, KEY_CACHE_RESOURCES_ID
|
create_success_msg, update_success_msg, KEY_CACHE_RESOURCES_ID
|
||||||
)
|
)
|
||||||
from common.mixins import JSONResponseMixin
|
from common.utils import get_logger, ssh_key_gen
|
||||||
from common.utils import get_logger, get_object_or_none, is_uuid, ssh_key_gen
|
from common.permissions import (
|
||||||
from common.permissions import PermissionsMixin, IsOrgAdmin, IsValidUser
|
PermissionsMixin, IsOrgAdmin, IsValidUser,
|
||||||
|
UserCanUpdatePassword, UserCanUpdateSSHKey,
|
||||||
|
)
|
||||||
from orgs.utils import current_org
|
from orgs.utils import current_org
|
||||||
from .. import forms
|
from .. import forms
|
||||||
from ..models import User, UserGroup
|
from ..models import User, UserGroup
|
||||||
|
@ -260,6 +252,7 @@ class UserPasswordUpdateView(PermissionsMixin, UpdateView):
|
||||||
model = User
|
model = User
|
||||||
form_class = forms.UserPasswordForm
|
form_class = forms.UserPasswordForm
|
||||||
success_url = reverse_lazy('users:user-profile')
|
success_url = reverse_lazy('users:user-profile')
|
||||||
|
permission_classes = [IsValidUser, UserCanUpdatePassword]
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
return self.request.user
|
return self.request.user
|
||||||
|
@ -279,12 +272,6 @@ class UserPasswordUpdateView(PermissionsMixin, UpdateView):
|
||||||
return super().get_success_url()
|
return super().get_success_url()
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
if not self.request.user.can_update_password():
|
|
||||||
error = _("User auth from {}, go there change password").format(
|
|
||||||
self.request.source_display
|
|
||||||
)
|
|
||||||
form.add_error("password", error)
|
|
||||||
return self.form_invalid(form)
|
|
||||||
password = form.cleaned_data.get('new_password')
|
password = form.cleaned_data.get('new_password')
|
||||||
is_ok = check_password_rules(password)
|
is_ok = check_password_rules(password)
|
||||||
if not is_ok:
|
if not is_ok:
|
||||||
|
@ -300,7 +287,7 @@ class UserPublicKeyUpdateView(PermissionsMixin, UpdateView):
|
||||||
template_name = 'users/user_pubkey_update.html'
|
template_name = 'users/user_pubkey_update.html'
|
||||||
model = User
|
model = User
|
||||||
form_class = forms.UserPublicKeyForm
|
form_class = forms.UserPublicKeyForm
|
||||||
permission_classes = [IsValidUser]
|
permission_classes = [IsValidUser, UserCanUpdateSSHKey]
|
||||||
success_url = reverse_lazy('users:user-profile')
|
success_url = reverse_lazy('users:user-profile')
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
|
|
Loading…
Reference in New Issue