diff --git a/packages/api/src/graphql/metadata.ts b/packages/api/src/graphql/metadata.ts index 7263313f..2ff34139 100644 --- a/packages/api/src/graphql/metadata.ts +++ b/packages/api/src/graphql/metadata.ts @@ -1,9 +1,9 @@ import { gql } from "@apollo/client"; import { - TMetadataCollection, - TMetadataCollectionRequest, - TMetadataDocument, - TMetadataDocumentRequest, + TCollectionMetadata, + TCollectionMetadataRequest, + TDocumentMetadata, + TDocumentMetadataRequest, } from "@zkdb/common"; import { createQueryFunction, TApolloClient } from "./common"; @@ -14,13 +14,13 @@ const METADATA_COLLECTION = gql``; export const metadata = (client: TApolloClient) => ({ document: createQueryFunction< - TMetadataDocument, - TMetadataDocumentRequest, - { getMetadataDocument: TMetadataDocument } + TDocumentMetadata, + TDocumentMetadataRequest, + { documentMetadata: TDocumentMetadata } >(client, METADATA_DOCUMENT, (data) => data), collection: createQueryFunction< - TMetadataCollection, - TMetadataCollectionRequest, - { getMetadataCollection: TMetadataCollection } + TCollectionMetadata, + TCollectionMetadataRequest, + { collectionMetadata: TCollectionMetadata } >(client, METADATA_COLLECTION, (data) => data), }); diff --git a/packages/common/src/types/collection.ts b/packages/common/src/types/collection.ts index 74bafe2a..98d06d20 100644 --- a/packages/common/src/types/collection.ts +++ b/packages/common/src/types/collection.ts @@ -2,7 +2,7 @@ import { OwnershipAndPermission } from '@zkdb/permission'; import { IndexDirection } from 'mongodb'; import { TPickAlter } from './common.js'; import { TDatabaseRequest } from './database.js'; -import { TMetadataCollection } from './metadata.js'; +import { TCollectionMetadata } from './metadata.js'; import { TSchemaFieldDefinition } from './schema.js'; /** @@ -82,7 +82,7 @@ export type TCollectionCreateResponse = boolean; // Collection list export type TCollectionListRequest = TDatabaseRequest; -export type TCollectionListResponse = TMetadataCollection[]; +export type TCollectionListResponse = TCollectionMetadata[]; // Collection exist export type TCollectionExistRequest = TCollectionRequest; diff --git a/packages/common/src/types/database.ts b/packages/common/src/types/database.ts index fd23ea96..434a8966 100644 --- a/packages/common/src/types/database.ts +++ b/packages/common/src/types/database.ts @@ -88,11 +88,4 @@ export type TDatabaseFindByIndexRequest = TDatabaseRequest & { index: number; }; -// Database change owner -export type TDatabaseChangeOwnerRequest = TDatabaseRequest & { - newOwner: string; -}; - -export type TDatabaseChangeOwnerResponse = boolean; - export type TDatabaseExistResponse = boolean; diff --git a/packages/common/src/types/document.ts b/packages/common/src/types/document.ts index ab1dbfa7..5d987604 100644 --- a/packages/common/src/types/document.ts +++ b/packages/common/src/types/document.ts @@ -2,7 +2,7 @@ import { ObjectId } from 'mongodb'; import { TContractSchemaField } from '../schema.js'; import { TDbRecord, TNullable } from './common.js'; import { TMerkleProof } from './merkle-tree.js'; -import { TMetadataDocument } from './metadata.js'; +import { TDocumentMetadata } from './metadata.js'; import { TPagination, TPaginationReturn } from './pagination.js'; import { EProofStatusDocument } from './proof.js'; @@ -42,7 +42,7 @@ export type TDocumentFindRequest = TDocumentNamespace & { export type TDocumentFindResponse = TPaginationReturn< Array< TDocumentResponse & { - metadata?: TMetadataDocument; + metadata?: TDocumentMetadata; proofStatus?: EProofStatusDocument; } > diff --git a/packages/common/src/types/metadata.ts b/packages/common/src/types/metadata.ts index 0fb404ad..dced4467 100644 --- a/packages/common/src/types/metadata.ts +++ b/packages/common/src/types/metadata.ts @@ -7,26 +7,26 @@ import { TDocument } from './document.js'; export type TMetadataBasic = OwnershipAndPermission; // Document metadata -export type TMetadataDocument = TMetadataBasic & { +export type TDocumentMetadata = TMetadataBasic & { collectionName: string; docId: string; merkleIndex: string; }; -export type TMetadataDocumentRecord = TDbRecord; +export type TDocumentMetadataRecord = TDbRecord; // Metadata from mongodb -export type TMetadataCollectionMongo = { +export type TCollectionMetadataMongo = { sizeOnDisk: number; }; // Collection metadata -export type TMetadataCollection = TMetadataDetail< - TCollection & Partial, +export type TCollectionMetadata = TMetadataDetail< + TCollection & Partial, TMetadataBasic >; -export type TMetadataCollectionRecord = TDbRecord; +export type TCollectionMetadataRecord = TDbRecord; /** * Not sure what this is for? @@ -37,13 +37,17 @@ export type TMetadataCollectionRecord = TDbRecord; */ export type TMetadataDetail = T & { metadata: M }; -export type TMetadataDetailDocument = TMetadataDetail; +export type TMetadataDetailDocument = TMetadataDetail; -export type TMetadataDocumentRequest = TDatabaseRequest & +export type TDocumentMetadataRequest = TDatabaseRequest & Pick & Pick; -export type TMetadataCollectionRequest = Omit< - TMetadataDocumentRequest, +export type TDocumentMetadataResponse = TDocumentMetadata; + +export type TCollectionMetadataRequest = Omit< + TDocumentMetadataRequest, 'docId' >; + +export type TCollectionMetadataResponse = TCollectionMetadata; diff --git a/packages/serverless/src/apollo/app/collection.ts b/packages/serverless/src/apollo/app/collection.ts index f40ab462..4ce2247f 100644 --- a/packages/serverless/src/apollo/app/collection.ts +++ b/packages/serverless/src/apollo/app/collection.ts @@ -1,4 +1,5 @@ -import { Collection } from '@domain'; +import { GROUP_DEFAULT_ADMIN } from '@common'; +import { Collection, Metadata } from '@domain'; import { gql } from '@helper'; import { collectionName, @@ -13,13 +14,14 @@ import { TCollectionExistResponse, TCollectionListRequest, TCollectionListResponse, + TCollectionMetadataRequest, + TCollectionMetadataResponse, } from '@zkdb/common'; import { Permission } from '@zkdb/permission'; import { withTransaction } from '@zkdb/storage'; import GraphQLJSON from 'graphql-type-json'; import Joi from 'joi'; import { authorizeWrapper, publicWrapper } from '../validation'; -import { GROUP_DEFAULT_ADMIN } from '@common'; export const schemaField = Joi.object({ name: Joi.string() @@ -58,7 +60,12 @@ export const typeDefsCollection = gql` extend type Query { collectionList(databaseName: String!): [MetadataCollection]! - collectionExist(databaseName: String!, collectionName: String!): Boolean + collectionMetadata( + databaseName: String! + collectionName: String! + ): MetadataCollection! + + collectionExist(databaseName: String!, collectionName: String!): Boolean! } extend type Mutation { @@ -68,7 +75,7 @@ export const typeDefsCollection = gql` schema: [SchemaFieldInput!]! group: String permission: Int - ): Boolean + ): Boolean! } `; @@ -124,11 +131,35 @@ const collectionCreate = authorizeWrapper< ) ); +const collectionMetadata = authorizeWrapper< + TCollectionMetadataRequest, + TCollectionMetadataResponse +>( + Joi.object({ + databaseName, + collectionName, + }), + async (_root, { databaseName, collectionName }, ctx) => { + const collectionMetadata = await Metadata.collection({ + databaseName, + collectionName, + actor: ctx.userName, + }); + + if (!collectionMetadata) { + throw new Error(`Can't find metadata collection: ${collectionName}`); + } + + return collectionMetadata; + } +); + export const resolversCollection = { JSON: GraphQLJSON, Query: { collectionList, collectionExist, + collectionMetadata, }, Mutation: { collectionCreate, diff --git a/packages/serverless/src/apollo/app/database.ts b/packages/serverless/src/apollo/app/database.ts index e86583d7..3c7628f5 100644 --- a/packages/serverless/src/apollo/app/database.ts +++ b/packages/serverless/src/apollo/app/database.ts @@ -1,6 +1,6 @@ +import { Database } from '@domain'; +import { config, gql } from '@helper'; import { - TDatabaseChangeOwnerRequest, - TDatabaseChangeOwnerResponse, TDatabaseCreateRequest, TDatabaseCreateResponse, TDatabaseExistResponse, @@ -14,7 +14,6 @@ import { merkleHeight, pagination, publicKey, - userName, } from '@zkdb/common'; import { ModelDatabase, @@ -24,8 +23,6 @@ import { import GraphQLJSON from 'graphql-type-json'; import Joi from 'joi'; import { Document, ObjectId } from 'mongodb'; -import { Database } from '@domain'; -import { config, gql } from '@helper'; import { authorizeWrapper, publicWrapper } from '../validation'; export const typeDefsDatabase = gql` @@ -69,7 +66,6 @@ export const typeDefsDatabase = gql` extend type Mutation { dbCreate(databaseName: String!, merkleHeight: Int!): Boolean - dbTransferOwner(databaseName: String!, newOwner: String!): Boolean dbDeploy(databaseName: String!, appPublicKey: String!): Boolean } `; @@ -107,12 +103,6 @@ export const JOI_DATABASE_UPDATE_DEPLOY = appPublicKey: publicKey, }); -export const JOI_DATABASE_TRANSFER_OWNER = - Joi.object({ - databaseName, - newOwner: userName, - }); - // Query const dbStats = publicWrapper( Joi.object({ @@ -178,17 +168,6 @@ const dbCreate = authorizeWrapper< ) ); -const dbTransferOwner = authorizeWrapper< - TDatabaseChangeOwnerRequest, - TDatabaseChangeOwnerResponse ->(JOI_DATABASE_TRANSFER_OWNER, async (_root, { databaseName, newOwner }, ctx) => - Database.transferOwnership({ - databaseName, - newOwner, - databaseOwner: ctx.userName, - }) -); - const dbExist = publicWrapper( Joi.object({ databaseName, @@ -224,7 +203,6 @@ export const resolversDatabase = { }, Mutation: { dbCreate, - dbTransferOwner, dbDeploy, }, }; diff --git a/packages/serverless/src/apollo/app/document.ts b/packages/serverless/src/apollo/app/document.ts index 226d32c8..930cf5f4 100644 --- a/packages/serverless/src/apollo/app/document.ts +++ b/packages/serverless/src/apollo/app/document.ts @@ -4,7 +4,7 @@ import { withCompoundTransaction, withTransaction } from '@zkdb/storage'; import GraphQLJSON from 'graphql-type-json'; import Joi from 'joi'; -import { Document } from '@domain'; +import { Document, Metadata } from '@domain'; import { gql } from '@helper'; import { authorizeWrapper } from '../validation'; import { @@ -24,6 +24,8 @@ import { TDocumentDropRequest, TDocumentDropResponse, docId, + TDocumentMetadataRequest, + TDocumentMetadataResponse, } from '@zkdb/common'; import { Permission } from '@zkdb/permission'; @@ -121,6 +123,15 @@ export const typeDefsDocument = gql` offset: Int! } + type DocumentMetadataResponse { + owner: String! + group: String! + permission: Int! + collectionName: String! + docId: String! + merkleIndex: String! + } + extend type Query { documentFind( databaseName: String! @@ -129,6 +140,12 @@ export const typeDefsDocument = gql` pagination: PaginationInput ): DocumentFindResponse + documentMetadata( + databaseName: String! + collectionName: String! + docId: String! + ): DocumentMetadataResponse + documentHistoryFind( databaseName: String! collectionName: String! @@ -299,11 +316,37 @@ const documentHistoryFind = authorizeWrapper< } ); +const documentMetadata = authorizeWrapper< + TDocumentMetadataRequest, + TDocumentMetadataResponse +>( + Joi.object({ + databaseName, + collectionName, + docId, + }), + async (_root, { databaseName, collectionName, docId }, ctx) => { + const documentMetadata = await Metadata.document({ + databaseName, + collectionName, + docId, + actor: ctx.userName, + }); + + if (!documentMetadata) { + throw new Error(`Can't find metadata document: ${docId}`); + } + + return documentMetadata; + } +); + export const resolversDocument = { JSON: GraphQLJSON, Query: { documentFind, documentHistoryFind, + documentMetadata, }, Mutation: { documentCreate, diff --git a/packages/serverless/src/apollo/app/index.ts b/packages/serverless/src/apollo/app/index.ts index c6add872..919e391b 100644 --- a/packages/serverless/src/apollo/app/index.ts +++ b/packages/serverless/src/apollo/app/index.ts @@ -5,7 +5,6 @@ export * from './database'; export * from './document'; export * from './group'; export * from './merkle-tree'; -export * from './metadata'; export * from './proof'; export * from './rollup'; export * from './transaction'; diff --git a/packages/serverless/src/apollo/app/metadata.ts b/packages/serverless/src/apollo/app/metadata.ts deleted file mode 100644 index ea5748d9..00000000 --- a/packages/serverless/src/apollo/app/metadata.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Metadata } from '@domain'; -import { - collectionName, - databaseName, - docId, - TMetadataCollection, - TMetadataCollectionRequest, - TMetadataDocument, - TMetadataDocumentRequest, -} from '@zkdb/common'; -import GraphQLJSON from 'graphql-type-json'; -import Joi from 'joi'; -import { authorizeWrapper } from '../validation'; -import { gql } from '@helper'; - -export const typeDefsMetadata = gql` - #graphql - scalar JSON - type Query - type Mutation - - type MetadataDocumentResponse { - owner: String! - group: String! - permission: Int! - collectionName: String! - docId: String! - merkleIndex: String! - } - - # @TODO Refactor after document - extend type Query { - getMetadataDocument( - databaseName: String! - collectionName: String! - docId: String! - ): MetadataDocumentResponse - - # TODO: keep JSON for now since we have to make sure what it will return - getMetadataCollection( - databaseName: String! - collectionName: String! - ): MetadataCollection! - } -`; - -// Query -const getMetadataDocument = authorizeWrapper< - TMetadataDocumentRequest, - TMetadataDocument ->( - Joi.object({ - databaseName, - collectionName, - docId, - }), - async (_root, { databaseName, collectionName, docId }, ctx) => { - const documentMetadata = await Metadata.document({ - databaseName, - collectionName, - docId, - actor: ctx.userName, - }); - - if (!documentMetadata) { - throw new Error(`Can't find metadata document: ${docId}`); - } - - return documentMetadata; - } -); - -const getMetadataCollection = authorizeWrapper< - TMetadataCollectionRequest, - TMetadataCollection ->( - Joi.object({ - databaseName, - collectionName, - }), - async (_root, { databaseName, collectionName }, ctx) => { - const collectionMetadata = await Metadata.collection({ - databaseName, - collectionName, - actor: ctx.userName, - }); - - if (!collectionMetadata) { - throw new Error(`Can't find metadata collection: ${collectionName}`); - } - - return collectionMetadata; - } -); - -export const resolversMetadata = { - JSON: GraphQLJSON, - Query: { - getMetadataCollection, - getMetadataDocument, - }, - Mutation: {}, -}; diff --git a/packages/serverless/src/apollo/index.ts b/packages/serverless/src/apollo/index.ts index 71ed8c77..4f3c1955 100644 --- a/packages/serverless/src/apollo/index.ts +++ b/packages/serverless/src/apollo/index.ts @@ -5,7 +5,6 @@ import { resolversDocument, resolversGroup, resolversMerkleTree, - resolversMetadata, resolversProof, resolversRollUp, resolversTransaction, @@ -17,7 +16,6 @@ import { typeDefsDocument, typeDefsGroup, typeDefsMerkleTree, - typeDefsMetadata, typeDefsProof, typeDefsRollUp, typeDefsTransaction, @@ -32,7 +30,6 @@ export const TypedefsApp = [ typeDefsCollectionIndex, typeDefsUser, typeDefsGroup, - typeDefsMetadata, typeDefsMerkleTree, typeDefsProof, typeDefsTransaction, @@ -46,7 +43,6 @@ export const ResolversApp = [ resolversCollectionIndex, resolversUser, resolversGroup, - resolversMetadata, resolversMerkleTree, resolversProof, resolversTransaction, diff --git a/packages/serverless/src/domain/use-case/collection.ts b/packages/serverless/src/domain/use-case/collection.ts index 1e926cd3..ea382f23 100644 --- a/packages/serverless/src/domain/use-case/collection.ts +++ b/packages/serverless/src/domain/use-case/collection.ts @@ -3,7 +3,7 @@ import { PERMISSION_DEFAULT, TCollectionIndexInfo, TCollectionIndexMap, - TMetadataCollectionRecord, + TCollectionMetadataRecord, TParamCollection, TPermissionSudo, TSchemaFieldDefinition, @@ -266,8 +266,8 @@ export class Collection { databaseName: string, actor: string, session?: ClientSession - ): Promise { - const listMetadataCollection = await ModelMetadataCollection.getInstance( + ): Promise { + const lisTCollectionMetadata = await ModelMetadataCollection.getInstance( databaseName ) .find() @@ -275,7 +275,7 @@ export class Collection { return PermissionSecurity.filterMetadataCollection( databaseName, - listMetadataCollection, + lisTCollectionMetadata, actor, PermissionBase.permissionRead(), session diff --git a/packages/serverless/src/domain/use-case/database.ts b/packages/serverless/src/domain/use-case/database.ts index fb215ae6..150749f9 100644 --- a/packages/serverless/src/domain/use-case/database.ts +++ b/packages/serverless/src/domain/use-case/database.ts @@ -179,25 +179,6 @@ export class Database { }; } - public static async transferOwnership( - paramTransferOwner: TDatabaseParamTransferOwner - ): Promise { - const { databaseName, databaseOwner, newOwner } = paramTransferOwner; - const { collection } = new ModelMetadataDatabase(); - if (await Database.isOwner({ databaseName, databaseOwner })) { - const result = await collection.findOneAndUpdate( - { databaseName, databaseOwner }, - { - $set: { databaseOwner: newOwner }, - } - ); - - return result != null; - } - - return false; - } - public static async deploy( paramDeploy: TDatabaseParamDeploy, session: ClientSession diff --git a/packages/serverless/src/domain/use-case/metadata.ts b/packages/serverless/src/domain/use-case/metadata.ts index 577a841a..274768f0 100644 --- a/packages/serverless/src/domain/use-case/metadata.ts +++ b/packages/serverless/src/domain/use-case/metadata.ts @@ -1,6 +1,6 @@ import { - TMetadataCollection, - TMetadataDocument, + TCollectionMetadata, + TDocumentMetadata, TParamCollection, TParamDocument, TPermissionSudo, @@ -10,11 +10,13 @@ import { ClientSession } from 'mongodb'; import { ModelMetadataCollection, ModelMetadataDocument } from '@model'; import { PermissionSecurity } from './permission-security'; +// We create metadata class to manage all metadata of these model +// In Graphql metadata stay on it model FE: graphql metadata of document will be on document.ts export class Metadata { public static async collection( paramCollection: TPermissionSudo, session?: ClientSession - ): Promise { + ): Promise { const { sudo, databaseName, collectionName, actor } = paramCollection; const modelCollectionMetadata = ModelMetadataCollection.getInstance(databaseName); @@ -62,7 +64,7 @@ export class Metadata { public static async document( paramDocument: TPermissionSudo, session?: ClientSession - ): Promise { + ): Promise { const { sudo, databaseName, collectionName, docId, actor } = paramDocument; const modelMetadata = new ModelMetadataDocument(databaseName); diff --git a/packages/serverless/src/domain/use-case/permission-security.ts b/packages/serverless/src/domain/use-case/permission-security.ts index 145d940c..9ecd38f4 100644 --- a/packages/serverless/src/domain/use-case/permission-security.ts +++ b/packages/serverless/src/domain/use-case/permission-security.ts @@ -1,7 +1,7 @@ import { TDocumentRecordNullable, - TMetadataCollectionRecord, - TMetadataDocument, + TCollectionMetadataRecord, + TDocumentMetadata, TParamCollection, TParamDatabase, TParamDocument, @@ -162,11 +162,11 @@ export class PermissionSecurity { public static async filterMetadataCollection( databaseName: string, - listCollection: TMetadataCollectionRecord[], + listCollection: TCollectionMetadataRecord[], actor: string, requiredPermission: PermissionBase, session?: ClientSession - ): Promise { + ): Promise { // If user is database owner then return all system permissions if (await Database.isOwner({ databaseName, databaseOwner: actor })) { return listCollection; @@ -204,7 +204,7 @@ export class PermissionSecurity { const imMetadataDocument = new ModelMetadataDocument(databaseName); const listDocId = listDoc.map((doc) => doc.docId); - const listMetadata: TMetadataDocument[] = await imMetadataDocument + const listMetadata: TDocumentMetadata[] = await imMetadataDocument .find( { $and: [{ collectionName }, { docId: { $in: listDocId } }], diff --git a/packages/serverless/src/model/database/metadata-collection.ts b/packages/serverless/src/model/database/metadata-collection.ts index b3303ba3..5389cf0d 100644 --- a/packages/serverless/src/model/database/metadata-collection.ts +++ b/packages/serverless/src/model/database/metadata-collection.ts @@ -1,4 +1,4 @@ -import { TMetadataCollectionRecord } from '@zkdb/common'; +import { TCollectionMetadataRecord } from '@zkdb/common'; import { addTimestampMongoDB, DATABASE_ENGINE, @@ -9,7 +9,7 @@ import { import { ClientSession, FindOptions, OptionalId } from 'mongodb'; export class ModelMetadataCollection extends ModelGeneral< - OptionalId + OptionalId > { private static collectionName: string = zkDatabaseConstant.databaseCollection.metadataCollection; diff --git a/packages/serverless/src/model/database/metadata-document.ts b/packages/serverless/src/model/database/metadata-document.ts index b5100490..c371cb93 100644 --- a/packages/serverless/src/model/database/metadata-document.ts +++ b/packages/serverless/src/model/database/metadata-document.ts @@ -1,4 +1,4 @@ -import { TMetadataDocumentRecord } from '@zkdb/common'; +import { TDocumentMetadataRecord } from '@zkdb/common'; import { addTimestampMongoDB, DATABASE_ENGINE, @@ -9,7 +9,7 @@ import { import { ClientSession, WithoutId } from 'mongodb'; export class ModelMetadataDocument extends ModelGeneral< - WithoutId + WithoutId > { static collectionName: string = zkDatabaseConstant.databaseCollection.metadataDocument;