feat(authorization): add admin API for community authorization
Add new endpoint POST /api/v1/admin/authorizations/community that allows administrators to directly authorize users as community managers without requiring the user to self-apply first. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
003bef1c76
commit
f8cfb5e597
|
|
@ -1,8 +1,8 @@
|
|||
import { Controller, Post, Body, UseGuards, HttpCode, HttpStatus } from '@nestjs/common'
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger'
|
||||
import { AuthorizationApplicationService } from '@/application/services'
|
||||
import { GrantProvinceCompanyCommand, GrantCityCompanyCommand } from '@/application/commands'
|
||||
import { GrantProvinceCompanyDto, GrantCityCompanyDto } from '@/api/dto/request'
|
||||
import { GrantCommunityCommand, GrantProvinceCompanyCommand, GrantCityCompanyCommand } from '@/application/commands'
|
||||
import { GrantCommunityDto, GrantProvinceCompanyDto, GrantCityCompanyDto } from '@/api/dto/request'
|
||||
import { CurrentUser } from '@/shared/decorators'
|
||||
import { JwtAuthGuard } from '@/shared/guards'
|
||||
|
||||
|
|
@ -13,6 +13,25 @@ import { JwtAuthGuard } from '@/shared/guards'
|
|||
export class AdminAuthorizationController {
|
||||
constructor(private readonly applicationService: AuthorizationApplicationService) {}
|
||||
|
||||
@Post('community')
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@ApiOperation({ summary: '授权社区(管理员)' })
|
||||
@ApiResponse({ status: 201, description: '授权成功' })
|
||||
async grantCommunity(
|
||||
@CurrentUser() user: { userId: string; accountSequence: number },
|
||||
@Body() dto: GrantCommunityDto,
|
||||
): Promise<{ message: string }> {
|
||||
const command = new GrantCommunityCommand(
|
||||
dto.userId,
|
||||
dto.accountSequence,
|
||||
dto.communityName,
|
||||
user.userId,
|
||||
user.accountSequence,
|
||||
)
|
||||
await this.applicationService.grantCommunity(command)
|
||||
return { message: '社区授权成功' }
|
||||
}
|
||||
|
||||
@Post('province-company')
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@ApiOperation({ summary: '授权正式省公司(管理员)' })
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import { IsString, IsNotEmpty, MaxLength, IsNumber } from 'class-validator'
|
||||
import { ApiProperty } from '@nestjs/swagger'
|
||||
|
||||
export class GrantCommunityDto {
|
||||
@ApiProperty({ description: '用户ID' })
|
||||
@IsString()
|
||||
@IsNotEmpty({ message: '用户ID不能为空' })
|
||||
userId: string
|
||||
|
||||
@ApiProperty({ description: '账户序列号' })
|
||||
@IsNumber()
|
||||
@IsNotEmpty({ message: '账户序列号不能为空' })
|
||||
accountSequence: number
|
||||
|
||||
@ApiProperty({ description: '社区名称', example: '深圳社区' })
|
||||
@IsString()
|
||||
@IsNotEmpty({ message: '社区名称不能为空' })
|
||||
@MaxLength(100, { message: '社区名称最大100字符' })
|
||||
communityName: string
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
export * from './apply-community-auth.dto'
|
||||
export * from './apply-auth-province.dto'
|
||||
export * from './apply-auth-city.dto'
|
||||
export * from './grant-community.dto'
|
||||
export * from './grant-province-company.dto'
|
||||
export * from './grant-city-company.dto'
|
||||
export * from './revoke-authorization.dto'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
export class GrantCommunityCommand {
|
||||
constructor(
|
||||
public readonly userId: string,
|
||||
public readonly accountSequence: number,
|
||||
public readonly communityName: string,
|
||||
public readonly adminId: string,
|
||||
public readonly adminAccountSequence: number,
|
||||
) {}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
export * from './apply-community-auth.command'
|
||||
export * from './apply-auth-province-company.command'
|
||||
export * from './apply-auth-city-company.command'
|
||||
export * from './grant-community.command'
|
||||
export * from './grant-province-company.command'
|
||||
export * from './grant-city-company.command'
|
||||
export * from './revoke-authorization.command'
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import {
|
|||
ApplyAuthProvinceCompanyResult,
|
||||
ApplyAuthCityCompanyCommand,
|
||||
ApplyAuthCityCompanyResult,
|
||||
GrantCommunityCommand,
|
||||
GrantProvinceCompanyCommand,
|
||||
GrantCityCompanyCommand,
|
||||
RevokeAuthorizationCommand,
|
||||
|
|
@ -218,6 +219,24 @@ export class AuthorizationApplicationService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员直接授权社区
|
||||
*/
|
||||
async grantCommunity(command: GrantCommunityCommand): Promise<void> {
|
||||
const userId = UserId.create(command.userId, command.accountSequence)
|
||||
const adminId = AdminUserId.create(command.adminId, command.adminAccountSequence)
|
||||
|
||||
const authorization = AuthorizationRole.createCommunity({
|
||||
userId,
|
||||
communityName: command.communityName,
|
||||
adminId,
|
||||
})
|
||||
|
||||
await this.authorizationRepository.save(authorization)
|
||||
await this.eventPublisher.publishAll(authorization.domainEvents)
|
||||
authorization.clearDomainEvents()
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员授权正式省公司
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import { RoleType, AuthorizationStatus, MonthlyTargetType } from '@/domain/enums'
|
||||
import { DomainError } from '@/shared/exceptions'
|
||||
import {
|
||||
CommunityAuthorizedEvent,
|
||||
CommunityAuthRequestedEvent,
|
||||
AuthProvinceCompanyRequestedEvent,
|
||||
AuthCityCompanyRequestedEvent,
|
||||
|
|
@ -215,6 +216,48 @@ export class AuthorizationRole extends AggregateRoot {
|
|||
return auth
|
||||
}
|
||||
|
||||
// 工厂方法 - 管理员直接授权社区
|
||||
static createCommunity(params: {
|
||||
userId: UserId
|
||||
communityName: string
|
||||
adminId: AdminUserId
|
||||
}): AuthorizationRole {
|
||||
const auth = new AuthorizationRole({
|
||||
authorizationId: AuthorizationId.generate(),
|
||||
userId: params.userId,
|
||||
roleType: RoleType.COMMUNITY,
|
||||
regionCode: RegionCode.create(params.communityName),
|
||||
regionName: params.communityName,
|
||||
status: AuthorizationStatus.AUTHORIZED,
|
||||
displayTitle: params.communityName,
|
||||
authorizedAt: new Date(),
|
||||
authorizedBy: params.adminId,
|
||||
revokedAt: null,
|
||||
revokedBy: null,
|
||||
revokeReason: null,
|
||||
assessmentConfig: AssessmentConfig.forCommunity(),
|
||||
requireLocalPercentage: 0,
|
||||
exemptFromPercentageCheck: true,
|
||||
benefitActive: true,
|
||||
benefitActivatedAt: new Date(),
|
||||
benefitDeactivatedAt: null,
|
||||
currentMonthIndex: 1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
|
||||
auth.addDomainEvent(
|
||||
new CommunityAuthorizedEvent({
|
||||
authorizationId: auth.authorizationId.value,
|
||||
userId: params.userId.value,
|
||||
communityName: params.communityName,
|
||||
authorizedBy: params.adminId.value,
|
||||
}),
|
||||
)
|
||||
|
||||
return auth
|
||||
}
|
||||
|
||||
// 工厂方法 - 创建授权省公司
|
||||
static createAuthProvinceCompany(params: {
|
||||
userId: UserId
|
||||
|
|
|
|||
|
|
@ -1,6 +1,29 @@
|
|||
import { DomainEvent } from './domain-event.base'
|
||||
import { RoleType } from '@/domain/enums'
|
||||
|
||||
// 社区授权事件(管理员直接授权)
|
||||
export class CommunityAuthorizedEvent extends DomainEvent {
|
||||
readonly eventType = 'authorization.community.authorized'
|
||||
readonly aggregateId: string
|
||||
readonly payload: {
|
||||
authorizationId: string
|
||||
userId: string
|
||||
communityName: string
|
||||
authorizedBy: string
|
||||
}
|
||||
|
||||
constructor(data: {
|
||||
authorizationId: string
|
||||
userId: string
|
||||
communityName: string
|
||||
authorizedBy: string
|
||||
}) {
|
||||
super()
|
||||
this.aggregateId = data.authorizationId
|
||||
this.payload = data
|
||||
}
|
||||
}
|
||||
|
||||
// 社区授权申请事件
|
||||
export class CommunityAuthRequestedEvent extends DomainEvent {
|
||||
readonly eventType = 'authorization.community.requested'
|
||||
|
|
|
|||
Loading…
Reference in New Issue