UNPKG

appwrite-database-repository

Version:

249 lines (248 loc) 11.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppwriteRepository = void 0; const node_appwrite_1 = require("node-appwrite"); const permission_type_enum_1 = require("./domain/permission-type.enum"); const NOT_FOUND_STATUS_CODE = 404; const MAX_PAGE_SIZE = 5000; class AppwriteRepository { constructor(client, databaseId, collectionId) { this.client = client; this.databaseId = databaseId; this.collectionId = collectionId; this.databases = new node_appwrite_1.Databases(this.client); } async listDocuments(queries) { return this.databases.listDocuments(this.databaseId, this.collectionId, queries); } async listByProperties(properties, extraQueries) { const queries = []; for (const [key, value] of Object.entries(properties)) { queries.push(node_appwrite_1.Query.equal(key, value)); } if (extraQueries) { queries.push(...extraQueries); } return this.databases.listDocuments(this.databaseId, this.collectionId, queries); } async createDocument(data, permissions) { const result = await this.databases.createDocument(this.databaseId, this.collectionId, node_appwrite_1.ID.unique(), data, permissions); return result; } async createDocumentWithId(documentId, data, permissions) { const result = await this.databases.createDocument(this.databaseId, this.collectionId, documentId, data, permissions); return result; } async getDocument(documentId, queries) { try { return await this.databases.getDocument(this.databaseId, this.collectionId, documentId, queries); } catch (err) { if (err.code === NOT_FOUND_STATUS_CODE) { return null; } throw err; } } async getDocumentBy(query) { const queryList = []; for (const [key, value] of Object.entries(query)) { queryList.push(node_appwrite_1.Query.equal(key, value)); } queryList.push(node_appwrite_1.Query.limit(1)); const { documents } = await this.databases.listDocuments(this.databaseId, this.collectionId, queryList); return documents.length ? documents[0] : null; } async updateDocument(documentId, data, permissions) { const result = await this.databases.updateDocument(this.databaseId, this.collectionId, documentId, data, permissions); return result; } async deleteDocument(documentId) { await this.databases.deleteDocument(this.databaseId, this.collectionId, documentId); } async createOrUpdateDocument(query, data, permissions) { const existingDocument = await this.getDocumentBy(query); if (existingDocument) { return this.updateDocument(existingDocument.$id, data, permissions); } return this.createDocument(data, permissions); } async createOrUpdateBooleanAttribute(key, required, xdefault, array) { const exists = await this.attributeExists(key); if (exists) { await this.databases.updateBooleanAttribute(this.databaseId, this.collectionId, key, required, xdefault ?? null); } else { await this.databases.createBooleanAttribute(this.databaseId, this.collectionId, key, required, xdefault, array); } } async createOrUpdateStringAttribute(key, size, required, xdefault, array, encrypt) { const exists = await this.attributeExists(key); if (exists) { await this.databases.updateStringAttribute(this.databaseId, this.collectionId, key, required, xdefault ?? null); } else { await this.databases.createStringAttribute(this.databaseId, this.collectionId, key, size, required, xdefault, array, encrypt); } } async createOrUpdateDateTimeAttribute(key, required, xdefault, array) { const exists = await this.attributeExists(key); if (exists) { await this.databases.updateDatetimeAttribute(this.databaseId, this.collectionId, key, required, xdefault ?? null); } else { await this.databases.createDatetimeAttribute(this.databaseId, this.collectionId, key, required, xdefault, array); } } async createOrUpdateEmailAttribute(key, required, xdefault, array) { const exists = await this.attributeExists(key); if (exists) { await this.databases.updateEmailAttribute(this.databaseId, this.collectionId, key, required, xdefault ?? null); } else { await this.databases.createEmailAttribute(this.databaseId, this.collectionId, key, required, xdefault, array); } } async createOrUpdateEnumAttribute(key, elements, required, xdefault, array) { const exists = await this.attributeExists(key); if (exists) { await this.databases.updateEnumAttribute(this.databaseId, this.collectionId, key, elements, required, xdefault ?? null); } else { await this.databases.createEnumAttribute(this.databaseId, this.collectionId, key, elements, required, xdefault, array); } } async createOrUpdateFloatAttribute(key, required, min, max, xdefault, array) { const exists = await this.attributeExists(key); if (exists) { await this.databases.updateFloatAttribute(this.databaseId, this.collectionId, key, required, min ?? null, max ?? null, xdefault ?? null); } else { await this.databases.createFloatAttribute(this.databaseId, this.collectionId, key, required, min, max, xdefault, array); } } async createOrUpdateIntegerAttribute(key, required, min, max, xdefault) { const exists = await this.attributeExists(key); if (exists) { await this.databases.updateIntegerAttribute(this.databaseId, this.collectionId, key, required, min ?? null, max ?? null, xdefault ?? null); } else { await this.databases.createIntegerAttribute(this.databaseId, this.collectionId, key, required, min, max, xdefault); } } async createOrUpdateIndex(key, type, attributes, orders) { try { return await this.databases.getIndex(this.databaseId, this.collectionId, key); } catch (err) { if (err.code === NOT_FOUND_STATUS_CODE) { return await this.databases.createIndex(this.databaseId, this.collectionId, key, type, attributes, orders); } console.error(err); return await this.databases.createIndex(this.databaseId, this.collectionId, key, type, attributes, orders); } } async getIndex(key) { return this.databases.getIndex(this.databaseId, this.collectionId, key); } async attributeExists(key) { try { await this.getAttribute(key); } catch (err) { if (err.code === NOT_FOUND_STATUS_CODE) { return false; } } return true; } async getAttribute(key) { return this.databases.getAttribute(this.databaseId, this.collectionId, key); } async deleteAttribute(key) { await this.databases.deleteAttribute(this.databaseId, this.collectionId, key); } async getCollection() { return this.databases.getCollection(this.databaseId, this.collectionId); } async createOrUpdateCollection(name, permissions, documentSecurity, enabled) { try { await this.databases.getCollection(this.databaseId, this.collectionId); } catch (err) { if (err.code === NOT_FOUND_STATUS_CODE) { return this.databases.createCollection(this.databaseId, this.collectionId, name, permissions, documentSecurity, enabled); } console.error(err); } return this.databases.updateCollection(this.databaseId, this.collectionId, name, permissions, documentSecurity, enabled); } async hasCollectionPermission(client, permissionType) { const collection = await this.getCollection(); return await this.hasPermission(client, collection.$permissions, permissionType); } async hasDocumentPermission(client, document, permissionType) { return this.hasPermission(client, document.$permissions, permissionType); } async hasPermission(client, permissionsToCheck, permissionType) { const typeIsWritePermission = [permission_type_enum_1.PermissionType.Create, permission_type_enum_1.PermissionType.Delete, permission_type_enum_1.PermissionType.Update].includes(permissionType); if (typeIsWritePermission) { const allowedByWritePermission = permissionsToCheck.some(permission => permission === 'write("any")'); if (allowedByWritePermission) { return true; } } const permissionsOfType = permissionsToCheck.filter((permission) => permission.startsWith(permissionType)); const allowedByAnyPermission = permissionsOfType.some(permission => permission === `${permissionType}("any")`); if (allowedByAnyPermission) { return true; } const userId = client.decodedToken.userId; const allowedByUserPermission = permissionsOfType.some(permission => permission === `${permissionType}("user:${userId}")`); if (allowedByUserPermission) { return true; } const clientTeams = await this.findAllTeams(client); const teamPermissionsWithoutRole = permissionsOfType.filter(permission => permission.includes('team:')); const allowedByTeamPermission = teamPermissionsWithoutRole.some((teamPermission) => { return clientTeams.some(team => teamPermission === `${permissionType}("team:${team.$id}")`); }); if (allowedByTeamPermission) { return true; } const teams = new node_appwrite_1.Teams(this.client); const teamPermissionsWithRole = permissionsOfType.filter(permission => permission.startsWith(`${permissionType}("team:`) && permission.includes('/')); for (const rolePermission of teamPermissionsWithRole) { const teamId = this.getTeamIdFromTeamRolePermission(rolePermission); if (!teamId) { continue; } const memberships = (await teams.listMemberships(teamId, [node_appwrite_1.Query.equal('userId', client.decodedToken.userId)])).memberships; const allMemberRoles = memberships.map(membership => membership.roles).flat(); const hasRolePermission = allMemberRoles.some((role) => rolePermission === `${permissionType}("team:${teamId}/${role}")`); if (hasRolePermission) { return true; } } return false; } getTeamIdFromTeamRolePermission(permission) { const teamSearch = 'team:'; const startIndex = permission.indexOf(teamSearch) + teamSearch.length; const endIndex = permission.indexOf('/'); if (startIndex >= 5 && endIndex !== -1) { return permission.substring(startIndex, endIndex); } else { return null; } } async findAllTeams(client) { const teams = new node_appwrite_1.Teams(client); return (await teams.list([node_appwrite_1.Query.limit(MAX_PAGE_SIZE)])).teams; } asAppClient(client) { return new AppwriteRepository(client, this.databaseId, this.collectionId); } } exports.AppwriteRepository = AppwriteRepository;