def put(self, request, uid): dept_ids = request.data.get('dept_ids', []) depts = Dept.get_from_pks(pks=dept_ids, pk_name='id', raise_exception=True, is_del=False) Dept.sort_as(depts) return Response({'error_code': 0})
def sort_depts_in_dept(self, depts, parent_dept): ''' 调整一批部门在父部门中的排序 ''' for dept in depts: if dept.parent != parent_dept: raise ValidationError({'node': ['unrelated']}) Dept.sort_as(depts)
def create_dept(self, dept_info): ''' 创建部门 ''' serializer = DeptDetailSerializer(data=dept_info) serializer.is_valid(raise_exception=True) serializer.save() dept = serializer.instance dept.order_no = Dept.get_max_order_no(parent=dept.parent) + 1 dept.save() # 批量创建组权限 # 1) 去重 perm_ids = Perm.valid_objects.values_list('pk', flat=True) exist_perm_ids = DeptPerm.valid_objects.filter( owner=serializer.instance).values_list('perm_id', flat=True) perm_ids = set(perm_ids).difference(exist_perm_ids) # 2) 批量创建 dept_perms = [ DeptPerm(owner=serializer.instance, perm_id=x) for x in perm_ids ] DeptPerm.objects.bulk_create(dept_perms) return serializer.instance
def get_access_result(self, instance): ''' 某个节点或人,有无访问该应用的权限 ''' request = self.context['request'] owner = None node_uid = request.query_params.get('node_uid', '') if node_uid: node, _ = Dept.retrieve_node(node_uid) if not node: raise ValidationError({'node_uid': ['not found']}) owner = node user_uid = request.query_params.get('user_uid', '') if user_uid: user = User.valid_objects.filter(username=user_uid).first() if not user: raise ValidationError({'user_uid': ['not found']}) owner = user return { 'node_uid': node_uid, 'user_uid': user_uid, 'value': owner.owner_perm_cls.get(perm=instance.access_perm, owner=owner).value if owner else False, }
def update(self, request, *args, **kwargs): # pylint: disable=unused-argument, too-many-locals ''' 黑白名单局部操作 ''' perm = self.get_object() clean = self.request.data.get('clean', False) if clean: UserPerm.valid_objects.filter(perm=perm).update(status='0') DeptPerm.valid_objects.filter(perm=perm).update(status='0') GroupPerm.valid_objects.filter(perm=perm).update(status='0') user_perm_status = self.request.data.get('user_perm_status', []) for ups in user_perm_status: user = User.valid_objects.filter(username=ups['uid']).first() if user: owner_perm = UserPerm.get(user, perm) owner_perm.update_status(ups['status']) node_perm_status = self.request.data.get('node_perm_status', []) for nps in node_perm_status: node, _ = Dept.retrieve_node(nps['uid']) if node: node_perm = node.owner_perm_cls.get(node, perm) node_perm.update_status(nps['status']) cli = LOG_CLI() cli.assign_perm_owners(perm) return Response({ 'user_perm_status': user_perm_status, 'node_perm_status': node_perm_status })
def patch(self, request, *args, **kwargs): # pylint: disable=unused-argument ''' 调整子部门 [PATCH] 目前应只需要排序和移入 ''' parent_dept = self.get_object() data = json.loads(request.body.decode('utf-8')) subject = data.get('subject', '') if subject not in ['sort', 'add']: raise ValidationError( {'subject': ['this field must be `sort` or `add`']}) filters = {} if subject == 'sort': filters = {'parent': parent_dept} dept_uids = get_patch_scope(request) try: depts = Dept.get_from_pks(pks=dept_uids, pk_name='uid', raise_exception=True, **filters) except ObjectDoesNotExist as error: bad_uid = error.args[0] raise ValidationError( {'dept_uids': ['dept:{} invalid'.format(bad_uid)]}) cli = CLI() if subject == 'sort': cli.sort_depts_in_dept(depts, parent_dept) elif subject == 'add': for dept in depts: cli.move_dept_to_dept(dept, parent_dept) return Response(DeptListSerializer(parent_dept).data)
def test_patch_perm_owner(self): self.client.json_patch(reverse('siteapi:perm_owner', args=(PERM_UID, )), data={ 'node_perm_status': [{ 'uid': 'd_root', 'status': -1 }], }) dept, _ = Dept.retrieve_node('d_root') owner_perm = dept.owner_perm_cls.get(dept, self.perm) self.assertFalse(owner_perm.value) self.client.json_patch(reverse('siteapi:perm_owner', args=(PERM_UID, )), data={ 'user_perm_status': [{ 'uid': 'admin', 'status': -1 }], }) user = User.objects.get(username='******') owner_perm = user.owner_perm_cls.get(user, self.perm) self.assertFalse(owner_perm.value) res = self.client.json_patch(reverse('siteapi:perm_owner', args=(PERM_UID, )), data={ 'node_perm_status': [{ 'uid': 'd_root', 'status': 1 }], 'user_perm_status': [{ 'uid': 'admin', 'status': 1 }], }) dept, _ = Dept.retrieve_node('d_root') owner_perm = dept.owner_perm_cls.get(dept, self.perm) self.assertTrue(owner_perm.value) user = User.objects.get(username='******') owner_perm = user.owner_perm_cls.get(user, self.perm) self.assertTrue(owner_perm.value)
def move_dept_to_dept(self, dept, parent_dept): ''' 将一个已有部门移至另一部门下 ''' if dept == parent_dept or parent_dept.if_belong_to_dept( dept, recursive=True): raise ValidationError({'node': ['deadlock']}) dept.order_no = Dept.get_max_order_no(parent=parent_dept) + 1 dept.parent = parent_dept dept.save(update_fields=['order_no', 'parent'])
def flush_dept_perm(dept=None, perms=None): ''' 从上往下刷新部门权限 ''' if not dept: dept = Dept.get_root() DeptCash.get_dept(dept.id) DeptPerm.valid_objects.filter(owner=dept) return _flush_node_perm(node_cls=Dept, perm_cls=DeptPerm, start_node=dept, perms=perms)
def get_depts_from_uids(dept_uids): ''' 根据dept uid按顺序返回dept list ''' try: depts = Dept.get_from_pks(pks=dept_uids, pk_name='uid', raise_exception=True, is_del=False) except ObjectDoesNotExist as error: bad_uid = error.args[0] raise ValidationError( {'dept_uids': ['dept:{} does not exist'.format(bad_uid)]}) return depts
def create_dept(self, dept_info): ''' 创建部门 ''' serializer = DeptDetailSerializer(data=dept_info) serializer.is_valid(raise_exception=True) serializer.save() dept = serializer.instance dept.order_no = Dept.get_max_order_no(parent=dept.parent) + 1 dept.save() for perm in Perm.valid_objects.all(): DeptPerm.valid_objects.create(owner=serializer.instance, perm=perm) return dept
def update(self, request, *args, **kwargs): # pylint: disable=unused-argument, too-many-locals ''' 黑白名单局部操作 ''' perm = self.get_object() clean = self.request.data.get('clean', False) if clean: UserPerm.valid_objects.filter(perm=perm).update(status='0') DeptPerm.valid_objects.filter(perm=perm).update(status='0') GroupPerm.valid_objects.filter(perm=perm).update(status='0') user_perm_status = self.request.data.get('user_perm_status', []) node_perm_status = self.request.data.get('node_perm_status', []) if not isinstance(user_perm_status, list): raise ValidationError({'user_perm_status': ['must be a list']}) if not isinstance(node_perm_status, list): raise ValidationError({'node_perm_status': ['must be a list']}) for ups in user_perm_status: user = User.valid_objects.filter(username=ups['uid']).first() # TODO: 目前对每个对象都逐一检验 under_manage,开销大; 且对于没有权限的,只是静默跳过,没有提示。需改进。 if not (user and user.under_manage(request.user)): raise ValidationError( {'user_perm_status': [f'invalid uid: `{ups["uid"]}`']}) ups['instance'] = user for nps in node_perm_status: node, _ = Dept.retrieve_node(nps['uid']) if not (node and node.under_manage(request.user)): raise ValidationError( {'node_perm_status': [f'invalid uid: `{nps["uid"]}`']}) nps['instance'] = node for ups in user_perm_status: instance = ups.pop('instance') owner_perm = UserPerm.get(instance, perm) owner_perm.update_status(ups['status']) for nps in node_perm_status: instance = nps.pop('instance') owner_perm = instance.owner_perm_cls.get(instance, perm) owner_perm.update_status(nps['status']) cli = LOG_CLI() cli.assign_perm_owners(perm) return Response({ 'user_perm_status': user_perm_status, 'node_perm_status': node_perm_status })
def get_queryset(self): # pylint: disable=too-many-locals ''' get app list ''' kwargs = {} name = self.request.query_params.get('name', '') if name: kwargs = {'name__icontains': name} # 可管理范围 manager_app_uids = set() for manager_group in self.request.user.manager_groups: manager_app_uids.update(set(manager_group.apps)) kwargs['uid__in'] = manager_app_uids if self.request.user.is_admin: kwargs.pop('uid__in') manager_app_uids = None # 筛选-对owner可访问 owner = None access_app_uids = None node_uid = self.request.query_params.get('node_uid', None) if node_uid: node, _ = Dept.retrieve_node(node_uid) if not node: raise ValidationError({'node_uid': ['not found']}) owner = node user_uid = self.request.query_params.get('user_uid', None) if user_uid: user = User.valid_objects.filter(username=user_uid).first() if not user: raise ValidationError({'user_uid': ['not found']}) owner = user if owner: owner_access = self.request.query_params.get('owner_access', None) if owner_access is not None: # 一些基础的access判断 if owner_access in (True, 'true', 'True'): value = True elif owner_access in (False, 'false', 'False'): value = False else: raise ValidationError( {'owner_access': ['must be a boolean']}) scope_kwargs = {} if manager_app_uids is None else { 'perm__scope__in': manager_app_uids } if value is True and not user_uid is None: # 获取的是用户指定应用的权限 uids = [ item['perm__scope'] for item in UserPerm.valid_objects.filter( owner=owner, value=True, perm__subject='app', perm__action__startswith='access', ).values('perm__scope') ] # 获取的是指定应用部门的权限 data = [] dms = DeptMember.valid_objects.filter(user=owner) result = APP.valid_objects.filter( **kwargs).order_by('-created') for item in result: uid = item.uid if item.allow_any_user is True: if item.uuid not in data: data.append(item.uuid) else: if uid in uids: if item.uuid not in data: data.append(item.uuid) else: # 取的当前分组的所拥有的部门和当前用户的部门进行比对 perms = Perm.valid_objects.filter( scope=uid, subject='app', action__startswith='access').order_by('id') for perm in perms: deps = DeptPerm.valid_objects.filter( status=1, perm=perm) for dep in deps: owner = dep.owner # 用户的部门是否属于指定的部门 for dm in dms: dm_owner = dm.owner if dm_owner == owner: if item.uuid not in data: data.append(item.uuid) else: if dm_owner.if_belong_to_dept( owner, True) is True: if item.uuid not in data: data.append(item.uuid) return APP.valid_objects.filter( uuid__in=data).order_by('-created') else: access_app_uids = [ item['perm__scope'] for item in owner.owner_perm_cls.valid_objects.filter( owner=owner, perm__subject='app', perm__action='access', value=value, **scope_kwargs, ).values('perm__scope') ] kwargs['uid__in'] = access_app_uids apps = APP.valid_objects.filter(**kwargs).exclude( uid='oneid').order_by('-created') return apps
def get_queryset(self): ''' get app list ''' kwargs = {} name = self.request.query_params.get('name', '') if name: kwargs = {'name__icontains': name} # 可管理范围 manager_app_uids = set() for manager_group in self.request.user.manager_groups: manager_app_uids.update(set(manager_group.apps)) kwargs['uid__in'] = manager_app_uids if self.request.user.is_admin: kwargs.pop('uid__in') manager_app_uids = None # 筛选-对owner可访问 owner = None access_app_uids = None node_uid = self.request.query_params.get('node_uid', None) if node_uid: node, _ = Dept.retrieve_node(node_uid) if not node: raise ValidationError({'node_uid': ['not found']}) owner = node user_uid = self.request.query_params.get('user_uid', None) if user_uid: user = User.valid_objects.filter(username=user_uid).first() if not user: raise ValidationError({'user_uid': ['not found']}) owner = user if owner: owner_access = self.request.query_params.get('owner_access', None) if owner_access is not None: if owner_access in (True, 'true', 'True'): value = True elif owner_access in (False, 'false', 'False'): value = False else: raise ValidationError( {'owner_access': ['must be a boolean']}) scope_kwargs = {} if manager_app_uids is None else { 'perm__scope__in': manager_app_uids } access_app_uids = [ item['perm__scope'] for item in owner.owner_perm_cls.valid_objects.filter( owner=owner, perm__subject='app', perm__action='access', value=value, **scope_kwargs, ).values('perm__scope') ] kwargs['uid__in'] = access_app_uids apps = APP.valid_objects.filter(**kwargs).exclude( uid='oneid').order_by('-created') return apps