Skip to content

Commit

Permalink
Assign wallet to a user
Browse files Browse the repository at this point in the history
  • Loading branch information
wcalderipe committed Feb 13, 2024
1 parent bc1d38a commit b39874c
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 10 deletions.
100 changes: 100 additions & 0 deletions apps/orchestration/src/store/entity/__test__/e2e/user-wallet.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Action, OrganizationEntity, Signature } from '@narval/authz-shared'
import { HttpStatus, INestApplication } from '@nestjs/common'
import { ConfigModule } from '@nestjs/config'
import { Test, TestingModule } from '@nestjs/testing'
import request from 'supertest'
import { generateSignature } from '../../../../__test__/fixture/authorization-request.fixture'
import { load } from '../../../../orchestration.config'
import { REQUEST_HEADER_ORG_ID } from '../../../../orchestration.constant'
import { PolicyEngineModule } from '../../../../policy-engine/policy-engine.module'
import { PersistenceModule } from '../../../../shared/module/persistence/persistence.module'
import { TestPrismaService } from '../../../../shared/module/persistence/service/test-prisma.service'
import { QueueModule } from '../../../../shared/module/queue/queue.module'
import { EntityStoreModule } from '../../entity-store.module'
import { OrganizationRepository } from '../../persistence/repository/organization.repository'

const API_RESOURCE_USER_ENTITY = '/store/user-wallets'

describe('Wallet Group Store', () => {
let app: INestApplication
let module: TestingModule
let testPrismaService: TestPrismaService
let orgRepository: OrganizationRepository

const organization: OrganizationEntity = {
uid: 'ac1374c2-fd62-4b6e-bd49-a4afcdcb91cc'
}

const authentication: Signature = generateSignature()

const approvals: Signature[] = [generateSignature(), generateSignature()]

const nonce = 'b6d826b4-72cb-4c14-a6ca-235a2d8e9060'

const walletId = 'c7eac7d1-7572-4756-b52e-0caebe208364'

const userId = '2a1509ad-ea87-422e-bebd-974547cd4fee'

beforeAll(async () => {
module = await Test.createTestingModule({
imports: [
ConfigModule.forRoot({
load: [load],
isGlobal: true
}),
PersistenceModule,
QueueModule.forRoot(),
PolicyEngineModule,
EntityStoreModule
]
}).compile()

testPrismaService = module.get<TestPrismaService>(TestPrismaService)
orgRepository = module.get<OrganizationRepository>(OrganizationRepository)

app = module.createNestApplication()

await app.init()
})

afterAll(async () => {
await testPrismaService.truncateAll()
await module.close()
await app.close()
})

beforeEach(async () => {
await orgRepository.create(organization.uid)
})

afterEach(async () => {
await testPrismaService.truncateAll()
})

describe(`POST ${API_RESOURCE_USER_ENTITY}`, () => {
it('assigns a wallet to a user', async () => {
const payload = {
authentication,
approvals,
request: {
nonce,
action: Action.ASSIGN_USER_WALLET,
data: { userId, walletId }
}
}

const { status, body } = await request(app.getHttpServer())
.post(API_RESOURCE_USER_ENTITY)
.set(REQUEST_HEADER_ORG_ID, organization.uid)
.send(payload)

expect(body).toEqual({
data: {
walletId,
userId
}
})
expect(status).toEqual(HttpStatus.CREATED)
})
})
})
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { AuthCredential, UserEntity, UserRole } from '@narval/authz-shared'
import { AuthCredential, UserEntity, UserRole, UserWallet } from '@narval/authz-shared'
import { Injectable } from '@nestjs/common'
import { UserWalletRepository } from '../../persistence/repository/user-wallet.repository'
import { UserRepository } from '../../persistence/repository/user.repository'

@Injectable()
export class UserService {
constructor(private userRepository: UserRepository) {}
constructor(private userRepository: UserRepository, private userWalletRepository: UserWalletRepository) {}

create(orgId: string, user: UserEntity, credential?: AuthCredential): Promise<UserEntity> {
return this.userRepository.create(orgId, user, credential)
Expand All @@ -20,4 +21,8 @@ export class UserService {
role
})
}

async assignWallet(assignment: UserWallet): Promise<UserWallet> {
return this.userWalletRepository.assign(assignment)
}
}
26 changes: 18 additions & 8 deletions apps/orchestration/src/store/entity/entity-store.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,40 @@ import { UserService } from './core/service/user.service'
import { WalletService } from './core/service/wallet.service'
import { OrganizationController } from './http/rest/controller/organization.controller'
import { UserGroupController } from './http/rest/controller/user-group.controller'
import { UserWalletController } from './http/rest/controller/user-wallet.controller'
import { UserController } from './http/rest/controller/user.controller'
import { WalletGroupController } from './http/rest/controller/wallet-group.controller'
import { WalletController } from './http/rest/controller/wallet.controller'
import { AuthCredentialRepository } from './persistence/repository/auth-credential.repository'
import { OrganizationRepository } from './persistence/repository/organization.repository'
import { UserGroupRepository } from './persistence/repository/user-group.repository'
import { UserWalletRepository } from './persistence/repository/user-wallet.repository'
import { UserRepository } from './persistence/repository/user.repository'
import { WalletGroupRepository } from './persistence/repository/wallet-group.repository'
import { WalletRepository } from './persistence/repository/wallet.repository'

@Module({
imports: [ConfigModule.forRoot({ load: [load] }), PersistenceModule, PolicyEngineModule],
controllers: [OrganizationController, UserController, UserGroupController, WalletController, WalletGroupController],
controllers: [
OrganizationController,
UserController,
UserGroupController,
UserWalletController,
WalletController,
WalletGroupController
],
providers: [
OrganizationService,
AuthCredentialRepository,
OrganizationRepository,
UserService,
UserRepository,
UserGroupService,
OrganizationService,
UserGroupRepository,
AuthCredentialRepository,
WalletService,
WalletRepository,
UserGroupService,
UserRepository,
UserService,
UserWalletRepository,
WalletGroupRepository,
WalletRepository,
WalletService,
{
provide: APP_INTERCEPTOR,
useClass: ClassSerializerInterceptor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Body, Controller, HttpStatus, Post } from '@nestjs/common'
import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'
import { REQUEST_HEADER_ORG_ID } from '../../../../../orchestration.constant'
import { OrgId } from '../../../../../shared/decorator/org-id.decorator'
import { UserService } from '../../../core/service/user.service'
import { AssignUserWalletRequestDto } from '../dto/assign-user-wallet-request.dto'
import { AssignUserWalletResponseDto } from '../dto/assign-user-wallet-response.dto'

@Controller('/store/user-wallets')
@ApiTags('Entity Store')
export class UserWalletController {
constructor(private userService: UserService) {}

@Post()
@ApiOperation({
summary: 'Assigns a wallet to a user.'
})
@ApiHeader({
name: REQUEST_HEADER_ORG_ID
})
@ApiResponse({
status: HttpStatus.CREATED,
type: AssignUserWalletResponseDto
})
async assign(@OrgId() orgId: string, @Body() body: AssignUserWalletRequestDto) {
const { data } = body.request

await this.userService.assignWallet(body.request.data)

return new AssignUserWalletResponseDto({ data })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Action, BaseAdminRequestPayloadDto } from '@narval/authz-shared'
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import { IsDefined, IsEnum, ValidateNested } from 'class-validator'
import { BaseActionDto } from './base-action.dto'
import { UserWalletDto } from './user-wallet.dto'

class AssignUserWalletActionDto extends BaseActionDto {
@IsEnum(Object.values(Action))
@ApiProperty({
enum: Object.values(Action),
default: Action.ASSIGN_USER_WALLET
})
action: typeof Action.ASSIGN_USER_WALLET

@IsDefined()
@Type(() => UserWalletDto)
@ValidateNested()
@ApiProperty({
type: UserWalletDto
})
data: UserWalletDto
}

export class AssignUserWalletRequestDto extends BaseAdminRequestPayloadDto {
@IsDefined()
@Type(() => AssignUserWalletActionDto)
@ValidateNested()
@ApiProperty({
type: AssignUserWalletActionDto
})
request: AssignUserWalletActionDto
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import { IsDefined, ValidateNested } from 'class-validator'
import { UserWalletDto } from './user-wallet.dto'

export class AssignUserWalletResponseDto {
@IsDefined()
@Type(() => UserWalletDto)
@ValidateNested()
@ApiProperty({
type: UserWalletDto
})
data: UserWalletDto

constructor(partial: Partial<AssignUserWalletResponseDto>) {
Object.assign(this, partial)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ApiProperty } from '@nestjs/swagger'
import { IsNotEmpty, IsString } from 'class-validator'

export class UserWalletDto {
@IsString()
@IsNotEmpty()
@ApiProperty()
walletId: string

@IsString()
@IsNotEmpty()
@ApiProperty()
userId: string

constructor(partial: Partial<UserWalletDto>) {
Object.assign(this, partial)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { UserWallet } from '@narval/authz-shared'
import { Injectable } from '@nestjs/common'
import { PrismaService } from '../../../../shared/module/persistence/service/prisma.service'

@Injectable()
export class UserWalletRepository {
constructor(private prismaService: PrismaService) {}

async assign(assignment: UserWallet): Promise<UserWallet> {
await this.prismaService.userWalletAssignment.create({
data: assignment
})

return assignment
}
}

0 comments on commit b39874c

Please sign in to comment.