Arno Kaimbacher
f67b736a88
Some checks failed
CI Pipeline / japa-tests (push) Failing after 1m0s
- Added preloads 'allowed_extensions_mimetypes' and 'dependent_array_min_length' in adonisrc.ts - Updated @symfony/webpack-encore from ^4.6.1 to ^5.0.1 - AdminuserController: Implemented pagination for 10 records in index method - Enabled reviewers to reject datasets to editors with email notifications (DatasetController.ts) - Submitter DatasetController: Files now loaded in ascending order (sort_order) in edit mode - file.ts: Removed serialization of fileData due to browser issues - Modified FileUpload.vue to mark already uploaded files as deleted - Improved keyword search in SearchCategoryAutocomplete.vue - Started development on Category.vue for submitters to categorize DDC - Added new route /dataset/categorize in routes.ts - Introduced 2 new rules in start/rules: allowed_extensions_mimetypes.ts and dependent_array_min_length.ts - Performed npm updates
185 lines
5.3 KiB
TypeScript
185 lines
5.3 KiB
TypeScript
import { DateTime } from 'luxon';
|
|
import { column, hasMany, belongsTo, SnakeCaseNamingStrategy, computed } from '@adonisjs/lucid/orm';
|
|
import HashValue from './hash_value.js';
|
|
import Dataset from './dataset.js';
|
|
import BaseModel from './base_model.js';
|
|
// import { Buffer } from 'buffer';
|
|
import * as fs from 'fs';
|
|
import crypto from 'crypto';
|
|
// import Drive from '@ioc:Adonis/Core/Drive';
|
|
// import Drive from '@adonisjs/drive';
|
|
import drive from '#services/drive';
|
|
|
|
import type { HasMany } from "@adonisjs/lucid/types/relations";
|
|
import type { BelongsTo } from "@adonisjs/lucid/types/relations";
|
|
// import { TransactionClientContract } from "@adonisjs/lucid/database";
|
|
import { TransactionClientContract } from '@adonisjs/lucid/types/database';
|
|
|
|
|
|
|
|
|
|
|
|
export default class File extends BaseModel {
|
|
// private readonly _data: Uint8Array;
|
|
// private readonly _type: string;
|
|
// private readonly _size: number;
|
|
|
|
public static namingStrategy = new SnakeCaseNamingStrategy();
|
|
public static primaryKey = 'id';
|
|
public static table = 'document_files';
|
|
public static selfAssignPrimaryKey = false;
|
|
|
|
@column({
|
|
isPrimary: true,
|
|
})
|
|
public id: number;
|
|
|
|
@column({})
|
|
public document_id: number;
|
|
|
|
@column({})
|
|
public pathName: string;
|
|
|
|
@column()
|
|
public label: string;
|
|
|
|
@column()
|
|
public comment: string;
|
|
|
|
@column()
|
|
public mimeType: string;
|
|
|
|
@column()
|
|
public language: string;
|
|
|
|
@column()
|
|
public fileSize: number;
|
|
|
|
@column()
|
|
public visibleInOai: boolean;
|
|
|
|
@column()
|
|
public visibleInFrontdoor: boolean;
|
|
|
|
@column()
|
|
public sortOrder: number;
|
|
|
|
@column.dateTime({ autoCreate: true })
|
|
public createdAt: DateTime;
|
|
|
|
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
|
public updatedAt: DateTime;
|
|
|
|
// public function dataset()
|
|
// {
|
|
// return $this->belongsTo(Dataset::class, 'document_id', 'id');
|
|
// }
|
|
@belongsTo(() => Dataset, {
|
|
foreignKey: 'document_id',
|
|
})
|
|
public dataset: BelongsTo<typeof Dataset>;
|
|
|
|
@hasMany(() => HashValue, {
|
|
foreignKey: 'file_id',
|
|
})
|
|
public hashvalues: HasMany<typeof HashValue>;
|
|
|
|
@computed({
|
|
serializeAs: 'filePath',
|
|
})
|
|
public get filePath() {
|
|
return `/storage/app/public/${this.pathName}`;
|
|
// const mainTitle = this.titles?.find((title) => title.type === 'Main');
|
|
// return mainTitle ? mainTitle.value : null;
|
|
}
|
|
|
|
@computed({
|
|
serializeAs: 'size',
|
|
})
|
|
public get size() {
|
|
return this.fileSize;
|
|
}
|
|
|
|
@computed({
|
|
serializeAs: 'type',
|
|
})
|
|
public get type() {
|
|
return this.mimeType;
|
|
}
|
|
|
|
@computed({
|
|
serializeAs: 'name',
|
|
})
|
|
get name(): string {
|
|
return this.label;
|
|
}
|
|
|
|
@computed({
|
|
serializeAs: 'lastModified',
|
|
})
|
|
get lastModified(): number {
|
|
return this.updatedAt.toUnixInteger(); //.toFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
|
}
|
|
|
|
readonly webkitRelativePath: string = '';
|
|
|
|
// @computed({
|
|
// serializeAs: 'fileData',
|
|
// })
|
|
// public get fileData(): string {
|
|
// try {
|
|
// const fileContent: Buffer = fs.readFileSync(this.filePath);
|
|
// // Create a Blob from the file content
|
|
// // const blob = new Blob([fileContent], { type: this.type }); // Adjust
|
|
// // let fileSrc = URL.createObjectURL(blob);
|
|
// // return fileSrc;
|
|
|
|
// // create a JSON string that contains the data in the property "blob"
|
|
// const json = JSON.stringify({ blob: fileContent.toString('base64') });
|
|
// return json;
|
|
// } catch (err) {
|
|
// // console.error(`Error reading file: ${err}`);
|
|
// return '';
|
|
// }
|
|
// }
|
|
|
|
public async createHashValues(trx?: TransactionClientContract) {
|
|
const hashtypes: string[] = ['md5', 'sha512'];
|
|
|
|
for (const type of hashtypes) {
|
|
const hash = new HashValue();
|
|
hash.type = type;
|
|
const hashString = await this._checksumFile(this.filePath, type); // Assuming getRealHash is a method in the same model
|
|
hash.value = hashString;
|
|
|
|
// https://github.com/adonisjs/core/discussions/1872#discussioncomment-132289
|
|
const file: File = this;
|
|
if (trx) {
|
|
await file.useTransaction(trx).related('hashvalues').save(hash); // Save the hash value to the database
|
|
} else {
|
|
await file.related('hashvalues').save(hash); // Save the hash value to the database
|
|
}
|
|
}
|
|
}
|
|
|
|
public async delete() {
|
|
if (this.pathName) {
|
|
// Delete file from additional storage
|
|
await drive.delete(this.pathName);
|
|
}
|
|
|
|
// Call the original delete method of the BaseModel to remove the record from the database
|
|
await super.delete();
|
|
}
|
|
|
|
private async _checksumFile(path: string, hashName = 'md5'): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
const hash = crypto.createHash(hashName);
|
|
const stream = fs.createReadStream(path);
|
|
stream.on('error', (err) => reject(err));
|
|
stream.on('data', (chunk) => hash.update(chunk));
|
|
stream.on('end', () => resolve(hash.digest('hex')));
|
|
});
|
|
}
|
|
}
|