backend: extend storage provider to manage user data with new methods for retrieving and saving users
This commit is contained in:
parent
55bc8726d0
commit
7d128ed699
@ -58,5 +58,5 @@ export const registerDependencies = () => {
|
|||||||
export const initializeEagerServices = async () => {
|
export const initializeEagerServices = async () => {
|
||||||
// Force the creation of services that need to be initialized at startup
|
// Force the creation of services that need to be initialized at startup
|
||||||
container.get(RecordingService);
|
container.get(RecordingService);
|
||||||
await container.get(MeetStorageService).initializeGlobalPreferences();
|
await container.get(MeetStorageService).initialize();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -24,6 +24,7 @@ const INTERNAL_CONFIG = {
|
|||||||
S3_INITIAL_RETRY_DELAY_MS: '100',
|
S3_INITIAL_RETRY_DELAY_MS: '100',
|
||||||
S3_ROOMS_PREFIX: 'rooms',
|
S3_ROOMS_PREFIX: 'rooms',
|
||||||
S3_RECORDINGS_PREFIX: 'recordings',
|
S3_RECORDINGS_PREFIX: 'recordings',
|
||||||
|
S3_USERS_PREFIX: 'users',
|
||||||
|
|
||||||
// Garbage collection and recording lock intervals
|
// Garbage collection and recording lock intervals
|
||||||
ROOM_GC_INTERVAL: '1h' as StringValue, // e.g. garbage collector interval for rooms
|
ROOM_GC_INTERVAL: '1h' as StringValue, // e.g. garbage collector interval for rooms
|
||||||
|
|||||||
@ -4,7 +4,8 @@ export const enum RedisKeyPrefix {
|
|||||||
|
|
||||||
export const enum RedisKeyName {
|
export const enum RedisKeyName {
|
||||||
GLOBAL_PREFERENCES = `${RedisKeyPrefix.BASE}global_preferences`,
|
GLOBAL_PREFERENCES = `${RedisKeyPrefix.BASE}global_preferences`,
|
||||||
ROOM = `${RedisKeyPrefix.BASE}room:`
|
ROOM = `${RedisKeyPrefix.BASE}room:`,
|
||||||
|
USER = `${RedisKeyPrefix.BASE}user:`,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum RedisLockPrefix {
|
export const enum RedisLockPrefix {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { PutObjectCommandOutput } from '@aws-sdk/client-s3';
|
import { PutObjectCommandOutput } from '@aws-sdk/client-s3';
|
||||||
import { GlobalPreferences, MeetRecordingInfo, MeetRoom } from '@typings-ce';
|
import { GlobalPreferences, MeetRecordingInfo, MeetRoom, User } from '@typings-ce';
|
||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import INTERNAL_CONFIG from '../../../config/internal-config.js';
|
import INTERNAL_CONFIG from '../../../config/internal-config.js';
|
||||||
import { errorRecordingNotFound, OpenViduMeetError, RedisKeyName } from '../../../models/index.js';
|
import { errorRecordingNotFound, OpenViduMeetError, RedisKeyName } from '../../../models/index.js';
|
||||||
@ -11,8 +11,8 @@ import { Readable } from 'stream';
|
|||||||
* Implementation of the StorageProvider interface using AWS S3 for persistent storage
|
* Implementation of the StorageProvider interface using AWS S3 for persistent storage
|
||||||
* with Redis caching for improved performance.
|
* with Redis caching for improved performance.
|
||||||
*
|
*
|
||||||
* This class provides operations for storing and retrieving application preferences and room data
|
* This class provides operations for storing and retrieving application preferences,
|
||||||
* with a two-tiered storage approach:
|
* rooms, recordings metadata and users with a two-tiered storage approach:
|
||||||
* - Redis is used as a primary cache for fast access
|
* - Redis is used as a primary cache for fast access
|
||||||
* - S3 serves as the persistent storage layer and fallback when data is not in Redis
|
* - S3 serves as the persistent storage layer and fallback when data is not in Redis
|
||||||
*
|
*
|
||||||
@ -21,6 +21,8 @@ import { Readable } from 'stream';
|
|||||||
*
|
*
|
||||||
* @template GPrefs - Type for global preferences data, defaults to GlobalPreferences
|
* @template GPrefs - Type for global preferences data, defaults to GlobalPreferences
|
||||||
* @template MRoom - Type for room data, defaults to MeetRoom
|
* @template MRoom - Type for room data, defaults to MeetRoom
|
||||||
|
* @template MRec - Type for recording metadata, defaults to MeetRecordingInfo
|
||||||
|
* @template MUser - Type for user data, defaults to User
|
||||||
*
|
*
|
||||||
* @implements {StorageProvider}
|
* @implements {StorageProvider}
|
||||||
*/
|
*/
|
||||||
@ -28,10 +30,12 @@ import { Readable } from 'stream';
|
|||||||
export class S3StorageProvider<
|
export class S3StorageProvider<
|
||||||
GPrefs extends GlobalPreferences = GlobalPreferences,
|
GPrefs extends GlobalPreferences = GlobalPreferences,
|
||||||
MRoom extends MeetRoom = MeetRoom,
|
MRoom extends MeetRoom = MeetRoom,
|
||||||
MRec extends MeetRecordingInfo = MeetRecordingInfo
|
MRec extends MeetRecordingInfo = MeetRecordingInfo,
|
||||||
|
MUser extends User = User
|
||||||
> implements StorageProvider
|
> implements StorageProvider
|
||||||
{
|
{
|
||||||
protected readonly S3_GLOBAL_PREFERENCES_KEY = `global-preferences.json`;
|
protected readonly S3_GLOBAL_PREFERENCES_KEY = `global-preferences.json`;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject(LoggerService) protected logger: LoggerService,
|
@inject(LoggerService) protected logger: LoggerService,
|
||||||
@inject(S3Service) protected s3Service: S3Service,
|
@inject(S3Service) protected s3Service: S3Service,
|
||||||
@ -479,15 +483,13 @@ export class S3StorageProvider<
|
|||||||
*/
|
*/
|
||||||
async getRecordingMetadataByPath(recordingPath: string): Promise<MRec> {
|
async getRecordingMetadataByPath(recordingPath: string): Promise<MRec> {
|
||||||
try {
|
try {
|
||||||
return await this.s3Service.getObjectAsJson(recordingPath) as MRec;
|
return (await this.s3Service.getObjectAsJson(recordingPath)) as MRec;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError(error, `Error fetching recording metadata for path ${recordingPath}`);
|
this.handleError(error, `Error fetching recording metadata for path ${recordingPath}`);
|
||||||
throw error;
|
throw error;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async saveRecordingMetadata(recordingInfo: MRec): Promise<MRec> {
|
async saveRecordingMetadata(recordingInfo: MRec): Promise<MRec> {
|
||||||
try {
|
try {
|
||||||
const metadataPath = RecordingHelper.buildMetadataFilePath(recordingInfo.recordingId);
|
const metadataPath = RecordingHelper.buildMetadataFilePath(recordingInfo.recordingId);
|
||||||
@ -516,6 +518,77 @@ export class S3StorageProvider<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getUser(username: string): Promise<MUser | null> {
|
||||||
|
try {
|
||||||
|
const userKey = RedisKeyName.USER + username;
|
||||||
|
const user: MUser | null = await this.getFromRedis<MUser>(userKey);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
this.logger.debug(`User ${username} not found in Redis. Fetching from S3...`);
|
||||||
|
const s3Path = `${INTERNAL_CONFIG.S3_USERS_PREFIX}/${username}.json`;
|
||||||
|
return await this.getFromS3<MUser>(s3Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug(`User ${username} retrieved from Redis`);
|
||||||
|
return user;
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error, `Error fetching user ${username}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a user object to both S3 storage and Redis cache atomically.
|
||||||
|
*
|
||||||
|
* This method attempts to persist the user data in S3 (as a JSON file) and in Redis (as a serialized string).
|
||||||
|
* If both operations succeed, the user is considered saved and the method returns the user object.
|
||||||
|
* If either operation fails, the method attempts to roll back any successful operation to maintain consistency.
|
||||||
|
* In case of failure, the error is logged and rethrown after rollback attempts.
|
||||||
|
*
|
||||||
|
* @param user - The user object to be saved.
|
||||||
|
* @returns A promise that resolves to the saved user object if both operations succeed.
|
||||||
|
* @throws An error if either the S3 or Redis operation fails, after attempting rollback.
|
||||||
|
*/
|
||||||
|
async saveUser(user: MUser): Promise<MUser> {
|
||||||
|
const userKey = RedisKeyName.USER + user.username;
|
||||||
|
const redisPayload = JSON.stringify(user);
|
||||||
|
const s3Path = `${INTERNAL_CONFIG.S3_USERS_PREFIX}/${user.username}.json`;
|
||||||
|
|
||||||
|
const [s3Result, redisResult] = await Promise.allSettled([
|
||||||
|
this.s3Service.saveObject(s3Path, user),
|
||||||
|
this.redisService.set(userKey, redisPayload, false)
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (s3Result.status === 'fulfilled' && redisResult.status === 'fulfilled') {
|
||||||
|
this.logger.info(`User ${user.username} saved successfully`);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rollback any changes made by the successful operation
|
||||||
|
if (s3Result.status === 'fulfilled') {
|
||||||
|
try {
|
||||||
|
await this.s3Service.deleteObjects([s3Path]);
|
||||||
|
} catch (rollbackError) {
|
||||||
|
this.logger.error(`Error rolling back S3 save for user ${user.username}: ${rollbackError}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redisResult.status === 'fulfilled') {
|
||||||
|
try {
|
||||||
|
await this.redisService.delete(userKey);
|
||||||
|
} catch (rollbackError) {
|
||||||
|
this.logger.error(`Error rolling back Redis set for user ${user.username}: ${rollbackError}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the error that occurred first
|
||||||
|
const failedOperation: PromiseRejectedResult =
|
||||||
|
s3Result.status === 'rejected' ? s3Result : (redisResult as PromiseRejectedResult);
|
||||||
|
const error = failedOperation.reason;
|
||||||
|
this.handleError(error, `Error saving user ${user.username}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves an object of type U from Redis by the given key.
|
* Retrieves an object of type U from Redis by the given key.
|
||||||
* Returns null if the key is not found or an error occurs.
|
* Returns null if the key is not found or an error occurs.
|
||||||
|
|||||||
@ -1,21 +1,24 @@
|
|||||||
import { GlobalPreferences, MeetRecordingInfo, MeetRoom } from '@typings-ce';
|
import { GlobalPreferences, MeetRecordingInfo, MeetRoom, User } from '@typings-ce';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface that defines the contract for storage providers in the OpenVidu Meet application.
|
* An interface that defines the contract for storage providers in the OpenVidu Meet application.
|
||||||
* Storage providers handle persistence of global application preferences and meeting room data.
|
* Storage providers handle persistence of global application preferences, rooms, recordings metadata and users.
|
||||||
*
|
*
|
||||||
* @template GPrefs - The type of global preferences, extending GlobalPreferences
|
* @template GPrefs - The type of global preferences, extending GlobalPreferences
|
||||||
* @template MRoom - The type of room data, extending MeetRoom
|
* @template MRoom - The type of room data, extending MeetRoom
|
||||||
|
* @template MRec - The type of recording metadata, extending MeetRecordingInfo
|
||||||
|
* @template MUser - The type of user data, extending User
|
||||||
*
|
*
|
||||||
* Implementations of this interface should handle the persistent storage
|
* Implementations of this interface should handle the persistent storage
|
||||||
* of application settings and room information, which could be backed by
|
* of application settings, room information, recording metadata, and user data,
|
||||||
* various storage solutions (database, file system, cloud storage, etc.).
|
* which could be backed by various storage solutions (database, file system, cloud storage, etc.).
|
||||||
*/
|
*/
|
||||||
export interface StorageProvider<
|
export interface StorageProvider<
|
||||||
GPrefs extends GlobalPreferences = GlobalPreferences,
|
GPrefs extends GlobalPreferences = GlobalPreferences,
|
||||||
MRoom extends MeetRoom = MeetRoom,
|
MRoom extends MeetRoom = MeetRoom,
|
||||||
MRec extends MeetRecordingInfo = MeetRecordingInfo
|
MRec extends MeetRecordingInfo = MeetRecordingInfo,
|
||||||
|
MUser extends User = User
|
||||||
> {
|
> {
|
||||||
/**
|
/**
|
||||||
* Initializes the storage with default preferences if they are not already set.
|
* Initializes the storage with default preferences if they are not already set.
|
||||||
@ -77,9 +80,9 @@ export interface StorageProvider<
|
|||||||
*
|
*
|
||||||
* @param maxItems - The maximum number of items to retrieve. If not provided, all items will be retrieved.
|
* @param maxItems - The maximum number of items to retrieve. If not provided, all items will be retrieved.
|
||||||
* @param nextPageToken - The token for the next page of results. If not provided, the first page will be retrieved.
|
* @param nextPageToken - The token for the next page of results. If not provided, the first page will be retrieved.
|
||||||
* @returns A promise that resolves to an object containing ç
|
* @returns A promise that resolves to an object containing:
|
||||||
* - the retrieved rooms,
|
* - the retrieved rooms.
|
||||||
* - a boolean indicating if there are more items to retrieve
|
* - a boolean indicating if there are more items to retrieve.
|
||||||
* - an optional next page token.
|
* - an optional next page token.
|
||||||
*/
|
*/
|
||||||
getMeetRooms(
|
getMeetRooms(
|
||||||
@ -94,7 +97,7 @@ export interface StorageProvider<
|
|||||||
/**
|
/**
|
||||||
* Retrieves the {@link MeetRoom}.
|
* Retrieves the {@link MeetRoom}.
|
||||||
*
|
*
|
||||||
* @param roomId - The name of the room to retrieve.
|
* @param roomId - The identifier of the room to retrieve.
|
||||||
* @returns A promise that resolves to the OpenVidu Room, or null if not found.
|
* @returns A promise that resolves to the OpenVidu Room, or null if not found.
|
||||||
**/
|
**/
|
||||||
getMeetRoom(roomId: string): Promise<MRoom | null>;
|
getMeetRoom(roomId: string): Promise<MRoom | null>;
|
||||||
@ -103,14 +106,14 @@ export interface StorageProvider<
|
|||||||
* Saves the OpenVidu Meet Room.
|
* Saves the OpenVidu Meet Room.
|
||||||
*
|
*
|
||||||
* @param meetRoom - The OpenVidu Room to save.
|
* @param meetRoom - The OpenVidu Room to save.
|
||||||
* @returns A promise that resolves to the saved
|
* @returns A promise that resolves to the saved OpenVidu Room.
|
||||||
**/
|
**/
|
||||||
saveMeetRoom(meetRoom: MRoom): Promise<MRoom>;
|
saveMeetRoom(meetRoom: MRoom): Promise<MRoom>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes OpenVidu Meet Rooms.
|
* Deletes OpenVidu Meet Rooms.
|
||||||
*
|
*
|
||||||
* @param roomIds - The room names to delete.
|
* @param roomIds - The room IDs to delete.
|
||||||
* @returns A promise that resolves when the room have been deleted.
|
* @returns A promise that resolves when the room have been deleted.
|
||||||
**/
|
**/
|
||||||
deleteMeetRooms(roomIds: string[]): Promise<void>;
|
deleteMeetRooms(roomIds: string[]): Promise<void>;
|
||||||
@ -194,6 +197,7 @@ export interface StorageProvider<
|
|||||||
start: number;
|
start: number;
|
||||||
}
|
}
|
||||||
): Promise<Readable>;
|
): Promise<Readable>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes multiple recording binary files by their paths.
|
* Deletes multiple recording binary files by their paths.
|
||||||
*
|
*
|
||||||
@ -201,4 +205,20 @@ export interface StorageProvider<
|
|||||||
* @returns A promise that resolves when the recording binary files have been deleted.
|
* @returns A promise that resolves when the recording binary files have been deleted.
|
||||||
*/
|
*/
|
||||||
deleteRecordingBinaryFilesByPaths(recordingPaths: string[]): Promise<void>;
|
deleteRecordingBinaryFilesByPaths(recordingPaths: string[]): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the user data for a specific username.
|
||||||
|
*
|
||||||
|
* @param username - The username of the user to retrieve.
|
||||||
|
* @returns A promise that resolves to the user data, or null if not found.
|
||||||
|
*/
|
||||||
|
getUser(username: string): Promise<MUser | null>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the user data.
|
||||||
|
*
|
||||||
|
* @param user - The user data to save.
|
||||||
|
* @returns A promise that resolves to the saved user data.
|
||||||
|
*/
|
||||||
|
saveUser(user: MUser): Promise<MUser>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
import { AuthMode, AuthType, GlobalPreferences, MeetRecordingInfo, MeetRoom } from '@typings-ce';
|
import { AuthMode, AuthType, GlobalPreferences, MeetRecordingInfo, MeetRoom, User, UserRole } from '@typings-ce';
|
||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import ms from 'ms';
|
import ms from 'ms';
|
||||||
import { MEET_NAME_ID, MEET_SECRET, MEET_USER, MEET_WEBHOOK_ENABLED, MEET_WEBHOOK_URL } from '../../environment.js';
|
import { Readable } from 'stream';
|
||||||
|
import {
|
||||||
|
MEET_ADMIN_SECRET,
|
||||||
|
MEET_ADMIN_USER,
|
||||||
|
MEET_NAME_ID,
|
||||||
|
MEET_WEBHOOK_ENABLED,
|
||||||
|
MEET_WEBHOOK_URL
|
||||||
|
} from '../../environment.js';
|
||||||
import { MeetLock, PasswordHelper } from '../../helpers/index.js';
|
import { MeetLock, PasswordHelper } from '../../helpers/index.js';
|
||||||
import { errorRoomNotFound, internalError, OpenViduMeetError } from '../../models/error.model.js';
|
import { errorRoomNotFound, internalError, OpenViduMeetError } from '../../models/error.model.js';
|
||||||
import { LoggerService, MutexService, StorageFactory, StorageProvider } from '../index.js';
|
import { LoggerService, MutexService, StorageFactory, StorageProvider } from '../index.js';
|
||||||
import { Readable } from 'stream';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service for managing storage operations related to OpenVidu Meet rooms and preferences.
|
* A service for managing storage operations related to OpenVidu Meet rooms and preferences.
|
||||||
@ -20,9 +26,11 @@ import { Readable } from 'stream';
|
|||||||
export class MeetStorageService<
|
export class MeetStorageService<
|
||||||
GPrefs extends GlobalPreferences = GlobalPreferences,
|
GPrefs extends GlobalPreferences = GlobalPreferences,
|
||||||
MRoom extends MeetRoom = MeetRoom,
|
MRoom extends MeetRoom = MeetRoom,
|
||||||
MRec extends MeetRecordingInfo = MeetRecordingInfo
|
MRec extends MeetRecordingInfo = MeetRecordingInfo,
|
||||||
|
MUser extends User = User
|
||||||
> {
|
> {
|
||||||
protected storageProvider: StorageProvider;
|
protected storageProvider: StorageProvider;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject(LoggerService) protected logger: LoggerService,
|
@inject(LoggerService) protected logger: LoggerService,
|
||||||
@inject(StorageFactory) protected storageFactory: StorageFactory,
|
@inject(StorageFactory) protected storageFactory: StorageFactory,
|
||||||
@ -68,10 +76,10 @@ export class MeetStorageService<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes default preferences if not already initialized.
|
* Initializes default preferences if not already initialized and saves the admin user.
|
||||||
* @returns {Promise<GPrefs>} Default global preferences.
|
* @returns {Promise<GPrefs>} Default global preferences.
|
||||||
*/
|
*/
|
||||||
async initializeGlobalPreferences(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// Acquire a global lock to prevent multiple initializations at the same time when running in HA mode
|
// Acquire a global lock to prevent multiple initializations at the same time when running in HA mode
|
||||||
const lock = await this.mutexService.acquire(MeetLock.getGlobalPreferencesLock(), ms('30s'));
|
const lock = await this.mutexService.acquire(MeetLock.getGlobalPreferencesLock(), ms('30s'));
|
||||||
@ -83,10 +91,17 @@ export class MeetStorageService<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const preferences = await this.getDefaultPreferences();
|
|
||||||
|
|
||||||
this.logger.verbose('Initializing global preferences with default values');
|
this.logger.verbose('Initializing global preferences with default values');
|
||||||
|
const preferences = await this.getDefaultPreferences();
|
||||||
await this.storageProvider.initialize(preferences);
|
await this.storageProvider.initialize(preferences);
|
||||||
|
|
||||||
|
// Save the default admin user
|
||||||
|
const admin = {
|
||||||
|
username: MEET_ADMIN_USER,
|
||||||
|
passwordHash: await PasswordHelper.hashPassword(MEET_ADMIN_SECRET),
|
||||||
|
roles: [UserRole.ADMIN, UserRole.USER]
|
||||||
|
} as MUser;
|
||||||
|
await this.saveUser(admin);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError(error, 'Error initializing default preferences');
|
this.handleError(error, 'Error initializing default preferences');
|
||||||
}
|
}
|
||||||
@ -101,7 +116,7 @@ export class MeetStorageService<
|
|||||||
|
|
||||||
if (preferences) return preferences as GPrefs;
|
if (preferences) return preferences as GPrefs;
|
||||||
|
|
||||||
await this.initializeGlobalPreferences();
|
await this.initialize();
|
||||||
preferences = await this.storageProvider.getGlobalPreferences();
|
preferences = await this.storageProvider.getGlobalPreferences();
|
||||||
|
|
||||||
if (!preferences) {
|
if (!preferences) {
|
||||||
@ -125,8 +140,8 @@ export class MeetStorageService<
|
|||||||
/**
|
/**
|
||||||
* Saves the meet room to the storage provider.
|
* Saves the meet room to the storage provider.
|
||||||
*
|
*
|
||||||
* @param meetRoom - The meeting room object to be saved
|
* @param meetRoom - The room object to be saved
|
||||||
* @returns A promise that resolves to the saved meeting room object
|
* @returns A promise that resolves to the saved room object
|
||||||
*/
|
*/
|
||||||
async saveMeetRoom(meetRoom: MRoom): Promise<MRoom> {
|
async saveMeetRoom(meetRoom: MRoom): Promise<MRoom> {
|
||||||
this.logger.info(`Saving OpenVidu room ${meetRoom.roomId}`);
|
this.logger.info(`Saving OpenVidu room ${meetRoom.roomId}`);
|
||||||
@ -134,12 +149,12 @@ export class MeetStorageService<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a paginated list of meeting rooms from the storage provider.
|
* Retrieves a paginated list of rooms from the storage provider.
|
||||||
*
|
*
|
||||||
* @param maxItems - Optional maximum number of rooms to retrieve in a single request
|
* @param maxItems - Optional maximum number of rooms to retrieve in a single request
|
||||||
* @param nextPageToken - Optional token for pagination to get the next page of results
|
* @param nextPageToken - Optional token for pagination to get the next page of results
|
||||||
* @returns A promise that resolves to an object containing:
|
* @returns A promise that resolves to an object containing:
|
||||||
* - rooms: Array of MRoom objects representing the meeting rooms
|
* - rooms: Array of MRoom objects representing the rooms
|
||||||
* - isTruncated: Boolean indicating if there are more results available
|
* - isTruncated: Boolean indicating if there are more results available
|
||||||
* - nextPageToken: Optional token for retrieving the next page of results
|
* - nextPageToken: Optional token for retrieving the next page of results
|
||||||
*/
|
*/
|
||||||
@ -159,7 +174,7 @@ export class MeetStorageService<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the preferences associated with a specific room.
|
* Retrieves the room by its unique identifier.
|
||||||
*
|
*
|
||||||
* @param roomId - The unique identifier for the room.
|
* @param roomId - The unique identifier for the room.
|
||||||
* @returns A promise that resolves to the room's preferences.
|
* @returns A promise that resolves to the room's preferences.
|
||||||
@ -177,7 +192,7 @@ export class MeetStorageService<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes multiple meeting rooms from storage.
|
* Deletes multiple rooms from storage.
|
||||||
*
|
*
|
||||||
* @param roomIds - Array of room identifiers to be deleted
|
* @param roomIds - Array of room identifiers to be deleted
|
||||||
* @returns A promise that resolves when all rooms have been successfully deleted
|
* @returns A promise that resolves when all rooms have been successfully deleted
|
||||||
@ -305,6 +320,27 @@ export class MeetStorageService<
|
|||||||
return this.storageProvider.deleteRecordingBinaryFilesByPaths(recordingPaths);
|
return this.storageProvider.deleteRecordingBinaryFilesByPaths(recordingPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves user data for a specific username.
|
||||||
|
*
|
||||||
|
* @param username - The username of the user to retrieve
|
||||||
|
* @returns A promise that resolves to the user data, or null if not found
|
||||||
|
*/
|
||||||
|
async getUser(username: string): Promise<MUser | null> {
|
||||||
|
return this.storageProvider.getUser(username) as Promise<MUser | null>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves user data to the storage provider.
|
||||||
|
*
|
||||||
|
* @param user - The user data to be saved
|
||||||
|
* @returns A promise that resolves to the saved user data
|
||||||
|
*/
|
||||||
|
async saveUser(user: MUser): Promise<MUser> {
|
||||||
|
this.logger.info(`Saving user data for ${user.username}`);
|
||||||
|
return this.storageProvider.saveUser(user) as Promise<MUser>;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the default global preferences.
|
* Returns the default global preferences.
|
||||||
* @returns {GPrefs}
|
* @returns {GPrefs}
|
||||||
@ -317,19 +353,11 @@ export class MeetStorageService<
|
|||||||
url: MEET_WEBHOOK_URL
|
url: MEET_WEBHOOK_URL
|
||||||
},
|
},
|
||||||
securityPreferences: {
|
securityPreferences: {
|
||||||
roomCreationPolicy: {
|
|
||||||
allowRoomCreation: true,
|
|
||||||
requireAuthentication: true
|
|
||||||
},
|
|
||||||
authentication: {
|
authentication: {
|
||||||
authMode: AuthMode.NONE,
|
authMethod: {
|
||||||
method: {
|
type: AuthType.SINGLE_USER
|
||||||
type: AuthType.SINGLE_USER,
|
},
|
||||||
credentials: {
|
authModeToAccessRoom: AuthMode.NONE
|
||||||
username: MEET_USER,
|
|
||||||
passwordHash: await PasswordHelper.hashPassword(MEET_SECRET)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} as GPrefs;
|
} as GPrefs;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user