diff --git a/ai-service/.gitignore b/ai-service/.gitignore index 4b0d8c5b69..e1597c74f3 100644 --- a/ai-service/.gitignore +++ b/ai-service/.gitignore @@ -1,3 +1,2 @@ -/faiss-vector -/data - +/faiss-vector/ +/data/ diff --git a/ai-service/package.json b/ai-service/package.json index f7f19606c2..526b4cd51d 100644 --- a/ai-service/package.json +++ b/ai-service/package.json @@ -1,11 +1,11 @@ { "name": "ai-service", - "version": "2.25.0", + "version": "2.25.1", "main": "dist/app.js", "license": "Apache-2.0", "dependencies": { - "@guardian/common": "^2.25.0", - "@guardian/interfaces": "^2.25.0", + "@guardian/common": "^2.25.1", + "@guardian/interfaces": "^2.25.1", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", "@nestjs/common": "^9.4.1", diff --git a/analytics-service/package.json b/analytics-service/package.json index 89cf74106a..1e0dbf0d0a 100644 --- a/analytics-service/package.json +++ b/analytics-service/package.json @@ -13,8 +13,8 @@ }, "author": "Envision Blockchain Solutions ", "dependencies": { - "@guardian/common": "^2.25.0", - "@guardian/interfaces": "^2.25.0", + "@guardian/common": "^2.25.1", + "@guardian/interfaces": "^2.25.1", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", "@nestjs/jwt": "^10.0.3", @@ -82,5 +82,5 @@ "test": "mocha tests/**/*.test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../test_results/ui-service.xml" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/api-gateway/package.json b/api-gateway/package.json index f4040e8912..6d1b17da42 100644 --- a/api-gateway/package.json +++ b/api-gateway/package.json @@ -4,8 +4,8 @@ "@fastify/formbody": "^7.4.0", "@fastify/multipart": "^8.2.0", "@fastify/static": "^7.0.0", - "@guardian/common": "^2.25.0", - "@guardian/interfaces": "^2.25.0", + "@guardian/common": "^2.25.1", + "@guardian/interfaces": "^2.25.1", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", "@nestjs/jwt": "^10.0.3", @@ -87,5 +87,5 @@ "test": "mocha tests/**/*.test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../test_results/ui-service.xml" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/api-gateway/src/api/service/permissions.ts b/api-gateway/src/api/service/permissions.ts index e1979b0541..ae80525cc7 100644 --- a/api-gateway/src/api/service/permissions.ts +++ b/api-gateway/src/api/service/permissions.ts @@ -443,7 +443,7 @@ export class PermissionsApi { try { const owner = user.parent || user.did; const users = new Users(); - const row = await users.getUser(username); + const row = await users.getUserPermissions(username); if (!row || row.parent !== owner || row.did === user.did) { throw new HttpException('User does not exist.', HttpStatus.NOT_FOUND); } @@ -500,7 +500,7 @@ export class PermissionsApi { let row: any; const users = new Users(); try { - row = await users.getUser(username); + row = await users.getUserPermissions(username); } catch (error) { await InternalException(error); } @@ -583,7 +583,7 @@ export class PermissionsApi { const owner = user.parent || user.did; let target: any; try { - target = await (new Users()).getUser(username); + target = await (new Users()).getUserPermissions(username); } catch (error) { await InternalException(error); } @@ -648,7 +648,7 @@ export class PermissionsApi { let row: any; const users = new Users(); try { - row = await users.getUser(username); + row = await users.getUserPermissions(username); } catch (error) { await InternalException(error); } @@ -713,7 +713,7 @@ export class PermissionsApi { let row: any; const users = new Users(); try { - row = await users.getUser(username); + row = await users.getUserPermissions(username); } catch (error) { await InternalException(error); } @@ -773,7 +773,7 @@ export class PermissionsApi { let row: any; const users = new Users(); try { - row = await users.getUser(username); + row = await users.getUserPermissions(username); } catch (error) { await InternalException(error); } diff --git a/api-gateway/src/helpers/users.ts b/api-gateway/src/helpers/users.ts index 3283c65577..47df033e71 100644 --- a/api-gateway/src/helpers/users.ts +++ b/api-gateway/src/helpers/users.ts @@ -88,6 +88,14 @@ export class Users extends NatsService { return await this.sendMessage(AuthEvents.GET_USER, { username }); } + /** + * Return user by username + * @param username + */ + public async getUserPermissions(username: string): Promise { + return await this.sendMessage(AuthEvents.GET_USER_PERMISSIONS, { username }); + } + /** * Return user by did * @param did diff --git a/api-tests/package.json b/api-tests/package.json index f77de614ac..a66d2c69a3 100644 --- a/api-tests/package.json +++ b/api-tests/package.json @@ -1,6 +1,6 @@ { "name": "api-tests", - "version": "2.25.0", + "version": "2.25.1", "description": "API Tests", "main": "index.js", "type": "module", diff --git a/auth-service/package.json b/auth-service/package.json index 427fcbce40..ad915994b0 100644 --- a/auth-service/package.json +++ b/auth-service/package.json @@ -10,8 +10,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.25.0", - "@guardian/interfaces": "^2.25.0", + "@guardian/common": "^2.25.1", + "@guardian/interfaces": "^2.25.1", "@meeco/cryppo": "^2.0.2", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", @@ -75,5 +75,5 @@ "test": "mocha tests/**/*.test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../test_results/ui-service.xml" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/auth-service/src/api/account-service.ts b/auth-service/src/api/account-service.ts index 2f7f668b72..8b3511bdb7 100644 --- a/auth-service/src/api/account-service.ts +++ b/auth-service/src/api/account-service.ts @@ -20,6 +20,7 @@ import { IGetUsersByAccountMessage, IGetUsersByIdMessage, IGetUsersByIRoleMessage, + IGroup, IRegisterNewUserMessage, ISaveUserMessage, IStandardRegistryUserResponse, @@ -71,7 +72,12 @@ export async function createNewUser( default: true, readonly: true }); - const permissionsGroup = defaultRole ? [defaultRole.id] : []; + const permissionsGroup: IGroup[] = defaultRole ? [{ + uuid: defaultRole.uuid, + roleId: defaultRole.id, + roleName: defaultRole.name, + owner: null + }] : []; const permissions = defaultRole ? defaultRole.permissions : []; const user = (new DataBaseHelper(User)).create({ username, @@ -88,6 +94,14 @@ export async function createNewUser( return await (new DataBaseHelper(User)).save(user); } +export function getRequiredProps(user: User): IUser { + const userRequiredProps: IUser = {} + for (const prop of Object.values(USER_REQUIRED_PROPS)) { + userRequiredProps[prop] = user[prop]; + } + return userRequiredProps; +} + /** * Account service */ @@ -125,15 +139,7 @@ export class AccountService extends NatsService { } const user = await new DataBaseHelper(User).findOne({ username: decryptedToken.username }); - const puser = setDefaultPermissions(user) - - const userRequiredProps = {} - - for (const prop of Object.values(USER_REQUIRED_PROPS)) { - userRequiredProps[prop] = puser[prop]; - } - - return new MessageResponse(userRequiredProps); + return new MessageResponse(getRequiredProps(setDefaultPermissions(user))); } catch (error) { return new MessageError(error); } @@ -221,7 +227,7 @@ export class AccountService extends NatsService { this.getMessages(AuthEvents.GET_USERS_BY_ID, async (msg: any) => { const { dids } = msg; try { - return new MessageResponse(await new DataBaseHelper(User).find({ where: { did: { $in: dids } } })); + return new MessageResponse(await new DataBaseHelper(User).find({ did: { $in: dids } })); } catch (error) { new Logger().error(error, ['AUTH_SERVICE']); return new MessageError(error); @@ -247,11 +253,13 @@ export class AccountService extends NatsService { */ this.getMessages(AuthEvents.GET_ALL_USER_ACCOUNTS, async (_: any) => { try { - const userAccounts = (await new DataBaseHelper(User).find({ role: UserRole.USER })).map((e) => ({ - username: e.username, - parent: e.parent, - did: e.did - })); + const userAccounts = (await new DataBaseHelper(User) + .find({ role: UserRole.USER })) + .map((e) => ({ + username: e.username, + parent: e.parent, + did: e.did + })); return new MessageResponse(userAccounts); } catch (error) { new Logger().error(error, ['AUTH_SERVICE']); @@ -264,10 +272,12 @@ export class AccountService extends NatsService { */ this.getMessages(AuthEvents.GET_ALL_STANDARD_REGISTRY_ACCOUNTS, async (_) => { try { - const userAccounts = (await new DataBaseHelper(User).find({ role: UserRole.STANDARD_REGISTRY })).map((e) => ({ - username: e.username, - did: e.did - })); + const userAccounts = (await new DataBaseHelper(User) + .find({ role: UserRole.STANDARD_REGISTRY })) + .map((e) => ({ + username: e.username, + did: e.did + })); return new MessageResponse(userAccounts); } catch (error) { new Logger().error(error, ['AUTH_SERVICE']); @@ -280,7 +290,9 @@ export class AccountService extends NatsService { */ this.getMessages(AuthEvents.GET_ALL_USER_ACCOUNTS_DEMO, async (_) => { try { - const userAccounts = (await new DataBaseHelper(User).findAll()).map((e) => ({ + const userAccounts = (await new DataBaseHelper(User).find({ + template: { $ne: true } + })).map((e) => ({ parent: e.parent, did: e.did, username: e.username, @@ -322,10 +334,31 @@ export class AccountService extends NatsService { } }); + this.getMessages(AuthEvents.REGISTER_NEW_TEMPLATE, + async (msg: { role: string, did: string, parent: string }) => { + try { + const { role, did, parent } = msg; + const username = `template_${Date.now()}${Math.round(Math.random() * 1000)}`; + const row = (new DataBaseHelper(User)).create({ + username, + role, + parent, + did, + template: true + }); + const user = await (new DataBaseHelper(User)).save(row); + return new MessageResponse(user); + } catch (error) { + new Logger().error(error, ['AUTH_SERVICE']); + return new MessageError(error) + } + }); + this.getMessages(AuthEvents.GENERATE_NEW_TOKEN_BASED_ON_USER_PROVIDER, async (msg: ProviderAuthUser) => { try { - let user = await (new DataBaseHelper(User)).findOne({ username: msg.username }); + let user = await (new DataBaseHelper(User)) + .findOne({ username: msg.username, template: { $ne: true } }); if (!user) { user = await createNewUser( msg.username, @@ -368,7 +401,10 @@ export class AccountService extends NatsService { const REFRESH_TOKEN_UPDATE_INTERVAL = process.env.REFRESH_TOKEN_UPDATE_INTERVAL || '31536000000' // 1 year - const user = await new DataBaseHelper(User).findOne({ username }); + const user = await new DataBaseHelper(User).findOne({ + username, + template: { $ne: true } + }); if (user && passwordDigest === user.password) { const tokenId = GenerateUUIDv4(); const refreshToken = sign({ @@ -405,7 +441,11 @@ export class AccountService extends NatsService { return new MessageResponse({}) } - const user = await new DataBaseHelper(User).findOne({ refreshToken: decryptedToken.id, username: decryptedToken.name }); + const user = await new DataBaseHelper(User).findOne({ + refreshToken: decryptedToken.id, + username: decryptedToken.name, + template: { $ne: true } + }); if (!user) { return new MessageResponse({}) } @@ -424,9 +464,22 @@ export class AccountService extends NatsService { this.getMessages(AuthEvents.UPDATE_USER, async (msg) => { const { username, item } = msg; - try { - return new MessageResponse(await new DataBaseHelper(User).update(item, { username })); + const user = await (new DataBaseHelper(User)) + .findOne({ username }); + if (!user) { + return new MessageResponse(null); + } + Object.assign(user, item); + const template = await (new DataBaseHelper(User)) + .findOne({ did: item.did, template: true }); + if (template) { + user.permissions = template.permissions; + user.permissionsGroup = template.permissionsGroup; + await new DataBaseHelper(User).delete(template); + } + const result = await new DataBaseHelper(User).update(user); + return new MessageResponse(result); } catch (error) { new Logger().error(error, ['AUTH_SERVICE']); return new MessageError(error); @@ -435,7 +488,6 @@ export class AccountService extends NatsService { this.getMessages(AuthEvents.SAVE_USER, async (msg) => { const { user } = msg; - try { return new MessageResponse(await new DataBaseHelper(User).save(user)); } catch (error) { @@ -459,6 +511,7 @@ export class AccountService extends NatsService { 'role', 'permissionsGroup', 'permissions', + 'template' ] }; const _pageSize = parseInt(pageSize, 10); diff --git a/auth-service/src/api/role-service.ts b/auth-service/src/api/role-service.ts index 6d42ad3b72..c8b8f8ee8b 100644 --- a/auth-service/src/api/role-service.ts +++ b/auth-service/src/api/role-service.ts @@ -1,14 +1,8 @@ -import { - DataBaseHelper, - Logger, - MessageError, - MessageResponse, - NatsService, - Singleton -} from '@guardian/common'; -import { AuthEvents, DefaultRoles, GenerateUUIDv4, IGroup, IOwner, Permissions, PermissionsArray, UserRole } from '@guardian/interfaces'; +import { DataBaseHelper, Logger, MessageError, MessageResponse, NatsService, Singleton } from '@guardian/common'; +import { AuthEvents, GenerateUUIDv4, IGroup, IOwner, PermissionsArray } from '@guardian/interfaces'; import { DynamicRole } from '../entity/dynamic-role.js'; import { User } from '../entity/user.js'; +import { getRequiredProps } from './account-service.js'; const permissionList = PermissionsArray.filter((p) => !p.disabled).map((p) => { return { @@ -159,16 +153,7 @@ export class RoleService extends NatsService { otherOptions.limit = 100; } - const options: any = { - $or: [ - { owner }, - { - owner: null, - default: true, - readonly: true - } - ] - }; + const options: any = { owner }; if (name) { options.name = { $regex: '.*' + name + '.*' }; } @@ -205,20 +190,23 @@ export class RoleService extends NatsService { * @returns {any} new role */ this.getMessages(AuthEvents.CREATE_ROLE, - async (msg: { role: DynamicRole, owner: IOwner }) => { + async (msg: { role: DynamicRole, owner: IOwner, restore: boolean }) => { try { if (!msg) { throw new Error('Invalid create role parameters'); } - const { role, owner } = msg; - + const { role, owner, restore } = msg; delete role._id; delete role.id; role.owner = owner.creator; - role.uuid = GenerateUUIDv4(); role.permissions = ListPermissions.unique(role.permissions); role.default = false; role.readonly = false; + if (restore) { + role.uuid = role.uuid || GenerateUUIDv4(); + } else { + role.uuid = GenerateUUIDv4(); + } let item = new DataBaseHelper(DynamicRole).create(role); item = await new DataBaseHelper(DynamicRole).save(item); return new MessageResponse(item); @@ -362,6 +350,13 @@ export class RoleService extends NatsService { if (!target) { return new MessageError('User does not exist'); } + if ( + target.permissionsGroup && + target.permissionsGroup.length && + target.permissionsGroup[0].owner + ) { + return new MessageResponse(getRequiredProps(target)); + } const defaultRole = await getDefaultRole(owner); if (defaultRole) { target.permissionsGroup = [{ @@ -376,92 +371,7 @@ export class RoleService extends NatsService { target.permissions = []; } const result = await new DataBaseHelper(User).update(target); - return new MessageResponse(result); - } catch (error) { - new Logger().error(error, ['GUARDIAN_SERVICE']); - return new MessageError(error); - } - }); - - /** - * Set default role - * - * @param {any} msg - default role parameters - * - * @returns {boolean} - Operation success - */ - this.getMessages(AuthEvents.CREATE_DEFAULT_USER_ROLE, - async (msg: { username: string }) => { - try { - if (!msg) { - return new MessageError('Invalid delete role parameters'); - } - const { username } = msg; - const user = await new DataBaseHelper(User).findOne({ username }) - if (!user) { - return new MessageError('User does not exist'); - } - const db = new DataBaseHelper(User); - if (user.role === UserRole.STANDARD_REGISTRY) { - await db.save(db.create({ - uuid: GenerateUUIDv4(), - name: 'Policy Approver', - description: '', - owner: user.did, - permissions: [ - Permissions.ANALYTIC_POLICY_READ, - Permissions.POLICIES_POLICY_READ, - Permissions.ANALYTIC_MODULE_READ, - Permissions.ANALYTIC_TOOL_READ, - Permissions.ANALYTIC_SCHEMA_READ, - Permissions.POLICIES_POLICY_REVIEW, - Permissions.SCHEMAS_SCHEMA_READ, - Permissions.MODULES_MODULE_READ, - Permissions.TOOLS_TOOL_READ, - Permissions.TOKENS_TOKEN_READ, - Permissions.ARTIFACTS_FILE_READ, - Permissions.SETTINGS_THEME_READ, - Permissions.SETTINGS_THEME_CREATE, - Permissions.SETTINGS_THEME_UPDATE, - Permissions.SETTINGS_THEME_DELETE, - Permissions.TAGS_TAG_READ, - Permissions.TAGS_TAG_CREATE, - Permissions.SUGGESTIONS_SUGGESTIONS_READ, - Permissions.ACCESS_POLICY_ASSIGNED - ], - default: false, - readonly: false - })) - await db.save(db.create({ - uuid: GenerateUUIDv4(), - name: 'Policy Manager', - description: '', - owner: user.did, - permissions: [ - Permissions.ANALYTIC_DOCUMENT_READ, - Permissions.POLICIES_POLICY_MANAGE, - Permissions.POLICIES_POLICY_READ, - Permissions.TOKENS_TOKEN_MANAGE, - Permissions.TOKENS_TOKEN_READ, - Permissions.ACCOUNTS_ACCOUNT_READ, - Permissions.TAGS_TAG_READ, - Permissions.TAGS_TAG_CREATE, - Permissions.ACCESS_POLICY_ASSIGNED_AND_PUBLISHED - ], - default: false, - readonly: false - })) - await db.save(db.create({ - uuid: GenerateUUIDv4(), - name: 'Policy User', - description: '', - owner: user.did, - permissions: DefaultRoles, - default: false, - readonly: false - })) - } - return new MessageResponse(true); + return new MessageResponse(getRequiredProps(result)); } catch (error) { new Logger().error(error, ['GUARDIAN_SERVICE']); return new MessageError(error); @@ -527,7 +437,7 @@ export class RoleService extends NatsService { } target.permissions = Array.from(permissions); const result = await new DataBaseHelper(User).update(target); - return new MessageResponse(result); + return new MessageResponse(getRequiredProps(result)); } catch (error) { new Logger().error(error, ['GUARDIAN_SERVICE']); return new MessageError(error); @@ -570,7 +480,8 @@ export class RoleService extends NatsService { user.permissions = Array.from(permissions); await new DataBaseHelper(User).update(user); } - return new MessageResponse(users); + const result = users?.map((row) => getRequiredProps(row)); + return new MessageResponse(result); } catch (error) { new Logger().error(error, ['GUARDIAN_SERVICE']); return new MessageError(error); @@ -645,11 +556,26 @@ export class RoleService extends NatsService { target.permissionsGroup = permissionsGroup; target.permissions = Array.from(permissions); await new DataBaseHelper(User).update(target); - return new MessageResponse(target); + return new MessageResponse(getRequiredProps(target)); } catch (error) { new Logger().error(error, ['GUARDIAN_SERVICE']); return new MessageError(error); } }); + + /** + * Get user by username + * @param username - username + */ + this.getMessages(AuthEvents.GET_USER_PERMISSIONS, async (msg: any) => { + const { username } = msg; + try { + const user = await new DataBaseHelper(User).findOne({ username }) + return new MessageResponse(getRequiredProps(user)); + } catch (error) { + new Logger().error(error, ['AUTH_SERVICE']); + return new MessageError(error); + } + }); } -} \ No newline at end of file +} diff --git a/auth-service/src/entity/user.ts b/auth-service/src/entity/user.ts index e490582029..5041b5767c 100644 --- a/auth-service/src/entity/user.ts +++ b/auth-service/src/entity/user.ts @@ -93,6 +93,12 @@ export class User extends BaseEntity implements IUser { @Property({ nullable: true }) permissions?: string[]; + /** + * Template + */ + @Property({ nullable: true }) + template?: boolean; + /** * Set defaults */ diff --git a/auth-service/src/migrations/v2-24-1.ts b/auth-service/src/migrations/v2-24-1.ts index d5f9a347fd..83c94ce48e 100644 --- a/auth-service/src/migrations/v2-24-1.ts +++ b/auth-service/src/migrations/v2-24-1.ts @@ -35,7 +35,7 @@ const policyManager = [ ]; /** - * Migration to version 2.9.0 + * Migration to version 2.25.0 */ export class ReleaseMigration extends Migration { /** diff --git a/auth-service/src/migrations/v2-25-1.ts b/auth-service/src/migrations/v2-25-1.ts new file mode 100644 index 0000000000..ccde5f865b --- /dev/null +++ b/auth-service/src/migrations/v2-25-1.ts @@ -0,0 +1,35 @@ +import { DefaultRoles, GenerateUUIDv4, UserRole } from '@guardian/interfaces'; +import { Migration } from '@mikro-orm/migrations-mongodb'; + +/** + * Migration to version 2.25.1 + */ +export class ReleaseMigration extends Migration { + /** + * Up migration + */ + async up(): Promise { + await this.setDefaultRoles(); + } + + /** + * Change document state format + */ + async setDefaultRoles() { + const roleCollection = this.getCollection('DynamicRole'); + const userCollection = this.getCollection('User'); + const srs = userCollection.find({ role: UserRole.STANDARD_REGISTRY }, { session: this.ctx }); + while (await srs.hasNext()) { + const sr = await srs.next(); + const defaultRole = await roleCollection.findOne({ owner: sr.did, default: true }, { session: this.ctx }); + await roleCollection.insertMany([{ + uuid: GenerateUUIDv4(), + name: 'Default policy user', + description: 'Default policy user', + owner: sr.did, + permissions: DefaultRoles, + default: !defaultRole + }], { session: this.ctx }); + } + } +} diff --git a/common/package.json b/common/package.json index 6b033665e4..e11fbe600d 100644 --- a/common/package.json +++ b/common/package.json @@ -5,7 +5,7 @@ "@azure/identity": "^3.2.2", "@azure/keyvault-secrets": "^4.7.0", "@google-cloud/secret-manager": "^4.2.2", - "@guardian/interfaces": "^2.25.0", + "@guardian/interfaces": "^2.25.1", "@hashgraph/sdk": "2.34.1", "@mattrglobal/jsonld-signatures-bbs": "^1.1.2", "@meeco/cryppo": "^2.0.2", @@ -88,5 +88,5 @@ "test:stability": "mocha tests/stability.test.js" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/common/src/helpers/users.ts b/common/src/helpers/users.ts index 669723f46c..65d37ee460 100644 --- a/common/src/helpers/users.ts +++ b/common/src/helpers/users.ts @@ -1,4 +1,4 @@ -import { AuthEvents, GenerateUUIDv4, IRootConfig, UserRole } from '@guardian/interfaces'; +import { AuthEvents, GenerateUUIDv4, IOwner, IRootConfig, UserRole } from '@guardian/interfaces'; import { Singleton } from '../decorators/singleton.js'; import { KeyType, Wallet } from './wallet.js'; import { NatsService } from '../mq/index.js'; @@ -127,7 +127,7 @@ export class Users extends NatsService { /** * Update current user entity - * @param req + * @param username * @param item */ public async updateCurrentUser(username: string, item: any) { @@ -135,20 +135,31 @@ export class Users extends NatsService { } /** - * Create default roles - * @param req - * @param item + * Det default role + * @param id + * @param owner + * @returns Operation Success */ - public async createDefaultRole(username: string) { - return await this.sendMessage(AuthEvents.CREATE_DEFAULT_USER_ROLE, { username }); + public async setDefaultRole(id: string, owner: string): Promise { + return await this.sendMessage(AuthEvents.SET_DEFAULT_ROLE, { id, owner }); + } + + /** + * Create role + * @param role + * @param did + * @returns Operation Success + */ + public async createRole(role: any, owner: IOwner, restore = false): Promise { + return await this.sendMessage(AuthEvents.CREATE_ROLE, { role, owner, restore }); } /** * Update current user entity - * @param req - * @param item + * @param username + * @param owner */ - public async setDefaultRole(username: string, owner: string) { + public async setDefaultUserRole(username: string, owner: string): Promise { return await this.sendMessage(AuthEvents.SET_DEFAULT_USER_ROLE, { username, owner }); } @@ -208,6 +219,36 @@ export class Users extends NatsService { return await this.sendMessage(AuthEvents.GET_ALL_USER_ACCOUNTS_DEMO); } + /** + * Generate new template + * @param role + * @param did + * @param parent + * @returns Operation Success + */ + public async generateNewTemplate( + role: string, + did: string, + parent: string + ): Promise { + return await this.sendMessage(AuthEvents.REGISTER_NEW_TEMPLATE, { role, did, parent }); + } + + /** + * Update user role + * @param username + * @param user + * @param owner + * @returns Operation Success + */ + public async updateUserRole( + username: string, + userRoles: string[], + owner: IOwner + ): Promise { + return await this.sendMessage(AuthEvents.UPDATE_USER_ROLE, { username, userRoles, owner }); + } + /** * Get hedera account * @param did diff --git a/docs/guardian/readme/roadmap.md b/docs/guardian/readme/roadmap.md index c1bc4071fa..834bcda044 100644 --- a/docs/guardian/readme/roadmap.md +++ b/docs/guardian/readme/roadmap.md @@ -269,6 +269,8 @@ Development of all the tool involved in the policy Referral Link : [https://github.com/hashgraph/guardian/issues/2921](https://github.com/hashgraph/guardian/issues/2921) +Documentation Link: [https://docs.hedera.com/guardian/guardian/demo-guide/carbon-offsets/methane-emission-reduction-by-adjusted-water-management-practice-in-rice-cultivation](https://docs.hedera.com/guardian/guardian/demo-guide/carbon-offsets/methane-emission-reduction-by-adjusted-water-management-practice-in-rice-cultivation) + ### Full project data comparison as produced/captured by policies Introduce a comparison functionality where it'd be possible to 'diff' arbitrary sections or the entire trust-chains for different tokens, potentially issued by different policies such that the system would: @@ -278,6 +280,8 @@ Introduce a comparison functionality where it'd be possible to 'diff' arbitrary Referral Link : [https://github.com/hashgraph/guardian/issues/2704](https://github.com/hashgraph/guardian/issues/2704) +Documentation Link: [https://docs.hedera.com/guardian/guardian/standard-registry/project-comparison/project-comparison-using-ui](https://docs.hedera.com/guardian/guardian/standard-registry/project-comparison/project-comparison-using-ui) + ### Global environmental/Guardian data search (indexer) component for Hedera and IPFS * Improve the data storage and indexing capabilities of Guardian for the data belonging to the local instance such that complex analytical queries could be run efficiently, such as 'search for data similar to this' and 'what is the possibility of this being a double entry for something submitted elsewhere'. @@ -286,6 +290,8 @@ Referral Link : [https://github.com/hashgraph/guardian/issues/2704](https://gith Referral Link : [https://github.com/hashgraph/guardian/issues/2629](https://github.com/hashgraph/guardian/issues/2629) +Documentation Link: [https://docs.hedera.com/guardian/guardian/global-indexer/indexer-user-guide](https://docs.hedera.com/guardian/guardian/global-indexer/indexer-user-guide) + ### Revamp Guardian user/roles and permissions model * Fundamentally separate the concept of users, roles and permissions in Guardian @@ -303,55 +309,7 @@ Referral Link : [https://github.com/hashgraph/guardian/issues/2629](https://gith Referral Link : [https://github.com/hashgraph/guardian/issues/2844](https://github.com/hashgraph/guardian/issues/2844) -### Development of AMS-I.F.: Renewable Electricity Generation for Captive Use and Mini-Grid - -1. Designing of the Schema and getting it approved. -2. Development of the policy using Schema -3. Development of all the tools involved in the policy: - - * Tool 01- Tool for the demonstration and assessment of additionality - * Tool 03- Tool to calculate project or leakage CO2 emissions from fossil fuel combustion - * Tool 04- Emissions from solid waste disposal sites - * Tool 05- Baseline, project and/or leakage emissions from electricity consumption and monitoring of electricity generation - * Tool 06- Project emissions from flaring - * Tool 12- Project and leakage emissions from transportation of freight - * Tool 13- Project and leakage emissions from composting - * Tool 14- Project and leakage emissions from anaerobic digesters - * Tool 16- Project and leakage emissions from biomass - * Tool 33- Default values for common parameters - - Referral Link: [https://github.com/hashgraph/guardian/issues/2882](https://github.com/hashgraph/guardian/issues/2882) - -### Development of AMS-I.A. - -1. Designing of the Schema and getting it approved. -2. Development of the policy using Schema -3. Development of all the tools involved in the policy: - * Tool 05- Baseline, project and/or leakage emissions from electricity consumption and monitoring of electricity generation - * Tool 16- Project and leakage emissions from biomass - * Tool 21- Demonstration of additionality of small-scale project activities  - * Tool 33- Default values for common parameters - -Referral Link: [https://github.com/hashgraph/guardian/issues/2884](https://github.com/hashgraph/guardian/issues/2884) - -### Development of AMS-I.C.: Thermal Energy Production with or Without Electricity - -1. Designing the Schema for the methodology -2. Development of the policy -3. Development of all the tools involved in this policy - - * Tool 03- Tool to calculate project or leakage CO2 emissions from fossil fuel combustion - * Tool 05- Baseline, project and/or leakage emissions from electricity consumption and monitoring of electricity generation - * Tool 06- Project emissions from flaring - * Tool 07- Tool to calculate the emission factor for an electricity system - * Tool 09- Determining the baseline efficiency of thermal or electric energy generation systems - * Tool 12- Project and leakage emissions from transportation of freight - * Tool 16- Project and leakage emissions from biomas - * Tool 19- Demonstration of additionality of microscale project activities - * Tool 21- Demonstration of additionality of small-scale project activities  - * Tool 22- Leakage in biomass small-scale project activities - - Referral Link : [https://github.com/hashgraph/guardian/issues/2873](https://github.com/hashgraph/guardian/issues/2873) +Documentation Link: [https://docs.hedera.com/guardian/guardian/standard-registry/roles-and-permissions/roles-and-permissions-user-guide](https://docs.hedera.com/guardian/guardian/standard-registry/roles-and-permissions/roles-and-permissions-user-guide) ## ---- June 2024---- @@ -399,6 +357,55 @@ Create a Guardian policy that quantifies and reports GHG emissions from HBAR, us Referral Link : [https://github.com/hashgraph/guardian/issues/1667](https://github.com/hashgraph/guardian/issues/1667) +### Development of AMS-I.F.: Renewable Electricity Generation for Captive Use and Mini-Grid + +1. Designing of the Schema and getting it approved. +2. Development of the policy using Schema +3. Development of all the tools involved in the policy: + * Tool 01- Tool for the demonstration and assessment of additionality + * Tool 03- Tool to calculate project or leakage CO2 emissions from fossil fuel combustion + * Tool 04- Emissions from solid waste disposal sites + * Tool 05- Baseline, project and/or leakage emissions from electricity consumption and monitoring of electricity generation + * Tool 06- Project emissions from flaring + * Tool 12- Project and leakage emissions from transportation of freight + * Tool 13- Project and leakage emissions from composting + * Tool 14- Project and leakage emissions from anaerobic digesters + * Tool 16- Project and leakage emissions from biomass + * Tool 33- Default values for common parameters + +Referral Link: [https://github.com/hashgraph/guardian/issues/2882](https://github.com/hashgraph/guardian/issues/2882) + +### Development of AMS-I.A. + +1. Designing of the Schema and getting it approved. +2. Development of the policy using Schema +3. Development of all the tools involved in the policy: + * Tool 05- Baseline, project and/or leakage emissions from electricity consumption and monitoring of electricity generation + * Tool 16- Project and leakage emissions from biomass + * Tool 21- Demonstration of additionality of small-scale project activities  + * Tool 33- Default values for common parameters + +Referral Link: [https://github.com/hashgraph/guardian/issues/2884](https://github.com/hashgraph/guardian/issues/2884) + +### Development of AMS-I.C.: Thermal Energy Production with or Without Electricity + +1. Designing the Schema for the methodology +2. Development of the policy +3. Development of all the tools involved in this policy + + * Tool 03- Tool to calculate project or leakage CO2 emissions from fossil fuel combustion + * Tool 05- Baseline, project and/or leakage emissions from electricity consumption and monitoring of electricity generation + * Tool 06- Project emissions from flaring + * Tool 07- Tool to calculate the emission factor for an electricity system + * Tool 09- Determining the baseline efficiency of thermal or electric energy generation systems + * Tool 12- Project and leakage emissions from transportation of freight + * Tool 16- Project and leakage emissions from biomas + * Tool 19- Demonstration of additionality of microscale project activities + * Tool 21- Demonstration of additionality of small-scale project activities  + * Tool 22- Leakage in biomass small-scale project activities + + Referral Link : [https://github.com/hashgraph/guardian/issues/2873](https://github.com/hashgraph/guardian/issues/2873) + ## ---- July 2024---- ### Development of AMS-I.E: Switch from Non-Renewable Biomass for Thermal Applications by the User – v.13.0 diff --git a/frontend/package.json b/frontend/package.json index 8ec3a79193..b23b430e68 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -74,5 +74,5 @@ "test": "ng test", "watch": "ng build --watch --configuration development --output-path ../www-data" }, - "version": "2.25.0" + "version": "2.25.1" } diff --git a/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.html b/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.html index a301e93d83..e918584069 100644 --- a/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.html +++ b/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.html @@ -151,15 +151,29 @@ + \ No newline at end of file diff --git a/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.scss b/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.scss index 77c98af3a6..3aba316bfc 100644 --- a/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.scss +++ b/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.scss @@ -153,4 +153,4 @@ .error-type-error>div { color: var(--color-accent-red-1, #FF432A); } -} +} \ No newline at end of file diff --git a/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.ts b/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.ts index 1c59c7c1ff..12d39d3d0e 100644 --- a/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.ts +++ b/frontend/src/app/modules/policy-engine/helpers/preview-policy-dialog/preview-policy-dialog.component.ts @@ -29,6 +29,19 @@ export class PreviewPolicyDialog { public toolForm?: FormGroup; public isFile?: boolean; + public get valid(): boolean { + if (this.policy) { + return !!this.toolForm?.valid; + } + if (this.module) { + return true; + } + if (this.tool) { + return !!this.toolForm?.valid; + } + return false; + } + constructor( public ref: DynamicDialogRef, public config: DynamicDialogConfig @@ -115,14 +128,14 @@ export class PreviewPolicyDialog { }) .join(', '); - const tools = this.xlsx.tools || []; - this.tools = tools - .map((s: any) => { - return s.name; - }) - .join(', '); + const tools = this.xlsx.tools || []; + this.tools = tools + .map((s: any) => { + return s.name; + }) + .join(', '); - tools + tools this.errors = this.xlsx.errors || []; for (const error of this.errors) { if (error.cell) { diff --git a/frontend/src/app/modules/policy-engine/modules-list/modules-list.component.ts b/frontend/src/app/modules/policy-engine/modules-list/modules-list.component.ts index 12f9a250ba..559764e6ce 100644 --- a/frontend/src/app/modules/policy-engine/modules-list/modules-list.component.ts +++ b/frontend/src/app/modules/policy-engine/modules-list/modules-list.component.ts @@ -161,7 +161,8 @@ export class ModulesListComponent implements OnInit, OnDestroy { private importDetails(result: any) { const { type, data, module } = result; const dialogRef = this.dialog.open(PreviewPolicyDialog, { - width: '950px', + header: 'Import module', + width: '720px', closable: true, data: { module, diff --git a/frontend/src/app/modules/policy-engine/tools-list/tools-list.component.scss b/frontend/src/app/modules/policy-engine/tools-list/tools-list.component.scss index 3f5a67450b..08ec1291e9 100644 --- a/frontend/src/app/modules/policy-engine/tools-list/tools-list.component.scss +++ b/frontend/src/app/modules/policy-engine/tools-list/tools-list.component.scss @@ -534,7 +534,7 @@ border: 1px solid var(--color-primary); margin-left: 10px; height: 40px; - padding: 8px; + padding: 8px 16px 8px 8px; color: var(--color-grey-white, #FFF); font-family: Inter; font-size: 14px; diff --git a/frontend/src/app/views/user-management/user-management.component.html b/frontend/src/app/views/user-management/user-management.component.html index e56fa6f7ff..e16b9678a1 100644 --- a/frontend/src/app/views/user-management/user-management.component.html +++ b/frontend/src/app/views/user-management/user-management.component.html @@ -78,7 +78,7 @@ - + {{ row.username }}
diff --git a/frontend/src/app/views/user-management/user-management.component.scss b/frontend/src/app/views/user-management/user-management.component.scss index 8323769413..ce4efa81ce 100644 --- a/frontend/src/app/views/user-management/user-management.component.scss +++ b/frontend/src/app/views/user-management/user-management.component.scss @@ -192,6 +192,10 @@ background: #fff; } + &[template="true"]>td { + background: #f7f7f7; + } + &:first-child { .row-cell-text:first-child { border-top-left-radius: 8px !important; diff --git a/guardian-service/package.json b/guardian-service/package.json index b4abfcb0f2..51335c620c 100644 --- a/guardian-service/package.json +++ b/guardian-service/package.json @@ -16,8 +16,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.25.0", - "@guardian/interfaces": "^2.25.0", + "@guardian/common": "^2.25.1", + "@guardian/interfaces": "^2.25.1", "@hashgraph/sdk": "2.34.1", "@mattrglobal/jsonld-signatures-bbs": "^1.1.2", "@meeco/cryppo": "^2.0.2", @@ -99,5 +99,5 @@ "test:stability": "mocha tests/stability.test.mjs" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/guardian-service/src/api/permission.service.ts b/guardian-service/src/api/permission.service.ts index 2f1ddb6ae0..4da8ba76ad 100644 --- a/guardian-service/src/api/permission.service.ts +++ b/guardian-service/src/api/permission.service.ts @@ -70,6 +70,11 @@ async function createVc( credentialSubject ); } + if (Array.isArray(credentialSubject.role)) { + for (const role of credentialSubject.roles) { + role.owner = role.owner || ''; + } + } const didDocument = await vcHelper.loadDidDocument(owner.creator); return await vcHelper.createVerifiableCredential(credentialSubject, didDocument, null, null); } @@ -87,6 +92,43 @@ async function createMessageServer(owner: IOwner): Promise { return messageServer; } +export async function serDefaultRole(user: IAuthUser, owner: IOwner): Promise { + const roles: any[] = []; + for (const group of user.permissionsGroup) { + roles.push({ + uuid: group.uuid, + name: group.roleName, + owner: group.owner + }) + } + const data = { + user: user.did + } + const messageServer = await createMessageServer(owner); + const document = await createVc(SchemaEntity.USER_PERMISSIONS, { + id: GenerateUUIDv4(), + userId: user.did, + roles + }, owner, messageServer); + const message = new UserPermissionsMessage(MessageAction.SetRole); + message.setRole(data); + message.setDocument(document); + await messageServer.sendMessage(message); + const result = await new DataBaseHelper(VcDocumentCollection).save({ + hash: message.hash, + owner: owner.owner, + creator: owner.creator, + document: message.document, + type: SchemaEntity.USER_PERMISSIONS, + documentFields: [ + 'credentialSubject.0.id', + 'credentialSubject.0.roles', + 'credentialSubject.0.userId' + ] + }); + return result; +} + /** * Demo API * @param channel @@ -205,39 +247,7 @@ export async function permissionAPI(): Promise { async (msg: { user: IAuthUser, owner: IOwner }) => { try { const { user, owner } = msg; - const roles: any[] = []; - for (const group of user.permissionsGroup) { - roles.push({ - uuid: group.uuid, - name: group.roleName, - owner: group.owner - }) - } - const data = { - user: user.did - } - const messageServer = await createMessageServer(owner); - const document = await createVc(SchemaEntity.USER_PERMISSIONS, { - id: GenerateUUIDv4(), - userId: user.did, - roles - }, owner, messageServer); - const message = new UserPermissionsMessage(MessageAction.SetRole); - message.setRole(data); - message.setDocument(document); - await messageServer.sendMessage(message); - const result = await new DataBaseHelper(VcDocumentCollection).save({ - hash: message.hash, - owner: owner.owner, - creator: owner.creator, - document: message.document, - type: SchemaEntity.USER_PERMISSIONS, - documentFields: [ - 'credentialSubject.0.id', - 'credentialSubject.0.roles', - 'credentialSubject.0.userId' - ] - }); + const result = await serDefaultRole(user, owner); return new MessageResponse(result); } catch (error) { new Logger().error(error, ['GUARDIAN_SERVICE']); diff --git a/guardian-service/src/api/profile.service.ts b/guardian-service/src/api/profile.service.ts index 72f41f6e8a..8d74b7b451 100644 --- a/guardian-service/src/api/profile.service.ts +++ b/guardian-service/src/api/profile.service.ts @@ -1,4 +1,4 @@ -import { DidDocumentStatus, DocumentStatus, EntityOwner, IOwner, ISignOptions, MessageAPI, Schema, SchemaEntity, SchemaHelper, SignType, TopicType, UserRole, WorkerTaskType } from '@guardian/interfaces'; +import { DefaultRoles, DidDocumentStatus, DocumentStatus, EntityOwner, GenerateUUIDv4, IOwner, ISignOptions, MessageAPI, Permissions, Schema, SchemaEntity, SchemaHelper, SignType, TopicType, UserRole, WorkerTaskType } from '@guardian/interfaces'; import { ApiResponse } from '../api/helpers/api-response.js'; import { CommonDidDocument, @@ -6,6 +6,7 @@ import { DidDocument as DidDocumentCollection, DIDMessage, Environment, + GuardianRoleMessage, HederaBBSMethod, HederaDid, HederaEd25519Method, @@ -36,6 +37,7 @@ import { publishSystemSchema } from './helpers/schema-publish-helper.js'; import { Controller, Module } from '@nestjs/common'; import { ClientsModule, Transport } from '@nestjs/microservices'; import { AccountId, PrivateKey } from '@hashgraph/sdk'; +import { serDefaultRole } from './permission.service.js'; interface IFireblocksConfig { fireBlocksVaultId: string; @@ -123,8 +125,12 @@ async function setupUserProfile( hederaAccountId: profile.hederaAccountId, useFireblocksSigning: profile.useFireblocksSigning }); - await users.createDefaultRole(username); - await users.setDefaultRole(username, profile.parent); + + notifier.completedAndStart('Update permissions'); + if (user.role === UserRole.USER) { + const changeRole = await users.setDefaultUserRole(username, profile.parent); + await serDefaultRole(changeRole, EntityOwner.sr(profile.parent)) + } notifier.completedAndStart('Set up wallet'); await wallet.setKey(user.walletToken, KeyType.KEY, did, profile.hederaAccountKey); @@ -460,10 +466,125 @@ async function createUserProfile( .sendMessage(regMessage) } + // ----------------------- + // Publish Role Document --> + // ----------------------- + if (user.role === UserRole.STANDARD_REGISTRY) { + messageServer.setTopicObject(topicConfig); + await createDefaultRoles(userDID, currentDidDocument, messageServer, notifier); + } + notifier.completed(); return userDID; } +/** + * Create default roles + * @param username + * @param notifier + */ +async function createDefaultRoles( + did: string, + didDocument: CommonDidDocument, + messageServer: MessageServer, + notifier: INotifier +): Promise { + notifier.completedAndStart('Create roles'); + const owner = EntityOwner.sr(did); + const users = new Users(); + const vcHelper = new VcHelper(); + const roles = [{ + name: 'Default policy user', + description: 'Default policy user', + permissions: DefaultRoles, + }, { + name: 'Policy Approver', + description: '', + permissions: [ + Permissions.ANALYTIC_POLICY_READ, + Permissions.POLICIES_POLICY_READ, + Permissions.ANALYTIC_MODULE_READ, + Permissions.ANALYTIC_TOOL_READ, + Permissions.ANALYTIC_SCHEMA_READ, + Permissions.POLICIES_POLICY_REVIEW, + Permissions.SCHEMAS_SCHEMA_READ, + Permissions.MODULES_MODULE_READ, + Permissions.TOOLS_TOOL_READ, + Permissions.TOKENS_TOKEN_READ, + Permissions.ARTIFACTS_FILE_READ, + Permissions.SETTINGS_THEME_READ, + Permissions.SETTINGS_THEME_CREATE, + Permissions.SETTINGS_THEME_UPDATE, + Permissions.SETTINGS_THEME_DELETE, + Permissions.TAGS_TAG_READ, + Permissions.TAGS_TAG_CREATE, + Permissions.SUGGESTIONS_SUGGESTIONS_READ, + Permissions.ACCESS_POLICY_ASSIGNED + ] + }, { + name: 'Policy Manager', + description: '', + permissions: [ + Permissions.ANALYTIC_DOCUMENT_READ, + Permissions.POLICIES_POLICY_MANAGE, + Permissions.POLICIES_POLICY_READ, + Permissions.TOKENS_TOKEN_MANAGE, + Permissions.TOKENS_TOKEN_READ, + Permissions.ACCOUNTS_ACCOUNT_READ, + Permissions.TAGS_TAG_READ, + Permissions.TAGS_TAG_CREATE, + Permissions.ACCESS_POLICY_ASSIGNED_AND_PUBLISHED + ] + }, { + name: 'Policy User', + description: '', + permissions: DefaultRoles, + }]; + const ids: string[] = []; + for (const config of roles) { + notifier.info(`Create role (${config.name})`); + const role = await users.createRole(config, owner); + let credentialSubject: any = { + id: GenerateUUIDv4(), + uuid: role.uuid, + name: role.name, + description: role.description, + permissions: role.permissions + } + const schema = await new DataBaseHelper(SchemaCollection).findOne({ + entity: SchemaEntity.ROLE, + readonly: true, + topicId: messageServer.getTopic() + }); + const schemaObject = new Schema(schema); + if (schemaObject) { + credentialSubject = SchemaHelper.updateObjectContext( + schemaObject, + credentialSubject + ); + } + const document = await vcHelper.createVerifiableCredential(credentialSubject, didDocument, null, null); + const message = new GuardianRoleMessage(MessageAction.CreateRole); + message.setRole(credentialSubject); + message.setDocument(document); + await messageServer.sendMessage(message); + await new DataBaseHelper(VcDocumentCollection).save({ + hash: message.hash, + owner: owner.owner, + creator: owner.creator, + document: message.document, + type: SchemaEntity.ROLE, + documentFields: [ + 'credentialSubject.0.id', + 'credentialSubject.0.name', + 'credentialSubject.0.uuid' + ], + }); + ids.push(role.id); + } + await users.setDefaultRole(ids[0], owner.creator); +} + @Controller() export class ProfileController { } diff --git a/guardian-service/src/api/tag.service.ts b/guardian-service/src/api/tag.service.ts index 696e6901c1..4af4c7df62 100644 --- a/guardian-service/src/api/tag.service.ts +++ b/guardian-service/src/api/tag.service.ts @@ -338,7 +338,7 @@ export async function tagsAPI(): Promise { if (tag.document && typeof tag.document === 'object') { const vcHelper = new VcHelper(); let credentialSubject: any = { ...tag.document } || {}; - credentialSubject.id = owner; + credentialSubject.id = owner.creator; const tagSchema = await DatabaseServer.getSchema({ iri: tag.schema }); if ( tagSchema && diff --git a/guardian-service/src/helpers/restore-data-from-hedera.ts b/guardian-service/src/helpers/restore-data-from-hedera.ts index 8c377e4971..35a3f87969 100644 --- a/guardian-service/src/helpers/restore-data-from-hedera.ts +++ b/guardian-service/src/helpers/restore-data-from-hedera.ts @@ -38,9 +38,11 @@ import { } from '@guardian/common'; import { DidDocumentStatus, + EntityOwner, ISchema, PolicyType, SchemaCategory, + SchemaEntity, SchemaStatus, TopicType, UserRole, @@ -127,6 +129,7 @@ export class RestoreDataFromHedera { for (const m of messages) { try { const r = MessageServer.fromMessage(m.message); + r.setAccount(m.payer_account_id); r.setTopicId(topicId); r.setId(m.id); result.push(r); @@ -452,7 +455,7 @@ export class RestoreDataFromHedera { * @private */ private findMessagesByType(type: MessageType, messages: Message[]): T[] { - return messages.filter((m) => m.type === type) as T[]; + return (messages?.filter((m) => m.type === type) || []) as T[]; } /** @@ -618,7 +621,8 @@ export class RestoreDataFromHedera { hederaAccountId: hederaAccountID, }); - await this.restoreUsers(allMessages); + await this.restoreUsers(allMessages, did); + await this.restorePermissions(allMessages, did, user, hederaAccountID); await this.restoreTopic( { @@ -655,21 +659,101 @@ export class RestoreDataFromHedera { } } - private async restoreUsers(messages: Message[]) { + private async restoreUsers(messages: Message[], owner: string) { const userDIDs = this.findMessagesByType(MessageType.DIDDocument, messages); - if (!userDIDs) { - return; - } userDIDs.shift(); + for (const message of userDIDs) { await this.loadIPFS(message); + const did = message.document.id; await new DataBaseHelper(DidDocumentCollection).save({ - did: message.document.id, + did, document: message.document, status: DidDocumentStatus.CREATE, messageId: message.id, topicId: message.topicId, }); + this.users.generateNewTemplate(UserRole.USER, did, owner); + } + } + + private async restorePermissions( + messages: Message[], + parentDid: string, + parent: IAuthUser, + hederaAccountID: string + ) { + const guardianRoles = this.findMessagesByType(MessageType.GuardianRole, messages); + const _guardianRoles = new Map(); + for (const message of guardianRoles) { + if (message.payer === hederaAccountID) { + _guardianRoles.set(message.uuid, message); + } + } + + const _owner = EntityOwner.sr(parentDid); + const _roleMap = new Map(); + for (const message of _guardianRoles.values()) { + await this.loadIPFS(message); + const vcDoc = VcDocument.fromJsonTree(message.document); + const uuid = vcDoc.getField('uuid'); + const role = await this.users.createRole({ + uuid, + name: vcDoc.getField('name'), + description: vcDoc.getField('description'), + permissions: vcDoc.getField('permissions') + }, _owner, true); + await new DataBaseHelper(VcDocumentCollection).save({ + hash: vcDoc.toCredentialHash(), + owner: parentDid, + messageId: message.id, + topicId: message.topicId, + document: vcDoc.toJsonTree(), + type: SchemaEntity.ROLE + }); + _roleMap.set(uuid, role) + } + + const permissions = this.findMessagesByType(MessageType.UserPermissions, messages); + const _permissions = new Map(); + for (const message of permissions) { + if (message.payer === hederaAccountID) { + _permissions.set(message.user, message); + } + } + + for (const message of _permissions.values()) { + await this.loadIPFS(message); + const vcDoc = VcDocument.fromJsonTree(message.document); + const userRoles = vcDoc.getField<{ + uuid: string, + name: string, + owner: string + }[]>('roles'); + const userDid = vcDoc.getField('userId'); + const template = await this.users.getUserById(userDid); + if ( + template && + template.role === UserRole.USER && + template.parent === parentDid + ) { + const roleIds: string[] = []; + for (const item of userRoles) { + const role = _roleMap.get(item.uuid); + if (role) { + roleIds.push(role.id); + await this.users.updateUserRole(template.username, roleIds, _owner); + await new DataBaseHelper(VcDocumentCollection).save({ + hash: vcDoc.toCredentialHash(), + owner: parentDid, + messageId: message.id, + topicId: message.topicId, + document: vcDoc.toJsonTree(), + type: SchemaEntity.USER_PERMISSIONS + }); + } + } + } } } } diff --git a/guardian-service/src/policy-engine/helpers/policy-data-migrator.ts b/guardian-service/src/policy-engine/helpers/policy-data-migrator.ts index 8a6ab4008d..7356affd7a 100644 --- a/guardian-service/src/policy-engine/helpers/policy-data-migrator.ts +++ b/guardian-service/src/policy-engine/helpers/policy-data-migrator.ts @@ -48,19 +48,21 @@ import { ISignOptions, } from '@guardian/interfaces'; import { INotifier } from '../../helpers/notifier.js'; -import { BlockStateLoader } from './policy-data/loaders/block-state.loader.js'; -import { RolesLoader } from './policy-data/loaders/roles.loader.js'; -import { DidLoader } from './policy-data/loaders/did.loader.js'; -import { MintRequestLoader } from './policy-data/loaders/mint-request.loader.js'; -import { MintTransactionLoader } from './policy-data/loaders/mint-transaction.loader.js'; -import { MultiSignDocumentLoader } from './policy-data/loaders/multi-sign-document.loader.js'; import { + BlockStateLoader, + RolesLoader, + DidLoader, + MintRequestLoader, AggregateVCLoader, + MintTransactionLoader, DocumentStateLoader, + VcDocumentLoader, + VpDocumentLoader, + SplitDocumentLoader, + MultiSignDocumentLoader, + TokensLoader, + RetirePoolLoader } from './policy-data/loaders/index.js'; -import { SplitDocumentLoader } from './policy-data/loaders/split-document.loader.js'; -import { TokensLoader } from './policy-data/loaders/tokens.loader.js'; -import { RetirePoolLoader } from './policy-data/loaders/retire-pool.loader.js'; import { createHederaToken } from '../../api/token.service.js'; import { createContract } from '../../api/helpers/contract-api.js'; import { setPoolContract } from '../../api/contract.service.js'; @@ -306,16 +308,28 @@ export class PolicyDataMigrator { category: SchemaCategory.SYSTEM, topicId: srcModel.topicId, }); - srcVCs = await DatabaseServer.getVCs({ - policyId: src, + srcVCs = await new VcDocumentLoader( + srcModel.id, + srcModel.topicId, + srcModel.instanceTopicId, + srcModel.status === PolicyType.DRY_RUN + ).get({ id: { $in: vcs }, }); - srcRoleVcs = await DatabaseServer.getVCs({ - policyId: src, + srcRoleVcs = await new VcDocumentLoader( + srcModel.id, + srcModel.topicId, + srcModel.instanceTopicId, + srcModel.status === PolicyType.DRY_RUN + ).get({ schema: '#UserRole', }); - srcVPs = await DatabaseServer.getVPs({ - policyId: src, + srcVPs = await await new VpDocumentLoader( + srcModel.id, + srcModel.topicId, + srcModel.instanceTopicId, + srcModel.status === PolicyType.DRY_RUN + ).get({ id: { $in: vps }, }); srcDids = await new DidLoader( diff --git a/guardian-service/src/policy-engine/helpers/policy-data/loaders/index.ts b/guardian-service/src/policy-engine/helpers/policy-data/loaders/index.ts index e2b7f0355f..ad2f09231a 100644 --- a/guardian-service/src/policy-engine/helpers/policy-data/loaders/index.ts +++ b/guardian-service/src/policy-engine/helpers/policy-data/loaders/index.ts @@ -11,3 +11,5 @@ export * from './schemas.loader.js'; export * from './split-document.loader.js'; export * from './vc-document.loader.js'; export * from './vp-document.loader.js'; +export * from './tokens.loader.js'; +export * from './retire-pool.loader.js'; diff --git a/guardian-service/src/policy-engine/helpers/policy-data/policy-data-import-export.ts b/guardian-service/src/policy-engine/helpers/policy-data/policy-data-import-export.ts index e1bc57288c..7d1470799e 100644 --- a/guardian-service/src/policy-engine/helpers/policy-data/policy-data-import-export.ts +++ b/guardian-service/src/policy-engine/helpers/policy-data/policy-data-import-export.ts @@ -1,5 +1,6 @@ import JSZip from 'jszip'; import { + SchemasLoader, BlockStateLoader, PolicyDataLoader, RolesLoader, @@ -12,6 +13,8 @@ import { AggregateVCLoader, SplitDocumentLoader, DocumentStateLoader, + TokensLoader, + RetirePoolLoader } from './loaders/index.js'; import { GuardiansService } from '../../../helpers/guardians.js'; import { IOwner, PolicyEvents, PolicyType, TopicType } from '@guardian/interfaces'; @@ -22,10 +25,7 @@ import { Users, findAllEntities, } from '@guardian/common'; -import { SchemasLoader } from './loaders/schemas.loader.js'; import { ObjectId } from 'bson'; -import { TokensLoader } from './loaders/tokens.loader.js'; -import { RetirePoolLoader } from './loaders/retire-pool.loader.js'; /** * Static loaders diff --git a/interfaces/package.json b/interfaces/package.json index de0d93c43f..ec4952a85b 100644 --- a/interfaces/package.json +++ b/interfaces/package.json @@ -33,5 +33,5 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/interfaces/src/type/auth-events.ts b/interfaces/src/type/auth-events.ts index 1d25aa896b..63d459110a 100644 --- a/interfaces/src/type/auth-events.ts +++ b/interfaces/src/type/auth-events.ts @@ -25,6 +25,7 @@ export enum AuthEvents { MEECO_REJECT_SUBMISSION = 'MEECO_REJECT_SUBMISSION', GENERATE_NEW_TOKEN_BASED_ON_USER_PROVIDER = 'GENERATE_NEW_TOKEN_BASED_ON_USER_PROVIDER', GET_USER_BY_PROVIDER_USER_DATA = 'GET_USER_BY_PROVIDER_USER_DATA', + REGISTER_NEW_TEMPLATE = 'REGISTER_NEW_TEMPLATE', GET_ROLES = 'GET_ROLES', GET_ROLE = 'GET_ROLE', CREATE_ROLE = 'CREATE_ROLE', @@ -37,5 +38,5 @@ export enum AuthEvents { REFRESH_USER_PERMISSIONS = 'REFRESH_USER_PERMISSIONS', SET_DEFAULT_USER_ROLE = 'SET_DEFAULT_USER_ROLE', DELEGATE_USER_ROLE = 'DELEGATE_USER_ROLE', - CREATE_DEFAULT_USER_ROLE = 'CREATE_DEFAULT_USER_ROLE' + GET_USER_PERMISSIONS = 'GET_USER_PERMISSIONS' } diff --git a/logger-service/package.json b/logger-service/package.json index 0c2a1824f7..8fc4f3c3d2 100644 --- a/logger-service/package.json +++ b/logger-service/package.json @@ -5,8 +5,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.25.0", - "@guardian/interfaces": "^2.25.0", + "@guardian/common": "^2.25.1", + "@guardian/interfaces": "^2.25.1", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", "@nestjs/common": "^9.4.1", @@ -54,5 +54,5 @@ "watch": "nodemon src/index.ts" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/mrv-sender/package.json b/mrv-sender/package.json index a1edd061f7..48898e85b4 100644 --- a/mrv-sender/package.json +++ b/mrv-sender/package.json @@ -5,7 +5,7 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.25.0", + "@guardian/common": "^2.25.1", "@transmute/credentials-context": "0.7.0-unstable.80", "@transmute/did-context": "0.7.0-unstable.80", "@transmute/ed25519-signature-2018": "0.7.0-unstable.80", @@ -44,5 +44,5 @@ "start": "node dist/index.js" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/notification-service/package.json b/notification-service/package.json index e7d5c9d1bd..0a4f1573ce 100644 --- a/notification-service/package.json +++ b/notification-service/package.json @@ -5,8 +5,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.25.0", - "@guardian/interfaces": "^2.25.0", + "@guardian/common": "^2.25.1", + "@guardian/interfaces": "^2.25.1", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", "@nestjs/common": "^9.4.1", @@ -53,5 +53,5 @@ "watch": "nodemon src/index.ts" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/package.json b/package.json index cf565f825a..5918a62c07 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "indexer-service", "indexer-worker-service" ], - "version": "2.25.0", + "version": "2.25.1", "devDependencies": { "detect-secrets": "^1.0.6" }, diff --git a/policy-service/package.json b/policy-service/package.json index 42e2b69825..11bee59512 100644 --- a/policy-service/package.json +++ b/policy-service/package.json @@ -15,8 +15,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "2.25.0", - "@guardian/interfaces": "2.25.0", + "@guardian/common": "2.25.1", + "@guardian/interfaces": "2.25.1", "@hashgraph/sdk": "2.34.1", "@mattrglobal/jsonld-signatures-bbs": "^1.1.2", "@meeco/cryppo": "2.0.2", @@ -97,5 +97,5 @@ "test:stability": "mocha tests/stability.test.js" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/policy-service/src/policy-engine/mint/mint-service.ts b/policy-service/src/policy-engine/mint/mint-service.ts index 31fc381efe..a3206f90f0 100644 --- a/policy-service/src/policy-engine/mint/mint-service.ts +++ b/policy-service/src/policy-engine/mint/mint-service.ts @@ -611,14 +611,14 @@ export class MintService { public static log(message: string, ref?: AnyBlockType) { if (ref) { MintService.logger.info(message, [ - 'GUARDIAN_SERVICE', + 'POLICY_SERVICE', ref.uuid, ref.blockType, ref.tag, ref.policyId, ]); } else { - MintService.logger.info(message, ['GUARDIAN_SERVICE']); + MintService.logger.info(message, ['POLICY_SERVICE']); } } @@ -629,14 +629,14 @@ export class MintService { public static error(message: string, ref?: AnyBlockType) { if (ref) { MintService.logger.error(message, [ - 'GUARDIAN_SERVICE', + 'POLICY_SERVICE', ref.uuid, ref.blockType, ref.tag, ref.policyId, ]); } else { - MintService.logger.error(message, ['GUARDIAN_SERVICE']); + MintService.logger.error(message, ['POLICY_SERVICE']); } } @@ -647,14 +647,14 @@ export class MintService { public static warn(message: string, ref?: AnyBlockType) { if (ref) { MintService.logger.warn(message, [ - 'GUARDIAN_SERVICE', + 'POLICY_SERVICE', ref.uuid, ref.blockType, ref.tag, ref.policyId, ]); } else { - MintService.logger.warn(message, ['GUARDIAN_SERVICE']); + MintService.logger.warn(message, ['POLICY_SERVICE']); } } } diff --git a/policy-service/src/policy-engine/mint/types/mint-ft.ts b/policy-service/src/policy-engine/mint/types/mint-ft.ts index ef9c4f0088..50e0f19b4d 100644 --- a/policy-service/src/policy-engine/mint/types/mint-ft.ts +++ b/policy-service/src/policy-engine/mint/types/mint-ft.ts @@ -170,23 +170,27 @@ export class MintFT extends TypedMint { } if (!this._ref?.dryRun) { - const startTransactions = await workers.addRetryableTask( - { - type: WorkerTaskType.GET_TRANSACTIONS, - data: { - accountId: this._token.treasuryId, - limit: 1, - order: 'desc', - transactiontype: 'TOKENMINT', + try { + const startTransactions = await workers.addRetryableTask( + { + type: WorkerTaskType.GET_TRANSACTIONS, + data: { + accountId: this._token.treasuryId, + limit: 1, + order: 'desc', + transactiontype: 'TOKENMINT', + }, }, - }, - 1, - 10 - ); + 1, + 10 + ); - this._mintRequest.startTransaction = - startTransactions[0]?.consensus_timestamp; - await this._db.saveMintRequest(this._mintRequest); + this._mintRequest.startTransaction = + startTransactions[0]?.consensus_timestamp; + await this._db.saveMintRequest(this._mintRequest); + } catch (error) { + this.error(error); + } } transaction.mintStatus = MintTransactionStatus.PENDING; @@ -238,23 +242,26 @@ export class MintFT extends TypedMint { } if (!this._ref?.dryRun) { - const startTransactions = await workers.addRetryableTask( - { - type: WorkerTaskType.GET_TRANSACTIONS, - data: { - accountId: this._token.treasuryId, - limit: 1, - order: 'desc', - transactiontype: 'CRYPTOTRANSFER', + try { + const startTransactions = await workers.addRetryableTask( + { + type: WorkerTaskType.GET_TRANSACTIONS, + data: { + accountId: this._token.treasuryId, + limit: 1, + order: 'desc', + transactiontype: 'CRYPTOTRANSFER', + }, }, - }, - 1, - 10 - ); - - this._mintRequest.startTransaction = - startTransactions[0]?.consensus_timestamp; - await this._db.saveMintRequest(this._mintRequest); + 1, + 10 + ); + this._mintRequest.startTransaction = + startTransactions[0]?.consensus_timestamp; + await this._db.saveMintRequest(this._mintRequest); + } catch (error) { + this.error(error); + } } transaction.transferStatus = MintTransactionStatus.PENDING; diff --git a/policy-service/src/policy-engine/mint/types/mint-nft.ts b/policy-service/src/policy-engine/mint/types/mint-nft.ts index 9472122404..ec2bb35c2c 100644 --- a/policy-service/src/policy-engine/mint/types/mint-nft.ts +++ b/policy-service/src/policy-engine/mint/types/mint-nft.ts @@ -130,20 +130,24 @@ export class MintNFT extends TypedMint { !this._ref?.dryRun && !Number.isInteger(this._mintRequest.startSerial) ) { - const startSerial = await new Workers().addRetryableTask( - { - type: WorkerTaskType.GET_TOKEN_NFTS, - data: { - tokenId: this._token.tokenId, - limit: 1, - order: 'desc', + try { + const startSerial = await new Workers().addRetryableTask( + { + type: WorkerTaskType.GET_TOKEN_NFTS, + data: { + tokenId: this._token.tokenId, + limit: 1, + order: 'desc', + }, }, - }, - 1, - 10 - ); - this._mintRequest.startSerial = startSerial[0] || 0; - await this._db.saveMintRequest(this._mintRequest); + 1, + 10 + ); + this._mintRequest.startSerial = startSerial[0] || 0; + await this._db.saveMintRequest(this._mintRequest); + } catch (error) { + this.error(error); + } } let transactions = await this._db.getMintTransactions( diff --git a/policy-service/src/policy-engine/mint/types/typed-mint.ts b/policy-service/src/policy-engine/mint/types/typed-mint.ts index 4660d0e502..680bd293d9 100644 --- a/policy-service/src/policy-engine/mint/types/typed-mint.ts +++ b/policy-service/src/policy-engine/mint/types/typed-mint.ts @@ -365,4 +365,12 @@ export abstract class TypedMint { return processed; } + + /** + * Log error + * @param error Error + */ + protected error(error: any) { + MintService.error(PolicyUtils.getErrorMessage(error), this._ref); + } } diff --git a/swagger-analytics.yaml b/swagger-analytics.yaml index afd26ec735..f63dc4bc88 100644 --- a/swagger-analytics.yaml +++ b/swagger-analytics.yaml @@ -208,7 +208,7 @@ info: the heart of the Guardian solution is a sophisticated Policy Workflow Engine (PWE) that enables applications to offer a requirements-based tokenization implementation. - version: 2.25.0 + version: 2.25.1 contact: name: API developer url: https://envisionblockchain.com diff --git a/swagger.yaml b/swagger.yaml index ee0a4d1e88..095966e57e 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -11322,7 +11322,7 @@ info: the heart of the Guardian solution is a sophisticated Policy Workflow Engine (PWE) that enables applications to offer a requirements-based tokenization implementation. - version: 2.25.0 + version: 2.25.1 contact: name: API developer url: https://envisionblockchain.com diff --git a/topic-viewer/package.json b/topic-viewer/package.json index cc3d80533b..45b2b201f0 100644 --- a/topic-viewer/package.json +++ b/topic-viewer/package.json @@ -30,5 +30,5 @@ "start": "node dist/index.js" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/tree-viewer/package.json b/tree-viewer/package.json index d4b09c1bce..b4670d0651 100644 --- a/tree-viewer/package.json +++ b/tree-viewer/package.json @@ -28,5 +28,5 @@ "start": "node dist/index.js" }, "type": "module", - "version": "2.25.0" + "version": "2.25.1" } diff --git a/worker-service/package.json b/worker-service/package.json index 73447fc063..1241826a32 100644 --- a/worker-service/package.json +++ b/worker-service/package.json @@ -2,8 +2,8 @@ "author": "Envision Blockchain Solutions ", "dependencies": { "@filebase/client": "^0.0.5", - "@guardian/common": "^2.25.0", - "@guardian/interfaces": "^2.25.0", + "@guardian/common": "^2.25.1", + "@guardian/interfaces": "^2.25.1", "@hashgraph/sdk": "2.34.1", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", @@ -66,5 +66,5 @@ }, "type": "module", "types": "dist/index.d.ts", - "version": "2.25.0" + "version": "2.25.1" }