690329:1621 Fixing superadmin by GPT-5.3 #01
CI / CD Pipeline / build (push) Successful in 14m25s
CI / CD Pipeline / deploy (push) Successful in 4m41s

This commit is contained in:
2026-03-29 16:21:57 +07:00
parent 2074654c18
commit 65aaae9d90
22 changed files with 3145 additions and 15 deletions
@@ -54,6 +54,14 @@ export class CreateTransmittalDto {
@IsNotEmpty()
recipientOrganizationId!: number | string;
@ApiProperty({
description:
'ผู้ส่ง Organization ID หรือ UUID (สำหรับผู้ใช้ที่มีสิทธิ system.manage_all)',
required: false,
})
@IsOptional()
originatorId?: number | string;
@ApiProperty({
description: 'Correspondence ID หรือ UUID (ADR-019)',
required: false,
@@ -4,6 +4,7 @@ import {
NotFoundException,
InternalServerErrorException,
BadRequestException,
ForbiddenException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
@@ -22,11 +23,17 @@ import { CorrespondenceType } from '../correspondence/entities/correspondence-ty
import { CorrespondenceStatus } from '../correspondence/entities/correspondence-status.entity';
import { UuidResolverService } from '../../common/services/uuid-resolver.service';
import { CorrespondenceRecipient } from '../correspondence/entities/correspondence-recipient.entity';
import { UserService } from '../user/user.service';
@Injectable()
export class TransmittalService {
private readonly logger = new Logger(TransmittalService.name);
private async hasSystemManageAllPermission(userId: number): Promise<boolean> {
const permissions = await this.userService.getUserPermissions(userId);
return permissions.includes('system.manage_all');
}
constructor(
@InjectRepository(Transmittal)
private transmittalRepo: Repository<Transmittal>,
@@ -38,7 +45,8 @@ export class TransmittalService {
private statusRepo: Repository<CorrespondenceStatus>,
private numberingService: DocumentNumberingService,
private dataSource: DataSource,
private uuidResolver: UuidResolverService
private uuidResolver: UuidResolverService,
private userService: UserService
) {}
async create(
@@ -61,7 +69,31 @@ export class TransmittalService {
await queryRunner.connect();
await queryRunner.startTransaction();
if (!user.primaryOrganizationId) {
let userOrgId = user.primaryOrganizationId;
if (!userOrgId) {
const fullUser = await this.userService.findOne(user.user_id);
if (fullUser) {
userOrgId = fullUser.primaryOrganizationId;
}
}
const resolvedOriginatorId = createDto.originatorId
? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)
: undefined;
if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {
const canManageAll = await this.hasSystemManageAllPermission(
user.user_id
);
if (!canManageAll) {
throw new ForbiddenException(
'You do not have permission to create documents on behalf of other organizations.'
);
}
userOrgId = resolvedOriginatorId;
}
if (!userOrgId) {
throw new BadRequestException(
'User must belong to an organization to create a transmittal'
);
@@ -76,7 +108,7 @@ export class TransmittalService {
// 2. Generate Number
const docNumber = await this.numberingService.generateNextNumber({
projectId: internalProjectId,
originatorOrganizationId: user.primaryOrganizationId,
originatorOrganizationId: userOrgId,
typeId: type.id,
year: new Date().getFullYear(),
customTokens: {
@@ -90,7 +122,7 @@ export class TransmittalService {
correspondenceNumber: docNumber.number,
correspondenceTypeId: type.id,
projectId: internalProjectId,
originatorId: user.primaryOrganizationId,
originatorId: userOrgId,
isInternal: false,
createdBy: user.user_id,
});