mirror of https://github.com/jumpserver/jumpserver
				
				
				
			change user api
							parent
							
								
									ea3f8af161
								
							
						
					
					
						commit
						8d7759d22f
					
				| 
						 | 
				
			
			@ -315,9 +315,8 @@ class Asset(models.Model):
 | 
			
		|||
    admin_user = models.ForeignKey(AdminUser, null=True, blank=True, related_name='assets',
 | 
			
		||||
                                   on_delete=models.SET_NULL, verbose_name=_("Admin user"))
 | 
			
		||||
    system_users = models.ManyToManyField(SystemUser, blank=True, related_name='assets', verbose_name=_("System User"))
 | 
			
		||||
    idc = models.ForeignKey(IDC, null=True, related_name='assets',
 | 
			
		||||
    idc = models.ForeignKey(IDC, blank=True, null=True, related_name='assets',
 | 
			
		||||
                            on_delete=models.SET_NULL, verbose_name=_('IDC'),)
 | 
			
		||||
                            # default=get_default_idc)
 | 
			
		||||
    mac_address = models.CharField(max_length=20, null=True, blank=True, verbose_name=_("Mac address"))
 | 
			
		||||
    brand = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('Brand'))
 | 
			
		||||
    cpu = models.CharField(max_length=64,  null=True, blank=True, verbose_name=_('CPU'))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,12 +30,11 @@
 | 
			
		|||
    <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 class="btn btn-default" type="reset"> {% trans 'Reset' %}</button>
 | 
			
		||||
            <button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
</form>
 | 
			
		||||
    </form>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block custom_foot_js %}
 | 
			
		||||
| 
						 | 
				
			
			@ -44,10 +43,9 @@
 | 
			
		|||
            $('.select2').select2();
 | 
			
		||||
            $("#id_tags").select2({
 | 
			
		||||
                tags: true,
 | 
			
		||||
                maximumSelectionLength: 8,  //最多能够选择的个数
 | 
			
		||||
                maximumSelectionLength: 8  //最多能够选择的个数
 | 
			
		||||
                //closeOnSelect: false
 | 
			
		||||
            });
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    </script>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ class AssetListView(AdminUserRequiredMixin, ListView):
 | 
			
		|||
        return super(AssetListView, self).get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AssetCreateView(AdminUserRequiredMixin,CreateAssetTagsMiXin,CreateView):
 | 
			
		||||
class AssetCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView):
 | 
			
		||||
    model = Asset
 | 
			
		||||
    tag_type = 'asset'
 | 
			
		||||
    form_class = AssetCreateForm
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +58,8 @@ class AssetCreateView(AdminUserRequiredMixin,CreateAssetTagsMiXin,CreateView):
 | 
			
		|||
        return super(AssetCreateView, self).form_valid(form)
 | 
			
		||||
 | 
			
		||||
    def form_invalid(self, form):
 | 
			
		||||
        print(form.errors)
 | 
			
		||||
        if form.errors.get('__all__'):
 | 
			
		||||
            form.errors['all'] = form.errors.get('__all__')
 | 
			
		||||
        return super(AssetCreateView, self).form_invalid(form)
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1610,7 +1610,7 @@ msgid ""
 | 
			
		|||
"here reset password</a>\n"
 | 
			
		||||
"    </br>\n"
 | 
			
		||||
"    This link is valid for 1 hour. After it expires, <a href=\"%"
 | 
			
		||||
"(forget_password_url)s?email=%(email)s\">request new one<</a>\n"
 | 
			
		||||
"(forget_password_url)s?email=%(email)s\">request new one</a>\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"    </br>\n"
 | 
			
		||||
"    ---\n"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -189,9 +189,9 @@ function activeNav() {
 | 
			
		|||
function APIUpdateAttr(props) {
 | 
			
		||||
  // props = {url: .., body: , success: , error: , method: ,}
 | 
			
		||||
  props = props || {};
 | 
			
		||||
  success_message = props.success_message || 'Update Successfully!';
 | 
			
		||||
  fail_message = props.fail_message || 'Error occurred while updating.';
 | 
			
		||||
 | 
			
		||||
  var success_message = props.success_message || 'Update Successfully!';
 | 
			
		||||
  var fail_message = props.fail_message || 'Error occurred while updating.';
 | 
			
		||||
  console.log(props.body);
 | 
			
		||||
  $.ajax({
 | 
			
		||||
    url: props.url,
 | 
			
		||||
    type: props.method || "PATCH",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,10 +28,17 @@
 | 
			
		|||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="ibox-content">
 | 
			
		||||
                        {% block form %} {% endblock %}
 | 
			
		||||
                        {% if form.errors.all %}
 | 
			
		||||
                            <div class="alert alert-danger" style="margin: 20px auto 0px">
 | 
			
		||||
                            {{ form.errors.all }}
 | 
			
		||||
                        </div>
 | 
			
		||||
                        {% endif %}
 | 
			
		||||
                        {% block form %}
 | 
			
		||||
                        {% endblock %}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,120 +6,119 @@ import base64
 | 
			
		|||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.core.cache import cache
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from rest_framework import generics, status
 | 
			
		||||
from rest_framework import generics, status, viewsets
 | 
			
		||||
from rest_framework.response import Response
 | 
			
		||||
from rest_framework.views import APIView
 | 
			
		||||
from rest_framework_bulk import ListBulkCreateUpdateDestroyAPIView
 | 
			
		||||
from rest_framework_bulk import ListBulkCreateUpdateDestroyAPIView, BulkModelViewSet
 | 
			
		||||
from rest_framework import authentication
 | 
			
		||||
 | 
			
		||||
from common.mixins import BulkDeleteApiMixin
 | 
			
		||||
from common.utils import get_logger
 | 
			
		||||
from .utils import check_user_valid, token_gen
 | 
			
		||||
from .models import User, UserGroup
 | 
			
		||||
from .serializers import UserDetailSerializer, UserAndGroupSerializer, \
 | 
			
		||||
    GroupDetailSerializer, UserPKUpdateSerializer, UserBulkUpdateSerializer, GroupBulkUpdateSerializer
 | 
			
		||||
from . import serializers
 | 
			
		||||
from .backends import IsSuperUser, IsTerminalUser, IsValidUser, IsSuperUserOrTerminalUser
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
logger = get_logger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserDetailApi(generics.RetrieveUpdateDestroyAPIView):
 | 
			
		||||
class UserViewSet(BulkModelViewSet):
 | 
			
		||||
    queryset = User.objects.all()
 | 
			
		||||
    serializer_class = UserDetailSerializer
 | 
			
		||||
    serializer_class = serializers.UserSerializer
 | 
			
		||||
    permission_classes = (IsSuperUser,)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserAndGroupEditApi(generics.RetrieveUpdateAPIView):
 | 
			
		||||
    queryset = User.objects.all()
 | 
			
		||||
    serializer_class = UserAndGroupSerializer
 | 
			
		||||
    permission_classes = (IsSuperUser,)
 | 
			
		||||
# class UserAndGroupEditApi(generics.RetrieveUpdateAPIView):
 | 
			
		||||
#     queryset = User.objects.all()
 | 
			
		||||
#     serializer_class = serializers.UserAndGroupSerializer
 | 
			
		||||
#     permission_classes = (IsSuperUser,)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserResetPasswordApi(generics.UpdateAPIView):
 | 
			
		||||
    queryset = User.objects.all()
 | 
			
		||||
    serializer_class = UserDetailSerializer
 | 
			
		||||
    serializer_class = serializers.UserSerializer
 | 
			
		||||
 | 
			
		||||
    def perform_update(self, serializer):
 | 
			
		||||
        # Note: we are not updating the user object here.
 | 
			
		||||
        # We just do the reset-password staff.
 | 
			
		||||
        user = self.get_object()
 | 
			
		||||
        import uuid
 | 
			
		||||
        from .utils import send_reset_password_mail
 | 
			
		||||
        user = self.get_object()
 | 
			
		||||
        user.password_raw = str(uuid.uuid4())
 | 
			
		||||
        user.save()
 | 
			
		||||
        from .utils import send_reset_password_mail
 | 
			
		||||
        send_reset_password_mail(user)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserResetPKApi(generics.UpdateAPIView):
 | 
			
		||||
class UserResetPubKeyApi(generics.UpdateAPIView):
 | 
			
		||||
    queryset = User.objects.all()
 | 
			
		||||
    serializer_class = UserDetailSerializer
 | 
			
		||||
    serializer_class = serializers.UserSerializer
 | 
			
		||||
 | 
			
		||||
    def perform_update(self, serializer):
 | 
			
		||||
        from .utils import send_reset_ssh_key_mail
 | 
			
		||||
        user = self.get_object()
 | 
			
		||||
        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()
 | 
			
		||||
#
 | 
			
		||||
# class UserUpdatePKApi(generics.UpdateAPIView):
 | 
			
		||||
#     queryset = User.objects.all()
 | 
			
		||||
#     serializer_class = serializers.UserPKUpdateSerializer
 | 
			
		||||
#
 | 
			
		||||
#     def perform_update(self, serializer):
 | 
			
		||||
#         user = self.get_object()
 | 
			
		||||
#         user.private_key = serializer.validated_data['_public_key']
 | 
			
		||||
#         user.save()
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# class GroupDetailApi(generics.RetrieveUpdateDestroyAPIView):
 | 
			
		||||
#     queryset = UserGroup.objects.all()
 | 
			
		||||
#     serializer_class = serializers.GroupDetailSerializer
 | 
			
		||||
#
 | 
			
		||||
#     def perform_update(self, serializer):
 | 
			
		||||
#         users = serializer.validated_data.get('users')
 | 
			
		||||
#         if users:
 | 
			
		||||
#             group = self.get_object()
 | 
			
		||||
#             Note: use `list` method to force hitting the db.
 | 
			
		||||
            # group_users = list(group.users.all())
 | 
			
		||||
            # serializer.save()
 | 
			
		||||
            # group.users.set(users + group_users)
 | 
			
		||||
            # group.save()
 | 
			
		||||
            # return
 | 
			
		||||
        # serializer.save()
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# class UserListUpdateApi(BulkDeleteApiMixin, ListBulkCreateUpdateDestroyAPIView):
 | 
			
		||||
#     queryset = User.objects.all()
 | 
			
		||||
#     serializer_class = serializers.UserBulkUpdateSerializer
 | 
			
		||||
#     permission_classes = (IsSuperUserOrTerminalUser,)
 | 
			
		||||
#
 | 
			
		||||
#     def get(self, request, *args, **kwargs):
 | 
			
		||||
#         return super(UserListUpdateApi, self).get(request, *args, **kwargs)
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# class GroupListUpdateApi(BulkDeleteApiMixin, ListBulkCreateUpdateDestroyAPIView):
 | 
			
		||||
#     queryset = UserGroup.objects.all()
 | 
			
		||||
#     serializer_class = serializers.GroupBulkUpdateSerializer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GroupDetailApi(generics.RetrieveUpdateDestroyAPIView):
 | 
			
		||||
    queryset = UserGroup.objects.all()
 | 
			
		||||
    serializer_class = GroupDetailSerializer
 | 
			
		||||
 | 
			
		||||
    def perform_update(self, serializer):
 | 
			
		||||
        users = serializer.validated_data.get('users')
 | 
			
		||||
        if users:
 | 
			
		||||
            group = self.get_object()
 | 
			
		||||
            # Note: use `list` method to force hitting the db.
 | 
			
		||||
            group_users = list(group.users.all())
 | 
			
		||||
            serializer.save()
 | 
			
		||||
            group.users.set(users + group_users)
 | 
			
		||||
            group.save()
 | 
			
		||||
            return
 | 
			
		||||
        serializer.save()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserListUpdateApi(BulkDeleteApiMixin, ListBulkCreateUpdateDestroyAPIView):
 | 
			
		||||
    queryset = User.objects.all()
 | 
			
		||||
    serializer_class = UserBulkUpdateSerializer
 | 
			
		||||
    permission_classes = (IsSuperUserOrTerminalUser,)
 | 
			
		||||
 | 
			
		||||
    # def get(self, request, *args, **kwargs):
 | 
			
		||||
    #     return super(UserListUpdateApi, self).get(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GroupListUpdateApi(BulkDeleteApiMixin, ListBulkCreateUpdateDestroyAPIView):
 | 
			
		||||
    queryset = UserGroup.objects.all()
 | 
			
		||||
    serializer_class = GroupBulkUpdateSerializer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DeleteUserFromGroupApi(generics.DestroyAPIView):
 | 
			
		||||
    queryset = UserGroup.objects.all()
 | 
			
		||||
    serializer_class = GroupDetailSerializer
 | 
			
		||||
 | 
			
		||||
    def destroy(self, request, *args, **kwargs):
 | 
			
		||||
        group = self.get_object()
 | 
			
		||||
        self.perform_destroy(group, **kwargs)
 | 
			
		||||
        return Response(status=status.HTTP_204_NO_CONTENT)
 | 
			
		||||
 | 
			
		||||
    def perform_destroy(self, instance, **kwargs):
 | 
			
		||||
        user_id = kwargs.get('uid')
 | 
			
		||||
        user = get_object_or_404(User, id=user_id)
 | 
			
		||||
        instance.users.remove(user)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserTokenApi(APIView):
 | 
			
		||||
# class DeleteUserFromGroupApi(generics.DestroyAPIView):
 | 
			
		||||
#     queryset = UserGroup.objects.all()
 | 
			
		||||
#     serializer_class = serializers.GroupDetailSerializer
 | 
			
		||||
#
 | 
			
		||||
#     def destroy(self, request, *args, **kwargs):
 | 
			
		||||
#         group = self.get_object()
 | 
			
		||||
#         self.perform_destroy(group, **kwargs)
 | 
			
		||||
#         return Response(status=status.HTTP_204_NO_CONTENT)
 | 
			
		||||
#
 | 
			
		||||
#     def perform_destroy(self, instance, **kwargs):
 | 
			
		||||
#         user_id = kwargs.get('uid')
 | 
			
		||||
#         user = get_object_or_404(User, id=user_id)
 | 
			
		||||
#         instance.users.remove(user)
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
class UserAuthApi(APIView):
 | 
			
		||||
    permission_classes = ()
 | 
			
		||||
    expiration = settings.CONFIG.TOKEN_EXPIRATION or 3600
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -128,9 +127,9 @@ class UserTokenApi(APIView):
 | 
			
		|||
        password = request.data.get('password', '')
 | 
			
		||||
        public_key = request.data.get('public_key', '')
 | 
			
		||||
        remote_addr = request.META.get('REMOTE_ADDR', '')
 | 
			
		||||
 | 
			
		||||
        remote_addr = base64.b64encode(remote_addr).replace('=', '')
 | 
			
		||||
        user = check_user_valid(username=username, password=password, public_key=public_key)
 | 
			
		||||
 | 
			
		||||
        if user:
 | 
			
		||||
            token = cache.get('%s_%s' % (user.id, remote_addr))
 | 
			
		||||
            if not token:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib.auth import logout
 | 
			
		||||
from django.contrib.auth.hashers import make_password
 | 
			
		||||
from django.contrib.auth.models import AbstractUser
 | 
			
		||||
from django.core import signing
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,10 +9,35 @@ from common.utils import signer
 | 
			
		|||
from .models import User, UserGroup
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserDetailSerializer(serializers.ModelSerializer):
 | 
			
		||||
# class UserDetailSerializer(BulkSerializerMixin, serializers.ModelSerializer):
 | 
			
		||||
#     class Meta:
 | 
			
		||||
#         model = User
 | 
			
		||||
#         fields = ['avatar', 'wechat', 'phone', 'enable_otp', 'comment', 'is_active', 'name']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
 | 
			
		||||
    group_display = serializers.SerializerMethodField()
 | 
			
		||||
    active_display = serializers.SerializerMethodField()
 | 
			
		||||
    groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all())
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = User
 | 
			
		||||
        fields = ['avatar', 'wechat', 'phone', 'enable_otp', 'comment', 'is_active', 'name']
 | 
			
		||||
        list_serializer_class = BulkListSerializer
 | 
			
		||||
        exclude = ['first_name', 'last_name', 'password', '_private_key', '_public_key']
 | 
			
		||||
 | 
			
		||||
    def get_field_names(self, declared_fields, info):
 | 
			
		||||
        fields = super(UserSerializer, self).get_field_names(declared_fields, info)
 | 
			
		||||
        fields.extend(['group_display', 'get_role_display'])
 | 
			
		||||
        return fields
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_group_display(obj):
 | 
			
		||||
        return " ".join([group.name for group in obj.groups.all()])
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_active_display(obj):
 | 
			
		||||
        # TODO: user active state
 | 
			
		||||
        return not (obj.is_expired and obj.is_active)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserPKUpdateSerializer(serializers.ModelSerializer):
 | 
			
		||||
| 
						 | 
				
			
			@ -44,43 +69,43 @@ class UserAndGroupSerializer(serializers.ModelSerializer):
 | 
			
		|||
        fields = ['id', 'groups']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GroupDetailSerializer(serializers.ModelSerializer):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = UserGroup
 | 
			
		||||
        fields = ['id', 'name', 'comment', 'date_created', 'created_by', 'users']
 | 
			
		||||
# class GroupDetailSerializer(serializers.ModelSerializer):
 | 
			
		||||
#     class Meta:
 | 
			
		||||
#         model = UserGroup
 | 
			
		||||
#         fields = ['id', 'name', 'comment', 'date_created', 'created_by', 'users']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
 | 
			
		||||
    group_display = serializers.SerializerMethodField()
 | 
			
		||||
    active_display = serializers.SerializerMethodField()
 | 
			
		||||
    groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all())
 | 
			
		||||
 | 
			
		||||
    class Meta(object):
 | 
			
		||||
        model = User
 | 
			
		||||
        list_serializer_class = BulkListSerializer
 | 
			
		||||
        fields = ['id', 'is_active', 'username', 'name', 'email', 'role', 'avatar',
 | 
			
		||||
                  'enable_otp', 'comment', 'groups', 'get_role_display',
 | 
			
		||||
                  'group_display', 'active_display']
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_group_display(obj):
 | 
			
		||||
        return " ".join([group.name for group in obj.groups.all()])
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_active_display(obj):
 | 
			
		||||
        # TODO: user active state
 | 
			
		||||
        return not (obj.is_expired and obj.is_active)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GroupBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
 | 
			
		||||
    user_amount = serializers.SerializerMethodField()
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = UserGroup
 | 
			
		||||
        list_serializer_class = BulkListSerializer
 | 
			
		||||
        fields = ['id', 'name', 'comment', 'user_amount']
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_user_amount(obj):
 | 
			
		||||
        return obj.users.count()
 | 
			
		||||
 | 
			
		||||
# class UserBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
 | 
			
		||||
#     group_display = serializers.SerializerMethodField()
 | 
			
		||||
#     active_display = serializers.SerializerMethodField()
 | 
			
		||||
#     groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all())
 | 
			
		||||
#
 | 
			
		||||
#     class Meta(object):
 | 
			
		||||
#         model = User
 | 
			
		||||
#         list_serializer_class = BulkListSerializer
 | 
			
		||||
#         fields = ['id', 'is_active', 'username', 'name', 'email', 'role', 'avatar',
 | 
			
		||||
#                   'enable_otp', 'comment', 'groups', 'get_role_display',
 | 
			
		||||
#                   'group_display', 'active_display']
 | 
			
		||||
#
 | 
			
		||||
#     @staticmethod
 | 
			
		||||
#     def get_group_display(obj):
 | 
			
		||||
#         return " ".join([group.name for group in obj.groups.all()])
 | 
			
		||||
#
 | 
			
		||||
#     @staticmethod
 | 
			
		||||
#     def get_active_display(obj):
 | 
			
		||||
#         TODO: user active state
 | 
			
		||||
        # return not (obj.is_expired and obj.is_active)
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# class GroupBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
 | 
			
		||||
#     user_amount = serializers.SerializerMethodField()
 | 
			
		||||
#
 | 
			
		||||
#     class Meta:
 | 
			
		||||
#         model = UserGroup
 | 
			
		||||
#         list_serializer_class = BulkListSerializer
 | 
			
		||||
#         fields = ['id', 'name', 'comment', 'user_amount']
 | 
			
		||||
#
 | 
			
		||||
#     @staticmethod
 | 
			
		||||
#     def get_user_amount(obj):
 | 
			
		||||
#         return obj.users.count()
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,82 +1,52 @@
 | 
			
		|||
{% extends 'base.html' %}
 | 
			
		||||
{% extends '_base_create_update.html' %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
{% load static %}
 | 
			
		||||
{% load bootstrap %}
 | 
			
		||||
{% block custom_head_css_js %}
 | 
			
		||||
    <link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
 | 
			
		||||
    <script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
 | 
			
		||||
    <link href="{% static "css/plugins/datepicker/datepicker3.css" %}" rel="stylesheet">
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% block form %}
 | 
			
		||||
     <form method="post" class="form-horizontal" action="" enctype="multipart/form-data">
 | 
			
		||||
         {% csrf_token %}
 | 
			
		||||
         <h3>{% trans 'Account' %}</h3>
 | 
			
		||||
         {% block username %} {% endblock %}
 | 
			
		||||
         {{ form.name|bootstrap_horizontal }}
 | 
			
		||||
         {{ form.email|bootstrap_horizontal }}
 | 
			
		||||
         {{ form.groups|bootstrap_horizontal }}
 | 
			
		||||
 | 
			
		||||
{% 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="ibox-title">
 | 
			
		||||
                        <h5>{% block user_template_title %}{% trans 'Create user' %}{% endblock %}</h5>
 | 
			
		||||
                        <div class="ibox-tools">
 | 
			
		||||
                            <a class="collapse-link">
 | 
			
		||||
                                <i class="fa fa-chevron-up"></i>
 | 
			
		||||
                            </a>
 | 
			
		||||
                            <a class="dropdown-toggle" data-toggle="dropdown" href="#">
 | 
			
		||||
                                <i class="fa fa-wrench"></i>
 | 
			
		||||
                            </a>
 | 
			
		||||
                            <a class="close-link">
 | 
			
		||||
                                <i class="fa fa-times"></i>
 | 
			
		||||
                            </a>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="ibox-content">
 | 
			
		||||
                        <form method="post" class="form-horizontal" action="" enctype="multipart/form-data">
 | 
			
		||||
                            {% csrf_token %}
 | 
			
		||||
                            <h3>{% trans 'Account' %}</h3>
 | 
			
		||||
                            {% block username %} {% endblock %}
 | 
			
		||||
                            {{ form.name|bootstrap_horizontal }}
 | 
			
		||||
                            {{ form.email|bootstrap_horizontal }}
 | 
			
		||||
                            {{ form.groups|bootstrap_horizontal }}
 | 
			
		||||
         <div class="hr-line-dashed"></div>
 | 
			
		||||
         {% block password %} {% endblock %}
 | 
			
		||||
 | 
			
		||||
                            <div class="hr-line-dashed"></div>
 | 
			
		||||
                            {% block password %} {% endblock %}
 | 
			
		||||
 | 
			
		||||
                            <div class="hr-line-dashed"></div>
 | 
			
		||||
                            <h3>{% trans 'Security and Role' %}</h3>
 | 
			
		||||
                            {{ form.role|bootstrap_horizontal }}
 | 
			
		||||
                            <div class="form-group {% if form.date_expired.errors %} has-error {% endif %}" id="date_5">
 | 
			
		||||
                                <label for="{{ form.date_expired.id_for_label }}" class="col-sm-2 control-label">{{ form.date_expired.label }}</label>
 | 
			
		||||
                                <div class="col-sm-9">
 | 
			
		||||
                                    <div class="input-group date">
 | 
			
		||||
                                        <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
 | 
			
		||||
                                        <input id="{{ form.date_expired.id_for_label }}" name="{{ form.date_expired.html_name }}" type="text" class="form-control" value="{{ form.date_expired.value|date:'Y-m-d' }}">
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <span class="help-block ">{{ form.date_expired.errors }}</span>
 | 
			
		||||
                                </div>
 | 
			
		||||
                             </div>
 | 
			
		||||
{#                            {{ form.date_expired|bootstrap_horizontal }}#}
 | 
			
		||||
                            <div class="form-group">
 | 
			
		||||
                                <label for="{{ form.enable_otp.id_for_label }}" class="col-sm-2 control-label">{% trans 'Enable OTP' %}</label>
 | 
			
		||||
                                <div class="col-sm-8">
 | 
			
		||||
                                    {{ form.enable_otp }}
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="hr-line-dashed"></div>
 | 
			
		||||
                            <h3>{% trans 'Profile' %}</h3>
 | 
			
		||||
                            {{ form.phone|bootstrap_horizontal }}
 | 
			
		||||
                            {{ form.wechat|bootstrap_horizontal }}
 | 
			
		||||
                            {{ form.comment|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 class="hr-line-dashed"></div>
 | 
			
		||||
         <h3>{% trans 'Security and Role' %}</h3>
 | 
			
		||||
         {{ form.role|bootstrap_horizontal }}
 | 
			
		||||
         <div class="form-group {% if form.date_expired.errors %} has-error {% endif %}" id="date_5">
 | 
			
		||||
             <label for="{{ form.date_expired.id_for_label }}" class="col-sm-2 control-label">{{ form.date_expired.label }}</label>
 | 
			
		||||
             <div class="col-sm-9">
 | 
			
		||||
                 <div class="input-group date">
 | 
			
		||||
                     <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
 | 
			
		||||
                     <input id="{{ form.date_expired.id_for_label }}" name="{{ form.date_expired.html_name }}" type="text" class="form-control" value="{{ form.date_expired.value|date:'Y-m-d' }}">
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <span class="help-block ">{{ form.date_expired.errors }}</span>
 | 
			
		||||
             </div>
 | 
			
		||||
          </div>
 | 
			
		||||
           {{ form.date_expired|bootstrap_horizontal }}#}
 | 
			
		||||
         <div class="form-group">
 | 
			
		||||
             <label for="{{ form.enable_otp.id_for_label }}" class="col-sm-2 control-label">{% trans 'Enable OTP' %}</label>
 | 
			
		||||
             <div class="col-sm-8">
 | 
			
		||||
                 {{ form.enable_otp }}
 | 
			
		||||
             </div>
 | 
			
		||||
         </div>
 | 
			
		||||
         <div class="hr-line-dashed"></div>
 | 
			
		||||
         <h3>{% trans 'Profile' %}</h3>
 | 
			
		||||
         {{ form.phone|bootstrap_horizontal }}
 | 
			
		||||
         {{ form.wechat|bootstrap_horizontal }}
 | 
			
		||||
         {{ form.comment|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>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% block custom_foot_js %}
 | 
			
		||||
    <script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,20 +18,23 @@
 | 
			
		|||
                    <div class="panel-options">
 | 
			
		||||
                        <ul class="nav nav-tabs">
 | 
			
		||||
                            <li class="active">
 | 
			
		||||
                                <a href="{% url 'users:user-detail' pk=user_object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
 | 
			
		||||
                                <a href="{% url 'users:user-detail' pk=user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
 | 
			
		||||
                            </li>
 | 
			
		||||
                            <li>
 | 
			
		||||
                                <a href="{% url 'users:user-asset-permission' pk=user_object.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
 | 
			
		||||
                                <a href="{% url 'users:user-asset-permission' pk=user.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
 | 
			
		||||
                            </li>
 | 
			
		||||
                            <li><a href="{% url 'users:user-granted-asset' pk=user.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a></li>
 | 
			
		||||
                            <li><a href="{% url 'users:user-login-history' pk=user.id %}" class="text-center"><i class="fa fa-calculator-o"></i> {% trans 'Login history' %}</a></li>
 | 
			
		||||
                            <li class="pull-right">
 | 
			
		||||
                                <a class="btn btn-outline btn-default" href="{% url 'users:user-update' pk=user.id %}"><i class="fa fa-edit"></i>Update</a>
 | 
			
		||||
                            </li>
 | 
			
		||||
                            <li><a href="{% url 'users:user-granted-asset' pk=user_object.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a></li>
 | 
			
		||||
                            <li><a href="{% url 'users:user-login-history' pk=user_object.id %}" class="text-center"><i class="fa fa-calculator-o"></i> {% trans 'Login history' %}</a></li>
 | 
			
		||||
                        </ul>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="tab-content">
 | 
			
		||||
                        <div class="col-sm-7" style="padding-left: 0">
 | 
			
		||||
                            <div class="ibox float-e-margins">
 | 
			
		||||
                                <div class="ibox-title">
 | 
			
		||||
                                    <span class="label"><b>{{ user_object.name }}</b></span>
 | 
			
		||||
                                    <span class="label"><b>{{ user.name }}</b></span>
 | 
			
		||||
                                    <div class="ibox-tools">
 | 
			
		||||
                                        <a class="collapse-link">
 | 
			
		||||
                                            <i class="fa fa-chevron-up"></i>
 | 
			
		||||
| 
						 | 
				
			
			@ -51,56 +54,56 @@
 | 
			
		|||
                                        <tbody>
 | 
			
		||||
                                        <tr class="no-borders-tr">
 | 
			
		||||
                                            <td colspan="2">
 | 
			
		||||
                                                <img src="{{ user_object | user_avatar_url }}" class="img-circle" width="64" height="64">
 | 
			
		||||
                                                <img src="{{ user | user_avatar_url }}" class="img-circle" width="64" height="64">
 | 
			
		||||
                                            </td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td width="20%">{% trans 'Name' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.name }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.name }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td>{% trans 'Username' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.username }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.username }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td>{% trans 'Email' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.email }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.email }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        {% if user_object.phone %}
 | 
			
		||||
                                        {% if user.phone %}
 | 
			
		||||
                                            <tr>
 | 
			
		||||
                                                <td>{% trans 'Phone' %}:</td>
 | 
			
		||||
                                                <td><b>{{ user_object.phone }}</b></td>
 | 
			
		||||
                                                <td><b>{{ user.phone }}</b></td>
 | 
			
		||||
                                            </tr>
 | 
			
		||||
                                        {% endif %}
 | 
			
		||||
                                        {% if user_object.wechat %}
 | 
			
		||||
                                        {% if user.wechat %}
 | 
			
		||||
                                            <tr>
 | 
			
		||||
                                                <td>{% trans 'Wechat' %}:</td>
 | 
			
		||||
                                                <td><b>{{ user_object.wechat }}</b></td>
 | 
			
		||||
                                                <td><b>{{ user.wechat }}</b></td>
 | 
			
		||||
                                            </tr>
 | 
			
		||||
                                        {% endif %}
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td>{% trans 'Role' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.get_role_display }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.get_role_display }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td>{% trans 'Date expired' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.date_expired|date:"Y-m-j H:i:s" }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.date_expired|date:"Y-m-j H:i:s" }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td>{% trans 'Created by' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.created_by }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.created_by }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td>{% trans 'Date joined' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.date_joined|date:"Y-m-j H:i:s" }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.date_joined|date:"Y-m-j H:i:s" }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td>{% trans 'Last login' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.last_login|date:"Y-m-j H:i:s" }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.last_login|date:"Y-m-j H:i:s" }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                            <td>{% trans 'Comment' %}:</td>
 | 
			
		||||
                                            <td><b>{{ user_object.comment }}</b></td>
 | 
			
		||||
                                            <td><b>{{ user.comment }}</b></td>
 | 
			
		||||
                                        </tr>
 | 
			
		||||
                                        </tbody>
 | 
			
		||||
                                    </table>
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +123,7 @@
 | 
			
		|||
                                            <td><span class="pull-right">
 | 
			
		||||
                                                <div class="switch">
 | 
			
		||||
                                                    <div class="onoffswitch">
 | 
			
		||||
                                                        <input type="checkbox" {% if user_object.is_active %} checked {% endif %}  class="onoffswitch-checkbox" id="is_active">
 | 
			
		||||
                                                        <input type="checkbox" {% if user.is_active %} checked {% endif %}  class="onoffswitch-checkbox" id="is_active">
 | 
			
		||||
                                                        <label class="onoffswitch-label" for="is_active">
 | 
			
		||||
                                                            <span class="onoffswitch-inner"></span>
 | 
			
		||||
                                                            <span class="onoffswitch-switch"></span>
 | 
			
		||||
| 
						 | 
				
			
			@ -134,7 +137,7 @@
 | 
			
		|||
                                            <td><span class="pull-right">
 | 
			
		||||
                                                <div class="switch">
 | 
			
		||||
                                                    <div class="onoffswitch">
 | 
			
		||||
                                                        <input type="checkbox" class="onoffswitch-checkbox" {% if user_object.enable_otp %} checked {% endif %}
 | 
			
		||||
                                                        <input type="checkbox" class="onoffswitch-checkbox" {% if user.enable_otp %} checked {% endif %}
 | 
			
		||||
                                                               id="enable_otp">
 | 
			
		||||
                                                        <label class="onoffswitch-label" for="enable_otp">
 | 
			
		||||
                                                            <span class="onoffswitch-inner"></span>
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +200,7 @@
 | 
			
		|||
                                            </tr>
 | 
			
		||||
                                        </form>
 | 
			
		||||
 | 
			
		||||
                                        {% for group in user_object.groups.all %}
 | 
			
		||||
                                        {% for group in user.groups.all %}
 | 
			
		||||
                                        <tr>
 | 
			
		||||
                                          <td ><b class="bdg_user_group" data-gid={{ group.id }}>{{ group.name }}</b></td>
 | 
			
		||||
                                          <td>
 | 
			
		||||
| 
						 | 
				
			
			@ -222,9 +225,9 @@
 | 
			
		|||
jumpserver.selected_groups = {};
 | 
			
		||||
 | 
			
		||||
function updateUserGroups(user_groups) {
 | 
			
		||||
    var the_url = "{% url 'users:group-user-edit-api' pk=user_object.id %}";
 | 
			
		||||
{#    var the_url = "{% url 'users:group-user-edit-api' pk=user.id %}";#}
 | 
			
		||||
    var body = {
 | 
			
		||||
        id: {{ user_object.id }},
 | 
			
		||||
        id: {{ user.id }},
 | 
			
		||||
        groups: Object.assign([], user_groups)
 | 
			
		||||
    };
 | 
			
		||||
    var success = function(data) {
 | 
			
		||||
| 
						 | 
				
			
			@ -262,8 +265,8 @@ $(document).ready(function() {
 | 
			
		|||
            delete jumpserver.selected_groups[data.id]
 | 
			
		||||
        })
 | 
			
		||||
}).on('click', '#is_active', function() {
 | 
			
		||||
    var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
 | 
			
		||||
    var checked = !$(this).prop('checked');
 | 
			
		||||
    var the_url = "{% url 'users:api-user-detail' pk=user.id %}";
 | 
			
		||||
    var checked = $(this).prop('checked');
 | 
			
		||||
    var body = {
 | 
			
		||||
        'is_active': checked
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -274,8 +277,8 @@ $(document).ready(function() {
 | 
			
		|||
        success_message: success
 | 
			
		||||
    });
 | 
			
		||||
}).on('click', '#enable_otp', function() {
 | 
			
		||||
    var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
 | 
			
		||||
    var checked = !$(this).prop('checked');
 | 
			
		||||
    var the_url = "{% url 'users:api-user-detail' pk=user.id %}";
 | 
			
		||||
    var checked = $(this).prop('checked');
 | 
			
		||||
    var body = {
 | 
			
		||||
        'enable_otp': checked
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -313,10 +316,10 @@ $(document).ready(function() {
 | 
			
		|||
    updateUserGroups(user_groups)
 | 
			
		||||
}).on('click', '#btn_reset_password', function() {
 | 
			
		||||
    function doReset() {
 | 
			
		||||
        var the_url = '{% url "users:user-reset-password-api" pk=user_object.id %}';
 | 
			
		||||
        var the_url = '{% url "users:user-reset-password-api" pk=user.id %}';
 | 
			
		||||
        var body = {};
 | 
			
		||||
        var success = function() {
 | 
			
		||||
            var msg = "{% trans 'E-mail sent successfully. An e-mail has been sent to the user\'s mailbox.' %}";
 | 
			
		||||
            var msg = "{% trans "An e-mail has been sent to the user\'s mailbox." %}";
 | 
			
		||||
            swal("{% trans 'Password-Reset' %}", msg, "success");
 | 
			
		||||
        };
 | 
			
		||||
        APIUpdateAttr({
 | 
			
		||||
| 
						 | 
				
			
			@ -338,7 +341,7 @@ $(document).ready(function() {
 | 
			
		|||
    });
 | 
			
		||||
}).on('click', '#btn_reset_pk', function() {
 | 
			
		||||
    function doReset() {
 | 
			
		||||
        var the_url = '{% url "users:user-reset-pk-api" pk=user_object.id %}';
 | 
			
		||||
{#        var the_url = '{% url "users:user-reset-pk-api" pk=user.id %}';#}
 | 
			
		||||
        var body = {};
 | 
			
		||||
        var success = function() {
 | 
			
		||||
            var msg = "{% trans 'The reset-ssh-public-key E-mail has been sent successfully. Please inform the user to update his new ssh public key.' %}";
 | 
			
		||||
| 
						 | 
				
			
			@ -364,7 +367,7 @@ $(document).ready(function() {
 | 
			
		|||
}).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 the_url = '{% url "users:user-update-pk-api" pk=user.id %}';#}
 | 
			
		||||
    var body = {'_public_key': pk};
 | 
			
		||||
    var success = function() {
 | 
			
		||||
        $('#txt_pk').val('');
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ $(document).ready(function(){
 | 
			
		|||
                    $(td).html(update_btn + del_btn)
 | 
			
		||||
                }
 | 
			
		||||
             }}],
 | 
			
		||||
        ajax_url: '{% url "users:user-bulk-update-api" %}',
 | 
			
		||||
        ajax_url: '{% url "users:api-user-list" %}',
 | 
			
		||||
        columns: [{data: function(){return ""}}, {data: "username" }, {data: "name" }, {data: "get_role_display" }, {data: "group_display" },
 | 
			
		||||
                  {data: function(){return 999}}, {data: "active_display" }, {data: "id" }],
 | 
			
		||||
        op_html: $('#actions').html()
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +90,7 @@ $(document).ready(function(){
 | 
			
		|||
    if (id_list === []) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    var the_url = "{% url 'users:user-bulk-update-api' %}";
 | 
			
		||||
    var the_url = "{% url 'users:api-user-list' %}";
 | 
			
		||||
    function doDeactive() {
 | 
			
		||||
        var body = $.each(id_list, function(index, user_object) {
 | 
			
		||||
            user_object['is_active'] = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +143,7 @@ $(document).ready(function(){
 | 
			
		|||
    var $this = $(this);
 | 
			
		||||
    function doDelete() {
 | 
			
		||||
        var uid = $this.data('uid');
 | 
			
		||||
        var the_url = '{% url "users:user-patch-api" pk=99991937 %}'.replace('99991937', uid);
 | 
			
		||||
        var the_url = '{% url "users:api-user-detail" pk=99991937 %}'.replace('99991937', uid);
 | 
			
		||||
        var body = {};
 | 
			
		||||
        var success = function() {
 | 
			
		||||
            var msg = "{% trans 'User Deleted.' %}";
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +198,7 @@ $(document).ready(function(){
 | 
			
		|||
    if (post_list === []) {
 | 
			
		||||
        return false
 | 
			
		||||
    }
 | 
			
		||||
    var the_url = "{% url 'users:user-bulk-update-api' %}";
 | 
			
		||||
    var the_url = "{% url 'users:api-user-list' %}";
 | 
			
		||||
    var success = function() {
 | 
			
		||||
        var msg = "{% trans 'The selected users has been updated successfully.' %}";
 | 
			
		||||
        swal("{% trans 'User Updated' %}", msg, "success");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
from django.conf.urls import url
 | 
			
		||||
 | 
			
		||||
from rest_framework_bulk.routes import BulkRouter
 | 
			
		||||
import views
 | 
			
		||||
import api
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ urlpatterns = [
 | 
			
		|||
    url(r'^password/reset$', views.UserResetPasswordView.as_view(), name='reset-password'),
 | 
			
		||||
    url(r'^password/reset/success$', views.UserResetPasswordSuccessView.as_view(),
 | 
			
		||||
        name='reset-password-success'),
 | 
			
		||||
    # User view
 | 
			
		||||
    url(r'^user$', views.UserListView.as_view(), name='user-list'),
 | 
			
		||||
    url(r'^user/(?P<pk>[0-9]+)$', views.UserDetailView.as_view(), name='user-detail'),
 | 
			
		||||
    url(r'^user/(?P<pk>[0-9]+)/asset-permission$', views.UserAssetPermissionView.as_view(),
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +28,8 @@ urlpatterns = [
 | 
			
		|||
    url(r'^user/(?P<pk>[0-9]+)/assets-perm$', views.UserDetailView.as_view(), name='user-detail'),
 | 
			
		||||
    url(r'^user/create$', views.UserCreateView.as_view(), name='user-create'),
 | 
			
		||||
    url(r'^user/(?P<pk>[0-9]+)/update$', views.UserUpdateView.as_view(), name='user-update'),
 | 
			
		||||
 | 
			
		||||
    # User group view
 | 
			
		||||
    url(r'^user-group$', views.UserGroupListView.as_view(), name='user-group-list'),
 | 
			
		||||
    url(r'^user-group/(?P<pk>[0-9]+)$', views.UserGroupDetailView.as_view(), name='user-group-detail'),
 | 
			
		||||
    url(r'^user-group/create$', views.UserGroupCreateView.as_view(), name='user-group-create'),
 | 
			
		||||
| 
						 | 
				
			
			@ -34,17 +37,23 @@ urlpatterns = [
 | 
			
		|||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
router = BulkRouter()
 | 
			
		||||
router.register(r'v1/users', api.UserViewSet, 'api-user')
 | 
			
		||||
# router.register(r'v1/user-groups', api.AssetViewSet, 'api-groups')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
urlpatterns += [
 | 
			
		||||
    url(r'^v1/users/$', api.UserListUpdateApi.as_view(), name='user-bulk-update-api'),
 | 
			
		||||
    url(r'^v1/users/token/$', api.UserTokenApi.as_view(), name='user-token-api'),
 | 
			
		||||
    url(r'^v1/users/(?P<pk>\d+)/$', api.UserDetailApi.as_view(), name='user-patch-api'),
 | 
			
		||||
    # url(r'^v1/users/$', api.UserListUpdateApi.as_view(), name='user-bulk-update-api'),
 | 
			
		||||
    url(r'^v1/users/token/$', api.UserAuthApi.as_view(), name='user-token-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.GroupListUpdateApi.as_view(), name='user-group-bulk-update-api'),
 | 
			
		||||
    url(r'^v1/user-groups/(?P<pk>\d+)/$', api.GroupDetailApi.as_view(), name='user-group-detail-api'),
 | 
			
		||||
    url(r'^v1/user-groups/(?P<pk>\d+)/user/(?P<uid>\d+)/$',
 | 
			
		||||
        api.DeleteUserFromGroupApi.as_view(), name='delete-user-from-group-api'),
 | 
			
		||||
    url(r'^v1/user-groups/(?P<pk>\d+)/users/$',
 | 
			
		||||
        api.UserAndGroupEditApi.as_view(), name='group-user-edit-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.GroupListUpdateApi.as_view(), name='user-group-bulk-update-api'),
 | 
			
		||||
    # url(r'^v1/user-groups/(?P<pk>\d+)/$', api.GroupDetailApi.as_view(), name='user-group-detail-api'),
 | 
			
		||||
    # url(r'^v1/user-groups/(?P<pk>\d+)/user/(?P<uid>\d+)/$',
 | 
			
		||||
    #     api.DeleteUserFromGroupApi.as_view(), name='delete-user-from-group-api'),
 | 
			
		||||
    # url(r'^v1/user-groups/(?P<pk>\d+)/users/$',
 | 
			
		||||
    #     api.UserAndGroupEditApi.as_view(), name='group-user-edit-api'),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
urlpatterns += router.urls
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,7 +78,7 @@ def send_reset_password_mail(user):
 | 
			
		|||
    </br>
 | 
			
		||||
    <a href="%(rest_password_url)s?token=%(rest_password_token)s">Click here reset password</a>
 | 
			
		||||
    </br>
 | 
			
		||||
    This link is valid for 1 hour. After it expires, <a href="%(forget_password_url)s?email=%(email)s">request new one<</a>
 | 
			
		||||
    This link is valid for 1 hour. After it expires, <a href="%(forget_password_url)s?email=%(email)s">request new one</a>
 | 
			
		||||
 | 
			
		||||
    </br>
 | 
			
		||||
    ---
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ class UserLoginView(FormView):
 | 
			
		|||
 | 
			
		||||
@method_decorator(never_cache, name='dispatch')
 | 
			
		||||
class UserLogoutView(TemplateView):
 | 
			
		||||
    template_name = 'common/flash_message_standalone.html'
 | 
			
		||||
    template_name = 'flash_message_standalone.html'
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        auth_logout(request)
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +142,7 @@ class UserUpdateView(AdminUserRequiredMixin, UpdateView):
 | 
			
		|||
class UserDetailView(AdminUserRequiredMixin, DetailView):
 | 
			
		||||
    model = User
 | 
			
		||||
    template_name = 'users/user_detail.html'
 | 
			
		||||
    context_object_name = "user_object"
 | 
			
		||||
    context_object_name = "user"
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        groups = UserGroup.objects.exclude(id__in=self.object.groups.all())
 | 
			
		||||
| 
						 | 
				
			
			@ -239,7 +239,7 @@ class UserForgotPasswordView(TemplateView):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class UserForgotPasswordSendmailSuccessView(TemplateView):
 | 
			
		||||
    template_name = 'common/flash_message_standalone.html'
 | 
			
		||||
    template_name = 'flash_message_standalone.html'
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = {
 | 
			
		||||
| 
						 | 
				
			
			@ -252,7 +252,7 @@ class UserForgotPasswordSendmailSuccessView(TemplateView):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class UserResetPasswordSuccessView(TemplateView):
 | 
			
		||||
    template_name = 'common/flash_message_standalone.html'
 | 
			
		||||
    template_name = 'flash_message_standalone.html'
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue