Chore: Api definitions (#23701)
Co-authored-by: Tasso Evangelista <tasso.evangelista@rocket.chat>pull/23723/head
parent
f05d8932db
commit
a858dbc237
@ -1,87 +0,0 @@ |
||||
import type { ExtractKeys, ValueOf } from '../../../definition/utils'; |
||||
import type { EngagementDashboardEndpoints } from '../../../ee/client/contexts/ServerContext/endpoints/v1/engagementDashboard'; |
||||
import type { AppsEndpoints } from './endpoints/apps'; |
||||
import type { ChannelsEndpoints } from './endpoints/v1/channels'; |
||||
import type { ChatEndpoints } from './endpoints/v1/chat'; |
||||
import type { CloudEndpoints } from './endpoints/v1/cloud'; |
||||
import type { CustomUserStatusEndpoints } from './endpoints/v1/customUserStatus'; |
||||
import type { DmEndpoints } from './endpoints/v1/dm'; |
||||
import type { DnsEndpoints } from './endpoints/v1/dns'; |
||||
import type { EmojiCustomEndpoints } from './endpoints/v1/emojiCustom'; |
||||
import type { GroupsEndpoints } from './endpoints/v1/groups'; |
||||
import type { ImEndpoints } from './endpoints/v1/im'; |
||||
import type { LDAPEndpoints } from './endpoints/v1/ldap'; |
||||
import type { LicensesEndpoints } from './endpoints/v1/licenses'; |
||||
import type { MiscEndpoints } from './endpoints/v1/misc'; |
||||
import type { OmnichannelEndpoints } from './endpoints/v1/omnichannel'; |
||||
import type { RoomsEndpoints } from './endpoints/v1/rooms'; |
||||
import type { StatisticsEndpoints } from './endpoints/v1/statistics'; |
||||
import type { TeamsEndpoints } from './endpoints/v1/teams'; |
||||
import type { UsersEndpoints } from './endpoints/v1/users'; |
||||
|
||||
type Endpoints = ChatEndpoints & |
||||
ChannelsEndpoints & |
||||
CloudEndpoints & |
||||
CustomUserStatusEndpoints & |
||||
DmEndpoints & |
||||
DnsEndpoints & |
||||
EmojiCustomEndpoints & |
||||
GroupsEndpoints & |
||||
ImEndpoints & |
||||
LDAPEndpoints & |
||||
RoomsEndpoints & |
||||
TeamsEndpoints & |
||||
UsersEndpoints & |
||||
EngagementDashboardEndpoints & |
||||
AppsEndpoints & |
||||
OmnichannelEndpoints & |
||||
StatisticsEndpoints & |
||||
LicensesEndpoints & |
||||
MiscEndpoints; |
||||
|
||||
type Endpoint = UnionizeEndpoints<Endpoints>; |
||||
|
||||
type UnionizeEndpoints<EE extends Endpoints> = ValueOf< |
||||
{ |
||||
[P in keyof EE]: UnionizeMethods<P, EE[P]>; |
||||
} |
||||
>; |
||||
|
||||
type ExtractOperations<OO, M extends keyof OO> = ExtractKeys<OO, M, (...args: any[]) => any>; |
||||
|
||||
type UnionizeMethods<P, OO> = ValueOf< |
||||
{ |
||||
[M in keyof OO as ExtractOperations<OO, M>]: ( |
||||
method: M, |
||||
path: OO extends { path: string } ? OO['path'] : P, |
||||
...params: Parameters<Extract<OO[M], (...args: any[]) => any>> |
||||
) => ReturnType<Extract<OO[M], (...args: any[]) => any>>; |
||||
} |
||||
>; |
||||
|
||||
export type Method = Parameters<Endpoint>[0]; |
||||
export type Path = Parameters<Endpoint>[1]; |
||||
|
||||
export type MethodFor<P extends Path> = P extends any |
||||
? Parameters<Extract<Endpoint, (method: any, path: P, ...params: any[]) => any>>[0] |
||||
: never; |
||||
export type PathFor<M extends Method> = M extends any |
||||
? Parameters<Extract<Endpoint, (method: M, path: any, ...params: any[]) => any>>[1] |
||||
: never; |
||||
|
||||
type Operation<M extends Method, P extends PathFor<M>> = M extends any |
||||
? P extends any |
||||
? Extract<Endpoint, (method: M, path: P, ...params: any[]) => any> |
||||
: never |
||||
: never; |
||||
|
||||
type ExtractParams<Q> = Q extends [any, any] |
||||
? [undefined?] |
||||
: Q extends [any, any, any, ...any[]] |
||||
? [Q[2]] |
||||
: never; |
||||
|
||||
export type Params<M extends Method, P extends PathFor<M>> = ExtractParams< |
||||
Parameters<Operation<M, P>> |
||||
>; |
||||
export type Return<M extends Method, P extends PathFor<M>> = ReturnType<Operation<M, P>>; |
||||
@ -1,21 +0,0 @@ |
||||
import type { IRoom } from '../../../../../definition/IRoom'; |
||||
import type { IUser } from '../../../../../definition/IUser'; |
||||
|
||||
export type DmEndpoints = { |
||||
'dm.create': { |
||||
POST: ( |
||||
params: ( |
||||
| { |
||||
username: Exclude<IUser['username'], undefined>; |
||||
} |
||||
| { |
||||
usernames: string; |
||||
} |
||||
) & { |
||||
excludeSelf?: boolean; |
||||
}, |
||||
) => { |
||||
room: IRoom & { rid: IRoom['_id'] }; |
||||
}; |
||||
}; |
||||
}; |
||||
@ -1,76 +0,0 @@ |
||||
import type { IRoom } from '../../../../../definition/IRoom'; |
||||
import type { IRecordsWithTotal, ITeam } from '../../../../../definition/ITeam'; |
||||
import type { IUser } from '../../../../../definition/IUser'; |
||||
|
||||
export type TeamsEndpoints = { |
||||
'teams.addRooms': { |
||||
POST: (params: { rooms: IRoom['_id'][]; teamId: string }) => void; |
||||
}; |
||||
'teams.info': { |
||||
GET: (params: { teamId: IRoom['teamId'] }) => { teamInfo: ITeam }; |
||||
}; |
||||
'teams.listRooms': { |
||||
GET: (params: { |
||||
teamId: ITeam['_id']; |
||||
offset?: number; |
||||
count?: number; |
||||
filter: string; |
||||
type: string; |
||||
}) => Omit<IRecordsWithTotal<IRoom>, 'records'> & { |
||||
count: number; |
||||
offset: number; |
||||
rooms: IRecordsWithTotal<IRoom>['records']; |
||||
}; |
||||
}; |
||||
'teams.listRoomsOfUser': { |
||||
GET: (params: { |
||||
teamId: ITeam['_id']; |
||||
teamName?: string; |
||||
userId?: string; |
||||
canUserDelete?: boolean; |
||||
offset?: number; |
||||
count?: number; |
||||
}) => Omit<IRecordsWithTotal<IRoom>, 'records'> & { |
||||
count: number; |
||||
offset: number; |
||||
rooms: IRecordsWithTotal<IRoom>['records']; |
||||
}; |
||||
}; |
||||
'teams.create': { |
||||
POST: (params: { |
||||
name: ITeam['name']; |
||||
type?: ITeam['type']; |
||||
members?: IUser['_id'][]; |
||||
room: { |
||||
id?: string; |
||||
name?: IRoom['name']; |
||||
members?: IUser['_id'][]; |
||||
readOnly?: boolean; |
||||
extraData?: { |
||||
teamId?: string; |
||||
teamMain?: boolean; |
||||
} & { [key: string]: string | boolean }; |
||||
options?: { |
||||
nameValidationRegex?: string; |
||||
creator: string; |
||||
subscriptionExtra?: { |
||||
open: boolean; |
||||
ls: Date; |
||||
prid: IRoom['_id']; |
||||
}; |
||||
} & { |
||||
[key: string]: |
||||
| string |
||||
| { |
||||
open: boolean; |
||||
ls: Date; |
||||
prid: IRoom['_id']; |
||||
}; |
||||
}; |
||||
}; |
||||
owner?: IUser['_id']; |
||||
}) => { |
||||
team: ITeam; |
||||
}; |
||||
}; |
||||
}; |
||||
@ -1,3 +1,2 @@ |
||||
export * from './ServerContext'; |
||||
export * from './endpoints'; |
||||
export * from './methods'; |
||||
|
||||
@ -0,0 +1,4 @@ |
||||
export type PaginatedRequest = { |
||||
count: number; |
||||
offset: number; |
||||
}; |
||||
@ -0,0 +1,5 @@ |
||||
export type PaginatedResult = { |
||||
count: number; |
||||
offset: number; |
||||
total: number; |
||||
}; |
||||
@ -0,0 +1,97 @@ |
||||
import type { EnterpriseEndpoints } from '../../ee/definition/rest'; |
||||
import type { ExtractKeys, ValueOf } from '../utils'; |
||||
import type { AppsEndpoints } from './apps'; |
||||
import { BannersEndpoints } from './v1/banners'; |
||||
import type { ChannelsEndpoints } from './v1/channels'; |
||||
import type { ChatEndpoints } from './v1/chat'; |
||||
import type { CloudEndpoints } from './v1/cloud'; |
||||
import type { CustomUserStatusEndpoints } from './v1/customUserStatus'; |
||||
import type { DmEndpoints } from './v1/dm'; |
||||
import type { DnsEndpoints } from './v1/dns'; |
||||
import type { EmojiCustomEndpoints } from './v1/emojiCustom'; |
||||
import type { GroupsEndpoints } from './v1/groups'; |
||||
import type { ImEndpoints } from './v1/im'; |
||||
import { InstancesEndpoints } from './v1/instances'; |
||||
import type { LDAPEndpoints } from './v1/ldap'; |
||||
import type { LicensesEndpoints } from './v1/licenses'; |
||||
import type { MiscEndpoints } from './v1/misc'; |
||||
import type { OmnichannelEndpoints } from './v1/omnichannel'; |
||||
import { PermissionsEndpoints } from './v1/permissions'; |
||||
import { RolesEndpoints } from './v1/roles'; |
||||
import type { RoomsEndpoints } from './v1/rooms'; |
||||
import { SettingsEndpoints } from './v1/settings'; |
||||
import type { StatisticsEndpoints } from './v1/statistics'; |
||||
import type { TeamsEndpoints } from './v1/teams'; |
||||
import type { UsersEndpoints } from './v1/users'; |
||||
|
||||
type CommunityEndpoints = BannersEndpoints & ChatEndpoints & |
||||
ChannelsEndpoints & |
||||
CloudEndpoints & |
||||
CustomUserStatusEndpoints & |
||||
DmEndpoints & |
||||
DnsEndpoints & |
||||
EmojiCustomEndpoints & |
||||
GroupsEndpoints & |
||||
ImEndpoints & |
||||
LDAPEndpoints & |
||||
RoomsEndpoints & |
||||
RolesEndpoints & |
||||
TeamsEndpoints & |
||||
SettingsEndpoints & |
||||
UsersEndpoints & |
||||
AppsEndpoints & |
||||
OmnichannelEndpoints & |
||||
StatisticsEndpoints & |
||||
LicensesEndpoints & |
||||
MiscEndpoints & |
||||
PermissionsEndpoints & |
||||
InstancesEndpoints; |
||||
|
||||
export type Endpoints = CommunityEndpoints & EnterpriseEndpoints; |
||||
|
||||
type Endpoint = UnionizeEndpoints<Endpoints>; |
||||
|
||||
type UnionizeEndpoints<EE extends Endpoints> = ValueOf< |
||||
{ |
||||
[P in keyof EE]: UnionizeMethods<P, EE[P]>; |
||||
} |
||||
>; |
||||
|
||||
type ExtractOperations<OO, M extends keyof OO> = ExtractKeys<OO, M, (...args: any[]) => any>; |
||||
|
||||
type UnionizeMethods<P, OO> = ValueOf< |
||||
{ |
||||
[M in keyof OO as ExtractOperations<OO, M>]: ( |
||||
method: M, |
||||
path: OO extends { path: string } ? OO['path'] : P, |
||||
...params: Parameters<Extract<OO[M], (...args: any[]) => any>> |
||||
) => ReturnType<Extract<OO[M], (...args: any[]) => any>>; |
||||
} |
||||
>; |
||||
|
||||
export type Method = Parameters<Endpoint>[0]; |
||||
export type Path = Parameters<Endpoint>[1]; |
||||
|
||||
export type MethodFor<P extends Path> = P extends any |
||||
? Parameters<Extract<Endpoint, (method: any, path: P, ...params: any[]) => any>>[0] |
||||
: never; |
||||
export type PathFor<M extends Method> = M extends any |
||||
? Parameters<Extract<Endpoint, (method: M, path: any, ...params: any[]) => any>>[1] |
||||
: never; |
||||
|
||||
type Operation<M extends Method, P extends PathFor<M>> = M extends any |
||||
? P extends any |
||||
? Extract<Endpoint, (method: M, path: P, ...params: any[]) => any> |
||||
: never |
||||
: never; |
||||
|
||||
type ExtractParams<Q> = Q extends [any, any] |
||||
? [undefined?] |
||||
: Q extends [any, any, any, ...any[]] |
||||
? [Q[2]] |
||||
: never; |
||||
|
||||
export type Params<M extends Method, P extends PathFor<M>> = ExtractParams< |
||||
Parameters<Operation<M, P>> |
||||
>; |
||||
export type Return<M extends Method, P extends PathFor<M>> = ReturnType<Operation<M, P>>; |
||||
@ -0,0 +1,26 @@ |
||||
import { IBanner } from '../../IBanner'; |
||||
|
||||
export type BannersEndpoints = { |
||||
/* @deprecated */ |
||||
'banners.getNew': { |
||||
GET: () => ({ |
||||
banners: IBanner[]; |
||||
}); |
||||
}; |
||||
|
||||
'banners/:id': { |
||||
GET: (params: { platform: string }) => ({ |
||||
banners: IBanner[]; |
||||
}); |
||||
}; |
||||
|
||||
'banners': { |
||||
GET: () => ({ |
||||
banners: IBanner[]; |
||||
}); |
||||
}; |
||||
|
||||
'banners.dismiss': { |
||||
POST: (params: { bannerId: string }) => void; |
||||
}; |
||||
}; |
||||
@ -1,6 +1,6 @@ |
||||
import type { IMessage } from '../../../../../definition/IMessage/IMessage'; |
||||
import type { IRoom } from '../../../../../definition/IRoom'; |
||||
import type { IUser } from '../../../../../definition/IUser'; |
||||
import type { IMessage } from '../../IMessage/IMessage'; |
||||
import type { IRoom } from '../../IRoom'; |
||||
import type { IUser } from '../../IUser'; |
||||
|
||||
export type ChannelsEndpoints = { |
||||
'channels.files': { |
||||
@ -1,5 +1,5 @@ |
||||
import type { IMessage } from '../../../../../definition/IMessage'; |
||||
import type { IRoom } from '../../../../../definition/IRoom'; |
||||
import type { IMessage } from '../../IMessage'; |
||||
import type { IRoom } from '../../IRoom'; |
||||
|
||||
export type ChatEndpoints = { |
||||
'chat.getMessage': { |
||||
@ -0,0 +1,21 @@ |
||||
import type { IRoom } from '../../IRoom'; |
||||
import type { IUser } from '../../IUser'; |
||||
|
||||
export type DmEndpoints = { |
||||
'dm.create': { |
||||
POST: ( |
||||
params: ( |
||||
| { |
||||
username: Exclude<IUser['username'], undefined>; |
||||
} |
||||
| { |
||||
usernames: string; |
||||
} |
||||
) & { |
||||
excludeSelf?: boolean; |
||||
}, |
||||
) => { |
||||
room: IRoom & { rid: IRoom['_id'] }; |
||||
}; |
||||
}; |
||||
}; |
||||
@ -1,4 +1,4 @@ |
||||
import type { ICustomEmojiDescriptor } from '../../../../../definition/ICustomEmojiDescriptor'; |
||||
import type { ICustomEmojiDescriptor } from '../../ICustomEmojiDescriptor'; |
||||
|
||||
export type EmojiCustomEndpoints = { |
||||
'emoji-custom.list': { |
||||
@ -1,6 +1,6 @@ |
||||
import type { IMessage } from '../../../../../definition/IMessage'; |
||||
import type { IRoom } from '../../../../../definition/IRoom'; |
||||
import type { IUser } from '../../../../../definition/IUser'; |
||||
import type { IMessage } from '../../IMessage'; |
||||
import type { IRoom } from '../../IRoom'; |
||||
import type { IUser } from '../../IUser'; |
||||
|
||||
export type GroupsEndpoints = { |
||||
'groups.files': { |
||||
@ -1,17 +1,17 @@ |
||||
import type { IMessage } from '../../../../../definition/IMessage'; |
||||
import type { IRoom } from '../../../../../definition/IRoom'; |
||||
import type { IUser } from '../../../../../definition/IUser'; |
||||
import type { IMessage } from '../../IMessage'; |
||||
import type { IRoom } from '../../IRoom'; |
||||
import type { IUser } from '../../IUser'; |
||||
|
||||
export type ImEndpoints = { |
||||
'im.create': { |
||||
POST: ( |
||||
params: ( |
||||
| { |
||||
username: Exclude<IUser['username'], undefined>; |
||||
} |
||||
username: Exclude<IUser['username'], undefined>; |
||||
} |
||||
| { |
||||
usernames: string; |
||||
} |
||||
usernames: string; |
||||
} |
||||
) & { |
||||
excludeSelf?: boolean; |
||||
}, |
||||
@ -0,0 +1,16 @@ |
||||
import { IInstanceStatus } from '../../IInstanceStatus'; |
||||
|
||||
export type InstancesEndpoints = { |
||||
'instances.get': { |
||||
GET: () => ({ |
||||
instances: (IInstanceStatus | { |
||||
connection: { |
||||
address: unknown; |
||||
currentStatus: unknown; |
||||
instanceRecord: unknown; |
||||
broadcastAuth: unknown; |
||||
}; |
||||
})[]; |
||||
}); |
||||
}; |
||||
}; |
||||
@ -1,9 +1,12 @@ |
||||
import type { ILicense } from '../../../../../ee/app/license/server/license'; |
||||
import type { ILicense } from '../../../ee/app/license/definitions/ILicense'; |
||||
|
||||
export type LicensesEndpoints = { |
||||
'licenses.get': { |
||||
GET: () => { licenses: Array<ILicense> }; |
||||
}; |
||||
'licenses.add': { |
||||
POST: (params: { license: string }) => void; |
||||
}; |
||||
'licenses.maxActiveUsers': { |
||||
GET: () => { maxActiveUsers: number | null; activeUsers: number }; |
||||
}; |
||||
@ -0,0 +1,43 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
import { IPermission } from '../../IPermission'; |
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
type PermissionsUpdateProps = { permissions: { _id: string; roles: string[] }[] }; |
||||
|
||||
const permissionUpdatePropsSchema: JSONSchemaType<PermissionsUpdateProps> = { |
||||
type: 'object', |
||||
properties: { |
||||
permissions: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'object', |
||||
properties: { |
||||
_id: { type: 'string' }, |
||||
roles: { type: 'array', items: { type: 'string' }, uniqueItems: true }, |
||||
}, |
||||
additionalProperties: false, |
||||
required: ['_id', 'roles'], |
||||
}, |
||||
}, |
||||
}, |
||||
required: ['permissions'], |
||||
additionalProperties: false, |
||||
}; |
||||
|
||||
export const isBodyParamsValidPermissionUpdate = ajv.compile(permissionUpdatePropsSchema); |
||||
|
||||
export type PermissionsEndpoints = { |
||||
'permissions.listAll': { |
||||
GET: (params: { updatedSince?: string }) => ({ |
||||
update: IPermission[]; |
||||
remove: IPermission[]; |
||||
}); |
||||
}; |
||||
'permissions.update': { |
||||
POST: (params: PermissionsUpdateProps) => ({ |
||||
permissions: IPermission[]; |
||||
}); |
||||
}; |
||||
}; |
||||
@ -0,0 +1,186 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
import { IRole, IUser } from '../../IUser'; |
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
type RoleCreateProps = Pick<IRole, 'name'> & Partial<Pick<IRole, 'description' | 'scope' |'mandatory2fa' >>; |
||||
|
||||
const roleCreatePropsSchema: JSONSchemaType<RoleCreateProps> = { |
||||
type: 'object', |
||||
properties: { |
||||
name: { |
||||
type: 'string', |
||||
}, |
||||
description: { |
||||
type: 'string', |
||||
nullable: true, |
||||
}, |
||||
scope: { |
||||
type: 'string', |
||||
enum: ['Users', 'Subscriptions'], |
||||
nullable: true, |
||||
}, |
||||
mandatory2fa: { |
||||
type: 'boolean', |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['name'], |
||||
additionalProperties: false, |
||||
}; |
||||
|
||||
export const isRoleCreateProps = ajv.compile(roleCreatePropsSchema); |
||||
|
||||
type RoleUpdateProps = { roleId: IRole['_id']; name: IRole['name'] } & Partial<RoleCreateProps>; |
||||
|
||||
const roleUpdatePropsSchema: JSONSchemaType<RoleUpdateProps> = { |
||||
type: 'object', |
||||
properties: { |
||||
roleId: { |
||||
type: 'string', |
||||
}, |
||||
name: { |
||||
type: 'string', |
||||
}, |
||||
description: { |
||||
type: 'string', |
||||
nullable: true, |
||||
}, |
||||
scope: { |
||||
type: 'string', |
||||
enum: ['Users', 'Subscriptions'], |
||||
nullable: true, |
||||
}, |
||||
mandatory2fa: { |
||||
type: 'boolean', |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['roleId', 'name'], |
||||
additionalProperties: false, |
||||
}; |
||||
|
||||
export const isRoleUpdateProps = ajv.compile(roleUpdatePropsSchema); |
||||
|
||||
type RoleDeleteProps = { roleId: IRole['_id'] }; |
||||
|
||||
const roleDeletePropsSchema: JSONSchemaType<RoleDeleteProps> = { |
||||
type: 'object', |
||||
properties: { |
||||
roleId: { |
||||
type: 'string', |
||||
}, |
||||
}, |
||||
required: ['roleId'], |
||||
additionalProperties: false, |
||||
}; |
||||
|
||||
export const isRoleDeleteProps = ajv.compile(roleDeletePropsSchema); |
||||
|
||||
type RoleAddUserToRoleProps = { |
||||
username: string; |
||||
roleName: string; |
||||
roomId?: string; |
||||
} |
||||
|
||||
const roleAddUserToRolePropsSchema: JSONSchemaType<RoleAddUserToRoleProps> = { |
||||
type: 'object', |
||||
properties: { |
||||
username: { |
||||
type: 'string', |
||||
}, |
||||
roleName: { |
||||
type: 'string', |
||||
}, |
||||
roomId: { |
||||
type: 'string', |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['username', 'roleName'], |
||||
additionalProperties: false, |
||||
}; |
||||
|
||||
|
||||
export const isRoleAddUserToRoleProps = ajv.compile(roleAddUserToRolePropsSchema); |
||||
|
||||
type RoleRemoveUserFromRoleProps = { |
||||
username: string; |
||||
roleName: string; |
||||
roomId?: string; |
||||
} |
||||
|
||||
const roleRemoveUserFromRolePropsSchema: JSONSchemaType<RoleRemoveUserFromRoleProps> = { |
||||
type: 'object', |
||||
properties: { |
||||
username: { |
||||
type: 'string', |
||||
}, |
||||
roleName: { |
||||
type: 'string', |
||||
}, |
||||
roomId: { |
||||
type: 'string', |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['username', 'roleName'], |
||||
additionalProperties: false, |
||||
}; |
||||
|
||||
export const isRoleRemoveUserFromRoleProps = ajv.compile(roleRemoveUserFromRolePropsSchema); |
||||
|
||||
type RoleSyncProps = { |
||||
updatedSince?: string; |
||||
} |
||||
|
||||
export type RolesEndpoints = { |
||||
'roles.list': { |
||||
GET: () => ({ |
||||
roles: IRole[]; |
||||
}); |
||||
}; |
||||
'roles.sync': { |
||||
GET: (params: RoleSyncProps) => ({ |
||||
roles: { |
||||
update: IRole[]; |
||||
remove: IRole[]; |
||||
}; |
||||
}); |
||||
}; |
||||
'roles.create': { |
||||
POST: (params: RoleCreateProps) => ({ |
||||
role: IRole; |
||||
}); |
||||
}; |
||||
|
||||
'roles.addUserToRole': { |
||||
POST: (params: RoleAddUserToRoleProps) => ({ |
||||
role: IRole; |
||||
}); |
||||
}; |
||||
|
||||
'roles.getUsersInRole': { |
||||
GET: (params: { roomId: string; role: string; offset: number; count: number }) => ({ |
||||
users: IUser[]; |
||||
total: number; |
||||
}); |
||||
}; |
||||
|
||||
'roles.update': { |
||||
POST: (role: RoleUpdateProps) => ({ |
||||
role: IRole; |
||||
}); |
||||
}; |
||||
|
||||
'roles.delete': { |
||||
POST: (prop: RoleDeleteProps) => void; |
||||
}; |
||||
|
||||
'roles.removeUserFromRole': { |
||||
POST: (props: RoleRemoveUserFromRoleProps) => ({ |
||||
role: IRole; |
||||
}); |
||||
}; |
||||
}; |
||||
@ -1,6 +1,6 @@ |
||||
import type { IMessage } from '../../../../../definition/IMessage'; |
||||
import type { IRoom } from '../../../../../definition/IRoom'; |
||||
import type { IUser } from '../../../../../definition/IUser'; |
||||
import type { IMessage } from '../../IMessage'; |
||||
import type { IRoom } from '../../IRoom'; |
||||
import type { IUser } from '../../IUser'; |
||||
|
||||
export type RoomsEndpoints = { |
||||
'rooms.autocomplete.channelAndPrivate': { |
||||
@ -0,0 +1,100 @@ |
||||
import { ISetting, ISettingColor } from '../../ISetting'; |
||||
import { PaginatedResult } from '../helpers/PaginatedResult'; |
||||
|
||||
type SettingsUpdateProps = SettingsUpdatePropDefault | SettingsUpdatePropsActions | SettingsUpdatePropsColor; |
||||
|
||||
type SettingsUpdatePropsActions = { |
||||
execute: boolean; |
||||
} |
||||
|
||||
export type OauthCustomConfiguration = { |
||||
_id: string; |
||||
clientId?: string; |
||||
custom: unknown; |
||||
service?: string; |
||||
serverURL: unknown; |
||||
tokenPath: unknown; |
||||
identityPath: unknown; |
||||
authorizePath: unknown; |
||||
scope: unknown; |
||||
loginStyle: unknown; |
||||
tokenSentVia: unknown; |
||||
identityTokenSentVia: unknown; |
||||
keyField: unknown; |
||||
usernameField: unknown; |
||||
emailField: unknown; |
||||
nameField: unknown; |
||||
avatarField: unknown; |
||||
rolesClaim: unknown; |
||||
groupsClaim: unknown; |
||||
mapChannels: unknown; |
||||
channelsMap: unknown; |
||||
channelsAdmin: unknown; |
||||
mergeUsers: unknown; |
||||
mergeRoles: unknown; |
||||
accessTokenParam: unknown; |
||||
showButton: unknown; |
||||
|
||||
appId: unknown; |
||||
consumerKey?: string; |
||||
|
||||
clientConfig: unknown; |
||||
buttonLabelText: unknown; |
||||
buttonLabelColor: unknown; |
||||
buttonColor: unknown; |
||||
} |
||||
|
||||
export const isOauthCustomConfiguration = (config: any): config is OauthCustomConfiguration => Boolean(config); |
||||
|
||||
export const isSettingsUpdatePropsActions = (props: Partial<SettingsUpdateProps>): props is SettingsUpdatePropsActions => 'execute' in props; |
||||
|
||||
type SettingsUpdatePropsColor = { |
||||
editor: ISettingColor['editor']; |
||||
value: ISetting['value']; |
||||
} |
||||
|
||||
export const isSettingsUpdatePropsColor = (props: Partial<SettingsUpdateProps>): props is SettingsUpdatePropsColor => 'editor' in props && 'value' in props; |
||||
|
||||
type SettingsUpdatePropDefault = { |
||||
value: ISetting['value']; |
||||
} |
||||
|
||||
export const isSettingsUpdatePropDefault = (props: Partial<SettingsUpdateProps>): props is SettingsUpdatePropDefault => 'value' in props; |
||||
|
||||
export type SettingsEndpoints = { |
||||
'settings.public': { |
||||
GET: () => PaginatedResult & { |
||||
settings: Array<ISetting>; |
||||
}; |
||||
}; |
||||
|
||||
'settings.oauth': { |
||||
GET: () => ({ |
||||
services: Partial<OauthCustomConfiguration>[]; |
||||
}); |
||||
}; |
||||
|
||||
'settings.addCustomOAuth': { |
||||
POST: (params: { name: string }) => void; |
||||
}; |
||||
|
||||
'settings': { |
||||
GET: () => ({ |
||||
settings: ISetting[]; |
||||
}); |
||||
}; |
||||
|
||||
'settings/:_id': { |
||||
GET: () => Pick<ISetting, '_id' | 'value'>; |
||||
POST: (params: SettingsUpdateProps) => void; |
||||
}; |
||||
|
||||
'service.configurations': { |
||||
GET: () => { |
||||
configurations: Array<{ |
||||
appId: string; |
||||
secret: string; |
||||
}>; |
||||
}; |
||||
}; |
||||
}; |
||||
@ -1,4 +1,4 @@ |
||||
import type { IStats } from '../../../../../definition/IStats'; |
||||
import type { IStats } from '../../IStats'; |
||||
|
||||
export type StatisticsEndpoints = { |
||||
statistics: { |
||||
@ -0,0 +1,71 @@ |
||||
/* eslint-env mocha */ |
||||
import chai from 'chai'; |
||||
|
||||
import { isTeamsAddMembersProps } from './TeamsAddMembersProps'; |
||||
|
||||
describe('TeamsAddMemberProps (definition/rest/v1)', () => { |
||||
describe('isTeamsAddMembersProps', () => { |
||||
it('should be a function', () => { |
||||
chai.assert.isFunction(isTeamsAddMembersProps); |
||||
}); |
||||
it('should return false if the parameter is empty', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({})); |
||||
}); |
||||
|
||||
it('should return false if teamId is provided but no member was provided', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ teamId: '123' })); |
||||
}); |
||||
|
||||
it('should return false if teamName is provided but no member was provided', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ teamName: '123' })); |
||||
}); |
||||
|
||||
it('should return false if members is provided but no teamId or teamName were provided', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ members: [{ userId: '123' }] })); |
||||
}); |
||||
|
||||
it('should return false if teamName was provided but members are empty', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ teamName: '123', members: [] })); |
||||
}); |
||||
|
||||
it('should return false if teamId was provided but members are empty', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ teamId: '123', members: [] })); |
||||
}); |
||||
|
||||
it('should return false if members with role is provided but no teamId or teamName were provided', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ members: [{ userId: '123', roles: ['123'] }] })); |
||||
}); |
||||
|
||||
it('should return true if members is provided and teamId is provided', () => { |
||||
chai.assert.isTrue(isTeamsAddMembersProps({ members: [{ userId: '123' }], teamId: '123' })); |
||||
}); |
||||
|
||||
it('should return true if members is provided and teamName is provided', () => { |
||||
chai.assert.isTrue(isTeamsAddMembersProps({ members: [{ userId: '123' }], teamName: '123' })); |
||||
}); |
||||
|
||||
it('should return true if members with role is provided and teamId is provided', () => { |
||||
chai.assert.isTrue(isTeamsAddMembersProps({ members: [{ userId: '123', roles: ['123'] }], teamId: '123' })); |
||||
}); |
||||
|
||||
it('should return true if members with role is provided and teamName is provided', () => { |
||||
chai.assert.isTrue(isTeamsAddMembersProps({ members: [{ userId: '123', roles: ['123'] }], teamName: '123' })); |
||||
}); |
||||
|
||||
it('should return false if teamName was provided and members contains an invalid property', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ teamName: '123', members: [{ userId: '123', roles: ['123'], invalid: true }] })); |
||||
}); |
||||
|
||||
it('should return false if teamId was provided and members contains an invalid property', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ teamId: '123', members: [{ userId: '123', roles: ['123'], invalid: true }] })); |
||||
}); |
||||
|
||||
it('should return false if teamName informed but contains an invalid property', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ member: [{ userId: '123', roles: ['123'] }], teamName: '123', invalid: true })); |
||||
}); |
||||
|
||||
it('should return false if teamId informed but contains an invalid property', () => { |
||||
chai.assert.isFalse(isTeamsAddMembersProps({ member: [{ userId: '123', roles: ['123'] }], teamId: '123', invalid: true })); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,80 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
import { ITeamMemberParams } from '../../../../server/sdk/types/ITeamService'; |
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
export type TeamsAddMembersProps = ({ teamId: string } | { teamName: string }) & { members: ITeamMemberParams[] }; |
||||
|
||||
const teamsAddMembersPropsSchema: JSONSchemaType<TeamsAddMembersProps> = { |
||||
oneOf: [ |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamId: { |
||||
type: 'string', |
||||
}, |
||||
members: { |
||||
type: 'array', |
||||
items: { |
||||
|
||||
type: 'object', |
||||
properties: { |
||||
userId: { |
||||
type: 'string', |
||||
}, |
||||
roles: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['userId'], |
||||
additionalProperties: false, |
||||
}, |
||||
minItems: 1, |
||||
uniqueItems: true, |
||||
}, |
||||
}, |
||||
required: ['teamId', 'members'], |
||||
additionalProperties: false, |
||||
}, |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamName: { |
||||
type: 'string', |
||||
}, |
||||
members: { |
||||
type: 'array', |
||||
items: { |
||||
|
||||
type: 'object', |
||||
properties: { |
||||
userId: { |
||||
type: 'string', |
||||
}, |
||||
roles: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['userId'], |
||||
additionalProperties: false, |
||||
}, |
||||
minItems: 1, |
||||
uniqueItems: true, |
||||
}, |
||||
}, |
||||
required: ['teamName', 'members'], |
||||
additionalProperties: false, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export const isTeamsAddMembersProps = ajv.compile(teamsAddMembersPropsSchema); |
||||
@ -0,0 +1,39 @@ |
||||
/* eslint-env mocha */ |
||||
import chai from 'chai'; |
||||
|
||||
import { isTeamsConvertToChannelProps } from './TeamsConvertToChannelProps'; |
||||
|
||||
describe('TeamsConvertToChannelProps (definition/rest/v1)', () => { |
||||
describe('isTeamsConvertToChannelProps', () => { |
||||
it('should be a function', () => { |
||||
chai.assert.isFunction(isTeamsConvertToChannelProps); |
||||
}); |
||||
it('should return false if neither teamName or teamId is provided', () => { |
||||
chai.assert.isFalse(isTeamsConvertToChannelProps({})); |
||||
}); |
||||
|
||||
it('should return true if teamName is provided', () => { |
||||
chai.assert.isTrue(isTeamsConvertToChannelProps({ teamName: 'teamName' })); |
||||
}); |
||||
|
||||
it('should return true if teamId is provided', () => { |
||||
chai.assert.isTrue(isTeamsConvertToChannelProps({ teamId: 'teamId' })); |
||||
}); |
||||
|
||||
it('should return false if both teamName and teamId are provided', () => { |
||||
chai.assert.isFalse(isTeamsConvertToChannelProps({ teamName: 'teamName', teamId: 'teamId' })); |
||||
}); |
||||
|
||||
it('should return false if teamName is not a string', () => { |
||||
chai.assert.isFalse(isTeamsConvertToChannelProps({ teamName: 1 })); |
||||
}); |
||||
|
||||
it('should return false if teamId is not a string', () => { |
||||
chai.assert.isFalse(isTeamsConvertToChannelProps({ teamId: 1 })); |
||||
}); |
||||
|
||||
it('should return false if an additionalProperties is provided', () => { |
||||
chai.assert.isFalse(isTeamsConvertToChannelProps({ teamName: 'teamName', additionalProperties: 'additionalProperties' })); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,54 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
export type TeamsConvertToChannelProps = { |
||||
roomsToRemove?: string[]; |
||||
} & ({ teamId: string } | { teamName: string }); |
||||
|
||||
const teamsConvertToTeamsPropsSchema: JSONSchemaType<TeamsConvertToChannelProps> = { |
||||
oneOf: [ |
||||
{ |
||||
type: 'object', |
||||
|
||||
properties: { |
||||
roomsToRemove: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
nullable: true, |
||||
}, |
||||
teamId: { |
||||
type: 'string', |
||||
}, |
||||
}, |
||||
required: [ |
||||
'teamId', |
||||
], |
||||
additionalProperties: false, |
||||
}, |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
roomsToRemove: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
nullable: true, |
||||
}, |
||||
teamName: { |
||||
type: 'string', |
||||
}, |
||||
}, |
||||
required: [ |
||||
'teamName', |
||||
], |
||||
additionalProperties: false, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export const isTeamsConvertToChannelProps = ajv.compile(teamsConvertToTeamsPropsSchema); |
||||
@ -0,0 +1,64 @@ |
||||
/* eslint-env mocha */ |
||||
import chai from 'chai'; |
||||
|
||||
import { isTeamsDeleteProps } from './TeamsDeleteProps'; |
||||
|
||||
describe('TeamsDeleteProps (definition/rest/v1)', () => { |
||||
describe('isTeamsDeleteProps', () => { |
||||
it('should be a function', () => { |
||||
chai.assert.isFunction(isTeamsDeleteProps); |
||||
}); |
||||
|
||||
it('should return false if neither teamName or teamId is provided', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({})); |
||||
}); |
||||
|
||||
it('should return true if teamId is provided', () => { |
||||
chai.assert.isTrue(isTeamsDeleteProps({ teamId: 'teamId' })); |
||||
}); |
||||
|
||||
it('should return true if teamName is provided', () => { |
||||
chai.assert.isTrue(isTeamsDeleteProps({ teamName: 'teamName' })); |
||||
}); |
||||
|
||||
it('should return false if teamId and roomsToRemove are provided, but roomsToRemove is empty', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({ teamId: 'teamId', roomsToRemove: [] })); |
||||
}); |
||||
|
||||
it('should return false if teamName and roomsToRemove are provided, but roomsToRemove is empty', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({ teamName: 'teamName', roomsToRemove: [] })); |
||||
}); |
||||
|
||||
it('should return true if teamId and roomsToRemove are provided', () => { |
||||
chai.assert.isTrue(isTeamsDeleteProps({ teamId: 'teamId', roomsToRemove: ['roomId'] })); |
||||
}); |
||||
|
||||
it('should return true if teamName and roomsToRemove are provided', () => { |
||||
chai.assert.isTrue(isTeamsDeleteProps({ teamName: 'teamName', roomsToRemove: ['roomId'] })); |
||||
}); |
||||
|
||||
it('should return false if teamId and roomsToRemove are provided, but roomsToRemove is not an array', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({ teamId: 'teamId', roomsToRemove: {} })); |
||||
}); |
||||
|
||||
it('should return false if teamName and roomsToRemove are provided, but roomsToRemove is not an array', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({ teamName: 'teamName', roomsToRemove: {} })); |
||||
}); |
||||
|
||||
it('should return false if teamId and roomsToRemove are provided, but roomsToRemove is not an array of strings', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({ teamId: 'teamId', roomsToRemove: [1] })); |
||||
}); |
||||
|
||||
it('should return false if teamName and roomsToRemove are provided, but roomsToRemove is not an array of strings', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({ teamName: 'teamName', roomsToRemove: [1] })); |
||||
}); |
||||
|
||||
it('should return false if teamName and rooms are provided but an extra property is provided', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({ teamName: 'teamName', roomsToRemove: ['roomsToRemove'], extra: 'extra' })); |
||||
}); |
||||
|
||||
it('should return false if teamId and rooms are provided but an extra property is provided', () => { |
||||
chai.assert.isFalse(isTeamsDeleteProps({ teamId: 'teamId', roomsToRemove: ['roomsToRemove'], extra: 'extra' })); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,50 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
export type TeamsDeleteProps = ({ teamId: string } | { teamName: string }) & { roomsToRemove?: string[] }; |
||||
|
||||
const teamsDeletePropsSchema: JSONSchemaType<TeamsDeleteProps> = { |
||||
oneOf: [ |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamId: { |
||||
type: 'string', |
||||
}, |
||||
roomsToRemove: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
minItems: 1, |
||||
uniqueItems: true, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['teamId'], |
||||
additionalProperties: false, |
||||
}, |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamName: { |
||||
type: 'string', |
||||
}, |
||||
roomsToRemove: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
minItems: 1, |
||||
uniqueItems: true, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['teamName'], |
||||
additionalProperties: false, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export const isTeamsDeleteProps = ajv.compile(teamsDeletePropsSchema); |
||||
@ -0,0 +1,64 @@ |
||||
/* eslint-env mocha */ |
||||
import chai from 'chai'; |
||||
|
||||
import { isTeamsLeaveProps } from './TeamsLeaveProps'; |
||||
|
||||
describe('TeamsLeaveProps (definition/rest/v1)', () => { |
||||
describe('isTeamsLeaveProps', () => { |
||||
it('should be a function', () => { |
||||
chai.assert.isFunction(isTeamsLeaveProps); |
||||
}); |
||||
|
||||
it('should return false if neither teamName or teamId is provided', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({})); |
||||
}); |
||||
|
||||
it('should return true if teamId is provided', () => { |
||||
chai.assert.isTrue(isTeamsLeaveProps({ teamId: 'teamId' })); |
||||
}); |
||||
|
||||
it('should return true if teamName is provided', () => { |
||||
chai.assert.isTrue(isTeamsLeaveProps({ teamName: 'teamName' })); |
||||
}); |
||||
|
||||
it('should return false if teamId and roomsToRemove are provided, but roomsToRemove is empty', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({ teamId: 'teamId', rooms: [] })); |
||||
}); |
||||
|
||||
it('should return false if teamName and rooms are provided, but rooms is empty', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({ teamName: 'teamName', rooms: [] })); |
||||
}); |
||||
|
||||
it('should return true if teamId and rooms are provided', () => { |
||||
chai.assert.isTrue(isTeamsLeaveProps({ teamId: 'teamId', rooms: ['roomId'] })); |
||||
}); |
||||
|
||||
it('should return true if teamName and rooms are provided', () => { |
||||
chai.assert.isTrue(isTeamsLeaveProps({ teamName: 'teamName', rooms: ['roomId'] })); |
||||
}); |
||||
|
||||
it('should return false if teamId and rooms are provided, but rooms is not an array', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({ teamId: 'teamId', rooms: {} })); |
||||
}); |
||||
|
||||
it('should return false if teamName and rooms are provided, but rooms is not an array', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({ teamName: 'teamName', rooms: {} })); |
||||
}); |
||||
|
||||
it('should return false if teamId and rooms are provided, but rooms is not an array of strings', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({ teamId: 'teamId', rooms: [1] })); |
||||
}); |
||||
|
||||
it('should return false if teamName and rooms are provided, but rooms is not an array of strings', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({ teamName: 'teamName', rooms: [1] })); |
||||
}); |
||||
|
||||
it('should return false if teamName and rooms are provided but an extra property is provided', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({ teamName: 'teamName', rooms: ['rooms'], extra: 'extra' })); |
||||
}); |
||||
|
||||
it('should return false if teamId and rooms are provided but an extra property is provided', () => { |
||||
chai.assert.isFalse(isTeamsLeaveProps({ teamId: 'teamId', rooms: ['rooms'], extra: 'extra' })); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,51 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
export type TeamsLeaveProps = ({ teamId: string } | { teamName: string }) & { rooms?: string[] }; |
||||
|
||||
const teamsLeavePropsSchema: JSONSchemaType<TeamsLeaveProps> = { |
||||
oneOf: [ |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamId: { |
||||
type: 'string', |
||||
}, |
||||
rooms: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
minItems: 1, |
||||
uniqueItems: true, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['teamId'], |
||||
additionalProperties: false, |
||||
}, |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamName: { |
||||
type: 'string', |
||||
}, |
||||
rooms: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
minItems: 1, |
||||
uniqueItems: true, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['teamName'], |
||||
additionalProperties: false, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export const isTeamsLeaveProps = ajv.compile(teamsLeavePropsSchema); |
||||
@ -0,0 +1,61 @@ |
||||
/* eslint-env mocha */ |
||||
import chai from 'chai'; |
||||
|
||||
import { isTeamsRemoveMemberProps } from './TeamsRemoveMemberProps'; |
||||
|
||||
describe('Teams (definition/rest/v1)', () => { |
||||
describe('isTeamsRemoveMemberProps', () => { |
||||
it('should be a function', () => { |
||||
chai.assert.isFunction(isTeamsRemoveMemberProps); |
||||
}); |
||||
it('should return false if parameter is empty', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({})); |
||||
}); |
||||
it('should return false if teamId is is informed but missing userId', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamId: 'teamId' })); |
||||
}); |
||||
it('should return false if teamName is is informed but missing userId', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamName: 'teamName' })); |
||||
}); |
||||
|
||||
it('should return true if teamId and userId are informed', () => { |
||||
chai.assert.isTrue(isTeamsRemoveMemberProps({ teamId: 'teamId', userId: 'userId' })); |
||||
}); |
||||
it('should return true if teamName and userId are informed', () => { |
||||
chai.assert.isTrue(isTeamsRemoveMemberProps({ teamName: 'teamName', userId: 'userId' })); |
||||
}); |
||||
|
||||
|
||||
it('should return false if teamName and userId are informed but rooms are empty', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamName: 'teamName', userId: 'userId', rooms: [] })); |
||||
}); |
||||
|
||||
it('should return false if teamId and userId are informed and rooms are empty', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamId: 'teamId', userId: 'userId', rooms: [] })); |
||||
}); |
||||
|
||||
it('should return false if teamId and userId are informed but rooms are empty', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamId: 'teamId', userId: 'userId', rooms: [] })); |
||||
}); |
||||
|
||||
it('should return true if teamId and userId are informed and rooms are informed', () => { |
||||
chai.assert.isTrue(isTeamsRemoveMemberProps({ teamId: 'teamId', userId: 'userId', rooms: ['room'] })); |
||||
}); |
||||
|
||||
it('should return false if teamId and userId are informed and rooms are informed but rooms is not an array of strings', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamId: 'teamId', userId: 'userId', rooms: [123] })); |
||||
}); |
||||
|
||||
it('should return false if teamName and userId are informed and rooms are informed but there is an extra property', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamName: 'teamName', userId: 'userId', rooms: ['room'], extra: 'extra' })); |
||||
}); |
||||
|
||||
it('should return false if teamId and userId are informed and rooms are informed but there is an extra property', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamId: 'teamId', userId: 'userId', rooms: ['room'], extra: 'extra' })); |
||||
}); |
||||
|
||||
it('should return false if teamName and userId are informed and rooms are informed but there is an extra property', () => { |
||||
chai.assert.isFalse(isTeamsRemoveMemberProps({ teamName: 'teamName', userId: 'userId', rooms: ['room'], extra: 'extra' })); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,56 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
export type TeamsRemoveMemberProps = ({ teamId: string } | { teamName: string }) & { userId: string; rooms?: Array<string> }; |
||||
|
||||
const teamsRemoveMemberPropsSchema: JSONSchemaType<TeamsRemoveMemberProps> = { |
||||
oneOf: [ |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamId: { |
||||
type: 'string', |
||||
}, |
||||
userId: { |
||||
type: 'string', |
||||
}, |
||||
rooms: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
minItems: 1, |
||||
uniqueItems: true, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['teamId', 'userId'], |
||||
additionalProperties: false, |
||||
}, |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamName: { |
||||
type: 'string', |
||||
}, |
||||
userId: { |
||||
type: 'string', |
||||
}, |
||||
rooms: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
minItems: 1, |
||||
uniqueItems: true, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['teamName', 'userId'], |
||||
additionalProperties: false, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export const isTeamsRemoveMemberProps = ajv.compile(teamsRemoveMemberPropsSchema); |
||||
@ -0,0 +1,27 @@ |
||||
/* eslint-env mocha */ |
||||
import chai from 'chai'; |
||||
|
||||
import { isTeamsRemoveRoomProps } from './TeamsRemoveRoomProps'; |
||||
|
||||
describe('TeamsRemoveRoomProps (definition/rest/v1)', () => { |
||||
describe('isTeamsRemoveRoomProps', () => { |
||||
it('should be a function', () => { |
||||
chai.assert.isFunction(isTeamsRemoveRoomProps); |
||||
}); |
||||
it('should return false if roomId is not provided', () => { |
||||
chai.assert.isFalse(isTeamsRemoveRoomProps({})); |
||||
}); |
||||
it('should return false if roomId is provided but no teamId or teamName were provided', () => { |
||||
chai.assert.isFalse(isTeamsRemoveRoomProps({ roomId: 'roomId' })); |
||||
}); |
||||
it('should return false if roomId is provided and teamId is provided', () => { |
||||
chai.assert.isTrue(isTeamsRemoveRoomProps({ roomId: 'roomId', teamId: 'teamId' })); |
||||
}); |
||||
it('should return true if roomId is provided and teamName is provided', () => { |
||||
chai.assert.isTrue(isTeamsRemoveRoomProps({ roomId: 'roomId', teamName: 'teamName' })); |
||||
}); |
||||
it('should return false if roomId and teamName are provided but an additional property is provided', () => { |
||||
chai.assert.isFalse(isTeamsRemoveRoomProps({ roomId: 'roomId', teamName: 'teamName', foo: 'bar' })); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,40 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
import type { IRoom } from '../../../IRoom'; |
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
export type TeamsRemoveRoomProps = ({ teamId: string } | { teamName: string }) & { roomId: IRoom['_id'] }; |
||||
|
||||
export const teamsRemoveRoomPropsSchema: JSONSchemaType<TeamsRemoveRoomProps> = { |
||||
oneOf: [ |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamId: { |
||||
type: 'string', |
||||
}, |
||||
roomId: { |
||||
type: 'string', |
||||
}, |
||||
}, |
||||
required: ['teamId', 'roomId'], |
||||
additionalProperties: false, |
||||
}, |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamName: { |
||||
type: 'string', |
||||
}, |
||||
roomId: { |
||||
type: 'string', |
||||
}, |
||||
}, |
||||
required: ['teamName', 'roomId'], |
||||
additionalProperties: false, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export const isTeamsRemoveRoomProps = ajv.compile(teamsRemoveRoomPropsSchema); |
||||
@ -0,0 +1,59 @@ |
||||
/* eslint-env mocha */ |
||||
import chai from 'chai'; |
||||
|
||||
import { isTeamsUpdateMemberProps } from './TeamsUpdateMemberProps'; |
||||
|
||||
describe('TeamsUpdateMemberProps (definition/rest/v1)', () => { |
||||
describe('isTeamsUpdateMemberProps', () => { |
||||
it('should be a function', () => { |
||||
chai.assert.isFunction(isTeamsUpdateMemberProps); |
||||
}); |
||||
it('should return false if the parameter is empty', () => { |
||||
chai.assert.isFalse(isTeamsUpdateMemberProps({})); |
||||
}); |
||||
|
||||
it('should return false if teamId is provided but no member was provided', () => { |
||||
chai.assert.isFalse(isTeamsUpdateMemberProps({ teamId: '123' })); |
||||
}); |
||||
|
||||
it('should return false if teamName is provided but no member was provided', () => { |
||||
chai.assert.isFalse(isTeamsUpdateMemberProps({ teamName: '123' })); |
||||
}); |
||||
|
||||
it('should return false if member is provided but no teamId or teamName were provided', () => { |
||||
chai.assert.isFalse(isTeamsUpdateMemberProps({ member: { userId: '123' } })); |
||||
}); |
||||
|
||||
it('should return false if member with role is provided but no teamId or teamName were provided', () => { |
||||
chai.assert.isFalse(isTeamsUpdateMemberProps({ member: { userId: '123', roles: ['123'] } })); |
||||
}); |
||||
|
||||
it('should return true if member is provided and teamId is provided', () => { |
||||
chai.assert.isTrue(isTeamsUpdateMemberProps({ member: { userId: '123' }, teamId: '123' })); |
||||
}); |
||||
|
||||
it('should return true if member is provided and teamName is provided', () => { |
||||
chai.assert.isTrue(isTeamsUpdateMemberProps({ member: { userId: '123' }, teamName: '123' })); |
||||
}); |
||||
|
||||
it('should return true if member with role is provided and teamId is provided', () => { |
||||
chai.assert.isTrue(isTeamsUpdateMemberProps({ member: { userId: '123', roles: ['123'] }, teamId: '123' })); |
||||
}); |
||||
|
||||
it('should return true if member with role is provided and teamName is provided', () => { |
||||
chai.assert.isTrue(isTeamsUpdateMemberProps({ member: { userId: '123', roles: ['123'] }, teamName: '123' })); |
||||
}); |
||||
|
||||
it('should return false if teamName was provided and member contains an invalid property', () => { |
||||
chai.assert.isFalse(isTeamsUpdateMemberProps({ member: { userId: '123', invalid: '123' }, teamName: '123' })); |
||||
}); |
||||
|
||||
it('should return false if teamId was provided and member contains an invalid property', () => { |
||||
chai.assert.isFalse(isTeamsUpdateMemberProps({ member: { userId: '123', invalid: '123' }, teamId: '123' })); |
||||
}); |
||||
|
||||
it('should return false if contains an invalid property', () => { |
||||
chai.assert.isFalse(isTeamsUpdateMemberProps({ member: { userId: '123', roles: ['123'] }, teamName: '123', invalid: true })); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,68 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
import { ITeamMemberParams } from '../../../../server/sdk/types/ITeamService'; |
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
export type TeamsUpdateMemberProps = ({ teamId: string } | { teamName: string }) & { member: ITeamMemberParams }; |
||||
|
||||
const teamsUpdateMemberPropsSchema: JSONSchemaType<TeamsUpdateMemberProps> = { |
||||
oneOf: [ |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamId: { |
||||
type: 'string', |
||||
}, |
||||
member: { |
||||
type: 'object', |
||||
properties: { |
||||
userId: { |
||||
type: 'string', |
||||
}, |
||||
roles: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['userId'], |
||||
additionalProperties: false, |
||||
}, |
||||
}, |
||||
required: ['teamId', 'member'], |
||||
additionalProperties: false, |
||||
}, |
||||
{ |
||||
type: 'object', |
||||
properties: { |
||||
teamName: { |
||||
type: 'string', |
||||
}, |
||||
member: { |
||||
type: 'object', |
||||
properties: { |
||||
userId: { |
||||
type: 'string', |
||||
}, |
||||
roles: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'string', |
||||
}, |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: ['userId'], |
||||
additionalProperties: false, |
||||
}, |
||||
}, |
||||
required: ['teamName', 'member'], |
||||
additionalProperties: false, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
export const isTeamsUpdateMemberProps = ajv.compile(teamsUpdateMemberPropsSchema); |
||||
@ -0,0 +1,161 @@ |
||||
/* eslint-env mocha */ |
||||
import chai from 'chai'; |
||||
|
||||
import { isTeamsUpdateProps } from './TeamsUpdateProps'; |
||||
|
||||
describe('TeamsUpdateMemberProps (definition/rest/v1)', () => { |
||||
describe('isTeamsUpdateProps', () => { |
||||
it('should be a function', () => { |
||||
chai.assert.isFunction(isTeamsUpdateProps); |
||||
}); |
||||
it('should return false when provided anything that is not an TeamsUpdateProps', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps(undefined)); |
||||
chai.assert.isFalse(isTeamsUpdateProps(null)); |
||||
chai.assert.isFalse(isTeamsUpdateProps('')); |
||||
chai.assert.isFalse(isTeamsUpdateProps(123)); |
||||
chai.assert.isFalse(isTeamsUpdateProps({})); |
||||
chai.assert.isFalse(isTeamsUpdateProps([])); |
||||
chai.assert.isFalse(isTeamsUpdateProps(new Date())); |
||||
chai.assert.isFalse(isTeamsUpdateProps(new Error())); |
||||
}); |
||||
it('should return false when only teamName is provided to TeamsUpdateProps', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamName: 'teamName', |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when only teamId is provided to TeamsUpdateProps', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamId: 'teamId', |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when teamName and data are provided to TeamsUpdateProps but data is an empty object', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamName: 'teamName', |
||||
data: {}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when teamId and data are provided to TeamsUpdateProps but data is an empty object', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamId: 'teamId', |
||||
data: {}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when teamName and data are provided to TeamsUpdateProps but data is not an object', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamName: 'teamName', |
||||
data: 'data', |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when teamId and data are provided to TeamsUpdateProps but data is not an object', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamId: 'teamId', |
||||
data: 'data', |
||||
})); |
||||
}); |
||||
|
||||
it('should return true when teamName and data.name are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isTrue(isTeamsUpdateProps({ |
||||
teamName: 'teamName', |
||||
data: { |
||||
name: 'name', |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return true when teamId and data.name are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isTrue(isTeamsUpdateProps({ |
||||
teamId: 'teamId', |
||||
data: { |
||||
name: 'name', |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return true when teamName and data.type are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isTrue(isTeamsUpdateProps({ |
||||
teamName: 'teamName', |
||||
data: { |
||||
type: 0, |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return true when teamId and data.type are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isTrue(isTeamsUpdateProps({ |
||||
teamId: 'teamId', |
||||
data: { |
||||
type: 0, |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return true when teamName and data.name and data.type are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isTrue(isTeamsUpdateProps({ |
||||
teamName: 'teamName', |
||||
data: { |
||||
name: 'name', |
||||
type: 0, |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return true when teamId and data.name and data.type are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isTrue(isTeamsUpdateProps({ |
||||
teamId: 'teamId', |
||||
data: { |
||||
name: 'name', |
||||
type: 0, |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when teamName, data.name, data.type are some more extra data are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamName: 'teamName', |
||||
data: { |
||||
name: 'name', |
||||
type: 0, |
||||
extra: 'extra', |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when teamId, data.name, data.type are some more extra data are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamId: 'teamId', |
||||
data: { |
||||
name: 'name', |
||||
type: 0, |
||||
extra: 'extra', |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when teamName, data.name, data.type are some more extra parameter are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamName: 'teamName', |
||||
extra: 'extra', |
||||
data: { |
||||
name: 'name', |
||||
type: 0, |
||||
}, |
||||
})); |
||||
}); |
||||
|
||||
it('should return false when teamId, data.name, data.type are some more extra parameter are provided to TeamsUpdateProps', () => { |
||||
chai.assert.isFalse(isTeamsUpdateProps({ |
||||
teamId: 'teamId', |
||||
extra: 'extra', |
||||
data: { |
||||
name: 'name', |
||||
type: 0, |
||||
}, |
||||
})); |
||||
}); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,75 @@ |
||||
import Ajv, { JSONSchemaType } from 'ajv'; |
||||
|
||||
import { TEAM_TYPE } from '../../../ITeam'; |
||||
|
||||
const ajv = new Ajv(); |
||||
|
||||
export type TeamsUpdateProps = ({ teamId: string } | { teamName: string }) & { |
||||
data: ({ |
||||
name: string; |
||||
type?: TEAM_TYPE; |
||||
} | { |
||||
name?: string; |
||||
type: TEAM_TYPE; |
||||
}); |
||||
}; |
||||
|
||||
const teamsUpdatePropsSchema: JSONSchemaType<TeamsUpdateProps> = { |
||||
type: 'object', |
||||
properties: { |
||||
updateRoom: { |
||||
type: 'boolean', |
||||
nullable: true, |
||||
}, |
||||
teamId: { |
||||
type: 'string', |
||||
nullable: true, |
||||
}, |
||||
teamName: { |
||||
type: 'string', |
||||
nullable: true, |
||||
}, |
||||
data: { |
||||
type: 'object', |
||||
properties: { |
||||
name: { |
||||
type: 'string', |
||||
nullable: true, |
||||
}, |
||||
type: { |
||||
type: 'number', |
||||
enum: [ |
||||
TEAM_TYPE.PUBLIC, |
||||
TEAM_TYPE.PRIVATE, |
||||
], |
||||
}, |
||||
}, |
||||
additionalProperties: false, |
||||
required: [], |
||||
anyOf: [ |
||||
{ |
||||
required: ['name'], |
||||
}, |
||||
{ |
||||
required: ['type'], |
||||
}, |
||||
], |
||||
}, |
||||
name: { |
||||
type: 'string', |
||||
nullable: true, |
||||
}, |
||||
}, |
||||
required: [], |
||||
oneOf: [ |
||||
{ |
||||
required: ['teamId', 'data'], |
||||
}, |
||||
{ |
||||
required: ['teamName', 'data'], |
||||
}, |
||||
], |
||||
additionalProperties: false, |
||||
}; |
||||
|
||||
export const isTeamsUpdateProps = ajv.compile(teamsUpdatePropsSchema); |
||||
@ -0,0 +1,148 @@ |
||||
|
||||
|
||||
import type { IRoom } from '../../../IRoom'; |
||||
import type { ITeam } from '../../../ITeam'; |
||||
import type { IUser } from '../../../IUser'; |
||||
import { PaginatedResult } from '../../helpers/PaginatedResult'; |
||||
import { PaginatedRequest } from '../../helpers/PaginatedRequest'; |
||||
import { ITeamAutocompleteResult, ITeamMemberInfo } from '../../../../server/sdk/types/ITeamService'; |
||||
import { TeamsRemoveRoomProps } from './TeamsRemoveRoomProps'; |
||||
import { TeamsConvertToChannelProps } from './TeamsConvertToChannelProps'; |
||||
import { TeamsUpdateMemberProps } from './TeamsUpdateMemberProps'; |
||||
import { TeamsAddMembersProps } from './TeamsAddMembersProps'; |
||||
import { TeamsRemoveMemberProps } from './TeamsRemoveMemberProps'; |
||||
import { TeamsDeleteProps } from './TeamsDeleteProps'; |
||||
import { TeamsLeaveProps } from './TeamsLeaveProps'; |
||||
import { TeamsUpdateProps } from './TeamsUpdateProps'; |
||||
|
||||
|
||||
type TeamProps = |
||||
| TeamsRemoveRoomProps |
||||
| TeamsConvertToChannelProps |
||||
| TeamsUpdateMemberProps |
||||
| TeamsAddMembersProps |
||||
| TeamsRemoveMemberProps |
||||
| TeamsDeleteProps |
||||
| TeamsLeaveProps |
||||
| TeamsUpdateProps; |
||||
|
||||
export const isTeamPropsWithTeamName = <T extends TeamProps>(props: T): props is T & { teamName: string } => 'teamName' in props; |
||||
|
||||
export const isTeamPropsWithTeamId = <T extends TeamProps>(props: T): props is T & { teamId: string } => 'teamId' in props; |
||||
|
||||
export type TeamsEndpoints = { |
||||
'teams.list': { |
||||
GET: () => PaginatedResult & { teams: ITeam[] }; |
||||
}; |
||||
'teams.listAll': { |
||||
GET: () => { teams: ITeam[] } & PaginatedResult; |
||||
}; |
||||
'teams.create': { |
||||
POST: (params: { |
||||
name: ITeam['name']; |
||||
type?: ITeam['type']; |
||||
members?: IUser['_id'][]; |
||||
room: { |
||||
id?: string; |
||||
name?: IRoom['name']; |
||||
members?: IUser['_id'][]; |
||||
readOnly?: boolean; |
||||
extraData?: { |
||||
teamId?: string; |
||||
teamMain?: boolean; |
||||
} & { [key: string]: string | boolean }; |
||||
options?: { |
||||
nameValidationRegex?: string; |
||||
creator: string; |
||||
subscriptionExtra?: { |
||||
open: boolean; |
||||
ls: Date; |
||||
prid: IRoom['_id']; |
||||
}; |
||||
} & { |
||||
[key: string]: |
||||
| string |
||||
| { |
||||
open: boolean; |
||||
ls: Date; |
||||
prid: IRoom['_id']; |
||||
}; |
||||
}; |
||||
}; |
||||
owner?: IUser['_id']; |
||||
}) => { |
||||
team: ITeam; |
||||
}; |
||||
}; |
||||
|
||||
'teams.convertToChannel': { |
||||
POST: (params: TeamsConvertToChannelProps) => void; |
||||
}; |
||||
|
||||
'teams.addRooms': { |
||||
POST: (params: { rooms: IRoom['_id'][]; teamId: string } | { rooms: IRoom['_id'][]; teamName: string }) => ({ rooms: IRoom[] }); |
||||
}; |
||||
|
||||
'teams.removeRoom': { |
||||
POST: (params: TeamsRemoveRoomProps) => ({ room: IRoom }); |
||||
}; |
||||
|
||||
'teams.members': { |
||||
GET: (params: ({ teamId: string } | { teamName: string }) & { status?: string[]; username?: string; name?: string }) => (PaginatedResult & { members: ITeamMemberInfo[] }); |
||||
}; |
||||
|
||||
'teams.addMembers': { |
||||
POST: (params: TeamsAddMembersProps) => void; |
||||
}; |
||||
|
||||
'teams.updateMember': { |
||||
POST: (params: TeamsUpdateMemberProps) => void; |
||||
}; |
||||
|
||||
'teams.removeMember': { |
||||
POST: (params: TeamsRemoveMemberProps) => void; |
||||
}; |
||||
|
||||
'teams.leave': { |
||||
POST: (params: TeamsLeaveProps) => void; |
||||
}; |
||||
|
||||
|
||||
'teams.info': { |
||||
GET: (params: ({ teamId: string } | { teamName: string }) & {}) => ({ teamInfo: Partial<ITeam> }); |
||||
}; |
||||
|
||||
'teams.autocomplete': { |
||||
GET: (params: { name: string }) => ({ teams: ITeamAutocompleteResult[] }); |
||||
}; |
||||
|
||||
'teams.update': { |
||||
POST: (params: TeamsUpdateProps) => void; |
||||
}; |
||||
|
||||
'teams.delete': { |
||||
POST: (params: TeamsDeleteProps) => void; |
||||
}; |
||||
|
||||
'teams.listRoomsOfUser': { |
||||
GET: (params: { |
||||
teamId: ITeam['_id']; |
||||
userId: IUser['_id']; |
||||
canUserDelete?: boolean; |
||||
} | { |
||||
teamName: ITeam['name']; |
||||
userId: IUser['_id']; |
||||
canUserDelete?: boolean; |
||||
} |
||||
) => PaginatedResult & { rooms: IRoom[] }; |
||||
}; |
||||
|
||||
'teams.listRooms': { |
||||
GET: (params: PaginatedRequest & ({ teamId: string } | { teamId: string }) & { filter?: string; type?: string }) => PaginatedResult & { rooms: IRoom[] }; |
||||
}; |
||||
|
||||
|
||||
'teams.updateRoom': { |
||||
POST: (params: { roomId: IRoom['_id']; isDefault: boolean }) => ({ room: IRoom }); |
||||
}; |
||||
}; |
||||
@ -1,5 +1,5 @@ |
||||
import type { ITeam } from '../../../../../definition/ITeam'; |
||||
import type { IUser } from '../../../../../definition/IUser'; |
||||
import type { ITeam } from '../../ITeam'; |
||||
import type { IUser } from '../../IUser'; |
||||
|
||||
export type UsersEndpoints = { |
||||
'users.2fa.sendEmailCode': { |
||||
@ -0,0 +1,11 @@ |
||||
import { ILicenseTag } from './ILicenseTag'; |
||||
|
||||
export interface ILicense { |
||||
url: string; |
||||
expiry: string; |
||||
maxActiveUsers: number; |
||||
modules: string[]; |
||||
maxGuestUsers: number; |
||||
maxRoomsPerGuest: number; |
||||
tag?: ILicenseTag; |
||||
} |
||||
@ -0,0 +1,4 @@ |
||||
export interface ILicenseTag { |
||||
name: string; |
||||
color: string; |
||||
} |
||||
@ -1,21 +1,20 @@ |
||||
import { API } from '../../../../../app/api/server'; |
||||
import { findBusinessHours } from '../business-hour/lib/business-hour'; |
||||
|
||||
// @ts-ignore
|
||||
API.v1.addRoute('livechat/business-hours.list', { authRequired: true }, { |
||||
get() { |
||||
async get() { |
||||
const { offset, count } = this.getPaginationItems(); |
||||
const { sort } = this.parseJsonQuery(); |
||||
const { name } = this.queryParams; |
||||
|
||||
// @ts-ignore
|
||||
return API.v1.success(Promise.await(findBusinessHours( |
||||
return API.v1.success(await findBusinessHours( |
||||
this.userId, |
||||
{ |
||||
offset, |
||||
count, |
||||
sort, |
||||
}, |
||||
name))); |
||||
name)); |
||||
}, |
||||
}); |
||||
|
||||
@ -1,10 +0,0 @@ |
||||
import { IDailyActiveUsers } from '../../../../../../definition/IUser'; |
||||
import { Serialized } from '../../../../../../definition/Serialized'; |
||||
|
||||
export type EngagementDashboardEndpoints = { |
||||
'engagement-dashboard/users/active-users': { |
||||
GET: (params: { start: string; end: string }) => { |
||||
month: Serialized<IDailyActiveUsers>[]; |
||||
}; |
||||
}; |
||||
}; |
||||
@ -0,0 +1,4 @@ |
||||
import type { EngagementDashboardEndpoints } from './v1/engagementDashboard'; |
||||
import type { OmnichannelBusinessHoursEndpoints } from './v1/omnichannel/businessHours'; |
||||
|
||||
export type EnterpriseEndpoints = EngagementDashboardEndpoints & OmnichannelBusinessHoursEndpoints; |
||||
@ -0,0 +1,62 @@ |
||||
import { IDirectMessageRoom, IRoom } from '../../../../definition/IRoom'; |
||||
import { IDailyActiveUsers } from '../../../../definition/IUser'; |
||||
import { Serialized } from '../../../../definition/Serialized'; |
||||
|
||||
export type EngagementDashboardEndpoints = { |
||||
'/v1/engagement-dashboard/channels/list': { |
||||
GET: (params: { start: Date; end: Date; offset: number; count: number }) => { |
||||
channels: { |
||||
room: { |
||||
_id: IRoom['_id']; |
||||
name: IRoom['name'] | IRoom['fname']; |
||||
ts: IRoom['ts']; |
||||
t: IRoom['t']; |
||||
_updatedAt: IRoom['_updatedAt']; |
||||
usernames?: IDirectMessageRoom['usernames']; |
||||
}; |
||||
messages: number; |
||||
lastWeekMessages: number; |
||||
diffFromLastWeek: number; |
||||
}[]; |
||||
count: number; |
||||
offset: number; |
||||
total: number; |
||||
}; |
||||
}; |
||||
'engagement-dashboard/messages/origin': { |
||||
GET: (params: { start: Date; end: Date }) => { |
||||
origins: { |
||||
t: IRoom['t']; |
||||
messages: number; |
||||
}[]; |
||||
}; |
||||
}; |
||||
'engagement-dashboard/messages/top-five-popular-channels': { |
||||
GET: (params: { start: Date; end: Date }) => { |
||||
channels: { |
||||
t: IRoom['t']; |
||||
messages: number; |
||||
name: IRoom['name'] | IRoom['fname']; |
||||
usernames?: IDirectMessageRoom['usernames']; |
||||
}[]; |
||||
}; |
||||
}; |
||||
'engagement-dashboard/messages/messages-sent': { |
||||
GET: (params: { start: Date; end: Date }) => { |
||||
days: { day: Date; messages: number }[]; |
||||
period: { |
||||
count: number; |
||||
variation: number; |
||||
}; |
||||
yesterday: { |
||||
count: number; |
||||
variation: number; |
||||
}; |
||||
}; |
||||
}; |
||||
'engagement-dashboard/users/active-users': { |
||||
GET: (params: { start: string; end: string }) => { |
||||
month: Serialized<IDailyActiveUsers>[]; |
||||
}; |
||||
}; |
||||
}; |
||||
@ -0,0 +1,7 @@ |
||||
import { ILivechatBusinessHour } from '../../../../../definition/ILivechatBusinessHour'; |
||||
|
||||
export type OmnichannelBusinessHoursEndpoints = { |
||||
'livechat/business-hours.list': { |
||||
GET: () => ({ businessHours: ILivechatBusinessHour[] }); |
||||
}; |
||||
} |
||||
@ -1,440 +0,0 @@ |
||||
import { expect } from 'chai'; |
||||
|
||||
import { |
||||
getCredentials, |
||||
api, |
||||
request, |
||||
credentials, |
||||
login, |
||||
apiRoleNameUsers, |
||||
apiRoleNameSubscriptions, |
||||
apiRoleScopeUsers, |
||||
apiRoleDescription, |
||||
apiRoleScopeSubscriptions, |
||||
} from '../../data/api-data.js'; |
||||
import { password } from '../../data/user'; |
||||
import { updatePermission } from '../../data/permissions.helper'; |
||||
import { createUser, login as doLogin } from '../../data/users.helper'; |
||||
|
||||
function createRole(name, scope, description) { |
||||
return new Promise((resolve) => { |
||||
request.post(api('roles.create')) |
||||
.set(credentials) |
||||
.send({ |
||||
name, |
||||
scope, |
||||
description, |
||||
}) |
||||
.end((err, req) => { |
||||
resolve(req.body.role); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
function addUserToRole(roleName, username, scope) { |
||||
return new Promise((resolve) => { |
||||
request.post(api('roles.addUserToRole')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleName, |
||||
username, |
||||
roomId: scope, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
}) |
||||
.end((err, req) => { |
||||
resolve(req.body.role); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
describe('[Roles]', function() { |
||||
this.retries(0); |
||||
|
||||
before((done) => getCredentials(done)); |
||||
|
||||
describe('GET [/roles.list]', () => { |
||||
it('should return all roles', (done) => { |
||||
request.get(api('roles.list')) |
||||
.set(credentials) |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.property('roles').and.to.be.an('array'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
|
||||
describe('GET [/roles.sync]', () => { |
||||
it('should return an array of roles which are updated after updatedSice date when search by "updatedSince" query parameter', (done) => { |
||||
request.get(api('roles.sync?updatedSince=2018-11-27T13:52:01Z')) |
||||
.set(credentials) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.property('roles'); |
||||
expect(res.body.roles).to.have.property('update').and.to.be.an('array'); |
||||
expect(res.body.roles).to.have.property('remove').and.to.be.an('array'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
|
||||
it('should return an error when updatedSince query parameter is not a valid ISODate string', (done) => { |
||||
request.get(api('roles.sync?updatedSince=fsafdf')) |
||||
.set(credentials) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(400) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', false); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
|
||||
describe('POST [/roles.create]', () => { |
||||
it('should create a new role with Users scope', (done) => { |
||||
request.post(api('roles.create')) |
||||
.set(credentials) |
||||
.send({ |
||||
name: apiRoleNameUsers, |
||||
description: apiRoleDescription, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.nested.property('role._id'); |
||||
expect(res.body).to.have.nested.property('role.name', apiRoleNameUsers); |
||||
expect(res.body).to.have.nested.property('role.scope', apiRoleScopeUsers); |
||||
expect(res.body).to.have.nested.property('role.description', apiRoleDescription); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
|
||||
it('should create a new role with Subscriptions scope', (done) => { |
||||
request.post(api('roles.create')) |
||||
.set(credentials) |
||||
.send({ |
||||
name: apiRoleNameSubscriptions, |
||||
scope: apiRoleScopeSubscriptions, |
||||
description: apiRoleDescription, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.nested.property('role._id'); |
||||
expect(res.body).to.have.nested.property('role.name', apiRoleNameSubscriptions); |
||||
expect(res.body).to.have.nested.property('role.scope', apiRoleScopeSubscriptions); |
||||
expect(res.body).to.have.nested.property('role.description', apiRoleDescription); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
|
||||
it('should NOT create a new role with an existing role name', (done) => { |
||||
request.post(api('roles.create')) |
||||
.set(credentials) |
||||
.send({ |
||||
name: apiRoleNameUsers, |
||||
description: apiRoleDescription, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(400) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', false); |
||||
expect(res.body).to.have.nested.property('error', 'Role name already exists [error-duplicate-role-names-not-allowed]'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
|
||||
describe('POST [/roles.addUserToRole]', () => { |
||||
it('should assign a role with User scope to an user', (done) => { |
||||
request.post(api('roles.addUserToRole')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleName: apiRoleNameUsers, |
||||
username: login.user, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.nested.property('role._id'); |
||||
expect(res.body).to.have.nested.property('role.name', apiRoleNameUsers); |
||||
expect(res.body).to.have.nested.property('role.scope', apiRoleScopeUsers); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
|
||||
it('should assign a role with Subscriptions scope to an user', (done) => { |
||||
request.post(api('roles.addUserToRole')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleName: apiRoleNameSubscriptions, |
||||
username: login.user, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.nested.property('role._id'); |
||||
expect(res.body).to.have.nested.property('role.name', apiRoleNameSubscriptions); |
||||
expect(res.body).to.have.nested.property('role.scope', apiRoleScopeSubscriptions); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
|
||||
describe('GET [/roles.getUsersInRole]', () => { |
||||
let userCredentials; |
||||
before((done) => { |
||||
createUser().then((createdUser) => { |
||||
doLogin(createdUser.username, password).then((createdUserCredentials) => { |
||||
userCredentials = createdUserCredentials; |
||||
updatePermission('access-permissions', ['admin', 'user']).then(done); |
||||
}); |
||||
}); |
||||
}); |
||||
it('should return an error when "role" query param is not provided', (done) => { |
||||
request.get(api('roles.getUsersInRole')) |
||||
.set(userCredentials) |
||||
.query({ |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(400) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', false); |
||||
expect(res.body.errorType).to.be.equal('error-param-not-provided'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
it('should return an error when the user does not the necessary permission', (done) => { |
||||
updatePermission('access-permissions', ['admin']).then(() => { |
||||
request.get(api('roles.getUsersInRole')) |
||||
.set(userCredentials) |
||||
.query({ |
||||
role: 'admin', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(400) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', false); |
||||
expect(res.body.errorType).to.be.equal('error-not-allowed'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
it('should return an error when the user try access rooms permissions and does not have the necessary permission', (done) => { |
||||
updatePermission('access-permissions', ['admin', 'user']).then(() => { |
||||
updatePermission('view-other-user-channels', []).then(() => { |
||||
request.get(api('roles.getUsersInRole')) |
||||
.set(userCredentials) |
||||
.query({ |
||||
role: 'admin', |
||||
roomId: 'GENERAL', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(400) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', false); |
||||
expect(res.body.errorType).to.be.equal('error-not-allowed'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
}); |
||||
it('should return the list of users', (done) => { |
||||
updatePermission('access-permissions', ['admin', 'user']).then(() => { |
||||
updatePermission('view-other-user-channels', ['admin', 'user']).then(() => { |
||||
request.get(api('roles.getUsersInRole')) |
||||
.set(userCredentials) |
||||
.query({ |
||||
role: 'admin', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body.users).to.be.an('array'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
}); |
||||
it('should return the list of users when find by room Id', (done) => { |
||||
request.get(api('roles.getUsersInRole')) |
||||
.set(userCredentials) |
||||
.query({ |
||||
role: 'admin', |
||||
roomId: 'GENERAL', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body.users).to.be.an('array'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
|
||||
describe('POST [/roles.update]', () => { |
||||
const roleName = `role-${ Date.now() }`; |
||||
let newRole; |
||||
before(async () => { |
||||
newRole = await createRole(roleName, 'Users', 'Role description test'); |
||||
}); |
||||
|
||||
it('should update an existing role', (done) => { |
||||
const newRoleName = `${ roleName }Updated`; |
||||
const newRoleDescription = 'New role description'; |
||||
|
||||
request.post(api('roles.update')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleId: newRole._id, |
||||
name: newRoleName, |
||||
description: newRoleDescription, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.nested.property('role._id', newRole._id); |
||||
expect(res.body).to.have.nested.property('role.name', newRoleName); |
||||
expect(res.body).to.have.nested.property('role.scope', newRole.scope); |
||||
expect(res.body).to.have.nested.property('role.description', newRoleDescription); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
|
||||
it('should NOT update a role with an existing role name', (done) => { |
||||
request.post(api('roles.update')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleId: newRole._id, |
||||
name: apiRoleNameUsers, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(400) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', false); |
||||
expect(res.body).to.have.nested.property('error', 'Role name already exists [error-duplicate-role-names-not-allowed]'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
|
||||
describe('POST [/roles.delete]', () => { |
||||
let roleWithUser; |
||||
let roleWithoutUser; |
||||
before(async () => { |
||||
roleWithUser = await createRole(`roleWithUser-${ Date.now() }`, 'Users'); |
||||
roleWithoutUser = await createRole(`roleWithoutUser-${ Date.now() }`, 'Users'); |
||||
|
||||
await addUserToRole(roleWithUser.name, login.user); |
||||
}); |
||||
|
||||
it('should delete a role that it is not being used', (done) => { |
||||
request.post(api('roles.delete')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleId: roleWithoutUser._id, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
|
||||
it('should NOT delete a role that it is protected', (done) => { |
||||
request.post(api('roles.delete')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleId: 'admin', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(400) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', false); |
||||
expect(res.body).to.have.nested.property('error', 'Cannot delete a protected role [error-role-protected]'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
|
||||
it('should NOT delete a role that it is being used', (done) => { |
||||
request.post(api('roles.delete')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleId: roleWithUser._id, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(400) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', false); |
||||
expect(res.body).to.have.nested.property('error', 'Cannot delete role because it\'s in use [error-role-in-use]'); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
|
||||
describe('POST [/roles.removeUserFromRole]', () => { |
||||
let usersScopedRole; |
||||
let subscriptionsScopedRole; |
||||
|
||||
before(async () => { |
||||
usersScopedRole = await createRole(`usersScopedRole-${ Date.now() }`, 'Users'); |
||||
subscriptionsScopedRole = await createRole(`subscriptionsScopedRole-${ Date.now() }`, 'Subscriptions'); |
||||
|
||||
await addUserToRole(usersScopedRole.name, login.user); |
||||
await addUserToRole(subscriptionsScopedRole.name, login.user, 'GENERAL'); |
||||
}); |
||||
|
||||
it('should unassign a role with User scope from an user', (done) => { |
||||
request.post(api('roles.removeUserFromRole')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleName: usersScopedRole.name, |
||||
username: login.user, |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.nested.property('role._id', usersScopedRole._id); |
||||
expect(res.body).to.have.nested.property('role.name', usersScopedRole.name); |
||||
expect(res.body).to.have.nested.property('role.scope', usersScopedRole.scope); |
||||
expect(res.body).to.have.nested.property('role.description', usersScopedRole.description); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
|
||||
it('should unassign a role with Subscriptions scope from an user', (done) => { |
||||
request.post(api('roles.removeUserFromRole')) |
||||
.set(credentials) |
||||
.send({ |
||||
roleName: subscriptionsScopedRole.name, |
||||
username: login.user, |
||||
scope: 'GENERAL', |
||||
}) |
||||
.expect('Content-Type', 'application/json') |
||||
.expect(200) |
||||
.expect((res) => { |
||||
expect(res.body).to.have.property('success', true); |
||||
expect(res.body).to.have.nested.property('role._id', subscriptionsScopedRole._id); |
||||
expect(res.body).to.have.nested.property('role.name', subscriptionsScopedRole.name); |
||||
expect(res.body).to.have.nested.property('role.scope', subscriptionsScopedRole.scope); |
||||
expect(res.body).to.have.nested.property('role.description', subscriptionsScopedRole.description); |
||||
}) |
||||
.end(done); |
||||
}); |
||||
}); |
||||
}); |
||||
Loading…
Reference in new issue