diff --git a/lib/command/impls/ls.ts b/lib/command/impls/ls.ts index a7a26e9..8adaeb7 100644 --- a/lib/command/impls/ls.ts +++ b/lib/command/impls/ls.ts @@ -1,8 +1,6 @@ -import { userService } from '~/services/users'; import { formatArg } from '../utils'; import type { AsyncCommandFunc } from './types'; import { fileService } from '~/services/files'; -import { groupService } from '~/services/groups'; export const ls: AsyncCommandFunc = async function (...args) { // discard `ls` @@ -21,8 +19,8 @@ export const ls: AsyncCommandFunc = async function (...args) { for (const file of files) { const fileType = formatFileType(file.fileType as string); const filePermissionBits = formatPermissionBits(file.permission as unknown as string); - const fileOwner = (await userService.getMetaOfUser(file.ownerId)).unwrap().name; - const fileGroup = (await groupService.getMetaOfGroup(file.groupId)).unwrap().name; + const fileOwner = file.ownerName; + const fileGroup = file.groupName; fileLines.push(`${fileType}${filePermissionBits} ${fileOwner} ${fileGroup} ${file.name}`); } return [ diff --git a/server/api/files/ls.get.ts b/server/api/files/ls.get.ts index a690c77..48cd6bd 100644 --- a/server/api/files/ls.get.ts +++ b/server/api/files/ls.get.ts @@ -17,7 +17,14 @@ export default defineEventHandler(async (event) => { return { error: { code: FileLsErrorCode.INVALID_PARAM, message: 'Expect the "name" query param to be valid path' } }; } try { - const { permission_bits: filePermissionBits, owner_id: fileOwnerId, group_id: fileGroupId, file_type: fileType, created_at: createdAt, updated_at: updatedAt } = await db.selectExactlyOne('files', { name: filepath.toString(), deleted_at: db.conditions.isNull }).run(dbPool); + const [{ permission_bits: filePermissionBits, owner_id: fileOwnerId, owner_name: ownerName, group_name: groupName, group_id: fileGroupId, file_type: fileType, created_at: createdAt, updated_at: updatedAt }] = await db.sql` + SELECT permission_bits, ${'files'}.${'name'}, owner_id, ${'users'}.${'name'} AS owner_name, ${'files'}.${'group_id'}, ${'groups'}.${'name'} AS group_name, file_type, ${'files'}.created_at, ${'files'}.updated_at + FROM ${'files'} + JOIN ${'users'} ON ${'files'}.${'owner_id'} = ${'users'}.${'id'} + JOIN ${'groups'} ON ${'files'}.${'group_id'} = ${'groups'}.${'id'} + WHERE ${'files'}.${'deleted_at'} IS NULL + AND ${'files'}.${'name'} = ${db.param(filepath.toString())} + `.run(dbPool); if ( !canAccess( { userId: event.context.auth.userId as number, groupId: event.context.auth.groupId as number }, @@ -29,12 +36,20 @@ export default defineEventHandler(async (event) => { } if (fileType === 'file') { - return { ok: { message: 'Fetch file meta successfully', data: { files: [{ name: filepath.toString(), ownerId: fileOwnerId, groupId: fileGroupId, fileType: fileType, createdAt, updatedAt, permissionBits: filePermissionBits }] } } }; + return { ok: { message: 'Fetch file meta successfully', data: { files: [{ name: filepath.toString(), ownerId: fileOwnerId, ownerName, groupName, groupId: fileGroupId, fileType: fileType, createdAt, updatedAt, permissionBits: filePermissionBits }] } } }; } - const files = await db.select('files', { name: db.conditions.and(db.conditions.like(`${filepath.toString()}/%`), db.conditions.notLike(`${filepath.toString()}/%/%`)), deleted_at: db.conditions.isNull }).run(dbPool); + const files = await db.sql` + SELECT permission_bits, ${'files'}.${'name'}, owner_id, ${'users'}.${'name'} AS owner_name, ${'files'}.${'group_id'}, ${'groups'}.${'name'} AS group_name, file_type, ${'files'}.created_at, ${'files'}.updated_at + FROM ${'files'} + JOIN ${'users'} ON ${'files'}.${'owner_id'} = ${'users'}.${'id'} + JOIN ${'groups'} ON ${'files'}.${'group_id'} = ${'groups'}.${'id'} + WHERE ${'files'}.${'deleted_at'} IS NULL + AND ${'files'}.${'name'} LIKE ${db.param(`${filepath.toString()}/%`)} + AND ${'files'}.${'name'} NOT LIKE ${db.param(`${filepath.toString()}/%/%`)} + `.run(dbPool); - return { ok: { message: 'Fetch folder\'s content successfully', data: { files: files.map(({ permission_bits, updated_at, name, file_type, created_at, owner_id, group_id }) => ({ name, fileType: file_type, createdAt: created_at, ownerId: owner_id, groupId: group_id, permissionBits: permission_bits, updatedAt: updated_at })) } } }; + return { ok: { message: 'Fetch folder\'s content successfully', data: { files: files.map(({ permission_bits, updated_at, name, file_type, created_at, owner_id, group_id, owner_name, group_name }) => ({ name, fileType: file_type, createdAt: created_at, ownerId: owner_id, groupId: group_id, permissionBits: permission_bits, updatedAt: updated_at, groupName: group_name, ownerName: owner_name })) } } }; } catch { return { error: { code: FileLsErrorCode.FILE_NOT_FOUND, message: 'File not found' } }; } diff --git a/services/files.ts b/services/files.ts index e4d0906..cffa7ad 100644 --- a/services/files.ts +++ b/services/files.ts @@ -30,7 +30,9 @@ export interface FileMeta { fullName: string; permission: FilePermission; ownerId: number; + ownerName: string; groupId: number; + groupName: string; createdAt: Date; updatedAt: Date; fileType: string; @@ -115,6 +117,8 @@ export const fileService = { createdAt: file.createdAt, updatedAt: file.updatedAt, fileType: file.fileType, + ownerName: file.ownerName, + groupName: file.groupName, }))); }, async removeFile (filename: string): Promise> {