Skip to content

Commit

Permalink
revising_event_logging (#118)
Browse files Browse the repository at this point in the history
* revising_event_logging

* removed process.exit

* catch errors in bootstrap
  • Loading branch information
yartman authored Oct 20, 2021
1 parent aefa42a commit b128bf2
Show file tree
Hide file tree
Showing 27 changed files with 770 additions and 397 deletions.
4 changes: 3 additions & 1 deletion apps/dsb-message-broker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@
"@energyweb/dsb-address-book-nats-js": "~0.0.1",
"ajv-formats": "2.1.1",
"node-libxml": "4.1.2",
"uuid": "8.3.2"
"uuid": "8.3.2",
"winston": "~3.3.3",
"nest-winston": "~1.6.1"
},
"devDependencies": {
"@nestjs/cli": "7.6.0",
Expand Down
22 changes: 14 additions & 8 deletions apps/dsb-message-broker/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import * as Joi from 'joi';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

import { APP_INTERCEPTOR } from '@nestjs/core';
import { AuthModule } from './auth/auth.module';
import { Module, Logger } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

import { AppController } from './app.controller';
import { HTTPLoggingInterceptor } from './httpLoggingInterceptor';

import { AuthModule } from './auth/auth.module';
import { ChannelModule } from './channel/channel.module';
import { HealthModule } from './health/health.module';
import { HTTPLoggingInterceptor } from './httpLoggingInterceptor';
import { MessageModule } from './message/message.module';

import { UtilsModule } from './utils/utils.module';

@Module({
imports: [
MessageModule,
Expand All @@ -25,7 +25,7 @@ import { UtilsModule } from './utils/utils.module';
PORT: Joi.number().optional().default(3000),
WEB3_URL: Joi.string().default('https://volta-rpc.energyweb.org/'),
CACHE_SERVER_URL: Joi.string().default(
'https://identitycache-dev.energyweb.org/v1'
'https://volta-identitycache.energyweb.org/v1'
),
WITH_SWAGGER: Joi.boolean().optional().default(true),
JWT_SECRET: Joi.string().required(),
Expand All @@ -37,6 +37,12 @@ import { UtilsModule } from './utils/utils.module';
UtilsModule
],
controllers: [AppController],
providers: [{ provide: APP_INTERCEPTOR, useClass: HTTPLoggingInterceptor }]
providers: [
Logger,
{
provide: APP_INTERCEPTOR,
useClass: HTTPLoggingInterceptor
}
]
})
export class AppModule {}
34 changes: 27 additions & 7 deletions apps/dsb-message-broker/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { IAM, setCacheClientOptions } from 'iam-client-lib';
import { ApplicationError } from '../global.errors';

@Injectable()
export class AuthService implements OnModuleInit {
private readonly logger = new Logger(AuthService.name);

constructor(private readonly configService: ConfigService) {}

private readonly role = 'messagebroker.roles.dsb.apps.energyweb.iam.ewc';
Expand All @@ -19,23 +22,40 @@ export class AuthService implements OnModuleInit {
});

const iam = new IAM({ rpcUrl, privateKey });
const init = await iam.initializeConnection({ initCacheServer: true });
let init;
try {
init = await iam.initializeConnection({ initCacheServer: true });
} catch (error) {
throw new ApplicationError([
'error in initializing connection to identity cache server',
error.message
]);
}

if (mbDID !== init.did) {
throw new Error(
throw new ApplicationError(
"Provided DID for the Message Broker doesn't correspond to PRIVATE_KEY"
);
}

const claims = await iam.getUserClaims({ did: init.did });
let claims;
try {
claims = await iam.getUserClaims({ did: init.did });
} catch (error) {
throw new ApplicationError([
'error in getting claims from identity cache server',
error.message
]);
}

const role = claims.find((claim) => claim.claimType === this.role);

//TODO: Add proper role verification
if (!role) {
throw new Error(
`Message Broker ${init.did} does not have "${this.role}" role. Please check https://github.com/energywebfoundation/dsb#configuration for more details`
);
throw new ApplicationError([
`Message Broker ${init.did} does not have "${this.role}" role.`,
'Please check https://github.com/energywebfoundation/dsb#configuration for more details'
]);
}
}
}
23 changes: 19 additions & 4 deletions apps/dsb-message-broker/src/auth/dynamic.roles.guard.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { extractFqcn } from '../utils';

@Injectable()
export class DynamicRolesGuard implements CanActivate {
private readonly logger = new Logger();
constructor(private readonly reflector: Reflector) {}

canActivate(context: ExecutionContext): boolean {
const requiredRoleTitle = this.reflector.get<string>('role', context.getHandler());
if (!requiredRoleTitle) return true;
const requiredRoles = [`${requiredRoleTitle}.roles.dsb.apps.energyweb.iam.ewc`];

const user = context.switchToHttp().getRequest().user;
const request = context.switchToHttp().getRequest();
const { app, method, url, user } = request;
const verifiedRoles = user.verifiedRoles?.map((role: any) => role.namespace) || [];
if (!verifiedRoles.length) return false;
if (!verifiedRoles.length) {
this.logger.error({
request: { app, method, url },
message: ["403 - token doesn't have verified roles"]
});
return false;
}

const fqcn =
context.switchToHttp().getRequest()?.body?.fqcn ??
Expand All @@ -28,8 +36,15 @@ export class DynamicRolesGuard implements CanActivate {
if (!requiredRoles.includes(organizationRole)) requiredRoles.push(organizationRole);
}

return requiredRoles.every((req: string) =>
const authorized = requiredRoles.every((req: string) =>
verifiedRoles.some((ver: string) => ver === req)
);
if (!authorized) {
this.logger.error({
request: { app, method, url },
message: ["403 - user verified roles doesn't match with required roles"]
});
}
return authorized;
}
}
85 changes: 29 additions & 56 deletions apps/dsb-message-broker/src/channel/channel.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
ClassSerializerInterceptor,
Controller,
HttpStatus,
Logger,
Post,
Get,
Patch,
Expand Down Expand Up @@ -33,18 +32,17 @@ import { FqcnValidationPipe } from '../utils/fqcn.validation.pipe';

import { ChannelService } from './channel.service';
import { CreateChannelDto, RemoveChannelDto, UpdateChannelDto, ReadChannelDto } from './dto';
import { ChannelErrorHandler } from './error.handler';
import { ChannelDataPipe } from './channel.data.pipe';
import { ChannelDataPipe } from './channel.pipe';
import { ChannelInterceptor } from './channel.interceptor';

@Controller('channel')
@UseGuards(JwtAuthGuard, DynamicRolesGuard)
@UseInterceptors(ClassSerializerInterceptor)
@UsePipes(ValidationPipe)
@UseInterceptors(ChannelInterceptor)
@ApiTags('channel')
@ApiBearerAuth('access-token')
export class ChannelController {
private readonly logger = new Logger(ChannelController.name);

constructor(private readonly channelService: ChannelService) {}

@Post()
Expand All @@ -62,18 +60,13 @@ export class ChannelController {
@UserDecorator() user: any,
@Body(FqcnValidationPipe, ChannelDataPipe) createDto: CreateChannelDto
): Promise<string> {
try {
const channelName = await this.channelService.createChannel({
...createDto,
maxMsgSize: createDto.maxMsgSize ?? 1048576, //1Mb default
createdBy: user.did,
createdDateTime: new Date().toISOString()
});
return channelName;
} catch (error) {
this.logger.error(error.message);
ChannelErrorHandler(error);
}
const channelName = await this.channelService.createChannel({
...createDto,
maxMsgSize: createDto.maxMsgSize ?? 1048576, //1Mb default
createdBy: user.did,
createdDateTime: new Date().toISOString()
});
return channelName;
}

@Patch()
Expand All @@ -91,17 +84,12 @@ export class ChannelController {
@UserDecorator() user: any,
@Body(FqcnValidationPipe, ChannelDataPipe) updateDto: UpdateChannelDto
): Promise<string> {
try {
const result = await this.channelService.updateChannel({
...updateDto,
modifiedBy: user.did,
modifiedDateTime: new Date().toISOString()
});
return result;
} catch (error) {
this.logger.error(error.message);
ChannelErrorHandler(error);
}
const result = await this.channelService.updateChannel({
...updateDto,
modifiedBy: user.did,
modifiedDateTime: new Date().toISOString()
});
return result;
}

@Get('/pubsub')
Expand All @@ -116,16 +104,11 @@ export class ChannelController {
description: 'Array of channels with their options'
})
public async getAccessibleChannels(@UserDecorator() user: any): Promise<Channel[]> {
try {
const channels = await this.channelService.getAccessibleChannels(
user.did,
user.verifiedRoles.map((role: any) => role.namespace)
);
return channels;
} catch (error) {
this.logger.error(error.message);
ChannelErrorHandler(error);
}
const channels = await this.channelService.getAccessibleChannels(
user.did,
user.verifiedRoles.map((role: any) => role.namespace)
);
return channels;
}

@Get('/:fqcn')
Expand All @@ -143,17 +126,12 @@ export class ChannelController {
@UserDecorator() user: any,
@Param(FqcnValidationPipe) { fqcn }: ReadChannelDto
): Promise<Channel> {
try {
const metadata = await this.channelService.getChannel({
fqcn,
userDID: user.did,
userVRs: user.verifiedRoles.map((role: any) => role.namespace)
});
return metadata;
} catch (error) {
this.logger.error(error.message);
ChannelErrorHandler(error);
}
const metadata = await this.channelService.getChannel({
fqcn,
userDID: user.did,
userVRs: user.verifiedRoles.map((role: any) => role.namespace)
});
return metadata;
}

@Delete('/:fqcn')
Expand All @@ -171,12 +149,7 @@ export class ChannelController {
@UserDecorator() user: any,
@Param(FqcnValidationPipe) { fqcn }: RemoveChannelDto
): Promise<string> {
try {
const result = await this.channelService.remove({ fqcn, userDID: user.did });
return result;
} catch (error) {
this.logger.error(error.message);
ChannelErrorHandler(error);
}
const result = await this.channelService.remove({ fqcn, userDID: user.did });
return result;
}
}
79 changes: 0 additions & 79 deletions apps/dsb-message-broker/src/channel/channel.data.pipe.ts

This file was deleted.

Loading

0 comments on commit b128bf2

Please sign in to comment.