- Updated Person interface to include first_name and last_name fields for better clarity and organization handling. - Modified TablePersons.vue to support new fields, including improved pagination and drag-and-drop functionality. - Added loading states and error handling for form controls within the table. - Enhanced the visual layout of the table with responsive design adjustments. - Updated solr.xslt to correctly reference ServerDateModified and EmbargoDate attributes. - updated AvatarController - improved download method for editor, and reviewer - improved security for officlial download file file API: filterd by server_state
90 lines
3.5 KiB
TypeScript
90 lines
3.5 KiB
TypeScript
import type { HttpContext } from '@adonisjs/core/http';
|
|
import File from '#models/file';
|
|
import { StatusCodes } from 'http-status-codes';
|
|
import * as fs from 'fs';
|
|
import { DateTime } from 'luxon';
|
|
|
|
// node ace make:controller Author
|
|
export default class FileController {
|
|
// @Get("download/:id")
|
|
public async findOne({ response, params }: HttpContext) {
|
|
const id = params.id;
|
|
// const file = await File.findOrFail(id);
|
|
// Load file with its related dataset to check embargo
|
|
const file = await File.query()
|
|
.where('id', id)
|
|
.preload('dataset') // or 'dataset' - whatever your relationship is named
|
|
.firstOrFail();
|
|
|
|
if (!file) {
|
|
return response.status(StatusCodes.NOT_FOUND).send({
|
|
message: `Cannot find File with id=${id}.`,
|
|
});
|
|
}
|
|
|
|
const dataset = file.dataset;
|
|
// Files from unpublished datasets are now blocked
|
|
if (dataset.server_state !== 'published') {
|
|
return response.status(StatusCodes.FORBIDDEN).send({
|
|
message: `File access denied: Dataset is not published.`,
|
|
});
|
|
}
|
|
if (dataset && this.isUnderEmbargo(dataset.embargo_date)) {
|
|
return response.status(StatusCodes.FORBIDDEN).send({
|
|
message: `File is under embargo until ${dataset.embargo_date?.toFormat('yyyy-MM-dd')}`,
|
|
});
|
|
}
|
|
|
|
// Proceed with file download
|
|
const filePath = '/storage/app/data/' + file.pathName;
|
|
const fileExt = file.filePath.split('.').pop() || '';
|
|
// const fileName = file.label + fileExt;
|
|
const fileName = file.label.toLowerCase().endsWith(`.${fileExt.toLowerCase()}`)
|
|
? file.label
|
|
: `${file.label}.${fileExt}`;
|
|
|
|
try {
|
|
fs.accessSync(filePath, fs.constants.R_OK); //| fs.constants.W_OK);
|
|
// console.log("can read/write:", filePath);
|
|
|
|
response
|
|
.header('Cache-Control', 'no-cache private')
|
|
.header('Content-Description', 'File Transfer')
|
|
.header('Content-Type', file.mimeType)
|
|
.header('Content-Disposition', 'inline; filename=' + fileName)
|
|
.header('Content-Transfer-Encoding', 'binary')
|
|
.header('Access-Control-Allow-Origin', '*')
|
|
.header('Access-Control-Allow-Methods', 'GET');
|
|
|
|
response.status(StatusCodes.OK).download(filePath);
|
|
} catch (err) {
|
|
// console.log("no access:", path);
|
|
response.status(StatusCodes.NOT_FOUND).send({
|
|
message: `File with id ${id} doesn't exist on file server`,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if the dataset is under embargo
|
|
* Compares only dates (ignoring time) for embargo check
|
|
* @param embargoDate - The embargo date from dataset
|
|
* @returns true if under embargo, false if embargo has passed or no embargo set
|
|
*/
|
|
private isUnderEmbargo(embargoDate: DateTime | null): boolean {
|
|
// No embargo date set - allow download
|
|
if (!embargoDate) {
|
|
return false;
|
|
}
|
|
|
|
// Get current date at start of day (00:00:00)
|
|
const today = DateTime.now().startOf('day');
|
|
|
|
// Get embargo date at start of day (00:00:00)
|
|
const embargoDateOnly = embargoDate.startOf('day');
|
|
|
|
// File is under embargo if embargo date is after today
|
|
// This means the embargo lifts at the start of the embargo date
|
|
return embargoDateOnly >= today;
|
|
}
|
|
}
|