diff --git a/spug_api/apps/account/models.py b/spug_api/apps/account/models.py index ea7615b..047a0f9 100644 --- a/spug_api/apps/account/models.py +++ b/spug_api/apps/account/models.py @@ -18,8 +18,8 @@ class User(models.Model, ModelMixin): token_expired = models.IntegerField(null=True) last_login = models.CharField(max_length=20) last_ip = models.CharField(max_length=50) - role = models.ForeignKey('Role', on_delete=models.PROTECT, null=True) wx_token = models.CharField(max_length=50, null=True) + roles = models.ManyToManyField('Role', db_table='user_role_rel') created_at = models.CharField(max_length=20, default=human_datetime) created_by = models.ForeignKey('User', models.PROTECT, related_name='+', null=True) @@ -35,26 +35,32 @@ class User(models.Model, ModelMixin): @property def page_perms(self): - if self.role and self.role.page_perms: - data = [] - perms = json.loads(self.role.page_perms) - for m, v in perms.items(): - for p, d in v.items(): - data.extend(f'{m}.{p}.{x}' for x in d) - return data - else: - return [] + data = set() + for item in self.roles.all(): + if item.page_perms: + perms = json.loads(item.page_perms) + for m, v in perms.items(): + for p, d in v.items(): + data.update(f'{m}.{p}.{x}' for x in d) + return list(data) @property def deploy_perms(self): - perms = json.loads(self.role.deploy_perms) if self.role and self.role.deploy_perms else {} - perms.setdefault('apps', []) - perms.setdefault('envs', []) - return perms + data = {'apps': set(), 'envs': set()} + for item in self.roles.all(): + if item.deploy_perms: + perms = json.loads(item.deploy_perms) + data['apps'].update(perms.get('apps', [])) + data['envs'].update(perms.get('envs', [])) + return data @property def group_perms(self): - return json.loads(self.role.group_perms) if self.role and self.role.group_perms else [] + data = set() + for item in self.roles.all(): + if item.group_perms: + data.update(json.loads(item.group_perms)) + return list(data) def has_perms(self, codes): # return self.is_supper or self.role in codes diff --git a/spug_api/apps/account/views.py b/spug_api/apps/account/views.py index a8cdfc9..3eebac7 100644 --- a/spug_api/apps/account/views.py +++ b/spug_api/apps/account/views.py @@ -3,7 +3,6 @@ # Released under the AGPL-3.0 License. from django.core.cache import cache from django.views.generic import View -from django.db.models import F from libs import JsonParser, Argument, human_datetime, json_response from libs.utils import get_request_real_ip, generate_random_str from libs.spug import send_login_wx_code @@ -19,49 +18,54 @@ import json class UserView(View): def get(self, request): users = [] - for u in User.objects.filter(deleted_by_id__isnull=True).annotate(role_name=F('role__name')): + for u in User.objects.filter(deleted_by_id__isnull=True): tmp = u.to_dict(excludes=('access_token', 'password_hash')) - tmp['role_name'] = u.role_name + tmp['role_ids'] = [x.id for x in u.roles.all()] + tmp['password'] = '******' users.append(tmp) return json_response(users) def post(self, request): form, error = JsonParser( + Argument('id', type=int, required=False), Argument('username', help='请输入登录名'), Argument('password', help='请输入密码'), Argument('nickname', help='请输入姓名'), - Argument('role_id', type=int, help='请选择角色'), + Argument('role_ids', type=list, default=[]), Argument('wx_token', required=False), ).parse(request.body) if error is None: - if User.objects.filter(username=form.username, deleted_by_id__isnull=True).exists(): + user = User.objects.filter(username=form.username, deleted_by_id__isnull=True).first() + if user and (not form.id or form.id != user.id): return json_response(error=f'已存在登录名为【{form.username}】的用户') - form.password_hash = User.make_password(form.pop('password')) - form.created_by = request.user - User.objects.create(**form) + + role_ids, password = form.pop('role_ids'), form.pop('password') + if form.id: + User.objects.filter(pk=form.id).update(**form) + else: + User.objects.create( + password_hash=User.make_password(password), + created_by=request.user, + **form + ) + user.roles.set(role_ids) return json_response(error=error) def patch(self, request): form, error = JsonParser( - Argument('id', type=int, help='请指定操作对象'), - Argument('username', required=False), + Argument('id', type=int, help='参数错误'), Argument('password', required=False), - Argument('nickname', required=False), - Argument('role_id', required=False), - Argument('wx_token', required=False), Argument('is_active', type=bool, required=False), - ).parse(request.body, True) + ).parse(request.body) if error is None: - if form.get('password'): - form.token_expired = 0 - form.password_hash = User.make_password(form.pop('password')) - if 'username' in form: - if User.objects.filter(username=form.username, deleted_by_id__isnull=True).exclude(id=form.id).exists(): - return json_response(error=f'已存在登录名为【{form.username}】的用户') - if 'is_active' in form: - user = User.objects.get(pk=form.id) + user = User.objects.get(pk=form.id) + if form.password: + user.token_expired = 0 + user.password_hash = User.make_password(form.pop('password')) + if form.is_active is not None: + user.is_active = form.is_active cache.delete(user.username) - User.objects.filter(pk=form.pop('id')).update(**form) + user.save() return json_response(error=error) def delete(self, request): @@ -73,7 +77,7 @@ class UserView(View): if user: if user.type == 'ldap': return json_response(error='ldap账户无法删除,请使用禁用功能来禁止该账户访问系统') - user.role_id = None + user.is_active = True user.deleted_at = human_datetime() user.deleted_by = request.user user.save() @@ -124,9 +128,10 @@ class RoleView(View): Argument('id', type=int, help='参数错误') ).parse(request.GET) if error is None: - if User.objects.filter(role_id=form.id).exists(): + role = Role.objects.get(pk=form.id) + if role.user_set.exists(): return json_response(error='已有用户使用了该角色,请解除关联后再尝试删除') - Role.objects.filter(pk=form.id).delete() + role.delete() return json_response(error=error) diff --git a/spug_web/src/pages/system/account/Form.js b/spug_web/src/pages/system/account/Form.js index 5ae5461..cf9395a 100644 --- a/spug_web/src/pages/system/account/Form.js +++ b/spug_web/src/pages/system/account/Form.js @@ -24,18 +24,13 @@ export default observer(function () { function handleSubmit() { setLoading(true); const formData = form.getFieldsValue(); - let request; - if (store.record.id) { - formData['id'] = store.record.id; - request = http.patch('/api/account/user/', formData) - } else { - request = http.post('/api/account/user/', formData) - } - request.then(() => { - message.success('操作成功'); - store.formVisible = false; - store.fetchRecords() - }, () => setLoading(false)) + formData.id = store.record.id; + http.post('/api/account/user/', formData) + .then(() => { + message.success('操作成功'); + store.formVisible = false; + store.fetchRecords() + }, () => setLoading(false)) } return ( @@ -54,14 +49,12 @@ export default observer(function () {