UNPKG

@sync-in/server

Version:

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

892 lines 60 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, "SharesQueries", {
    enumerable: true,
    get: function() {
        return SharesQueries;
    }
});
const _common = require("@nestjs/common");
const _drizzleorm = require("drizzle-orm");
const _mysqlcore = require("drizzle-orm/mysql-core");
const _constants = require("../../../common/constants");
const _functions = require("../../../common/functions");
const _shared = require("../../../common/shared");
const _cachedecorator = require("../../../infrastructure/cache/cache.decorator");
const _cacheservice = require("../../../infrastructure/cache/services/cache.service");
const _constants1 = require("../../../infrastructure/database/constants");
const _utils = require("../../../infrastructure/database/utils");
const _commentsschema = require("../../comments/schemas/comments.schema");
const _filesschema = require("../../files/schemas/files.schema");
const _linksschema = require("../../links/schemas/links.schema");
const _spacesrootsschema = require("../../spaces/schemas/spaces-roots.schema");
const _spacesschema = require("../../spaces/schemas/spaces.schema");
const _syncclientsschema = require("../../sync/schemas/sync-clients.schema");
const _syncpathsschema = require("../../sync/schemas/sync-paths.schema");
const _group = require("../../users/constants/group");
const _member = require("../../users/constants/member");
const _user = require("../../users/constants/user");
const _groupsschema = require("../../users/schemas/groups.schema");
const _usersgroupsschema = require("../../users/schemas/users-groups.schema");
const _usersschema = require("../../users/schemas/users.schema");
const _shares = require("../constants/shares");
const _sharechildmodel = require("../models/share-child.model");
const _sharesmembersschema = require("../schemas/shares-members.schema");
const _sharesschema = require("../schemas/shares.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 SharesQueries = class SharesQueries {
    async uniqueShareAlias(name) {
        let alias = (0, _shared.createSlug)(name, true);
        let count = 0;
        // Personal space name is reserved
        while(await this.shareExistsForAlias(alias)){
            count += 1;
            alias = `${name}-${count}`;
        }
        return alias;
    }
    shareExistsForOwner(userId, shareId) {
        return this.db.query.shares.findFirst({
            columns: {
                id: true
            },
            where: (0, _drizzleorm.and)((0, _drizzleorm.eq)(_sharesschema.shares.id, shareId), (0, _drizzleorm.eq)(_sharesschema.shares.ownerId, userId))
        });
    }
    async childExistsForShareOwner(userId, shareId, childId, isAdmin = false) {
        const childShare = (0, _mysqlcore.alias)(_sharesschema.shares, 'childShare');
        const withChildren = (0, _drizzleorm.sql)`
      WITH RECURSIVE child (id, parentId) AS
                       (SELECT ${_sharesschema.shares.id},
                               ${_sharesschema.shares.parentId}
                        FROM ${_sharesschema.shares}
                        WHERE ${_sharesschema.shares.id} = ${shareId}
                          AND (${_sharesschema.shares.ownerId} = ${userId} OR (${_sharesschema.shares.ownerId} IS NULL AND ${+isAdmin} = 1))
                        UNION
                        SELECT ${childShare.id},
                               ${childShare.parentId}
                        FROM ${_sharesschema.shares} AS childShare
                               INNER JOIN child AS cs ON ${childShare.parentId} = cs.id)
      SELECT child.id
      FROM child
      WHERE child.id = ${childId}
      LIMIT 1
    `;
        const [r] = await this.db.execute(withChildren);
        return r.length ? r[0].id : null;
    }
    async findHighestParentShare(childShareId) {
        const parentShare = (0, _mysqlcore.alias)(_sharesschema.shares, 'parentShare');
        const withParents = (0, _drizzleorm.sql)`
      WITH RECURSIVE parent (id, parentId) AS
                       (SELECT ${_sharesschema.shares.id},
                               ${_sharesschema.shares.parentId}
                        FROM ${_sharesschema.shares}
                        WHERE ${_sharesschema.shares.id} = ${childShareId}
                        UNION
                        SELECT ${parentShare.id},
                               ${parentShare.parentId}
                        FROM ${_sharesschema.shares} AS parentShare
                               INNER JOIN parent AS cs ON ${parentShare.id} = cs.parentId)
      SELECT parent.id
      FROM parent
      WHERE parent.parentId is NULL
      LIMIT 1
    `;
        const [r] = await this.db.execute(withParents);
        return r.length ? r[0].id : null;
    }
    selectShares(props) {
        const where = (0, _utils.convertToWhere)(_sharesschema.shares, props);
        return this.db.select({
            id: _sharesschema.shares.id,
            ownerId: _sharesschema.shares.ownerId,
            alias: _sharesschema.shares.alias,
            name: _sharesschema.shares.name
        }).from(_sharesschema.shares).where((0, _drizzleorm.and)(...where));
    }
    selectParentSharesFromSpaceId(spaceId, ownerIds) {
        const where = [
            (0, _drizzleorm.eq)(_sharesschema.shares.spaceId, spaceId),
            (0, _drizzleorm.isNull)(_sharesschema.shares.spaceRootId),
            (0, _drizzleorm.isNull)(_sharesschema.shares.parentId)
        ];
        if (ownerIds && ownerIds.length) {
            where.push((0, _drizzleorm.inArray)(_sharesschema.shares.ownerId, ownerIds));
        }
        return this.db.select({
            id: _sharesschema.shares.id,
            ownerId: _sharesschema.shares.ownerId
        }).from(_sharesschema.shares).where((0, _drizzleorm.and)(...where));
    }
    async listShareLinks(user, shareId, asAdmin = false) {
        if (!this.shareLinksListQuery) {
            const [selectFile, shareRootFile, parentShare, parentShareFile, childShareFromRoot, shareMembers] = this.shareFileSelect();
            const linkGuest = (0, _mysqlcore.alias)(_usersschema.users, 'linkGuest');
            const select = {
                id: _sharesschema.shares.id,
                ownerId: _sharesschema.shares.ownerId,
                name: _sharesschema.shares.name,
                externalPath: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.externalPath} IS NOT NULL AND ${_sharesschema.shares.ownerId} IS NOT NULL, '.', ${_sharesschema.shares.externalPath})`,
                description: _sharesschema.shares.description,
                parent: {
                    id: parentShare.id,
                    ownerId: parentShare.ownerId,
                    alias: parentShare.alias,
                    name: parentShare.name
                },
                file: selectFile,
                link: {
                    id: _linksschema.links.id,
                    name: _linksschema.links.name,
                    email: _linksschema.links.email,
                    uuid: _linksschema.links.uuid,
                    requireAuth: _linksschema.links.requireAuth,
                    nbAccess: _linksschema.links.nbAccess,
                    limitAccess: _linksschema.links.limitAccess,
                    permissions: shareMembers.permissions,
                    isActive: linkGuest.isActive,
                    language: linkGuest.language,
                    expiresAt: _linksschema.links.expiresAt,
                    createdAt: _linksschema.links.createdAt,
                    currentAccess: linkGuest.currentAccess,
                    lastAccess: linkGuest.lastAccess,
                    currentIp: linkGuest.currentIp,
                    lastIp: linkGuest.lastIp
                }
            };
            this.shareLinksListQuery = this.shareFileJoin(select, shareRootFile, parentShare, parentShareFile, childShareFromRoot, shareMembers).innerJoin(_linksschema.links, (0, _drizzleorm.eq)(_linksschema.links.id, shareMembers.linkId)).innerJoin(linkGuest, (0, _drizzleorm.eq)(linkGuest.id, _linksschema.links.userId)).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_sharesschema.shares.type, _shares.SHARE_TYPE.LINK), (0, _drizzleorm.or)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('shareId'), 0), (0, _drizzleorm.eq)(_sharesschema.shares.id, _drizzleorm.sql.placeholder('shareId'))), (0, _drizzleorm.or)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('asAdmin'), 1), (0, _drizzleorm.eq)(_sharesschema.shares.ownerId, _drizzleorm.sql.placeholder('userId')), (0, _drizzleorm.and)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('isAdmin'), 1), (0, _drizzleorm.isNull)(_sharesschema.shares.ownerId))))).prepare();
        }
        const shareLinks = await this.shareLinksListQuery.execute({
            userId: user.id,
            shareId: shareId || 0,
            isAdmin: +user.isAdmin,
            asAdmin: +asAdmin
        });
        if (shareId) {
            return shareLinks.length ? shareLinks[0] : null;
        }
        return shareLinks;
    }
    async getShareWithMembers(user, shareId, asAdmin = false) {
        // asAdmin : true if the user is the owner of the parent share or if the share is requested from the administration
        if (!this.shareWithMembersQuery) {
            const [selectFile, shareRootFile, parentShare, parentShareFile, childShareFromRoot, shareMembers] = this.shareFileSelect();
            const linkUsers = (0, _mysqlcore.alias)(_usersschema.users, 'linkUsers');
            const select = {
                id: _sharesschema.shares.id,
                ownerId: _sharesschema.shares.ownerId,
                name: _sharesschema.shares.name,
                alias: _sharesschema.shares.alias,
                externalPath: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.externalPath} IS NOT NULL AND ${_sharesschema.shares.ownerId} IS NOT NULL, '.', ${_sharesschema.shares.externalPath})`,
                enabled: _sharesschema.shares.enabled,
                description: _sharesschema.shares.description,
                createdAt: _sharesschema.shares.createdAt,
                modifiedAt: _sharesschema.shares.modifiedAt,
                disabledAt: _sharesschema.shares.disabledAt,
                parent: {
                    id: parentShare.id,
                    ownerId: parentShare.ownerId,
                    alias: parentShare.alias,
                    name: parentShare.name
                },
                file: selectFile,
                users: (0, _utils.concatDistinctObjectsInArray)(_usersschema.users.id, {
                    id: _usersschema.users.id,
                    login: _usersschema.users.login,
                    name: (0, _usersschema.userFullNameSQL)(_usersschema.users),
                    type: (0, _drizzleorm.sql)`IF (${_usersschema.users.role} = ${_user.USER_ROLE.GUEST}, ${_member.MEMBER_TYPE.GUEST}, ${_member.MEMBER_TYPE.USER})`,
                    description: _usersschema.users.email,
                    permissions: shareMembers.permissions,
                    createdAt: (0, _utils.dateTimeUTC)(shareMembers.createdAt)
                }),
                groups: (0, _utils.concatDistinctObjectsInArray)(_groupsschema.groups.id, {
                    id: _groupsschema.groups.id,
                    name: _groupsschema.groups.name,
                    type: (0, _drizzleorm.sql)`IF (${_groupsschema.groups.type} = ${_group.GROUP_TYPE.PERSONAL}, ${_member.MEMBER_TYPE.PGROUP}, ${_member.MEMBER_TYPE.GROUP})`,
                    description: _groupsschema.groups.description,
                    permissions: shareMembers.permissions,
                    createdAt: (0, _utils.dateTimeUTC)(shareMembers.createdAt)
                }),
                links: (0, _utils.concatDistinctObjectsInArray)(linkUsers.id, {
                    id: linkUsers.id,
                    linkId: _linksschema.links.id,
                    login: linkUsers.login,
                    name: _linksschema.links.name,
                    type: _drizzleorm.sql.raw(`'${_member.MEMBER_TYPE.USER}'`),
                    description: _linksschema.links.email,
                    permissions: shareMembers.permissions,
                    createdAt: (0, _utils.dateTimeUTC)(shareMembers.createdAt)
                })
            };
            this.shareWithMembersQuery = this.shareFileJoin(select, shareRootFile, parentShare, parentShareFile, childShareFromRoot, shareMembers).leftJoin(_usersschema.users, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(shareMembers.linkId), (0, _drizzleorm.eq)(_usersschema.users.id, shareMembers.userId))).leftJoin(_groupsschema.groups, (0, _drizzleorm.eq)(_groupsschema.groups.id, shareMembers.groupId)).leftJoin(linkUsers, (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(shareMembers.linkId), (0, _drizzleorm.eq)(linkUsers.id, shareMembers.userId))).leftJoin(_linksschema.links, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_linksschema.links.userId, linkUsers.id), (0, _drizzleorm.eq)(_linksschema.links.id, shareMembers.linkId))).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_sharesschema.shares.id, _drizzleorm.sql.placeholder('shareId')), (0, _drizzleorm.or)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('asAdmin'), 1), (0, _drizzleorm.eq)(_sharesschema.shares.ownerId, _drizzleorm.sql.placeholder('userId')), (0, _drizzleorm.and)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('isAdmin'), 1), (0, _drizzleorm.isNull)(_sharesschema.shares.ownerId))))).groupBy(_sharesschema.shares.id).limit(1).prepare();
        }
        const [share] = await this.shareWithMembersQuery.execute({
            userId: user.id,
            shareId,
            isAdmin: +user.isAdmin,
            asAdmin: +asAdmin
        });
        if (!share) return null;
        // merge members
        share.members = [
            ...(0, _shared.popFromObject)('users', share),
            ...(0, _shared.popFromObject)('links', share),
            ...(0, _shared.popFromObject)('groups', share)
        ];
        return share;
    }
    async createShare(share) {
        return (0, _utils.dbGetInsertedId)(await this.db.insert(_sharesschema.shares).values(share));
    }
    async updateShare(set, filters) {
        const where = (0, _utils.convertToWhere)(_sharesschema.shares, filters);
        try {
            (0, _utils.dbCheckAffectedRows)(await this.db.update(_sharesschema.shares).set(set).where((0, _drizzleorm.and)(...where)).limit(1), 1);
            this.logger.debug(`${this.updateShare.name} - ${JSON.stringify(filters)} was updated : ${JSON.stringify(set)}`);
        } catch (e) {
            this.logger.error(`${this.updateShare.name} - ${JSON.stringify(filters)} was not updated : ${JSON.stringify(set)} : ${e}`);
        }
    }
    async deleteShare(shareId) {
        return (0, _utils.dbCheckAffectedRows)(await this.db.delete(_sharesschema.shares).where((0, _drizzleorm.eq)(_sharesschema.shares.id, shareId)), 1);
    }
    async updateMember(set, filters) {
        const where = (0, _utils.convertToWhere)(_sharesmembersschema.sharesMembers, filters);
        try {
            (0, _utils.dbCheckAffectedRows)(await this.db.update(_sharesmembersschema.sharesMembers).set(set).where((0, _drizzleorm.and)(...where)).limit(1), 1);
            this.logger.debug(`${this.updateMember.name} - ${JSON.stringify(filters)} was updated : ${JSON.stringify(set)}`);
            return true;
        } catch (e) {
            this.logger.error(`${this.updateMember.name} - ${JSON.stringify(filters)} was not updated : ${JSON.stringify(set)} : ${e}`);
            return false;
        }
    }
    async updateMembers(shareId, add, update, remove) {
        // store status
        const status = {
            [_constants.ACTION.ADD]: {
                userIds: [],
                groupIds: []
            },
            [_constants.ACTION.UPDATE]: {
                userIds: [],
                groupIds: []
            },
            [_constants.ACTION.DELETE]: {
                userIds: [],
                groupIds: []
            }
        };
        // add
        for (const m of add){
            try {
                (0, _utils.dbCheckAffectedRows)(await this.db.insert(_sharesmembersschema.sharesMembers).values({
                    shareId: shareId,
                    ...m.type === _member.MEMBER_TYPE.USER || m.type === _member.MEMBER_TYPE.GUEST ? {
                        userId: m.id
                    } : {
                        groupId: m.id
                    },
                    permissions: m.permissions
                }), 1);
                status[_constants.ACTION.ADD][`${m.type === _member.MEMBER_TYPE.USER || m.type === _member.MEMBER_TYPE.GUEST ? 'userIds' : 'groupIds'}`].push(m.id);
                this.logger.debug(`${this.updateMembers.name} - ${m.type} (${m.id}) added to the share (${shareId})`);
            } catch (e) {
                this.logger.error(`${this.updateMembers.name} - ${m.type} (${m.id}) was not added to the share (${shareId}) ->  : ${e}`);
            }
        }
        // update
        for (const props of update){
            const m = (0, _shared.popFromObject)('object', props);
            try {
                (0, _utils.dbCheckAffectedRows)(await this.db.update(_sharesmembersschema.sharesMembers).set(props).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_sharesmembersschema.sharesMembers.shareId, shareId), (0, _drizzleorm.eq)(m.type === _member.MEMBER_TYPE.USER || m.type === _member.MEMBER_TYPE.GUEST ? _sharesmembersschema.sharesMembers.userId : _sharesmembersschema.sharesMembers.groupId, m.id))).limit(1), 1);
                status[_constants.ACTION.UPDATE][`${m.type === _member.MEMBER_TYPE.USER || m.type === _member.MEMBER_TYPE.GUEST ? 'userIds' : 'groupIds'}`].push(m.id);
                this.logger.debug(`${this.updateMembers.name} - ${m.type} (${m.id}) was updated on share (${shareId}) : ${JSON.stringify(props)}`);
            } catch (e) {
                this.logger.error(`${this.updateMembers.name} - ${m.type} (${m.id}) was not updated on share (${shareId}) : ${JSON.stringify(props)} : ${e}`);
            }
        }
        // remove
        for (const m of remove){
            try {
                (0, _utils.dbCheckAffectedRows)(await this.db.delete(_sharesmembersschema.sharesMembers).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_sharesmembersschema.sharesMembers.shareId, shareId), (0, _drizzleorm.eq)(m.type === _member.MEMBER_TYPE.USER || m.type === _member.MEMBER_TYPE.GUEST ? _sharesmembersschema.sharesMembers.userId : _sharesmembersschema.sharesMembers.groupId, m.id))), 1);
                status[_constants.ACTION.DELETE][`${m.type === _member.MEMBER_TYPE.USER || m.type === _member.MEMBER_TYPE.GUEST ? 'userIds' : 'groupIds'}`].push(m.id);
                this.logger.debug(`${this.updateMembers.name} - ${m.type} (${m.id}) removed from share (${shareId})`);
            } catch (e) {
                this.logger.error(`${this.updateMembers.name} - ${m.type} (${m.id}) was not removed from share (${shareId}) : ${e}`);
            }
        }
        return status;
    }
    async shareEnv(shareId) {
        const shareSpaceRoot = (0, _mysqlcore.alias)(_spacesrootsschema.spacesRoots, 'shareSpaceRoot');
        const select = {
            id: _sharesschema.shares.id,
            alias: _sharesschema.shares.alias,
            enabled: _sharesschema.shares.enabled,
            fileId: _sharesschema.shares.fileId,
            spaceId: _sharesschema.shares.spaceId,
            spaceRootId: _sharesschema.shares.spaceRootId,
            inSharesRepository: (0, _drizzleorm.sql)`${1}`.mapWith(Boolean),
            root: {
                id: _filesschema.files.id,
                owner: {
                    id: _usersschema.users.id,
                    login: _usersschema.users.login
                },
                file: {
                    path: (0, _drizzleorm.sql)`IF (${_filesschema.files.id} IS NOT NULL, ${(0, _filesschema.filePathSQL)(_filesschema.files)}, NULL)`,
                    inTrash: _filesschema.files.inTrash,
                    space: {
                        id: _spacesschema.spaces.id,
                        alias: _spacesschema.spaces.alias
                    },
                    root: {
                        id: (0, _drizzleorm.sql)`IF (${_spacesrootsschema.spacesRoots.id} IS NULL, ${shareSpaceRoot.id}, ${_spacesrootsschema.spacesRoots.id})`,
                        externalPath: (0, _drizzleorm.sql)`IF (${_spacesrootsschema.spacesRoots.externalPath} IS NULL,
                                  ${shareSpaceRoot.externalPath}, ${_spacesrootsschema.spacesRoots.externalPath})`
                    }
                },
                externalPath: _sharesschema.shares.externalPath
            }
        };
        const [shareEnv] = await this.db.select(select).from(_sharesschema.shares).leftJoin(shareSpaceRoot, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNull)(_sharesschema.shares.fileId), (0, _drizzleorm.eq)(shareSpaceRoot.id, _sharesschema.shares.spaceRootId))).leftJoin(_filesschema.files, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.or)((0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_sharesschema.shares.fileId), (0, _drizzleorm.eq)(_filesschema.files.id, _sharesschema.shares.fileId)), (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(shareSpaceRoot.fileId), (0, _drizzleorm.eq)(_filesschema.files.id, shareSpaceRoot.fileId))))).leftJoin(_spacesschema.spaces, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.or)((0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_filesschema.files.spaceId), (0, _drizzleorm.eq)(_spacesschema.spaces.id, _filesschema.files.spaceId)), (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(shareSpaceRoot.spaceId), (0, _drizzleorm.eq)(_spacesschema.spaces.id, shareSpaceRoot.spaceId))))).leftJoin(_spacesrootsschema.spacesRoots, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNotNull)(_filesschema.files.spaceExternalRootId), (0, _drizzleorm.eq)(_spacesrootsschema.spacesRoots.id, _filesschema.files.spaceExternalRootId))).leftJoin(_usersschema.users, (0, _drizzleorm.eq)(_usersschema.users.id, _filesschema.files.ownerId)).where((0, _drizzleorm.eq)(_sharesschema.shares.id, shareId)).execute();
        return shareEnv;
    }
    async shareIds(userId, isAdmin) {
        if (!this.shareIdsQuery) {
            const unionAlias = (0, _mysqlcore.union)(this.fromUserQuery({
                id: _sharesschema.shares.id
            }), this.fromGroupsQuery({
                id: _sharesschema.shares.id
            }), this.fromAdminSharesQuery({
                id: _sharesschema.shares.id
            })).as('unionAlias');
            this.shareIdsQuery = this.db.select({
                id: unionAlias.id
            }).from(unionAlias).groupBy(unionAlias.id).prepare();
        }
        return (await this.shareIdsQuery.execute({
            userId: userId,
            isAdmin: +isAdmin
        })).map((r)=>r.id);
    }
    async listShares(user) {
        if (!this.sharesListQuery) {
            const [selectFile, shareRootFile, parentShare, parentShareFile, childShareFromRoot, shareMembers] = this.shareFileSelect();
            const select = {
                id: _sharesschema.shares.id,
                name: _sharesschema.shares.name,
                alias: _sharesschema.shares.alias,
                externalPath: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.externalPath} IS NOT NULL, 1, 0)`.mapWith(Boolean),
                description: _sharesschema.shares.description,
                enabled: _sharesschema.shares.enabled,
                createdAt: _sharesschema.shares.createdAt,
                modifiedAt: _sharesschema.shares.modifiedAt,
                parent: {
                    id: (0, _drizzleorm.isNotNull)(parentShare.id),
                    alias: parentShare.alias,
                    name: parentShare.name
                },
                file: selectFile,
                hasComments: (0, _commentsschema.fileHasCommentsSubquerySQL)((0, _drizzleorm.sql)`IF (${_sharesschema.shares.fileId} IS NULL AND ${shareRootFile.id} IS NOT NULL, ${shareRootFile.id}, ${_filesschema.files.id})`),
                counts: {
                    users: (0, _drizzleorm.count)((0, _drizzleorm.sql)`CASE WHEN ${shareMembers.userId} IS NOT NULL AND ${shareMembers.linkId} IS NULL THEN 1 END`),
                    groups: (0, _drizzleorm.count)(shareMembers.groupId),
                    links: (0, _drizzleorm.count)(shareMembers.linkId)
                }
            };
            this.sharesListQuery = this.shareFileJoin(select, shareRootFile, parentShare, parentShareFile, childShareFromRoot, shareMembers).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_sharesschema.shares.type, _drizzleorm.sql.placeholder('shareType')), (0, _drizzleorm.or)((0, _drizzleorm.eq)(_sharesschema.shares.ownerId, _drizzleorm.sql.placeholder('userId')), (0, _drizzleorm.and)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('isAdmin'), 1), (0, _drizzleorm.isNull)(_sharesschema.shares.ownerId))))).groupBy(_sharesschema.shares.id).prepare();
        }
        const r = await this.sharesListQuery.execute({
            userId: user.id,
            shareType: _shares.SHARE_TYPE.COMMON,
            isAdmin: +user.isAdmin
        });
        await this.setShareCounts(r);
        return r;
    }
    async listChildShares(userId, shareId, isAdmin) {
        const childShare = (0, _mysqlcore.alias)(_sharesschema.shares, 'childShare');
        const withChildren = (0, _drizzleorm.sql)`
      WITH RECURSIVE child (id, parentId, ownerId, type, name, alias, fileId) AS
                       (SELECT ${_sharesschema.shares.id},
                               ${_sharesschema.shares.parentId},
                               ${_sharesschema.shares.ownerId},
                               ${_sharesschema.shares.type},
                               ${_sharesschema.shares.name},
                               ${_sharesschema.shares.alias},
                               ${_sharesschema.shares.fileId}
                        FROM ${_sharesschema.shares}
                        WHERE ${_sharesschema.shares.id} = ${shareId}
                          AND (${_sharesschema.shares.ownerId} = ${userId} OR (${isAdmin} = 1 AND ${_sharesschema.shares.ownerId} IS NULL))
                        UNION
                        SELECT ${childShare.id},
                               ${childShare.parentId},
                               ${childShare.ownerId},
                               ${childShare.type},
                               ${childShare.name},
                               ${childShare.alias},
                               ${childShare.fileId}
                        FROM ${_sharesschema.shares} AS childShare
                               INNER JOIN child AS cs ON ${childShare.parentId} = cs.id)
      SELECT child.id,
             child.alias,
             child.name,
             child.type,
             child.parentId,
             ${_usersschema.users.login}            AS ownerLogin,
             ${(0, _usersschema.userFullNameSQL)(_usersschema.users)} AS ownerFullName,
             ${_usersschema.users.email}            AS ownerEmail,
             ${_filesschema.files.mime}             AS fileMime
      FROM child
             LEFT JOIN ${_usersschema.users} ON child.ownerId = ${_usersschema.users.id}
             LEFT JOIN ${_filesschema.files} ON child.fileId = ${_filesschema.files.id}
      WHERE child.id != ${shareId}
    `;
        const [r] = await this.db.execute(withChildren);
        return r.map((s)=>new _sharechildmodel.ShareChild(s));
    }
    async listSpaceShares(spaceId) {
        const childShare = (0, _mysqlcore.alias)(_sharesschema.shares, 'childShare');
        const shareSpaceRoot = (0, _mysqlcore.alias)(_spacesrootsschema.spacesRoots, 'shareSpaceRoot');
        const childShareSpaceRoot = (0, _mysqlcore.alias)(_spacesrootsschema.spacesRoots, 'childShareSpaceRoot');
        const withChildren = (0, _drizzleorm.sql)`
      WITH RECURSIVE child (id, parentId, ownerId, type, name, alias, fileId) AS
                       (SELECT ${_sharesschema.shares.id},
                               ${_sharesschema.shares.parentId},
                               ${_sharesschema.shares.ownerId},
                               ${_sharesschema.shares.type},
                               ${_sharesschema.shares.name},
                               ${_sharesschema.shares.alias},
                               COALESCE(${_sharesschema.shares.fileId}, ${shareSpaceRoot.fileId}) AS fileId
                        FROM ${_sharesschema.shares}
                               LEFT JOIN ${_spacesrootsschema.spacesRoots} AS shareSpaceRoot ON ${_sharesschema.shares.spaceRootId} = ${shareSpaceRoot.id}
                        WHERE ${_sharesschema.shares.spaceId} = ${spaceId}
                        UNION
                        SELECT ${childShare.id},
                               ${childShare.parentId},
                               ${childShare.ownerId},
                               ${childShare.type},
                               ${childShare.name},
                               ${childShare.alias},
                               COALESCE(${childShare.fileId}, ${childShareSpaceRoot.fileId}) AS fileId
                        FROM ${_sharesschema.shares} AS childShare
                               INNER JOIN child AS cs ON ${childShare.parentId} = cs.id
                               LEFT JOIN ${_spacesrootsschema.spacesRoots} AS childShareSpaceRoot ON ${childShare.spaceRootId} = ${childShareSpaceRoot.id})
      SELECT child.id,
             child.alias,
             child.name,
             child.type,
             child.parentId,
             ${_usersschema.users.login}            AS ownerLogin,
             ${(0, _usersschema.userFullNameSQL)(_usersschema.users)} AS ownerFullName,
             ${_usersschema.users.email}            AS ownerEmail,
             ${_filesschema.files.mime}             AS fileMime
      FROM child
             LEFT JOIN ${_usersschema.users} ON child.ownerId = ${_usersschema.users.id}
             LEFT JOIN ${_filesschema.files} ON child.fileId = ${_filesschema.files.id}
    `;
        const [r] = await this.db.execute(withChildren);
        return r.map((s)=>new _sharechildmodel.ShareChild(s));
    }
    async membersFromChildSharesPermissions(shareId, userIds, matchPermRegexp, asParent = true) {
        const childShare = (0, _mysqlcore.alias)(_sharesschema.shares, 'childShare');
        const withChildren = (0, _drizzleorm.sql)`
      WITH RECURSIVE children (id, alias, name) AS
                       (SELECT ${_sharesschema.shares.id}, ${_sharesschema.shares.alias}, ${_sharesschema.shares.name}
                        FROM ${_sharesschema.shares}
                        WHERE ${asParent ? _sharesschema.shares.parentId : _sharesschema.shares.id} = ${shareId}
                          AND ${userIds === 'all' ? 1 : (0, _drizzleorm.inArray)(_sharesschema.shares.ownerId, userIds)}
                        UNION
                        SELECT ${childShare.id}, ${childShare.alias}, ${childShare.name}
                        FROM ${_sharesschema.shares} AS childShare
                               INNER JOIN children AS cs ON ${childShare.parentId} = cs.id)
      SELECT ${_sharesmembersschema.sharesMembers.id}          as id,
             ${_sharesmembersschema.sharesMembers.userId}      as userId,
             ${_sharesmembersschema.sharesMembers.permissions} as userPermissions,
             ${_sharesmembersschema.sharesMembers.shareId},
             children.alias               as shareAlias,
             children.name                as shareName
      FROM children
             INNER JOIN ${_sharesmembersschema.sharesMembers} ON children.id = ${_sharesmembersschema.sharesMembers.shareId}
    `;
        if (matchPermRegexp) {
            withChildren.append((0, _drizzleorm.sql)`WHERE ${_sharesmembersschema.sharesMembers.permissions} REGEXP ${matchPermRegexp}`);
        }
        const [r] = await this.db.execute(withChildren);
        return r;
    }
    async shareRootFiles(user, options) {
        if (!this.shareRootFilesQuery) {
            const shareSpaceRoot = (0, _mysqlcore.alias)(_spacesrootsschema.spacesRoots, 'shareSpaceRoot');
            const originOwner = (0, _mysqlcore.alias)(_usersschema.users, 'originOwner');
            const childShare = (0, _mysqlcore.alias)(_sharesschema.shares, 'childShare');
            const selectUnion = {
                id: _filesschema.files.id,
                path: (0, _drizzleorm.sql)`IF (${_filesschema.files.id} IS NOT NULL, ${(0, _filesschema.filePathSQL)(_filesschema.files)}, '')`.as('path'),
                isDir: _filesschema.files.isDir,
                inTrash: _filesschema.files.inTrash,
                size: _filesschema.files.size,
                ctime: _filesschema.files.ctime,
                mtime: _filesschema.files.mtime,
                mime: _filesschema.files.mime,
                originOwnerLogin: (0, _drizzleorm.sql)`${originOwner.login}`.as('originOwnerLogin'),
                originSpaceAlias: (0, _drizzleorm.sql)`${_spacesschema.spaces.alias}`.as('originSpaceAlias'),
                originSpaceRootExternalPath: (0, _drizzleorm.sql)`IF (${_spacesrootsschema.spacesRoots.externalPath} IS NULL,
                                             ${shareSpaceRoot.externalPath}, ${_spacesrootsschema.spacesRoots.externalPath})`.as('originSpaceRootExternalPath'),
                rootId: (0, _drizzleorm.sql)`${_sharesschema.shares.id}`.as('rootId'),
                rootAlias: _sharesschema.shares.alias,
                rootName: _sharesschema.shares.name,
                rootDescription: _sharesschema.shares.description,
                rootEnabled: _sharesschema.shares.enabled,
                rootExternalPath: _sharesschema.shares.externalPath,
                rootPermissions: _sharesmembersschema.sharesMembers.permissions,
                rootOwnerLogin: (0, _drizzleorm.sql)`${_usersschema.users.login}`.as('rootOwnerLogin'),
                rootOwnerEmail: (0, _drizzleorm.sql)`${_usersschema.users.email}`.as('rootOwnerEmail'),
                rootOwnerFullName: (0, _usersschema.userFullNameSQL)(_usersschema.users).as('rootOwnerFullName'),
                childShareId: (0, _drizzleorm.sql)`${childShare.id}`.as('childShareId'),
                childShareAlias: (0, _drizzleorm.sql)`${childShare.alias}`.as('childShareAlias'),
                childShareName: (0, _drizzleorm.sql)`${childShare.name}`.as('childShareName'),
                childShareType: (0, _drizzleorm.sql)`${childShare.type}`.as('childShareType'),
                syncPathId: (0, _drizzleorm.sql)`${_syncpathsschema.syncPaths.id}`.as('syncPathId'),
                syncPathClientId: (0, _drizzleorm.sql)`${_syncclientsschema.syncClients.id}`.as('syncPathClientId'),
                syncPathClientName: (0, _drizzleorm.sql)`JSON_VALUE(${_syncclientsschema.syncClients.info}, '$.node')`.as('syncPathClientName')
            };
            const filters = [
                (0, _drizzleorm.or)((0, _drizzleorm.isNull)(_sharesschema.shares.ownerId), (0, _drizzleorm.ne)(_sharesschema.shares.ownerId, _drizzleorm.sql.placeholder('userId')))
            ];
            const fromUser = this.fromUserQuery(selectUnion, filters).$dynamic();
            const fromGroups = this.fromGroupsQuery(selectUnion, filters).$dynamic();
            const fromAdminShares = this.fromAdminSharesQuery({
                ...selectUnion,
                rootPermissions: _drizzleorm.sql.raw(`'${_shares.SHARE_ALL_OPERATIONS}'`)
            }, filters).$dynamic();
            for (const q of [
                fromUser,
                fromGroups,
                fromAdminShares
            ]){
                q.leftJoin(shareSpaceRoot, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNull)(_sharesschema.shares.fileId), (0, _drizzleorm.eq)(shareSpaceRoot.id, _sharesschema.shares.spaceRootId))).leftJoin(_filesschema.files, (0, _drizzleorm.or)(// if the child share is from a share with an external path, the child share should have an external path and a fileId
                (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_sharesschema.shares.fileId), (0, _drizzleorm.eq)(_filesschema.files.id, _sharesschema.shares.fileId)), (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNull)(_sharesschema.shares.fileId), (0, _drizzleorm.isNotNull)(shareSpaceRoot.fileId), (0, _drizzleorm.eq)(_filesschema.files.id, shareSpaceRoot.fileId)))).leftJoin(_spacesschema.spaces, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNotNull)(_filesschema.files.spaceId), (0, _drizzleorm.eq)(_spacesschema.spaces.id, _filesschema.files.spaceId))).leftJoin(_spacesrootsschema.spacesRoots, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.eq)(_spacesrootsschema.spacesRoots.id, _filesschema.files.spaceExternalRootId))).leftJoin(childShare, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('withShares'), _drizzleorm.sql.raw('1')), (0, _drizzleorm.eq)(childShare.ownerId, _drizzleorm.sql.placeholder('userId')), (0, _drizzleorm.eq)(childShare.parentId, _sharesschema.shares.id), (0, _drizzleorm.or)((0, _drizzleorm.and)((0, _drizzleorm.isNull)(childShare.externalPath), (0, _drizzleorm.isNotNull)(childShare.fileId), (0, _drizzleorm.eq)(childShare.fileId, _sharesschema.shares.fileId)), (0, _drizzleorm.and)((0, _drizzleorm.isNull)(childShare.externalPath), (0, _drizzleorm.isNull)(childShare.fileId), (0, _drizzleorm.eq)(childShare.spaceId, _sharesschema.shares.spaceId), (0, _drizzleorm.eq)(childShare.spaceRootId, _sharesschema.shares.spaceRootId)), (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(childShare.externalPath), (0, _drizzleorm.isNull)(childShare.fileId), (0, _drizzleorm.eq)(_sharesschema.shares.externalPath, childShare.externalPath))))).leftJoin(_syncclientsschema.syncClients, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('withSyncs'), _drizzleorm.sql.raw('1')), (0, _drizzleorm.eq)(_syncclientsschema.syncClients.ownerId, _drizzleorm.sql.placeholder('userId')))).leftJoin(_syncpathsschema.syncPaths, (0, _drizzleorm.and)((0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('withSyncs'), _drizzleorm.sql.raw('1')), (0, _drizzleorm.eq)(_syncpathsschema.syncPaths.clientId, _syncclientsschema.syncClients.id), (0, _drizzleorm.isNull)(_syncpathsschema.syncPaths.fileId), (0, _drizzleorm.eq)(_syncpathsschema.syncPaths.shareId, _sharesschema.shares.id))).leftJoin(_usersschema.users, (0, _drizzleorm.eq)(_usersschema.users.id, _sharesschema.shares.ownerId)).leftJoin(originOwner, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.eq)(originOwner.id, _filesschema.files.ownerId)));
            }
            const unionAlias = (0, _mysqlcore.union)(fromUser, fromGroups, fromAdminShares).as('union_alias');
            const select = {
                id: unionAlias.id,
                path: unionAlias.path,
                isDir: unionAlias.isDir,
                inTrash: unionAlias.inTrash,
                size: unionAlias.size,
                ctime: unionAlias.ctime,
                mtime: unionAlias.mtime,
                mime: unionAlias.mime,
                origin: {
                    ownerLogin: unionAlias.originOwnerLogin,
                    spaceAlias: unionAlias.originSpaceAlias,
                    spaceRootExternalPath: unionAlias.originSpaceRootExternalPath
                },
                root: {
                    id: unionAlias.rootId,
                    alias: unionAlias.rootAlias,
                    name: unionAlias.rootName,
                    description: unionAlias.rootDescription,
                    enabled: unionAlias.rootEnabled,
                    externalPath: unionAlias.rootExternalPath,
                    permissions: (0, _spacesschema.spaceGroupConcatPermissions)(unionAlias.rootPermissions),
                    owner: {
                        login: unionAlias.rootOwnerLogin,
                        email: unionAlias.rootOwnerEmail,
                        fullName: unionAlias.rootOwnerFullName
                    }
                },
                shares: (0, _drizzleorm.sql)`IF (${_drizzleorm.sql.placeholder('withShares')}, ${(0, _utils.concatDistinctObjectsInArray)(unionAlias.childShareId, {
                    id: unionAlias.childShareId,
                    alias: unionAlias.childShareAlias,
                    name: unionAlias.childShareName,
                    type: unionAlias.childShareType
                })}, '[]')`.mapWith(JSON.parse),
                syncs: (0, _drizzleorm.sql)`IF (${_drizzleorm.sql.placeholder('withSyncs')}, ${(0, _utils.concatDistinctObjectsInArray)(unionAlias.syncPathId, {
                    id: unionAlias.syncPathId,
                    clientId: unionAlias.syncPathClientId,
                    clientName: unionAlias.syncPathClientName
                })}, '[]')`.mapWith(JSON.parse),
                hasComments: (0, _drizzleorm.sql)`IF (${_drizzleorm.sql.placeholder('withHasComments')}, ${(0, _commentsschema.fileHasCommentsSubquerySQL)(unionAlias.id)}, 0)`.mapWith(Boolean)
            };
            this.shareRootFilesQuery = this.db.select(select).from(unionAlias).groupBy(unionAlias.rootId).prepare();
        }
        const fps = await this.shareRootFilesQuery.execute({
            userId: user.id,
            isAdmin: +user.isAdmin,
            withHasComments: +!!options.withHasComments,
            withShares: +!!options.withShares,
            withSyncs: +!!options.withSyncs
        });
        for (const f of fps){
            f.root.permissions = (0, _functions.uniquePermissions)(f.root.permissions);
        }
        return fps;
    }
    async permissions(userId, shareAlias, isAdmin = 0) {
        if (!this.sharePermissionsQuery) {
            const shareSpaceRoot = (0, _mysqlcore.alias)(_spacesrootsschema.spacesRoots, 'shareSpaceRoot');
            const selectUnion = {
                id: _sharesschema.shares.id,
                alias: _sharesschema.shares.alias,
                name: _sharesschema.shares.name,
                enabled: _sharesschema.shares.enabled,
                permissions: _sharesmembersschema.sharesMembers.permissions,
                rootId: (0, _drizzleorm.sql)`${_filesschema.files.id}`.as('rootId'),
                rootOwnerId: (0, _drizzleorm.sql)`${_usersschema.users.id}`.as('rootOwnerId'),
                rootOwnerLogin: _usersschema.users.login,
                rootSpaceId: (0, _drizzleorm.sql)`${_spacesschema.spaces.id}`.as('rootSpaceId'),
                rootSpaceAlias: (0, _drizzleorm.sql)`${_spacesschema.spaces.alias}`.as('rootSpaceAlias'),
                rootPath: (0, _drizzleorm.sql)`IF (${_filesschema.files.id} IS NOT NULL, ${(0, _filesschema.filePathSQL)(_filesschema.files)}, NULL)`.as('rootPath'),
                rootInTrash: _filesschema.files.inTrash,
                rootExternalPath: _sharesschema.shares.externalPath,
                rootExternalParentShareId: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.externalPath} IS NOT NULL, ${_sharesschema.shares.parentId}, NULL)`.as('rootExternalParentShareId'),
                rootSpaceRootId: (0, _drizzleorm.sql)`IF (${_spacesrootsschema.spacesRoots.id} IS NULL, ${shareSpaceRoot.id}, ${_spacesrootsschema.spacesRoots.id})`.as('rootSpaceRootId'),
                rootSpaceRootExternalPath: (0, _drizzleorm.sql)`IF (${_spacesrootsschema.spacesRoots.externalPath} IS NULL,
                                           ${shareSpaceRoot.externalPath}, ${_spacesrootsschema.spacesRoots.externalPath})`.as('rootSpaceRootExternalPath')
            };
            const filters = [
                (0, _drizzleorm.eq)(_sharesschema.shares.alias, _drizzleorm.sql.placeholder('shareAlias'))
            ];
            const fromUser = this.fromUserQuery(selectUnion, filters).$dynamic();
            const fromGroups = this.fromGroupsQuery(selectUnion, filters).$dynamic();
            const fromAdminShares = this.fromAdminSharesQuery({
                ...selectUnion,
                permissions: _drizzleorm.sql.raw(`'${_shares.SHARE_ALL_OPERATIONS}'`)
            }, filters).$dynamic();
            for (const q of [
                fromUser,
                fromGroups,
                fromAdminShares
            ]){
                q.leftJoin(shareSpaceRoot, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNull)(_sharesschema.shares.fileId), (0, _drizzleorm.eq)(shareSpaceRoot.id, _sharesschema.shares.spaceRootId))).leftJoin(_filesschema.files, (0, _drizzleorm.or)(// in case of share child from a share with external path, child share should have an external path and a fileId
                (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_sharesschema.shares.fileId), (0, _drizzleorm.eq)(_filesschema.files.id, _sharesschema.shares.fileId)), (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNotNull)(shareSpaceRoot.fileId), (0, _drizzleorm.eq)(_filesschema.files.id, shareSpaceRoot.fileId)))).leftJoin(_spacesschema.spaces, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.or)((0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_filesschema.files.spaceId), (0, _drizzleorm.eq)(_spacesschema.spaces.id, _filesschema.files.spaceId)), (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(shareSpaceRoot.spaceId), (0, _drizzleorm.eq)(_spacesschema.spaces.id, shareSpaceRoot.spaceId))))).leftJoin(_spacesrootsschema.spacesRoots, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.eq)(_spacesrootsschema.spacesRoots.id, _filesschema.files.spaceExternalRootId))).leftJoin(_usersschema.users, (0, _drizzleorm.eq)(_usersschema.users.id, _filesschema.files.ownerId));
            }
            const unionAlias = (0, _mysqlcore.union)(fromUser, fromGroups, fromAdminShares).as('union_alias');
            const select = {
                id: unionAlias.id,
                alias: unionAlias.alias,
                name: unionAlias.name,
                enabled: unionAlias.enabled,
                permissions: (0, _spacesschema.spaceGroupConcatPermissions)(unionAlias.permissions),
                root: {
                    id: unionAlias.rootId,
                    owner: {
                        id: unionAlias.rootOwnerId,
                        login: unionAlias.rootOwnerLogin
                    },
                    file: {
                        path: unionAlias.rootPath,
                        inTrash: unionAlias.rootInTrash,
                        space: {
                            id: unionAlias.rootSpaceId,
                            alias: unionAlias.rootSpaceAlias
                        },
                        root: {
                            id: unionAlias.rootSpaceRootId,
                            externalPath: unionAlias.rootSpaceRootExternalPath
                        }
                    },
                    externalPath: unionAlias.rootExternalPath,
                    externalParentShareId: unionAlias.rootExternalParentShareId
                }
            };
            this.sharePermissionsQuery = this.db.select(select).from(unionAlias).groupBy(unionAlias.id).limit(1).prepare();
        }
        const [r] = await this.sharePermissionsQuery.execute({
            userId,
            shareAlias,
            isAdmin
        });
        if (r) {
            r.permissions = (0, _functions.uniquePermissions)(r.permissions);
        }
        return r;
    }
    async childSharesCount(shareId) {
        const childShare = (0, _mysqlcore.alias)(_sharesschema.shares, 'childShare');
        const withChildren = (0, _drizzleorm.sql)`
      WITH RECURSIVE children (id, parentId) AS
                       (SELECT ${_sharesschema.shares.id}, ${_sharesschema.shares.parentId}
                        FROM ${_sharesschema.shares}
                        WHERE ${_sharesschema.shares.parentId} IS NOT NULL
                          AND ${_sharesschema.shares.parentId} = ${shareId}
                        UNION
                        SELECT ${childShare.id}, cs.parentId
                        FROM ${_sharesschema.shares} AS childShare
                               INNER JOIN children AS cs ON ${childShare.parentId} = cs.id)
      SELECT COUNT(children.id) as count
      FROM children
      GROUP BY parentId
    `;
        const [r] = await this.db.execute(withChildren);
        return r.length ? r[0].count : 0;
    }
    async clearCachePermissions(shareAlias, userIds) {
        // `permissions` argument must match with `this.permissions.name` function
        for (const userId of userIds){
            const pattern = this.cache.genSlugKey(this.constructor.name, this.permissions.name, userId, shareAlias, '*');
            const keys = await this.cache.keys(pattern);
            if (keys.length) {
                this.logger.verbose(`${this.clearCachePermissions.name} - ${JSON.stringify(keys)}`);
                this.cache.mdel(keys).catch((e)=>this.logger.error(`${this.clearCachePermissions.name} - ${e}`));
            }
        }
    }
    shareExistsForAlias(alias) {
        return this.db.query.shares.findFirst({
            columns: {
                id: true
            },
            where: (0, _drizzleorm.eq)(_sharesschema.shares.alias, alias)
        });
    }
    fromUserQuery(select, filters = []) {
        const where = [
            (0, _drizzleorm.eq)(_sharesmembersschema.sharesMembers.userId, _drizzleorm.sql.placeholder('userId')),
            ...filters
        ];
        return this.db.select(select).from(_sharesmembersschema.sharesMembers).innerJoin(_sharesschema.shares, (0, _drizzleorm.eq)(_sharesmembersschema.sharesMembers.shareId, _sharesschema.shares.id)).where((0, _drizzleorm.and)(...where));
    }
    fromGroupsQuery(select, filters = []) {
        const where = [
            (0, _drizzleorm.eq)(_sharesmembersschema.sharesMembers.groupId, _usersgroupsschema.usersGroups.groupId),
            ...filters
        ];
        return this.db.select(select).from(_sharesmembersschema.sharesMembers).innerJoin(_usersgroupsschema.usersGroups, (0, _drizzleorm.eq)(_usersgroupsschema.usersGroups.userId, _drizzleorm.sql.placeholder('userId'))).innerJoin(_sharesschema.shares, (0, _drizzleorm.eq)(_sharesmembersschema.sharesMembers.shareId, _sharesschema.shares.id)).where((0, _drizzleorm.and)(...where));
    }
    fromAdminSharesQuery(select, filters = []) {
        const where = [
            (0, _drizzleorm.eq)(_drizzleorm.sql.placeholder('isAdmin'), _drizzleorm.sql.raw('1')),
            (0, _drizzleorm.isNull)(_sharesschema.shares.ownerId),
            ...filters
        ];
        return this.db.select(select).from(_sharesschema.shares).where((0, _drizzleorm.and)(...where));
    }
    shareFileSelect() {
        const shareRootFile = (0, _mysqlcore.alias)(_filesschema.files, 'shareRootFile');
        const parentShare = (0, _mysqlcore.alias)(_sharesschema.shares, 'parentShare');
        const parentShareFile = (0, _mysqlcore.alias)(_filesschema.files, 'parentShareFile');
        const childShareFromRoot = (0, _mysqlcore.alias)(_spacesrootsschema.spacesRoots, 'childShareFromRoot');
        const shareMembers = (0, _mysqlcore.alias)(_sharesmembersschema.sharesMembers, 'shareMembers');
        const selectFile = {
            id: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.fileId} IS NULL AND ${shareRootFile.id} IS NOT NULL,
                  ${shareRootFile.id}, ${_filesschema.files.id})`.as('fileId'),
            ownerId: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.spaceId} IS NOT NULL,
                       NULL, ${_filesschema.files.ownerId})`.as('fileOwnerId'),
            name: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.fileId} IS NULL AND ${_spacesrootsschema.spacesRoots.id} IS NOT NULL,
                    ${_spacesrootsschema.spacesRoots.name},
                    IF(${childShareFromRoot.id} IS NOT NULL
                           OR ${_sharesschema.shares.fileId} = ${parentShare.fileId}, ${parentShare.name}, ${_filesschema.files.name}))`.as('fileName'),
            path: (0, _drizzleorm.sql)`IF (${shareRootFile.id} IS NOT NULL AND ${_sharesschema.shares.fileId} IS NOT NULL,
                    REGEXP_REPLACE(${(0, _filesschema.filePathSQL)(_filesschema.files)}, CONCAT(${(0, _filesschema.filePathSQL)(shareRootFile)}, '/'), ''),
                    IF(${parentShareFile.id} IS NOT NULL AND ${_sharesschema.shares.fileId} IS NOT NULL,
                       IF(${parentShareFile.id} = ${_sharesschema.shares.fileId}, '.',
                          REGEXP_REPLACE(${(0, _filesschema.filePathSQL)(_filesschema.files)}, CONCAT(${(0, _filesschema.filePathSQL)(parentShareFile)}, '/'), '')),
                       IF(${_sharesschema.shares.fileId} IS NOT NULL, ${(0, _filesschema.filePathSQL)(_filesschema.files)}, '.')))`.as('filePath'),
            isDir: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.fileId} IS NULL AND ${_sharesschema.shares.spaceRootId} IS NOT NULL,
                     ${shareRootFile.isDir}, ${_filesschema.files.isDir})`.as('fileIsDir'),
            inTrash: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.fileId} IS NULL AND ${_sharesschema.shares.spaceRootId} IS NOT NULL,
                       ${shareRootFile.inTrash}, ${_filesschema.files.inTrash})`.as('fileInTrash'),
            mime: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.fileId} IS NULL AND ${_sharesschema.shares.spaceRootId} IS NOT NULL,
                    ${shareRootFile.mime}, ${_filesschema.files.mime})`.as('fileMime'),
            space: {
                alias: _spacesschema.spaces.alias,
                name: _spacesschema.spaces.name,
                root: {
                    alias: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.parentId} IS NULL, ${_spacesrootsschema.spacesRoots.alias}, NULL)`,
                    name: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.parentId} IS NULL, ${_spacesrootsschema.spacesRoots.name}, NULL)`
                }
            }
        };
        return [
            selectFile,
            shareRootFile,
            parentShare,
            parentShareFile,
            childShareFromRoot,
            shareMembers
        ];
    }
    shareFileJoin(select, shareRootFile, parentShare, parentShareFile, childShareFromRoot, shareMembers) {
        return this.db.select(select).from(_sharesschema.shares).leftJoin(_filesschema.files, (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_sharesschema.shares.fileId), (0, _drizzleorm.eq)(_filesschema.files.id, _sharesschema.shares.fileId))).leftJoin(_spacesschema.spaces, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNull)(_sharesschema.shares.parentId), (0, _drizzleorm.isNotNull)(_sharesschema.shares.spaceId), (0, _drizzleorm.eq)(_spacesschema.spaces.id, _sharesschema.shares.spaceId))).leftJoin(_spacesrootsschema.spacesRoots, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNull)(_sharesschema.shares.parentId), (0, _drizzleorm.isNotNull)(_sharesschema.shares.spaceRootId), (0, _drizzleorm.eq)(_spacesrootsschema.spacesRoots.id, _sharesschema.shares.spaceRootId))).leftJoin(childShareFromRoot, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNotNull)(_sharesschema.shares.parentId), (0, _drizzleorm.isNull)(_sharesschema.shares.fileId), (0, _drizzleorm.isNotNull)(_sharesschema.shares.spaceRootId), (0, _drizzleorm.eq)(childShareFromRoot.id, _sharesschema.shares.spaceRootId))).leftJoin(shareRootFile, (0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.externalPath), (0, _drizzleorm.isNotNull)(_sharesschema.shares.spaceRootId), (0, _drizzleorm.or)((0, _drizzleorm.and)((0, _drizzleorm.isNull)(_sharesschema.shares.parentId), (0, _drizzleorm.eq)(shareRootFile.id, _spacesrootsschema.spacesRoots.fileId)), (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_sharesschema.shares.parentId), (0, _drizzleorm.eq)(shareRootFile.id, childShareFromRoot.fileId))))).leftJoin(parentShare, (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_sharesschema.shares.parentId), (0, _drizzleorm.eq)(parentShare.id, _sharesschema.shares.parentId))).leftJoin(parentShareFile, (0, _drizzleorm.and)((0, _drizzleorm.isNotNull)(_sharesschema.shares.parentId), (0, _drizzleorm.isNotNull)(parentShare.fileId), (0, _drizzleorm.eq)(parentShareFile.id, parentShare.fileId))).leftJoin(shareMembers, (0, _drizzleorm.eq)(shareMembers.shareId, _sharesschema.shares.id)).$dynamic();
    }
    async setShareCounts(shares) {
        if (!shares.length) return;
        for (const share of shares){
            share.counts.shares = await this.childSharesCount(share.id);
        }
    }
    constructor(db, cache){
        this.db = db;
        this.cache = cache;
        this.logger = new _common.Logger(SharesQueries.name);
        this.sharesListQuery = null;
        this.shareIdsQuery = null;
        this.shareLinksListQuery = null;
        this.shareWithMembersQuery = null;
        this.sharePermissionsQuery = null;
        this.shareRootFilesQuery = null;
    }
};
_ts_decorate([
    (0, _cachedecorator.CacheDecorator)(),
    _ts_metadata("design:type", Function),
    _ts_metadata("design:paramtypes", [
        Number,
        Number
    ]),
    _ts_metadata("design:returntype", Promise)
], SharesQueries.prototype, "shareIds", null);
_ts_decorate([
    (0, _cachedecorator.CacheDecorator)(),
    _ts_metadata("design:type", Function),
    _ts_metadata("design:paramtypes", [
        Number,
        String,
        Number
    ]),
    _ts_metadata("design:returntype", Promise)
], SharesQueries.prototype, "permissions", null);
_ts_decorate([
    (0, _cachedecorator.CacheDecorator)(900, true),
    _ts_metadata("design:type", Function),
    _ts_metadata("design:paramtypes", [
        Number
    ]),
    _ts_metadata("design:returntype", Promise)
], SharesQueries.prototype, "childSharesCount", null);
SharesQueries = _ts_decorate([
    (0, _common.Injectable)(),
    _ts_param(0, (0, _common.Inject)(_constants1.DB_TOKEN_PROVIDER)),
    _ts_metadata("design:type", Function),
    _ts_metadata("design:paramtypes", [
        typeof DBSchema === "undefined" ? Object : DBSchema,
        typeof _cacheservice.Cache === "undefined" ? Object : _cacheservice.Cache
    ])
], SharesQueries);

//# sourceMappingURL=shares-queries.service.js.map