mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 06:23:06 +08:00
@@ -1,5 +1,7 @@
|
|||||||
import api from "@/lib/api-client";
|
import api from "@/lib/api-client";
|
||||||
import { IFileTask } from "@/features/file-task/types/file-task.types.ts";
|
import { IFileTask } from "@/features/file-task/types/file-task.types.ts";
|
||||||
|
import { IPagination, QueryParams } from "@/lib/types.ts";
|
||||||
|
import { IApiKey } from "@/ee/api-key";
|
||||||
|
|
||||||
export async function getFileTaskById(fileTaskId: string): Promise<IFileTask> {
|
export async function getFileTaskById(fileTaskId: string): Promise<IFileTask> {
|
||||||
const req = await api.post<IFileTask>("/file-tasks/info", {
|
const req = await api.post<IFileTask>("/file-tasks/info", {
|
||||||
@@ -8,7 +10,10 @@ export async function getFileTaskById(fileTaskId: string): Promise<IFileTask> {
|
|||||||
return req.data;
|
return req.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFileTasks(): Promise<IFileTask[]> {
|
export async function getFileTasks(
|
||||||
const req = await api.post<IFileTask[]>("/file-tasks");
|
params?: QueryParams,
|
||||||
|
): Promise<IPagination<IFileTask>> {
|
||||||
|
const req = await api.post("/file-tasks", { ...params });
|
||||||
return req.data;
|
return req.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,16 +74,13 @@ export class SearchService {
|
|||||||
queryResults = queryResults.where('spaceId', '=', searchParams.spaceId);
|
queryResults = queryResults.where('spaceId', '=', searchParams.spaceId);
|
||||||
} else if (opts.userId && !searchParams.spaceId) {
|
} else if (opts.userId && !searchParams.spaceId) {
|
||||||
// only search spaces the user is a member of
|
// only search spaces the user is a member of
|
||||||
const userSpaceIds = await this.spaceMemberRepo.getUserSpaceIds(
|
queryResults = queryResults
|
||||||
opts.userId,
|
.where(
|
||||||
);
|
'spaceId',
|
||||||
if (userSpaceIds.length > 0) {
|
'in',
|
||||||
queryResults = queryResults
|
this.spaceMemberRepo.getUserSpaceIdsQuery(opts.userId),
|
||||||
.where('spaceId', 'in', userSpaceIds)
|
)
|
||||||
.where('workspaceId', '=', opts.workspaceId);
|
.where('workspaceId', '=', opts.workspaceId);
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
} else if (searchParams.shareId && !searchParams.spaceId && !opts.userId) {
|
} else if (searchParams.shareId && !searchParams.spaceId && !opts.userId) {
|
||||||
// search in shares
|
// search in shares
|
||||||
const shareId = searchParams.shareId;
|
const shareId = searchParams.shareId;
|
||||||
|
|||||||
@@ -293,24 +293,18 @@ export class PageRepo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRecentPages(userId: string, pagination: PaginationOptions) {
|
async getRecentPages(userId: string, pagination: PaginationOptions) {
|
||||||
const userSpaceIds = await this.spaceMemberRepo.getUserSpaceIds(userId);
|
|
||||||
|
|
||||||
const query = this.db
|
const query = this.db
|
||||||
.selectFrom('pages')
|
.selectFrom('pages')
|
||||||
.select(this.baseFields)
|
.select(this.baseFields)
|
||||||
.select((eb) => this.withSpace(eb))
|
.select((eb) => this.withSpace(eb))
|
||||||
.where('spaceId', 'in', userSpaceIds)
|
.where('spaceId', 'in', this.spaceMemberRepo.getUserSpaceIdsQuery(userId))
|
||||||
.where('deletedAt', 'is', null)
|
.where('deletedAt', 'is', null)
|
||||||
.orderBy('updatedAt', 'desc');
|
.orderBy('updatedAt', 'desc');
|
||||||
|
|
||||||
const hasEmptyIds = userSpaceIds.length === 0;
|
return executeWithPagination(query, {
|
||||||
const result = executeWithPagination(query, {
|
|
||||||
page: pagination.page,
|
page: pagination.page,
|
||||||
perPage: pagination.limit,
|
perPage: pagination.limit,
|
||||||
hasEmptyIds,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDeletedPagesInSpace(spaceId: string, pagination: PaginationOptions) {
|
async getDeletedPagesInSpace(spaceId: string, pagination: PaginationOptions) {
|
||||||
|
|||||||
@@ -137,25 +137,19 @@ export class ShareRepo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getShares(userId: string, pagination: PaginationOptions) {
|
async getShares(userId: string, pagination: PaginationOptions) {
|
||||||
const userSpaceIds = await this.spaceMemberRepo.getUserSpaceIds(userId);
|
|
||||||
|
|
||||||
const query = this.db
|
const query = this.db
|
||||||
.selectFrom('shares')
|
.selectFrom('shares')
|
||||||
.select(this.baseFields)
|
.select(this.baseFields)
|
||||||
.select((eb) => this.withPage(eb))
|
.select((eb) => this.withPage(eb))
|
||||||
.select((eb) => this.withSpace(eb, userId))
|
.select((eb) => this.withSpace(eb, userId))
|
||||||
.select((eb) => this.withCreator(eb))
|
.select((eb) => this.withCreator(eb))
|
||||||
.where('spaceId', 'in', userSpaceIds)
|
.where('spaceId', 'in', this.spaceMemberRepo.getUserSpaceIdsQuery(userId))
|
||||||
.orderBy('updatedAt', 'desc');
|
.orderBy('updatedAt', 'desc');
|
||||||
|
|
||||||
const hasEmptyIds = userSpaceIds.length === 0;
|
return executeWithPagination(query, {
|
||||||
const result = executeWithPagination(query, {
|
|
||||||
page: pagination.page,
|
page: pagination.page,
|
||||||
perPage: pagination.limit,
|
perPage: pagination.limit,
|
||||||
hasEmptyIds,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
withPage(eb: ExpressionBuilder<DB, 'shares'>) {
|
withPage(eb: ExpressionBuilder<DB, 'shares'>) {
|
||||||
|
|||||||
@@ -209,34 +209,33 @@ export class SpaceMemberRepo {
|
|||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUserSpaceIds(userId: string): Promise<string[]> {
|
getUserSpaceIdsQuery(userId: string) {
|
||||||
const membership = await this.db
|
return this.db
|
||||||
.selectFrom('spaceMembers')
|
.selectFrom('spaceMembers')
|
||||||
.innerJoin('spaces', 'spaces.id', 'spaceMembers.spaceId')
|
.innerJoin('spaces', 'spaces.id', 'spaceMembers.spaceId')
|
||||||
.select(['spaces.id'])
|
.select('spaces.id')
|
||||||
.where('userId', '=', userId)
|
.where('userId', '=', userId)
|
||||||
.union(
|
.union(
|
||||||
this.db
|
this.db
|
||||||
.selectFrom('spaceMembers')
|
.selectFrom('spaceMembers')
|
||||||
.innerJoin('groupUsers', 'groupUsers.groupId', 'spaceMembers.groupId')
|
.innerJoin('groupUsers', 'groupUsers.groupId', 'spaceMembers.groupId')
|
||||||
.innerJoin('spaces', 'spaces.id', 'spaceMembers.spaceId')
|
.innerJoin('spaces', 'spaces.id', 'spaceMembers.spaceId')
|
||||||
.select(['spaces.id'])
|
.select('spaces.id')
|
||||||
.where('groupUsers.userId', '=', userId),
|
.where('groupUsers.userId', '=', userId),
|
||||||
)
|
);
|
||||||
.execute();
|
}
|
||||||
|
|
||||||
|
async getUserSpaceIds(userId: string): Promise<string[]> {
|
||||||
|
const membership = await this.getUserSpaceIdsQuery(userId).execute();
|
||||||
return membership.map((space) => space.id);
|
return membership.map((space) => space.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUserSpaces(userId: string, pagination: PaginationOptions) {
|
async getUserSpaces(userId: string, pagination: PaginationOptions) {
|
||||||
const userSpaceIds = await this.getUserSpaceIds(userId);
|
|
||||||
|
|
||||||
let query = this.db
|
let query = this.db
|
||||||
.selectFrom('spaces')
|
.selectFrom('spaces')
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.select((eb) => [this.spaceRepo.withMemberCount(eb)])
|
.select((eb) => [this.spaceRepo.withMemberCount(eb)])
|
||||||
//.where('workspaceId', '=', workspaceId)
|
.where('id', 'in', this.getUserSpaceIdsQuery(userId))
|
||||||
.where('id', 'in', userSpaceIds)
|
|
||||||
.orderBy('createdAt', 'asc');
|
.orderBy('createdAt', 'asc');
|
||||||
|
|
||||||
if (pagination.query) {
|
if (pagination.query) {
|
||||||
@@ -253,14 +252,9 @@ export class SpaceMemberRepo {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasEmptyIds = userSpaceIds.length === 0;
|
return executeWithPagination(query, {
|
||||||
|
|
||||||
const result = executeWithPagination(query, {
|
|
||||||
page: pagination.page,
|
page: pagination.page,
|
||||||
perPage: pagination.limit,
|
perPage: pagination.limit,
|
||||||
hasEmptyIds,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
Submodule apps/server/src/ee updated: 075761c2d9...b55f6f5d23
@@ -10,46 +10,59 @@ import {
|
|||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import SpaceAbilityFactory from '../../core/casl/abilities/space-ability.factory';
|
import SpaceAbilityFactory from '../../core/casl/abilities/space-ability.factory';
|
||||||
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
|
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
|
||||||
import { User } from '@docmost/db/types/entity.types';
|
import { User, Workspace } from '@docmost/db/types/entity.types';
|
||||||
import {
|
import {
|
||||||
SpaceCaslAction,
|
SpaceCaslAction,
|
||||||
SpaceCaslSubject,
|
SpaceCaslSubject,
|
||||||
} from '../../core/casl/interfaces/space-ability.type';
|
} from '../../core/casl/interfaces/space-ability.type';
|
||||||
|
import {
|
||||||
|
WorkspaceCaslAction,
|
||||||
|
WorkspaceCaslSubject,
|
||||||
|
} from '../../core/casl/interfaces/workspace-ability.type';
|
||||||
|
import WorkspaceAbilityFactory from '../../core/casl/abilities/workspace-ability.factory';
|
||||||
|
import { AuthWorkspace } from '../../common/decorators/auth-workspace.decorator';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
import { KyselyDB } from '@docmost/db/types/kysely.types';
|
import { KyselyDB } from '@docmost/db/types/kysely.types';
|
||||||
import { AuthUser } from '../../common/decorators/auth-user.decorator';
|
import { AuthUser } from '../../common/decorators/auth-user.decorator';
|
||||||
import { FileTaskIdDto } from './dto/file-task-dto';
|
import { FileTaskIdDto } from './dto/file-task-dto';
|
||||||
import { SpaceMemberRepo } from '@docmost/db/repos/space/space-member.repo';
|
import { SpaceMemberRepo } from '@docmost/db/repos/space/space-member.repo';
|
||||||
|
import { PaginationOptions } from '@docmost/db/pagination/pagination-options';
|
||||||
|
import { executeWithPagination } from '@docmost/db/pagination/pagination';
|
||||||
|
|
||||||
@Controller('file-tasks')
|
@Controller('file-tasks')
|
||||||
export class FileTaskController {
|
export class FileTaskController {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly spaceMemberRepo: SpaceMemberRepo,
|
|
||||||
private readonly spaceAbility: SpaceAbilityFactory,
|
private readonly spaceAbility: SpaceAbilityFactory,
|
||||||
|
private readonly workspaceAbility: WorkspaceAbilityFactory,
|
||||||
|
private readonly spaceMemberRepo: SpaceMemberRepo,
|
||||||
@InjectKysely() private readonly db: KyselyDB,
|
@InjectKysely() private readonly db: KyselyDB,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@Post()
|
@Post()
|
||||||
async getFileTasks(@AuthUser() user: User) {
|
async getFileTasks(
|
||||||
const userSpaceIds = await this.spaceMemberRepo.getUserSpaceIds(user.id);
|
@Body() pagination: PaginationOptions,
|
||||||
|
@AuthUser() user: User,
|
||||||
if (!userSpaceIds || userSpaceIds.length === 0) {
|
@AuthWorkspace() workspace: Workspace,
|
||||||
return [];
|
) {
|
||||||
|
const ability = this.workspaceAbility.createForUser(user, workspace);
|
||||||
|
if (
|
||||||
|
ability.cannot(WorkspaceCaslAction.Manage, WorkspaceCaslSubject.Settings)
|
||||||
|
) {
|
||||||
|
throw new ForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileTasks = await this.db
|
const query = this.db
|
||||||
.selectFrom('fileTasks')
|
.selectFrom('fileTasks')
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.where('spaceId', 'in', userSpaceIds)
|
.where('spaceId', 'in', this.spaceMemberRepo.getUserSpaceIdsQuery(user.id))
|
||||||
.execute();
|
.orderBy('createdAt', 'desc');
|
||||||
|
|
||||||
if (!fileTasks) {
|
return executeWithPagination(query, {
|
||||||
throw new NotFoundException('File task not found');
|
page: pagination.page,
|
||||||
}
|
perPage: pagination.limit,
|
||||||
|
});
|
||||||
return fileTasks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
|
|||||||
Reference in New Issue
Block a user