Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Code scanning - action / CodeQL-Build (push) Failing after 2s
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
423 lines
10 KiB
TypeScript
423 lines
10 KiB
TypeScript
import type {
|
|
IAbacAttribute,
|
|
IAbacAttributeDefinition,
|
|
IAuditServerActor,
|
|
IRoom,
|
|
IRoomAbacRedaction,
|
|
IServerEvents,
|
|
} from '@rocket.chat/core-typings';
|
|
import type { PaginatedResult, PaginatedRequest } from '@rocket.chat/rest-typings';
|
|
import { ajv, ajvQuery } from '@rocket.chat/rest-typings';
|
|
|
|
const ATTRIBUTE_KEY_PATTERN = '^[A-Za-z0-9_-]+$';
|
|
const MAX_ROOM_ATTRIBUTE_VALUES = 10;
|
|
const MAX_USERS_SYNC_ITEMS = 100;
|
|
const MAX_ROOM_ATTRIBUTE_KEYS = 10;
|
|
|
|
const GenericSuccess = {
|
|
type: 'object',
|
|
properties: {
|
|
success: { type: 'boolean', enum: [true] },
|
|
},
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const GenericSuccessSchema = ajv.compile<void>(GenericSuccess);
|
|
|
|
// Update ABAC attribute (request body)
|
|
const UpdateAbacAttributeBody = {
|
|
type: 'object',
|
|
properties: {
|
|
key: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
values: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
minItems: 1,
|
|
uniqueItems: true,
|
|
},
|
|
},
|
|
additionalProperties: false,
|
|
anyOf: [{ required: ['key'] }, { required: ['values'] }],
|
|
};
|
|
|
|
export const PUTAbacAttributeUpdateBodySchema = ajv.compile<IAbacAttributeDefinition>(UpdateAbacAttributeBody);
|
|
|
|
const AbacAttributeDefinition = {
|
|
type: 'object',
|
|
|
|
properties: {
|
|
key: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
values: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
minItems: 1,
|
|
uniqueItems: true,
|
|
},
|
|
},
|
|
required: ['key', 'values'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const POSTAbacAttributeDefinitionSchema = ajv.compile<IAbacAttributeDefinition>(AbacAttributeDefinition);
|
|
|
|
const GetAbacAttributesQuery = {
|
|
type: 'object',
|
|
properties: {
|
|
key: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
values: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
offset: { type: 'number' },
|
|
count: { type: 'number' },
|
|
},
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const GETAbacAttributesQuerySchema = ajvQuery.compile<{ key?: string; values?: string; offset: number; count?: number }>(
|
|
GetAbacAttributesQuery,
|
|
);
|
|
|
|
const AbacAttributeRecord = {
|
|
type: 'object',
|
|
properties: {
|
|
_id: { type: 'string', minLength: 1 },
|
|
key: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
values: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
minItems: 1,
|
|
uniqueItems: true,
|
|
},
|
|
},
|
|
required: ['_id', 'key', 'values'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
const GetAbacAttributesResponse = {
|
|
type: 'object',
|
|
properties: {
|
|
success: { type: 'boolean', enum: [true] },
|
|
attributes: {
|
|
type: 'array',
|
|
items: AbacAttributeRecord,
|
|
},
|
|
offset: { type: 'number' },
|
|
count: { type: 'number' },
|
|
total: { type: 'number' },
|
|
},
|
|
required: ['attributes', 'offset', 'count', 'total'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const GETAbacAttributesResponseSchema = ajv.compile<{
|
|
attributes: Pick<IAbacAttribute, '_id' | 'key' | 'values'>[];
|
|
offset: number;
|
|
count: number;
|
|
total: number;
|
|
}>(GetAbacAttributesResponse);
|
|
|
|
const GetAbacAttributeByIdResponse = {
|
|
type: 'object',
|
|
properties: {
|
|
success: { type: 'boolean', enum: [true] },
|
|
_id: { type: 'string', minLength: 1 },
|
|
key: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
values: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
minItems: 1,
|
|
uniqueItems: true,
|
|
},
|
|
},
|
|
required: ['key', 'values'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const GETAbacAttributeByIdResponseSchema = ajv.compile<{
|
|
key: string;
|
|
values: string[];
|
|
}>(GetAbacAttributeByIdResponse);
|
|
|
|
const GetAbacAttributeIsInUseResponse = {
|
|
type: 'object',
|
|
properties: {
|
|
success: { type: 'boolean', enum: [true] },
|
|
inUse: { type: 'boolean' },
|
|
},
|
|
required: ['inUse'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const GETAbacAttributeIsInUseResponseSchema = ajv.compile<{ inUse: boolean }>(GetAbacAttributeIsInUseResponse);
|
|
|
|
const GetAbacAuditEventsQuerySchemaObject = {
|
|
type: 'object',
|
|
properties: {
|
|
start: { type: 'string', format: 'date-time', nullable: true },
|
|
end: { type: 'string', format: 'date-time', nullable: true },
|
|
offset: { type: 'number', nullable: true },
|
|
count: { type: 'number', nullable: true },
|
|
actor: {
|
|
type: 'object',
|
|
nullable: true,
|
|
properties: {
|
|
type: {
|
|
type: 'string',
|
|
nullable: true,
|
|
},
|
|
_id: {
|
|
type: 'string',
|
|
nullable: true,
|
|
},
|
|
username: {
|
|
type: 'string',
|
|
nullable: true,
|
|
},
|
|
ip: {
|
|
type: 'string',
|
|
nullable: true,
|
|
},
|
|
useragent: {
|
|
type: 'string',
|
|
nullable: true,
|
|
},
|
|
reason: {
|
|
type: 'string',
|
|
nullable: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const GETAbacAuditEventsQuerySchema = ajvQuery.compile<
|
|
PaginatedRequest<{
|
|
start?: string;
|
|
end?: string;
|
|
actor?: IAuditServerActor;
|
|
}>
|
|
>(GetAbacAuditEventsQuerySchemaObject);
|
|
|
|
const GetAbacAuditEventsResponseSchemaObject = {
|
|
type: 'object',
|
|
properties: {
|
|
success: { type: 'boolean', enum: [true] },
|
|
events: {
|
|
type: 'array',
|
|
items: {
|
|
type: 'object',
|
|
},
|
|
},
|
|
count: {
|
|
type: 'number',
|
|
description: 'The number of events returned in this response.',
|
|
},
|
|
offset: {
|
|
type: 'number',
|
|
description: 'The number of events that were skipped in this response.',
|
|
},
|
|
total: {
|
|
type: 'number',
|
|
description: 'The total number of events that match the query.',
|
|
},
|
|
},
|
|
required: ['events', 'count', 'offset', 'total'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const GETAbacAuditEventsResponseSchema = ajv.compile<{
|
|
events: (
|
|
| IServerEvents['abac.action.performed']
|
|
| IServerEvents['abac.attribute.changed']
|
|
| IServerEvents['abac.object.attribute.changed']
|
|
| IServerEvents['abac.object.attributes.removed']
|
|
| IServerEvents['abac.attribute.store.switched']
|
|
)[];
|
|
count: number;
|
|
offset: number;
|
|
total: number;
|
|
}>(GetAbacAuditEventsResponseSchemaObject);
|
|
|
|
const PostRoomAbacAttributesBody = {
|
|
type: 'object',
|
|
properties: {
|
|
attributes: {
|
|
type: 'object',
|
|
propertyNames: { type: 'string', pattern: ATTRIBUTE_KEY_PATTERN },
|
|
minProperties: 1,
|
|
maxProperties: MAX_ROOM_ATTRIBUTE_KEYS,
|
|
additionalProperties: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
maxItems: MAX_ROOM_ATTRIBUTE_VALUES,
|
|
uniqueItems: true,
|
|
},
|
|
},
|
|
},
|
|
required: ['attributes'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const POSTRoomAbacAttributesBodySchema = ajv.compile<{ attributes: Record<string, string[]> }>(PostRoomAbacAttributesBody);
|
|
|
|
const PostSingleRoomAbacAttributeBody = {
|
|
type: 'object',
|
|
properties: {
|
|
values: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
minItems: 1,
|
|
maxItems: MAX_ROOM_ATTRIBUTE_VALUES,
|
|
uniqueItems: true,
|
|
},
|
|
},
|
|
required: ['values'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const POSTSingleRoomAbacAttributeBodySchema = ajv.compile<{ values: string[] }>(PostSingleRoomAbacAttributeBody);
|
|
|
|
const PutRoomAbacAttributeValuesBody = {
|
|
type: 'object',
|
|
properties: {
|
|
values: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1, pattern: ATTRIBUTE_KEY_PATTERN },
|
|
minItems: 1,
|
|
maxItems: MAX_ROOM_ATTRIBUTE_VALUES,
|
|
uniqueItems: true,
|
|
},
|
|
},
|
|
required: ['values'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
export const PUTRoomAbacAttributeValuesBodySchema = ajv.compile<{ values: string[] }>(PutRoomAbacAttributeValuesBody);
|
|
|
|
const GenericError = {
|
|
type: 'object',
|
|
properties: {
|
|
success: {
|
|
type: 'boolean',
|
|
},
|
|
message: {
|
|
type: 'string',
|
|
},
|
|
},
|
|
};
|
|
|
|
const PostAbacUsersSyncBody = {
|
|
type: 'object',
|
|
properties: {
|
|
usernames: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1 },
|
|
minItems: 1,
|
|
maxItems: MAX_USERS_SYNC_ITEMS,
|
|
uniqueItems: true,
|
|
},
|
|
ids: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1 },
|
|
minItems: 1,
|
|
maxItems: MAX_USERS_SYNC_ITEMS,
|
|
uniqueItems: true,
|
|
},
|
|
emails: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1 },
|
|
minItems: 1,
|
|
maxItems: MAX_USERS_SYNC_ITEMS,
|
|
uniqueItems: true,
|
|
},
|
|
ldapIds: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 1 },
|
|
minItems: 1,
|
|
maxItems: MAX_USERS_SYNC_ITEMS,
|
|
uniqueItems: true,
|
|
},
|
|
},
|
|
additionalProperties: false,
|
|
anyOf: [{ required: ['usernames'] }, { required: ['ids'] }, { required: ['emails'] }, { required: ['ldapIds'] }],
|
|
};
|
|
|
|
export const POSTAbacUsersSyncBodySchema = ajv.compile<{
|
|
usernames?: string[];
|
|
ids?: string[];
|
|
emails?: string[];
|
|
ldapIds?: string[];
|
|
}>(PostAbacUsersSyncBody);
|
|
|
|
export const GenericErrorSchema = ajv.compile<{ success: boolean; message: string }>(GenericError);
|
|
|
|
export const GETAbacPdpHealthResponseSchema = ajv.compile<{
|
|
available: boolean;
|
|
message: string;
|
|
}>({
|
|
type: 'object',
|
|
properties: {
|
|
success: { type: 'boolean', enum: [true] },
|
|
available: { type: 'boolean' },
|
|
message: { type: 'string' },
|
|
},
|
|
required: ['success', 'available', 'message'],
|
|
additionalProperties: false,
|
|
});
|
|
|
|
export const GETAbacPdpHealthErrorResponseSchema = ajv.compile<{ available: boolean; message: string }>({
|
|
type: 'object',
|
|
properties: {
|
|
success: { type: 'boolean', enum: [false] },
|
|
available: { type: 'boolean', enum: [false] },
|
|
message: { type: 'string' },
|
|
},
|
|
required: ['success', 'available', 'message'],
|
|
additionalProperties: false,
|
|
});
|
|
|
|
const GETAbacRoomsListQuerySchema = {
|
|
type: 'object',
|
|
properties: {
|
|
filter: { type: 'string', minLength: 1 },
|
|
filterType: { type: 'string', enum: ['all', 'roomName', 'attribute', 'value'] },
|
|
offset: { type: 'number' },
|
|
count: { type: 'number' },
|
|
},
|
|
additionalProperties: false,
|
|
};
|
|
|
|
type GETAbacRoomsListQuery = PaginatedRequest<{ filter?: string; filterType?: 'all' | 'roomName' | 'attribute' | 'value' }>;
|
|
|
|
export const GETAbacRoomsListQueryValidator = ajvQuery.compile<GETAbacRoomsListQuery>(GETAbacRoomsListQuerySchema);
|
|
|
|
export const GETAbacRoomsResponseSchema = {
|
|
type: 'object',
|
|
properties: {
|
|
success: {
|
|
type: 'boolean',
|
|
enum: [true],
|
|
},
|
|
rooms: {
|
|
type: 'array',
|
|
items: { type: 'object' },
|
|
},
|
|
offset: {
|
|
type: 'number',
|
|
},
|
|
count: {
|
|
type: 'number',
|
|
},
|
|
total: {
|
|
type: 'number',
|
|
},
|
|
},
|
|
required: ['rooms', 'offset', 'count', 'total'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
type GETAbacRoomsResponse = PaginatedResult<{
|
|
rooms: Array<IRoom & IRoomAbacRedaction>;
|
|
}>;
|
|
|
|
export const GETAbacRoomsResponseValidator = ajv.compile<GETAbacRoomsResponse>(GETAbacRoomsResponseSchema);
|