feat: 后端增加各个权限点的接入

pull/49/head
moonrailgun 3 years ago
parent 2662d154c6
commit b976a3b734

@ -153,6 +153,15 @@
color: rgba(255, 255, 255, 0.65);
}
}
.ant-dropdown-menu-item-disabled, .ant-dropdown-menu-submenu-title-disabled {
color: rgba(255, 255, 255, 0.25);
&:hover {
color: rgba(255, 255, 255, 0.25);
background-color: transparent;
}
}
}
}

@ -74,5 +74,23 @@ export function call(ctx: TcContext) {
groupId,
});
},
/**
*
*/
async checkUserPermissions(
groupId: string,
userId: string,
permissions: string[]
): Promise<boolean[]> {
const userAllPermissions: string[] = await ctx.call(
'group.getUserAllPermissions',
{
groupId,
userId,
}
);
return permissions.map((p) => (userAllPermissions ?? []).includes(p));
},
};
}

@ -0,0 +1,17 @@
export const PERMISSION = {
/**
* core
*/
core: {
owner: '__group_owner__', // 保留字段, 用于标识群组所有者
message: 'core.message',
invite: 'core.invite',
unlimitedInvite: 'core.unlimitedInvite',
groupDetail: 'core.groupDetail',
managePanel: 'core.managePanel',
manageInvite: 'core.manageInvite',
manageRoles: 'core.manageRoles',
},
};
export const allPermission = [...Object.values(PERMISSION.core)];

@ -10,6 +10,7 @@ import {
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';
import _ from 'lodash';
import { Types } from 'mongoose';
import { allPermission } from '../../lib/role';
import { User } from '../user/user';
export enum GroupPanelType {
@ -196,19 +197,13 @@ export class Group extends TimeStamps implements Base {
this: ReturnModelType<typeof Group>,
groupId: string,
roleId: string,
roleName: string,
operatorUserId: string
roleName: string
): Promise<Group> {
const group = await this.findById(groupId);
if (!group) {
throw new Error('Not Found Group');
}
// 首先判断是否有修改权限的权限
if (String(group.owner) !== operatorUserId) {
throw new Error('No Permission');
}
const modifyRole = group.roles.find((role) => String(role._id) === roleId);
if (!modifyRole) {
throw new Error('Not Found Role');
@ -227,19 +222,13 @@ export class Group extends TimeStamps implements Base {
this: ReturnModelType<typeof Group>,
groupId: string,
roleId: string,
permissions: string[],
operatorUserId: string
permissions: string[]
): Promise<Group> {
const group = await this.findById(groupId);
if (!group) {
throw new Error('Not Found Group');
}
// 首先判断是否有修改权限的权限
if (String(group.owner) !== operatorUserId) {
throw new Error('No Permission');
}
const modifyRole = group.roles.find((role) => String(role._id) === roleId);
if (!modifyRole) {
throw new Error('Not Found Role');
@ -264,6 +253,11 @@ export class Group extends TimeStamps implements Base {
throw new Error('Not Found Group');
}
if (String(group.owner) === userId) {
// 群组管理者有所有权限
return [...allPermission];
}
const member = group.members.find(
(member) => String(member.userId) === userId
);

@ -22,6 +22,7 @@ import {
} from 'tailchat-server-sdk';
import { call } from '../../../lib/call';
import moment from 'moment';
import { PERMISSION } from '../../../lib/role';
interface GroupService
extends TcService,
@ -320,14 +321,30 @@ class GroupService extends TcService {
throw new EntityError(t('该数据不允许修改'));
}
const group = await this.adapter.model.findById(groupId).exec();
if (String(group.owner) !== userId) {
throw new NoPermissionError();
const [isGroupOwner, hasRolePermission] = await call(
ctx
).checkUserPermissions(groupId, userId, [
PERMISSION.core.owner,
PERMISSION.core.manageRoles,
]);
if (fieldName === 'fallbackPermissions') {
if (!hasRolePermission) {
throw new NoPermissionError(t('没有操作权限'));
}
} else if (!isGroupOwner) {
throw new NoPermissionError(t('不是群组管理员无法编辑'));
}
const group = await this.adapter.model.findById(groupId).exec();
group[fieldName] = fieldValue;
await group.save();
if (fieldName === 'fallbackPermissions') {
await this.cleanGroupAllUserPermissionCache(groupId);
}
this.notifyGroupInfoUpdate(ctx, group);
}
@ -472,15 +489,12 @@ class GroupService extends TcService {
const { groupId, memberIds, roles } = ctx.params;
const { t, userId } = ctx.meta;
const isOwner: boolean = await this.actions['isGroupOwner'](
{
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
},
{
parentCtx: ctx,
}
userId,
[PERMISSION.core.manageRoles]
);
if (!isOwner) {
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
@ -520,15 +534,12 @@ class GroupService extends TcService {
const { groupId, memberIds, roles } = ctx.params;
const { t, userId } = ctx.meta;
const isOwner: boolean = await this.actions['isGroupOwner'](
{
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
},
{
parentCtx: ctx,
}
userId,
[PERMISSION.core.manageRoles]
);
if (!isOwner) {
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
@ -570,17 +581,15 @@ class GroupService extends TcService {
) {
const { groupId, name, type, parentId, provider, pluginPanelName, meta } =
ctx.params;
const { t } = ctx.meta;
const isOwner: boolean = await this.actions['isGroupOwner'](
{
const { t, userId } = ctx.meta;
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
},
{
parentCtx: ctx,
}
userId,
[PERMISSION.core.managePanel]
);
if (!isOwner) {
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
@ -626,16 +635,14 @@ class GroupService extends TcService {
) {
const { groupId, panelId, name, provider, pluginPanelName, meta } =
ctx.params;
const { t } = ctx.meta;
const isOwner: boolean = await this.actions['isGroupOwner'](
{
const { t, userId } = ctx.meta;
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
},
{
parentCtx: ctx,
}
userId,
[PERMISSION.core.managePanel]
);
if (!isOwner) {
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
@ -674,16 +681,14 @@ class GroupService extends TcService {
*/
async deleteGroupPanel(ctx: TcContext<{ groupId: string; panelId: string }>) {
const { groupId, panelId } = ctx.params;
const { t } = ctx.meta;
const isOwner: boolean = await this.actions['isGroupOwner'](
{
const { t, userId } = ctx.meta;
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
},
{
parentCtx: ctx,
}
userId,
[PERMISSION.core.managePanel]
);
if (!isOwner) {
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
@ -746,19 +751,27 @@ class GroupService extends TcService {
ctx: TcContext<{ groupId: string; roleName: string; permissions: string[] }>
) {
const { groupId, roleName, permissions } = ctx.params;
const userId = ctx.meta.userId;
const { userId, t } = ctx.meta;
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
userId,
[PERMISSION.core.managePanel]
);
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
const group = await this.adapter.model
.findOneAndUpdate(
{
_id: new Types.ObjectId(groupId),
owner: new Types.ObjectId(userId),
},
{
$push: {
roles: {
name: roleName,
permissions: [],
permissions,
},
},
},
@ -777,13 +790,21 @@ class GroupService extends TcService {
*/
async deleteGroupRole(ctx: TcContext<{ groupId: string; roleId: string }>) {
const { groupId, roleId } = ctx.params;
const userId = ctx.meta.userId;
const { userId, t } = ctx.meta;
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
userId,
[PERMISSION.core.managePanel]
);
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
const group = await this.adapter.model
.findOneAndUpdate(
{
_id: new Types.ObjectId(groupId),
owner: new Types.ObjectId(userId),
},
{
$pull: {
@ -813,13 +834,21 @@ class GroupService extends TcService {
}>
) {
const { groupId, roleId, roleName } = ctx.params;
const userId = ctx.meta.userId;
const { userId, t } = ctx.meta;
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
userId,
[PERMISSION.core.managePanel]
);
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
const group = await this.adapter.model.updateGroupRoleName(
groupId,
roleId,
roleName,
userId
roleName
);
const json = await this.notifyGroupInfoUpdate(ctx, group);
@ -837,13 +866,21 @@ class GroupService extends TcService {
}>
) {
const { groupId, roleId, permissions } = ctx.params;
const userId = ctx.meta.userId;
const { userId, t } = ctx.meta;
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
userId,
[PERMISSION.core.managePanel]
);
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
const group = await this.adapter.model.updateGroupRolePermission(
groupId,
roleId,
permissions,
userId
permissions
);
const json = await this.notifyGroupInfoUpdate(ctx, group);
@ -871,6 +908,7 @@ class GroupService extends TcService {
/**
* ()
* groupIduserId
*/
async getUserAllPermissions(
ctx: TcContext<{
@ -963,6 +1001,14 @@ class GroupService extends TcService {
private cleanGroupUserPermission(groupId: string, userId: string) {
this.cleanActionCache('getUserAllPermissions', [groupId, userId]);
}
/**
*
* @param groupId id
*/
private cleanGroupAllUserPermissionCache(groupId: string) {
this.cleanActionCache('getUserAllPermissions', [groupId]);
}
}
export default GroupService;

@ -12,6 +12,7 @@ import {
TcDbService,
PureContext,
} from 'tailchat-server-sdk';
import { PERMISSION } from '../../../lib/role';
interface GroupService
extends TcService,
@ -62,21 +63,21 @@ class GroupService extends TcService {
inviteType: 'normal' | 'permanent';
}>
): Promise<GroupInvite> {
const groupId = ctx.params.groupId;
const inviteType = ctx.params.inviteType;
const userId = ctx.meta.userId;
const t = ctx.meta.t;
// TODO: 基于RBAC判定群组权限
// 先视为仅群组所有者可以创建群组邀请
const isGroupOwner = await ctx.call<boolean, { groupId: string }>(
'group.isGroupOwner',
{
groupId,
}
);
if (isGroupOwner !== true) {
throw new NoPermissionError(t('不是群组所有者, 没有分享权限'));
const { groupId, inviteType } = ctx.params;
const { userId, t } = ctx.meta;
const [hasNormalPermission, hasUnlimitedPermission] = await call(
ctx
).checkUserPermissions(groupId, userId, [
PERMISSION.core.invite,
PERMISSION.core.unlimitedInvite,
]);
if (
(inviteType === 'normal' && !hasNormalPermission) ||
(inviteType === 'permanent' && !hasUnlimitedPermission)
) {
throw new NoPermissionError(t('没有创建邀请码权限'));
}
const invite = await this.adapter.model.createGroupInvite(
@ -96,18 +97,15 @@ class GroupService extends TcService {
}>
) {
const groupId = ctx.params.groupId;
const t = ctx.meta.t;
const { t, userId } = ctx.meta;
// TODO: 基于RBAC判定群组权限
// 先视为仅群组所有者可以创建群组邀请
const isGroupOwner = await ctx.call<boolean, { groupId: string }>(
'group.isGroupOwner',
{
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
}
userId,
[PERMISSION.core.manageInvite]
);
if (isGroupOwner !== true) {
throw new NoPermissionError(t('不是群组所有者, 没有查看权限'));
if (!hasPermission) {
throw new NoPermissionError(t('没有查看权限'));
}
const list = await this.adapter.model.find({
@ -170,18 +168,15 @@ class GroupService extends TcService {
async deleteInvite(ctx: TcContext<{ groupId: string; inviteId: string }>) {
const groupId = ctx.params.groupId;
const inviteId = ctx.params.inviteId;
const t = ctx.meta.t;
const { t, userId } = ctx.meta;
// TODO: 基于RBAC判定群组权限
// 先视为仅群组所有者可以创建群组邀请
const isGroupOwner = await ctx.call<boolean, { groupId: string }>(
'group.isGroupOwner',
{
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
}
userId,
[PERMISSION.core.manageInvite]
);
if (isGroupOwner !== true) {
throw new NoPermissionError(t('不是群组所有者, 没有查看权限'));
if (!hasPermission) {
throw new NoPermissionError(t('没有删除权限'));
}
await this.adapter.model.deleteOne({

Loading…
Cancel
Save