forked from FoundKeyGang/FoundKey
server: unify drive object types in database
Minor adjustment: The 'name' columns have the same max length. Major adjustment: Rename both columns to be "parentId" and update all references of this name in the backend. API parameters are not changed, since that would be an unnecessary breaking change.
This commit is contained in:
parent
701054b86e
commit
94d1cf75aa
14 changed files with 48 additions and 26 deletions
|
@ -0,0 +1,22 @@
|
||||||
|
export class unifyDriveObjects1679767920029 {
|
||||||
|
name = 'unifyDriveObjects1679767920029';
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "drive_file" RENAME COLUMN "folderId" TO "parentId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "drive_folder" ALTER COLUMN "name" TYPE character varying(256)`);
|
||||||
|
// The column name changed so the name that typeorm generates for indices and foreign keys changes too.
|
||||||
|
// To avoid reindexing, just rename them.
|
||||||
|
await queryRunner.query(`ALTER TABLE "drive_file" RENAME CONSTRAINT "FK_bb90d1956dafc4068c28aa7560a" TO "FK_84b4e3038e7e64a68764dd7ea3e"`);
|
||||||
|
await queryRunner.query(`ALTER INDEX "IDX_bb90d1956dafc4068c28aa7560" RENAME TO "IDX_84b4e3038e7e64a68764dd7ea3"`);
|
||||||
|
await queryRunner.query(`ALTER INDEX "IDX_55720b33a61a7c806a8215b825" RENAME TO "IDX_7c607687cd487292d16617b23e"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "drive_file" RENAME CONSTRAINT "FK_84b4e3038e7e64a68764dd7ea3e" TO "FK_bb90d1956dafc4068c28aa7560a"`);
|
||||||
|
await queryRunner.query(`ALTER INDEX "IDX_84b4e3038e7e64a68764dd7ea3" RENAME TO "IDX_bb90d1956dafc4068c28aa7560"`);
|
||||||
|
await queryRunner.query(`ALTER INDEX "IDX_7c607687cd487292d16617b23e" RENAME TO "IDX_55720b33a61a7c806a8215b825"`);
|
||||||
|
|
||||||
|
await queryRunner.query(`ALTER TABLE "drive_folder" ALTER COLUMN "name" TYPE character varying(128) USING substr("name", 1, 128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "drive_file" RENAME COLUMN "parentId" TO "folderId"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import { User } from './user.js';
|
||||||
import { DriveFolder } from './drive-folder.js';
|
import { DriveFolder } from './drive-folder.js';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'folderId', 'id'])
|
@Index(['userId', 'parentId', 'id'])
|
||||||
export class DriveFile {
|
export class DriveFile {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
@ -142,13 +142,13 @@ export class DriveFile {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The parent folder ID. If null, it means the DriveFile is located in root.',
|
comment: 'The parent folder ID. If null, it means the DriveFile is located in root.',
|
||||||
})
|
})
|
||||||
public folderId: DriveFolder['id'] | null;
|
public parentId: DriveFolder['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(() => DriveFolder, {
|
@ManyToOne(() => DriveFolder, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: 'SET NULL',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public folder: DriveFolder | null;
|
public parent: DriveFolder | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column('boolean', {
|
||||||
|
|
|
@ -14,7 +14,7 @@ export class DriveFolder {
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 128,
|
length: 256,
|
||||||
comment: 'The name of the DriveFolder.',
|
comment: 'The name of the DriveFolder.',
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
|
@ -105,8 +105,8 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
|
||||||
url: opts.self ? file.url : this.getPublicUrl(file, false),
|
url: opts.self ? file.url : this.getPublicUrl(file, false),
|
||||||
thumbnailUrl: this.getPublicUrl(file, true),
|
thumbnailUrl: this.getPublicUrl(file, true),
|
||||||
comment: file.comment,
|
comment: file.comment,
|
||||||
folderId: file.folderId,
|
folderId: file.parentId,
|
||||||
folder: opts.detail && file.folderId ? DriveFolders.pack(file.folderId, {
|
folder: opts.detail && file.parentId ? DriveFolders.pack(file.parentId, {
|
||||||
detail: true,
|
detail: true,
|
||||||
}) : undefined,
|
}) : undefined,
|
||||||
userId: file.userId,
|
userId: file.userId,
|
||||||
|
|
|
@ -28,7 +28,7 @@ export const DriveFolderRepository = db.getRepository(DriveFolder).extend({
|
||||||
parentId: folder.id,
|
parentId: folder.id,
|
||||||
}),
|
}),
|
||||||
filesCount: DriveFiles.countBy({
|
filesCount: DriveFiles.countBy({
|
||||||
folderId: folder.id,
|
parentId: folder.id,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
...(folder.parentId ? {
|
...(folder.parentId ? {
|
||||||
|
|
|
@ -38,9 +38,9 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.andWhere('file.userId = :userId', { userId: user.id });
|
.andWhere('file.userId = :userId', { userId: user.id });
|
||||||
|
|
||||||
if (ps.folderId) {
|
if (ps.folderId) {
|
||||||
query.andWhere('file.folderId = :folderId', { folderId: ps.folderId });
|
query.andWhere('file.parentId = :parentId', { parentId: ps.folderId });
|
||||||
} else {
|
} else {
|
||||||
query.andWhere('file.folderId IS NULL');
|
query.andWhere('file.parentId IS NULL');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.type) {
|
if (ps.type) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ export default define(meta, paramDef, async (ps, user, _, file, cleanup) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create file
|
// Create file
|
||||||
const driveFile = await addFile({ user, path: file.path, name, comment: ps.comment, folderId: ps.folderId, force: ps.force, sensitive: ps.isSensitive });
|
const driveFile = await addFile({ user, path: file.path, name, comment: ps.comment, parentId: ps.folderId, force: ps.force, sensitive: ps.isSensitive });
|
||||||
return await DriveFiles.pack(driveFile, { self: true });
|
return await DriveFiles.pack(driveFile, { self: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error || typeof e === 'string') {
|
if (e instanceof Error || typeof e === 'string') {
|
||||||
|
|
|
@ -36,7 +36,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
const files = await DriveFiles.findBy({
|
const files = await DriveFiles.findBy({
|
||||||
name: ps.name,
|
name: ps.name,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
folderId: ps.folderId ?? IsNull(),
|
parentId: ps.folderId ?? IsNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
return await Promise.all(files.map(file => DriveFiles.pack(file, { self: true })));
|
return await Promise.all(files.map(file => DriveFiles.pack(file, { self: true })));
|
||||||
|
|
|
@ -54,7 +54,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
|
|
||||||
if (ps.folderId !== undefined) {
|
if (ps.folderId !== undefined) {
|
||||||
if (ps.folderId === null) {
|
if (ps.folderId === null) {
|
||||||
file.folderId = null;
|
file.parentId = null;
|
||||||
} else {
|
} else {
|
||||||
const folder = await DriveFolders.findOneBy({
|
const folder = await DriveFolders.findOneBy({
|
||||||
id: ps.folderId,
|
id: ps.folderId,
|
||||||
|
@ -63,14 +63,14 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
|
|
||||||
if (folder == null) throw new ApiError('NO_SUCH_FOLDER');
|
if (folder == null) throw new ApiError('NO_SUCH_FOLDER');
|
||||||
|
|
||||||
file.folderId = folder.id;
|
file.parentId = folder.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await DriveFiles.update(file.id, {
|
await DriveFiles.update(file.id, {
|
||||||
name: file.name,
|
name: file.name,
|
||||||
comment: file.comment,
|
comment: file.comment,
|
||||||
folderId: file.folderId,
|
parentId: file.parentId,
|
||||||
isSensitive: file.isSensitive,
|
isSensitive: file.isSensitive,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const paramDef = {
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
uploadFromUrl({ url: ps.url, user, folderId: ps.folderId, sensitive: ps.isSensitive, force: ps.force, comment: ps.comment }).then(file => {
|
uploadFromUrl({ url: ps.url, user, parentId: ps.folderId, sensitive: ps.isSensitive, force: ps.force, comment: ps.comment }).then(file => {
|
||||||
DriveFiles.pack(file, { self: true }).then(packedFile => {
|
DriveFiles.pack(file, { self: true }).then(packedFile => {
|
||||||
publishMainStream(user.id, 'urlUploadFinished', {
|
publishMainStream(user.id, 'urlUploadFinished', {
|
||||||
marker: ps.marker,
|
marker: ps.marker,
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
|
|
||||||
const [childFoldersCount, childFilesCount] = await Promise.all([
|
const [childFoldersCount, childFilesCount] = await Promise.all([
|
||||||
DriveFolders.countBy({ parentId: folder.id }),
|
DriveFolders.countBy({ parentId: folder.id }),
|
||||||
DriveFiles.countBy({ folderId: folder.id }),
|
DriveFiles.countBy({ parentId: folder.id }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (childFoldersCount !== 0 || childFilesCount !== 0) {
|
if (childFoldersCount !== 0 || childFilesCount !== 0) {
|
||||||
|
|
|
@ -48,10 +48,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
|
|
||||||
if (ps.folderId) {
|
if (ps.folderId) {
|
||||||
foldersQuery.andWhere('folder.parentId = :parentId', { parentId: ps.folderId });
|
foldersQuery.andWhere('folder.parentId = :parentId', { parentId: ps.folderId });
|
||||||
filesQuery.andWhere('file.folderId = :folderId', { folderId: ps.folderId });
|
filesQuery.andWhere('file.parentId = :parentId', { parentId: ps.folderId });
|
||||||
} else {
|
} else {
|
||||||
foldersQuery.andWhere('folder.parentId IS NULL');
|
foldersQuery.andWhere('folder.parentId IS NULL');
|
||||||
filesQuery.andWhere('file.folderId IS NULL');
|
filesQuery.andWhere('file.parentId IS NULL');
|
||||||
}
|
}
|
||||||
|
|
||||||
const folders = await foldersQuery.take(ps.limit).getMany();
|
const folders = await foldersQuery.take(ps.limit).getMany();
|
||||||
|
|
|
@ -322,7 +322,7 @@ type AddFileArgs = {
|
||||||
/** Comment */
|
/** Comment */
|
||||||
comment?: string | null;
|
comment?: string | null;
|
||||||
/** Folder ID */
|
/** Folder ID */
|
||||||
folderId?: any;
|
parentId?: any;
|
||||||
/** If set to true, forcibly upload the file even if there is a file with the same hash. */
|
/** If set to true, forcibly upload the file even if there is a file with the same hash. */
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
/** Do not save file to local */
|
/** Do not save file to local */
|
||||||
|
@ -344,7 +344,7 @@ export async function addFile({
|
||||||
path,
|
path,
|
||||||
name = null,
|
name = null,
|
||||||
comment = null,
|
comment = null,
|
||||||
folderId = null,
|
parentId = null,
|
||||||
force = false,
|
force = false,
|
||||||
isLink = false,
|
isLink = false,
|
||||||
url = null,
|
url = null,
|
||||||
|
@ -392,12 +392,12 @@ export async function addFile({
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
const fetchFolder = async (): Promise<DriveFolder | null> => {
|
const fetchFolder = async (): Promise<DriveFolder | null> => {
|
||||||
if (!folderId) {
|
if (!parentId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const driveFolder = await DriveFolders.findOneBy({
|
const driveFolder = await DriveFolders.findOneBy({
|
||||||
id: folderId,
|
id: parentId,
|
||||||
userId: user ? user.id : IsNull(),
|
userId: user ? user.id : IsNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -429,7 +429,7 @@ export async function addFile({
|
||||||
file.createdAt = new Date();
|
file.createdAt = new Date();
|
||||||
file.userId = user ? user.id : null;
|
file.userId = user ? user.id : null;
|
||||||
file.userHost = user ? user.host : null;
|
file.userHost = user ? user.host : null;
|
||||||
file.folderId = folder?.id ?? null;
|
file.parentId = folder?.id ?? null;
|
||||||
file.comment = comment;
|
file.comment = comment;
|
||||||
file.properties = properties;
|
file.properties = properties;
|
||||||
file.blurhash = info.blurhash || null;
|
file.blurhash = info.blurhash || null;
|
||||||
|
|
|
@ -13,7 +13,7 @@ const logger = driveLogger.createSubLogger('downloader');
|
||||||
type Args = {
|
type Args = {
|
||||||
url: string;
|
url: string;
|
||||||
user: { id: User['id']; host: User['host'] } | null;
|
user: { id: User['id']; host: User['host'] } | null;
|
||||||
folderId?: DriveFolder['id'] | null;
|
parentId?: DriveFolder['id'] | null;
|
||||||
uri?: string | null;
|
uri?: string | null;
|
||||||
sensitive?: boolean;
|
sensitive?: boolean;
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
|
@ -24,7 +24,7 @@ type Args = {
|
||||||
export async function uploadFromUrl({
|
export async function uploadFromUrl({
|
||||||
url,
|
url,
|
||||||
user,
|
user,
|
||||||
folderId = null,
|
parentId = null,
|
||||||
uri = null,
|
uri = null,
|
||||||
sensitive = false,
|
sensitive = false,
|
||||||
force = false,
|
force = false,
|
||||||
|
@ -50,7 +50,7 @@ export async function uploadFromUrl({
|
||||||
// If the comment is same as the name, skip comment
|
// If the comment is same as the name, skip comment
|
||||||
// (image.name is passed in when receiving attachment)
|
// (image.name is passed in when receiving attachment)
|
||||||
comment: name === comment ? null : comment,
|
comment: name === comment ? null : comment,
|
||||||
folderId,
|
parentId,
|
||||||
force,
|
force,
|
||||||
isLink,
|
isLink,
|
||||||
url,
|
url,
|
||||||
|
|
Loading…
Reference in a new issue