UNPKG

@sync-in/server

Version:

The secure, open-source platform for file storage, sharing, collaboration, and sync

570 lines (568 loc) 33.6 kB
/* * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com> * This file is part of Sync-in | The open source file sync and share solution * See the LICENSE file for licensing details */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "UsersQueries", { enumerable: true, get: function() { return UsersQueries; } }); const _common = require("@nestjs/common"); const _drizzleorm = require("drizzle-orm"); const _mysqlcore = require("drizzle-orm/mysql-core"); const _functions = require("../../../common/functions"); const _cachedecorator = require("../../../infrastructure/cache/cache.decorator"); const _cacheservice = require("../../../infrastructure/cache/services/cache.service"); const _constants = require("../../../infrastructure/database/constants"); const _databaseinterface = require("../../../infrastructure/database/interfaces/database.interface"); const _utils = require("../../../infrastructure/database/utils"); const _group = require("../constants/group"); const _member = require("../constants/member"); const _user = require("../constants/user"); const _groupsschema = require("../schemas/groups.schema"); const _usersgroupsschema = require("../schemas/users-groups.schema"); const _usersguestsschema = require("../schemas/users-guests.schema"); const _usersschema = require("../schemas/users.schema"); function _ts_decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function _ts_metadata(k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); } function _ts_param(paramIndex, decorator) { return function(target, key) { decorator(target, key, paramIndex); }; } let UsersQueries = class UsersQueries { checkUserExists(login, email) { if (!login && !email) { throw new Error('login or email must be specified'); } const columns = {}; const where = []; if (login) { columns.login = true; where.push((0, _drizzleorm.eq)(_usersschema.users.login, login)); } if (email) { columns.email = true; where.push((0, _drizzleorm.eq)(_usersschema.users.email, email)); } const operator = login && email ? _drizzleorm.or : _drizzleorm.and; return this.db.query.users.findFirst({ columns: columns, where: operator(...where) }); } setOnlineStatus(userId, onlineStatus) { return this.updateUserOrGuest(userId, { onlineStatus: onlineStatus }); } getOnlineUsers(userIds) { return this.db.select({ id: _usersschema.users.id, login: _usersschema.users.login, email: _usersschema.users.email, fullName: (0, _usersschema.userFullNameSQL)(_usersschema.users), onlineStatus: _usersschema.users.onlineStatus }).from(_usersschema.users).where((0, _drizzleorm.inArray)(_usersschema.users.id, userIds)); } async checkGroupNameExists(groupName) { const [group] = await this.db.select({ name: _groupsschema.groups.name }).from(_groupsschema.groups).where((0, _drizzleorm.eq)(_groupsschema.groups.name, groupName)).limit(1); return !!group?.name; } async compareUserPassword(userId, password) { const [hash] = await this.selectUsers([ 'password' ], [ (0, _drizzleorm.eq)(_usersschema.users.id, userId) ]); if (!hash) return false; return (0, _functions.comparePassword)(password, hash.password); } async from(userId, loginOrEmail) { // retrieve user with application permissions let pQuery = userId ? this.fromIdPermissionsQuery : this.fromLoginOrEmailPermissionsQuery; if (!pQuery) { const where = userId ? (0, _drizzleorm.eq)(_usersschema.users.id, _drizzleorm.sql.placeholder('userId')) : (0, _drizzleorm.or)((0, _drizzleorm.eq)(_usersschema.users.login, _drizzleorm.sql.placeholder('loginOrEmail')), (0, _drizzleorm.eq)(_usersschema.users.email, _drizzleorm.sql.placeholder('loginOrEmail'))); pQuery = this.db.select({ user: _usersschema.users, groupsPermissions: (0, _drizzleorm.sql)`GROUP_CONCAT(DISTINCT (${_groupsschema.groups.permissions}) SEPARATOR ${_user.USER_PERMS_SEP})` }).from(_usersschema.users).leftJoin(_usersgroupsschema.usersGroups, (0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.userId, _usersschema.users.id)).leftJoin(_groupsschema.groups, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_groupsschema.groups.id, _usersgroupsschema.usersGroups.groupId), (0, _drizzleorm.ne)(_groupsschema.groups.permissions, ''))).where(where).groupBy(_usersschema.users.id).limit(1).prepare(); if (userId) { this.fromIdPermissionsQuery = pQuery; } else { this.fromLoginOrEmailPermissionsQuery = pQuery; } } const r = await pQuery.execute(userId ? { userId } : { loginOrEmail }); if (!r.length) return null; const [user, groupsPermissions] = [ r[0].user, r[0].groupsPermissions ]; // merge user and groups permissions user.permissions = (0, _functions.uniquePermissions)(`${user.permissions},${groupsPermissions}`, _user.USER_PERMS_SEP); return user; } selectUsers(fields = [ 'id', 'login', 'email' ], where) { const select = (0, _utils.convertToSelect)(_usersschema.users, fields); return this.db.select(select).from(_usersschema.users).where((0, _drizzleorm.and)(...where)); } async selectUserProperties(userId, fields) { const select = (0, _utils.convertToSelect)(_usersschema.users, fields); const [r] = await this.db.select(select).from(_usersschema.users).where((0, _drizzleorm.eq)(_usersschema.users.id, userId)).limit(1); return r; } async createUserOrGuest(createUserDto, userRole) { const userId = (0, _utils.dbGetInsertedId)(await this.db.insert(_usersschema.users).values({ ...createUserDto, role: userRole })); if (userRole === _user.USER_ROLE.USER && createUserDto.groups?.length) { await this.db.insert(_usersgroupsschema.usersGroups).values(createUserDto.groups.map((gid)=>({ userId: userId, groupId: gid }))); } if (userRole === _user.USER_ROLE.GUEST && createUserDto.managers?.length) { await this.db.insert(_usersguestsschema.usersGuests).values(createUserDto.managers.map((uid)=>({ guestId: userId, userId: uid }))); } return userId; } async updateUserOrGuest(userId, set, userRole) { try { (0, _utils.dbCheckAffectedRows)(await this.db.update(_usersschema.users).set({ ...set, ...userRole && { role: userRole } }).where((0, _drizzleorm.eq)(_usersschema.users.id, userId)), 1); this.logger.verbose(`${this.updateUserOrGuest.name} - user (${userId}) was updated : ${JSON.stringify((0, _functions.anonymizePassword)(set))}`); return true; } catch (e) { this.logger.error(`${this.updateUserOrGuest.name} - user (${userId}) was not updated : ${JSON.stringify((0, _functions.anonymizePassword)(set))} : ${e}`); return false; } } async deleteGuestLink(userId) { (0, _utils.dbCheckAffectedRows)(await this.db.delete(_usersschema.users).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_usersschema.users.id, userId), (0, _drizzleorm.eq)(_usersschema.users.role, _user.USER_ROLE.LINK))), 1); } async searchUsersOrGroups(searchMembersDto, userId) { const limit = searchMembersDto.onlyUsers || searchMembersDto.onlyGroups ? 6 : 3; const members = []; if (!searchMembersDto.onlyGroups) { for (const u of (await this.searchUsers(searchMembersDto, userId, limit))){ members.push({ id: u.id, login: u.login, name: u.fullName, description: u.email, type: u.role === _user.USER_ROLE.GUEST ? _member.MEMBER_TYPE.GUEST : _member.MEMBER_TYPE.USER, permissions: searchMembersDto.withPermissions ? u.permissions : undefined }); } } if (!searchMembersDto.onlyUsers) { for (const g of (await this.searchGroups(searchMembersDto, userId, limit))){ members.push({ id: g.id, name: g.name, description: g.description, type: g.type === _group.GROUP_TYPE.USER ? _member.MEMBER_TYPE.GROUP : _member.MEMBER_TYPE.PGROUP, permissions: searchMembersDto.withPermissions ? g.permissions : undefined }); } } return members; } async groupFromName(userId, name) { const [group] = await this.db.select({ id: _groupsschema.groups.id, name: _groupsschema.groups.name, type: _groupsschema.groups.type, role: _usersgroupsschema.usersGroups.role }).from(_usersgroupsschema.usersGroups).innerJoin(_groupsschema.groups, (0, _drizzleorm.eq)(_groupsschema.groups.id, _usersgroupsschema.usersGroups.groupId)).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.userId, userId), (0, _drizzleorm.eq)(_groupsschema.groups.name, name))).limit(1); return group; } async browseRootGroups(userId) { const members = (0, _mysqlcore.alias)(_usersgroupsschema.usersGroups, 'members'); return this.db.select({ id: _groupsschema.groups.id, name: _groupsschema.groups.name, description: _groupsschema.groups.description, createdAt: _groupsschema.groups.createdAt, modifiedAt: _groupsschema.groups.modifiedAt, type: (0, _drizzleorm.sql)`IF(${_groupsschema.groups.type} = ${_group.GROUP_TYPE.USER}, ${_member.MEMBER_TYPE.GROUP}, ${_member.MEMBER_TYPE.PGROUP})`, groupRole: (0, _drizzleorm.sql)`${_usersgroupsschema.usersGroups.role}`, counts: { users: (0, _drizzleorm.countDistinct)(members.userId) } }).from(_usersgroupsschema.usersGroups).innerJoin(_groupsschema.groups, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_groupsschema.groups.id, _usersgroupsschema.usersGroups.groupId), (0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.userId, userId))).leftJoin(members, (0, _drizzleorm.eq)(members.groupId, _groupsschema.groups.id)).groupBy(_groupsschema.groups.id); } async browseGroupMembers(groupId) { return this.db.select({ id: _usersschema.users.id, login: _usersschema.users.login, name: (0, _usersschema.userFullNameSQL)(_usersschema.users).as('name'), description: _usersschema.users.email, createdAt: _usersgroupsschema.usersGroups.createdAt, type: (0, _drizzleorm.sql)`${_member.MEMBER_TYPE.USER}`, groupRole: (0, _drizzleorm.sql)`${_usersgroupsschema.usersGroups.role}` }).from(_groupsschema.groups).innerJoin(_usersgroupsschema.usersGroups, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.groupId, _groupsschema.groups.id), (0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.groupId, groupId))).leftJoin(_usersschema.users, (0, _drizzleorm.eq)(_usersschema.users.id, _usersgroupsschema.usersGroups.userId)).groupBy(_usersschema.users.id); } async canDeletePersonalGroup(userId, groupId) { const [group] = await this.db.select({ id: _usersgroupsschema.usersGroups.groupId }).from(_usersgroupsschema.usersGroups).innerJoin(_groupsschema.groups, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_groupsschema.groups.id, _usersgroupsschema.usersGroups.groupId))).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_groupsschema.groups.type, _group.GROUP_TYPE.PERSONAL), (0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.userId, userId), (0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.groupId, groupId), (0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.role, _user.USER_GROUP_ROLE.MANAGER))).limit(1); return !!group?.id; } async getGroup(userId, groupId, asAdmin = false) { const [group] = await this.db.select({ id: _groupsschema.groups.id, name: _groupsschema.groups.name, description: _groupsschema.groups.description, createdAt: _groupsschema.groups.createdAt, modifiedAt: _groupsschema.groups.modifiedAt, type: (0, _drizzleorm.sql)`IF(${_groupsschema.groups.type} = ${_group.GROUP_TYPE.USER}, ${_member.MEMBER_TYPE.GROUP}, ${_member.MEMBER_TYPE.PGROUP})` }).from(_usersgroupsschema.usersGroups).innerJoin(_groupsschema.groups, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_groupsschema.groups.id, _usersgroupsschema.usersGroups.groupId))).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.groupId, groupId), (0, _drizzleorm.sql)`IF(${+asAdmin} = 0, ${_usersgroupsschema.usersGroups.userId} = ${userId} AND ${_usersgroupsschema.usersGroups.role} = ${_user.USER_GROUP_ROLE.MANAGER}, 1)`)).limit(1); return group; } async getGroupWithMembers(userId, groupId, asAdmin = false) { const usersGroupsAlias = (0, _mysqlcore.alias)(_usersgroupsschema.usersGroups, 'usersFromGroups'); const [group] = await this.db.select({ id: _groupsschema.groups.id, name: _groupsschema.groups.name, description: _groupsschema.groups.description, createdAt: _groupsschema.groups.createdAt, modifiedAt: _groupsschema.groups.modifiedAt, type: (0, _drizzleorm.sql)`IF(${_groupsschema.groups.type} = ${_group.GROUP_TYPE.USER}, ${_drizzleorm.sql.raw(`'${_member.MEMBER_TYPE.GROUP}'`)}, ${_drizzleorm.sql.raw(`'${_member.MEMBER_TYPE.PGROUP}'`)})`, members: (0, _utils.concatDistinctObjectsInArray)(_usersschema.users.id, { id: _usersschema.users.id, login: _usersschema.users.login, name: (0, _usersschema.userFullNameSQL)(_usersschema.users), description: _usersschema.users.email, type: _drizzleorm.sql.raw(`'${_member.MEMBER_TYPE.USER}'`), groupRole: usersGroupsAlias.role, createdAt: (0, _utils.dateTimeUTC)(usersGroupsAlias.createdAt) }) }).from(_usersgroupsschema.usersGroups).innerJoin(_groupsschema.groups, (0, _drizzleorm.eq)(_groupsschema.groups.id, _usersgroupsschema.usersGroups.groupId)).leftJoin(usersGroupsAlias, (0, _drizzleorm.and)((0, _drizzleorm.eq)(usersGroupsAlias.groupId, _groupsschema.groups.id))).leftJoin(_usersschema.users, (0, _drizzleorm.eq)(_usersschema.users.id, usersGroupsAlias.userId)).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.groupId, groupId), (0, _drizzleorm.sql)`IF(${+asAdmin} = 0, ${_usersgroupsschema.usersGroups.userId} = ${userId} AND ${_usersgroupsschema.usersGroups.role} = ${_user.USER_GROUP_ROLE.MANAGER}, 1)`)).groupBy(_groupsschema.groups.id).limit(1); return group; } async deletePersonalGroup(groupId) { return (0, _utils.dbCheckAffectedRows)(await this.db.delete(_groupsschema.groups).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_groupsschema.groups.id, groupId), (0, _drizzleorm.eq)(_groupsschema.groups.type, _group.GROUP_TYPE.PERSONAL))).limit(1), 1, false); } async createPersonalGroup(managerId, userCreateOrUpdateGroupDto) { const groupId = (0, _utils.dbGetInsertedId)(await this.db.insert(_groupsschema.groups).values({ ...userCreateOrUpdateGroupDto, type: _group.GROUP_TYPE.PERSONAL, visibility: _group.GROUP_VISIBILITY.PRIVATE })); await this.db.insert(_usersgroupsschema.usersGroups).values({ userId: managerId, groupId: groupId, role: _user.USER_GROUP_ROLE.MANAGER }); return groupId; } async updateGroup(groupId, set) { if (Object.keys(set).length) { try { await this.db.update(_groupsschema.groups).set(set).where((0, _drizzleorm.eq)(_groupsschema.groups.id, groupId)); this.logger.log(`${this.updateGroup.name} - group (${groupId}) was updated : ${JSON.stringify(set)}`); } catch (e) { this.logger.error(`${this.updateGroup.name} - group (${groupId}) was not updated : ${JSON.stringify(set)} : ${e}`); throw new Error('Group was not updated'); } } } async updateGroupMembers(groupId, members) { if (members?.add?.length) { try { await this.db.insert(_usersgroupsschema.usersGroups).values(members.add.map((m)=>({ userId: m.id, groupId: groupId, role: m.groupRole }))); // clear cache this.clearWhiteListCaches(members.add.map((m)=>m.id)); this.logger.log(`${this.updateGroupMembers.name} - users ${JSON.stringify(members.add.map((m)=>m.id))} was added to group (${groupId})`); } catch (e) { this.logger.error(`${this.updateGroupMembers.name} - users ${JSON.stringify(members.add.map((m)=>m.id))} was not added to group (${groupId}) : ${e}`); throw new Error('Group members was not added'); } } if (members?.remove?.length) { try { await this.db.delete(_usersgroupsschema.usersGroups).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.groupId, groupId), (0, _drizzleorm.inArray)(_usersgroupsschema.usersGroups.userId, members.remove))).limit(members.remove.length); // clear cache this.clearWhiteListCaches(members.remove); this.logger.log(`${this.updateGroupMembers.name} - users ${JSON.stringify(members.remove)} was removed from group (${groupId})`); } catch (e) { this.logger.error(`${this.updateGroupMembers.name} - users ${JSON.stringify(members.remove)} was not removed from group (${groupId}) : ${e}`); throw new Error('Group members was not removed'); } } } async listGuests(guestId, managerId, asAdmin = false) { const where = [ ...guestId ? [ (0, _drizzleorm.eq)(_usersguestsschema.usersGuests.guestId, guestId) ] : [], ...asAdmin ? [] : [ (0, _drizzleorm.eq)(_usersguestsschema.usersGuests.userId, managerId) ] ]; const managersGuestAlias = (0, _mysqlcore.alias)(_usersguestsschema.usersGuests, 'managersGuestAlias'); const managersAlias = (0, _mysqlcore.alias)(_usersschema.users, 'managersAlias'); const guests = await this.db.select({ id: _usersschema.users.id, login: _usersschema.users.login, email: _usersschema.users.email, firstName: _usersschema.users.firstName, lastName: _usersschema.users.lastName, fullName: (0, _usersschema.userFullNameSQL)(_usersschema.users), role: _usersschema.users.role, isActive: _usersschema.users.isActive, passwordAttempts: _usersschema.users.passwordAttempts, language: _usersschema.users.language, notification: _usersschema.users.notification, currentAccess: _usersschema.users.currentAccess, lastAccess: _usersschema.users.lastAccess, currentIp: _usersschema.users.currentIp, lastIp: _usersschema.users.lastIp, createdAt: _usersschema.users.createdAt, managers: (0, _utils.concatDistinctObjectsInArray)(managersAlias.id, { id: managersAlias.id, login: managersAlias.login, name: (0, _usersschema.userFullNameSQL)(managersAlias), type: _drizzleorm.sql.raw(`'${_member.MEMBER_TYPE.USER}'`), description: managersAlias.email, createdAt: (0, _utils.dateTimeUTC)(managersGuestAlias.createdAt) }) }).from(_usersguestsschema.usersGuests).innerJoin(_usersschema.users, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_usersschema.users.id, _usersguestsschema.usersGuests.guestId), (0, _drizzleorm.eq)(_usersschema.users.role, _user.USER_ROLE.GUEST))).leftJoin(managersGuestAlias, (0, _drizzleorm.eq)(managersGuestAlias.guestId, _usersschema.users.id)).leftJoin(managersAlias, (0, _drizzleorm.eq)(managersAlias.id, managersGuestAlias.userId)).where((0, _drizzleorm.and)(...where)).groupBy(_usersschema.users.id).limit(guestId ? 1 : undefined); return guestId ? guests[0] : guests; } async isGuestManager(managerId, guestId) { const [guest] = await this.db.select({ id: _usersguestsschema.usersGuests.guestId, login: _usersschema.users.login }).from(_usersguestsschema.usersGuests).innerJoin(_usersschema.users, (0, _drizzleorm.eq)(_usersschema.users.id, _usersguestsschema.usersGuests.guestId)).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_usersguestsschema.usersGuests.userId, managerId), (0, _drizzleorm.eq)(_usersguestsschema.usersGuests.guestId, guestId), (0, _drizzleorm.eq)(_usersschema.users.role, _user.USER_ROLE.GUEST))).limit(1); return guest; } async searchGroups(searchMembersDto, userId, limit = 3) { /* Search for groups */ const where = [ (0, _drizzleorm.like)(_groupsschema.groups.name, `%${searchMembersDto.search}%`) ]; if (userId) { let idsWhitelist = await this.groupsWhitelist(userId); if (searchMembersDto.ignoreGroupIds?.length) { idsWhitelist = idsWhitelist.filter((id)=>searchMembersDto.ignoreGroupIds.indexOf(id) === -1); } where.unshift((0, _drizzleorm.inArray)(_groupsschema.groups.id, idsWhitelist)); } else if (searchMembersDto.ignoreGroupIds?.length) { where.unshift((0, _drizzleorm.notInArray)(_groupsschema.groups.id, searchMembersDto.ignoreGroupIds)); } if (searchMembersDto.excludePersonalGroups) { where.unshift((0, _drizzleorm.eq)(_groupsschema.groups.type, _group.GROUP_TYPE.USER)); } return this.db.select({ id: _groupsschema.groups.id, name: _groupsschema.groups.name, description: _groupsschema.groups.description, type: _groupsschema.groups.type, permissions: _groupsschema.groups.permissions }).from(_groupsschema.groups).where((0, _drizzleorm.and)(...where)).limit(limit); } async searchUsers(searchMembersDto, userId, limit = 3) { /* Search for users */ const where = [ (0, _drizzleorm.ne)(_usersschema.users.role, _user.USER_ROLE.LINK), (0, _drizzleorm.or)((0, _drizzleorm.like)((0, _drizzleorm.sql)`CONCAT_WS('-', ${_usersschema.users.login}, ${_usersschema.users.email}, ${_usersschema.users.firstName}, ${_usersschema.users.lastName})`, `%${searchMembersDto.search}%`)) ]; if (userId) { let idsWhitelist = await this.usersWhitelist(userId); if (searchMembersDto.ignoreUserIds?.length) { idsWhitelist = idsWhitelist.filter((id)=>searchMembersDto.ignoreUserIds.indexOf(id) === -1); } where.unshift((0, _drizzleorm.inArray)(_usersschema.users.id, idsWhitelist)); } else { if (searchMembersDto.ignoreUserIds?.length) { where.unshift((0, _drizzleorm.notInArray)(_usersschema.users.id, searchMembersDto.ignoreUserIds)); } } if (typeof searchMembersDto.usersRole !== 'undefined') { if (searchMembersDto.usersRole === _user.USER_ROLE.USER) { // allow admin users where.unshift((0, _drizzleorm.lte)(_usersschema.users.role, searchMembersDto.usersRole)); } else { where.unshift((0, _drizzleorm.eq)(_usersschema.users.role, searchMembersDto.usersRole)); } } return this.db.select({ id: _usersschema.users.id, login: _usersschema.users.login, email: _usersschema.users.email, fullName: (0, _usersschema.userFullNameSQL)(_usersschema.users), role: _usersschema.users.role, permissions: _usersschema.users.permissions }).from(_usersschema.users).where((0, _drizzleorm.and)(...where)).limit(limit); } async usersWhitelist(userId, lowerOrEqualUserRole = _user.USER_ROLE.GUEST) { /* Get the list of user ids allowed to the current user - all users with no groups (except link users) - all users who are members of the current user's groups (excluding link users and members of isolated groups) - all guests managed by the current user - all managers who manage the current guest */ const usersAlias = (0, _mysqlcore.alias)(_usersschema.users, 'usersAlias'); const groupsAlias = (0, _mysqlcore.alias)(_groupsschema.groups, 'groupsAlias'); const userIds = (0, _drizzleorm.sql)` WITH RECURSIVE children (id, parentId) AS (SELECT ${_groupsschema.groups.id}, ${_groupsschema.groups.parentId} FROM ${_groupsschema.groups} WHERE (${_groupsschema.groups.id} IN (SELECT ${_usersgroupsschema.usersGroups.groupId} FROM ${_usersgroupsschema.usersGroups} WHERE ${_usersgroupsschema.usersGroups.userId} = ${userId} AND ${_groupsschema.groups.visibility} != ${_group.GROUP_VISIBILITY.ISOLATED})) UNION SELECT ${groupsAlias.id}, ${groupsAlias.parentId} FROM ${_groupsschema.groups} AS groupsAlias INNER JOIN children cs ON ${groupsAlias.parentId} = cs.id AND ${groupsAlias.visibility} = ${_drizzleorm.sql.raw(`${_group.GROUP_VISIBILITY.VISIBLE}`)}) SELECT JSON_ARRAYAGG(id) AS ids FROM ( -- Users from visible child groups SELECT ${_usersschema.users.id} AS id FROM children INNER JOIN ${_usersgroupsschema.usersGroups} ON ${_usersgroupsschema.usersGroups.groupId} = children.id INNER JOIN ${_usersschema.users} ON ${_usersgroupsschema.usersGroups.userId} = ${_usersschema.users.id} AND ${_usersschema.users.role} <= ${_drizzleorm.sql.raw(`${lowerOrEqualUserRole}`)} UNION -- Users visible but not assigned to groups SELECT ${usersAlias.id} AS id FROM ${_usersschema.users} AS usersAlias INNER JOIN ${_usersschema.users} ON ${_usersschema.users.id} = ${usersAlias.id} AND ${_usersschema.users.role} <= ${_drizzleorm.sql.raw(`${lowerOrEqualUserRole}`)} WHERE NOT EXISTS (SELECT ${_usersgroupsschema.usersGroups.userId} FROM ${_usersgroupsschema.usersGroups} WHERE ${_usersgroupsschema.usersGroups.userId} = ${usersAlias.id}) UNION -- Users or guests that are manager/managed SELECT CASE WHEN ${_usersguestsschema.usersGuests.userId} = ${userId} THEN ${_usersguestsschema.usersGuests.guestId} WHEN ${_usersguestsschema.usersGuests.guestId} = ${userId} THEN ${_usersguestsschema.usersGuests.userId} END AS id FROM ${_usersguestsschema.usersGuests} WHERE ${_usersguestsschema.usersGuests.userId} = ${userId} OR ${_usersguestsschema.usersGuests.guestId} = ${userId}) AS usersUnion `; const [r] = await this.db.execute(userIds); return JSON.parse(r[0].ids) || []; } async groupsWhitelist(userId) { /* Get the list of groups ids allowed to the current user - all parent groups for which the user is a member (includes personal groups, excludes isolated groups) - all subgroups inherited from parent groups */ const groupsAlias = (0, _mysqlcore.alias)(_groupsschema.groups, 'groupsAlias'); const groupIds = (0, _drizzleorm.sql)` WITH RECURSIVE children (id, parentId, type) AS (SELECT ${_groupsschema.groups.id}, ${_groupsschema.groups.parentId}, ${_groupsschema.groups.type} FROM ${_groupsschema.groups} WHERE (${_groupsschema.groups.id} IN (SELECT ${_usersgroupsschema.usersGroups.groupId} FROM ${_usersgroupsschema.usersGroups} WHERE ${_usersgroupsschema.usersGroups.userId} = ${userId} AND ${_groupsschema.groups.visibility} != ${_group.GROUP_VISIBILITY.ISOLATED})) UNION SELECT ${groupsAlias.id}, ${groupsAlias.parentId}, ${groupsAlias.type} FROM ${_groupsschema.groups} AS groupsAlias INNER JOIN children cs ON ${groupsAlias.parentId} = cs.id AND ${groupsAlias.visibility} = ${_group.GROUP_VISIBILITY.VISIBLE}) SELECT JSON_ARRAYAGG(children.id) as ids FROM children `; const [r] = await this.db.execute(groupIds); return JSON.parse(r[0].ids) || []; } clearWhiteListCaches(userIds) { this.cache.mdel([ ...userIds.map((id)=>this.cache.genSlugKey(this.constructor.name, this.usersWhitelist.name, id)), ...userIds.map((id)=>this.cache.genSlugKey(this.constructor.name, this.groupsWhitelist.name, id)) ]).catch((e)=>this.logger.error(`${this.clearWhiteListCaches.name} - ${e}`)); } async allUserIdsFromGroupsAndSubGroups(groupIds) { if (!groupIds.length) return []; const subGroup = (0, _mysqlcore.alias)(_groupsschema.groups, 'subGroup'); const withChildren = (0, _drizzleorm.sql)` WITH RECURSIVE child (id, parentId) AS (SELECT ${_groupsschema.groups.id}, ${_groupsschema.groups.parentId} FROM ${_groupsschema.groups} WHERE ${(0, _drizzleorm.inArray)(_groupsschema.groups.id, groupIds)} UNION SELECT ${subGroup.id}, ${subGroup.parentId} FROM ${_groupsschema.groups} AS subGroup INNER JOIN child AS cs ON ${subGroup.parentId} = cs.id) SELECT DISTINCT ${_usersgroupsschema.usersGroups.userId} as userId FROM child INNER JOIN ${_usersgroupsschema.usersGroups} ON child.id = ${_usersgroupsschema.usersGroups.groupId} `; const [r] = await this.db.execute(withChildren); return r.length ? r.map((r)=>r.userId) : []; } constructor(db, cache){ this.db = db; this.cache = cache; this.logger = new _common.Logger(UsersQueries.name); this.fromLoginOrEmailPermissionsQuery = null; this.fromIdPermissionsQuery = null; } }; _ts_decorate([ (0, _cachedecorator.CacheDecorator)(900), _ts_metadata("design:type", Function), _ts_metadata("design:paramtypes", [ Number, typeof _user.USER_ROLE === "undefined" ? Object : _user.USER_ROLE ]), _ts_metadata("design:returntype", Promise) ], UsersQueries.prototype, "usersWhitelist", null); _ts_decorate([ (0, _cachedecorator.CacheDecorator)(900), _ts_metadata("design:type", Function), _ts_metadata("design:paramtypes", [ Number ]), _ts_metadata("design:returntype", Promise) ], UsersQueries.prototype, "groupsWhitelist", null); UsersQueries = _ts_decorate([ (0, _common.Injectable)(), _ts_param(0, (0, _common.Inject)(_constants.DB_TOKEN_PROVIDER)), _ts_metadata("design:type", Function), _ts_metadata("design:paramtypes", [ typeof _databaseinterface.DBSchema === "undefined" ? Object : _databaseinterface.DBSchema, typeof _cacheservice.Cache === "undefined" ? Object : _cacheservice.Cache ]) ], UsersQueries); //# sourceMappingURL=users-queries.service.js.map