Skip to content

Commit 6350392

Browse files
authored
Merge pull request #195 from import-ai/refactor/resources
refactor(resources): update getRoot
2 parents 4fea7fb + 07b16dd commit 6350392

File tree

11 files changed

+433
-247
lines changed

11 files changed

+433
-247
lines changed

src/api-key/api-key.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,9 @@ export class APIKeyService {
206206

207207
async info(apiKey: APIKey): Promise<APIKeyInfoDto> {
208208
// Get the namespace
209-
const namespace = await this.namespacesService.get(apiKey.namespaceId);
209+
const namespace = await this.namespacesService.getNamespace(
210+
apiKey.namespaceId,
211+
);
210212

211213
// Get the user
212214
const user = await this.userService.find(apiKey.userId);

src/namespace-resources/dto/list-children-resp.dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Expose } from 'class-transformer';
22
import { ResourceMetaDto } from 'omniboxd/resources/dto/resource-meta.dto';
33

4-
export class ListChildrenRespDto extends ResourceMetaDto {
4+
export class ChildrenMetaDto extends ResourceMetaDto {
55
@Expose({ name: 'has_children' })
66
hasChildren: boolean;
77

src/namespace-resources/dto/update-resource.dto.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
IsOptional,
77
IsNotEmpty,
88
} from 'class-validator';
9-
import { UpdateResourceReqDto } from 'omniboxd/resources/dto/update-resource-req.dto';
109
import { ResourceType } from 'omniboxd/resources/entities/resource.entity';
1110

1211
export class UpdateResourceDto {
@@ -39,14 +38,4 @@ export class UpdateResourceDto {
3938
@IsObject()
4039
@IsOptional()
4140
attrs?: Record<string, any>;
42-
43-
toUpdateReq(): UpdateResourceReqDto {
44-
const updateReq = new UpdateResourceReqDto();
45-
updateReq.name = this.name;
46-
updateReq.parentId = this.parentId;
47-
updateReq.tagIds = this.tag_ids ? this.tag_ids : undefined;
48-
updateReq.content = this.content;
49-
updateReq.attrs = this.attrs;
50-
return updateReq;
51-
}
5241
}

src/namespace-resources/namespace-resources.controller.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
import { UserId } from 'omniboxd/decorators/user-id.decorator';
1919
import { Request } from 'express';
2020
import { ResourceMetaDto } from 'omniboxd/resources/dto/resource-meta.dto';
21-
import { ListChildrenRespDto } from './dto/list-children-resp.dto';
21+
import { ChildrenMetaDto } from './dto/list-children-resp.dto';
2222

2323
@Controller('api/v1/namespaces/:namespaceId/resources')
2424
export class NamespaceResourcesController {
@@ -92,7 +92,7 @@ export class NamespaceResourcesController {
9292
@UserId() userId: string,
9393
@Param('namespaceId') namespaceId: string,
9494
@Param('resourceId') resourceId: string,
95-
): Promise<ListChildrenRespDto[]> {
95+
): Promise<ChildrenMetaDto[]> {
9696
return this.namespaceResourcesService.listChildren(
9797
namespaceId,
9898
resourceId,
@@ -107,12 +107,12 @@ export class NamespaceResourcesController {
107107
@Param('resourceId') resourceId: string,
108108
@Param('targetId') targetId: string,
109109
) {
110-
return await this.namespaceResourcesService.move({
111-
userId: req.user!.id,
110+
return await this.namespaceResourcesService.move(
112111
namespaceId,
113112
resourceId,
113+
req.user!.id,
114114
targetId,
115-
});
115+
);
116116
}
117117

118118
@Get('search')

src/namespace-resources/namespace-resources.service.ts

Lines changed: 73 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { TagDto } from 'omniboxd/tag/dto/tag.dto';
4040
import { ResourceAttachmentsService } from 'omniboxd/resource-attachments/resource-attachments.service';
4141
import { ResourcesService } from 'omniboxd/resources/resources.service';
4242
import { ResourceMetaDto } from 'omniboxd/resources/dto/resource-meta.dto';
43-
import { ListChildrenRespDto } from './dto/list-children-resp.dto';
43+
import { ChildrenMetaDto } from './dto/list-children-resp.dto';
4444

4545
const TASK_PRIORITY = 5;
4646

@@ -128,28 +128,6 @@ export class NamespaceResourcesService {
128128
return resources.map((resource) => resource.id);
129129
}
130130

131-
private async hasChildren(
132-
namespaceId: string,
133-
parents: ResourceMetaDto[],
134-
userId: string,
135-
): Promise<boolean> {
136-
const children = await this.resourcesService.getSubResources(
137-
namespaceId,
138-
parents[0].id,
139-
);
140-
for (const child of children) {
141-
const permission = await this.permissionsService.getCurrentPermission(
142-
namespaceId,
143-
[child, ...parents],
144-
userId,
145-
);
146-
if (permission !== ResourcePermission.NO_ACCESS) {
147-
return true;
148-
}
149-
}
150-
return false;
151-
}
152-
153131
async findByIds(namespaceId: string, ids: Array<string>) {
154132
if (ids.length <= 0) {
155133
return [];
@@ -186,6 +164,12 @@ export class NamespaceResourcesService {
186164
data: CreateResourceDto,
187165
manager?: EntityManager,
188166
) {
167+
if (!manager) {
168+
return await this.dataSource.transaction(async (manager) => {
169+
return await this.create(userId, data, manager);
170+
});
171+
}
172+
189173
const ok = await this.permissionsService.userHasPermission(
190174
data.namespaceId,
191175
data.parentId,
@@ -198,49 +182,14 @@ export class NamespaceResourcesService {
198182
throw new ForbiddenException('Not authorized to create resource.');
199183
}
200184

201-
const transaction = async (manager: EntityManager) => {
202-
const repo = manager.getRepository(Resource);
203-
const parentResource = await repo.findOne({
204-
where: {
205-
id: data.parentId,
206-
namespaceId: data.namespaceId,
207-
},
208-
});
209-
if (!parentResource) {
210-
throw new BadRequestException('Parent resource not exists.');
211-
}
212-
if (data.namespaceId && parentResource.namespaceId !== data.namespaceId) {
213-
throw new BadRequestException(
214-
"Parent resource's namespace & space must match the resource's.",
215-
);
216-
}
217-
218-
// Use provided tag_ids directly
219-
const tagIds = data.tag_ids || [];
220-
221-
const resource = repo.create({
185+
return await this.resourcesService.createResource(
186+
{
222187
...data,
223188
userId,
224-
namespaceId: data.namespaceId,
225-
parentId: parentResource.id,
226-
tagIds: tagIds.length > 0 ? tagIds : undefined,
227-
});
228-
const savedResource = await repo.save(resource);
229-
await this.wizardTaskService.createIndexTask(
230-
TASK_PRIORITY,
231-
userId,
232-
savedResource,
233-
manager.getRepository(Task),
234-
);
235-
return savedResource;
236-
};
237-
238-
if (manager) {
239-
return await transaction(manager);
240-
}
241-
return await this.dataSource.transaction(async (manager) => {
242-
return await transaction(manager);
243-
});
189+
tagIds: data.tag_ids,
190+
},
191+
manager,
192+
);
244193
}
245194

246195
async duplicate(userId: string, resourceId: string) {
@@ -370,33 +319,26 @@ export class NamespaceResourcesService {
370319
: resourcesWithTags;
371320
}
372321

373-
async move({ namespaceId, resourceId, targetId, userId }) {
374-
const resourceHasPermission =
375-
await this.permissionsService.userHasPermission(
376-
namespaceId,
377-
resourceId,
378-
userId,
379-
);
380-
if (!resourceHasPermission) {
322+
async move(
323+
namespaceId: string,
324+
resourceId: string,
325+
userId: string,
326+
targetId: string,
327+
) {
328+
const ok = await this.permissionsService.userHasPermission(
329+
namespaceId,
330+
resourceId,
331+
userId,
332+
);
333+
if (!ok) {
381334
throw new ForbiddenException('Not authorized');
382335
}
383-
const resource = await this.resourceRepository.findOneByOrFail({
384-
id: resourceId,
385-
});
386-
387-
// Validate that the target resource exists
388-
const targetResource = await this.resourceRepository.findOne({
389-
where: { namespaceId, id: targetId },
390-
});
391-
if (!targetResource) {
392-
throw new NotFoundException('Target resource not found');
393-
}
394-
395-
const newResource = this.resourceRepository.create({
396-
...resource,
397-
parentId: targetId,
398-
});
399-
await this.resourceRepository.save(newResource);
336+
await this.resourcesService.updateResource(
337+
namespaceId,
338+
resourceId,
339+
userId,
340+
{ parentId: targetId },
341+
);
400342
}
401343

402344
async search({ namespaceId, excludeResourceId, name, userId }) {
@@ -470,10 +412,9 @@ export class NamespaceResourcesService {
470412
if (permission === ResourcePermission.NO_ACCESS) {
471413
return [];
472414
}
473-
const children = await this.resourcesService.getSubResources(
474-
namespaceId,
415+
const children = await this.resourcesService.getSubResources(namespaceId, [
475416
parents[0].id,
476-
);
417+
]);
477418
const filteredChildren: ResourceMetaDto[] = [];
478419
for (const child of children) {
479420
const permission = await this.permissionsService.getCurrentPermission(
@@ -492,26 +433,47 @@ export class NamespaceResourcesService {
492433
namespaceId: string,
493434
resourceId: string,
494435
userId: string,
495-
): Promise<ListChildrenRespDto[]> {
436+
): Promise<ChildrenMetaDto[]> {
496437
const parents = await this.resourcesService.getParentResourcesOrFail(
497438
namespaceId,
498439
resourceId,
499440
);
500-
const children = await this.getSubResourcesByParents(
441+
const children = await this.resourcesService.getSubResources(namespaceId, [
442+
resourceId,
443+
]);
444+
const subChildren = await this.resourcesService.getSubResources(
445+
namespaceId,
446+
children.map((child) => child.id),
447+
);
448+
const resources = [...parents, ...children, ...subChildren];
449+
const permissionMap = await this.permissionsService.getCurrentPermissions(
501450
namespaceId,
502-
parents,
503451
userId,
452+
resources,
504453
);
505-
const resps: ListChildrenRespDto[] = [];
454+
455+
const hasChildrenMap = new Map<string, boolean>();
456+
for (const subChild of subChildren) {
457+
if (!subChild.parentId) {
458+
continue;
459+
}
460+
const permission = permissionMap.get(subChild.id);
461+
if (!permission || permission === ResourcePermission.NO_ACCESS) {
462+
continue;
463+
}
464+
hasChildrenMap.set(subChild.parentId, true);
465+
}
466+
467+
const childrenDtos: ChildrenMetaDto[] = [];
506468
for (const child of children) {
507-
const hasChildren = await this.hasChildren(
508-
namespaceId,
509-
[child, ...parents],
510-
userId,
511-
);
512-
resps.push(new ListChildrenRespDto(child, hasChildren));
469+
const permission = permissionMap.get(child.id);
470+
if (!permission || permission === ResourcePermission.NO_ACCESS) {
471+
continue;
472+
}
473+
const hasChildren = hasChildrenMap.get(child.id) || false;
474+
childrenDtos.push(new ChildrenMetaDto(child, hasChildren));
513475
}
514-
return resps;
476+
return childrenDtos;
515477
}
516478

517479
async getSpaceType(
@@ -586,12 +548,17 @@ export class NamespaceResourcesService {
586548
return resource;
587549
}
588550

589-
async update(userId: string, id: string, data: UpdateResourceDto) {
551+
async update(userId: string, resourceId: string, data: UpdateResourceDto) {
590552
await this.resourcesService.updateResource(
591553
data.namespaceId,
592-
id,
554+
resourceId,
593555
userId,
594-
data.toUpdateReq(),
556+
{
557+
name: data.name,
558+
tagIds: data.tag_ids,
559+
content: data.content,
560+
attrs: data.attrs,
561+
},
595562
);
596563
}
597564

@@ -792,22 +759,6 @@ export class NamespaceResourcesService {
792759
return { fileStream, resource };
793760
}
794761

795-
async createFolder(
796-
namespaceId: string,
797-
parentId: string | null,
798-
userId: string | null,
799-
manager: EntityManager,
800-
) {
801-
return await manager.save(
802-
manager.create(Resource, {
803-
resourceType: ResourceType.FOLDER,
804-
namespaceId,
805-
parentId,
806-
userId,
807-
}),
808-
);
809-
}
810-
811762
async listAllUserAccessibleResources(
812763
namespaceId: string,
813764
userId: string,

src/namespaces/namespaces.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export class NamespacesController {
2323

2424
@Get(':namespaceId')
2525
async get(@Param('namespaceId') namespaceId: string) {
26-
return await this.namespacesService.get(namespaceId);
26+
return await this.namespacesService.getNamespace(namespaceId);
2727
}
2828

2929
@Get(':namespaceId/members')

src/namespaces/namespaces.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Namespace } from './entities/namespace.entity';
88
import { NamespaceMember } from './entities/namespace-member.entity';
99
import { NamespaceResourcesModule } from 'omniboxd/namespace-resources/namespace-resources.module';
1010
import { PermissionsModule } from 'omniboxd/permissions/permissions.module';
11+
import { ResourcesModule } from 'omniboxd/resources/resources.module';
1112

1213
@Module({
1314
exports: [NamespacesService],
@@ -16,6 +17,7 @@ import { PermissionsModule } from 'omniboxd/permissions/permissions.module';
1617
imports: [
1718
UserModule,
1819
NamespaceResourcesModule,
20+
ResourcesModule,
1921
PermissionsModule,
2022
TypeOrmModule.forFeature([Resource]),
2123
TypeOrmModule.forFeature([Namespace]),

0 commit comments

Comments
 (0)