tethys.backend/app/Controllers/Http/Reviewer/DatasetController.ts
Arno Kaimbacher ebc62d9117 - added api UserController.ts for 2FA
- added PersonalTotpSettings.vue vor enablin/disabling 2FA
- changed User.ts: added attributes: state, twoFactorSecret and twoFactorRecoveryCodes
- added resources/js/utils/toast.ts for notifications
- modified start/routes/api.ts
- npm updates
2024-01-19 15:33:46 +01:00

268 lines
11 KiB
TypeScript

import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import User from 'App/Models/User';
import Dataset from 'App/Models/Dataset';
import type { ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm';
import Field from 'App/Library/Field';
import BaseModel from 'App/Models/BaseModel';
import { DateTime } from 'luxon';
import { schema, rules } from '@ioc:Adonis/Core/Validator';
export default class DatasetsController {
public async index({ auth, request, inertia }: HttpContextContract) {
const user = (await User.find(auth.user?.id)) as User;
const page = request.input('page', 1);
let datasets: ModelQueryBuilderContract<typeof Dataset, Dataset> = Dataset.query();
// if (request.input('search')) {
// // users = users.whereRaw('name like %?%', [request.input('search')])
// const searchTerm = request.input('search');
// datasets.where('name', 'ilike', `%${searchTerm}%`);
// }
if (request.input('sort')) {
type SortOrder = 'asc' | 'desc' | undefined;
let attribute = request.input('sort');
let sortOrder: SortOrder = 'asc';
if (attribute.substr(0, 1) === '-') {
sortOrder = 'desc';
// attribute = substr(attribute, 1);
attribute = attribute.substr(1);
}
datasets.orderBy(attribute, sortOrder);
} else {
// users.orderBy('created_at', 'desc');
datasets.orderBy('id', 'asc');
}
// const users = await User.query().orderBy('login').paginate(page, limit);
const myDatasets = await datasets
.where('server_state', 'approved')
.where('reviewer_id', user.id)
.preload('titles')
.preload('user', (query) => query.select('id', 'login'))
.preload('editor', (query) => query.select('id', 'login'))
.paginate(page, 10);
return inertia.render('Reviewer/Dataset/Index', {
datasets: myDatasets.serialize(),
filters: request.all(),
can: {
review: await auth.user?.can(['dataset-review']),
reject: await auth.user?.can(['dataset-review-reject']),
},
});
}
public async review({ request, inertia, response }: HttpContextContract) {
const id = request.param('id');
const dataset = await Dataset.query()
.where('id', id)
// .preload('titles')
// .preload('descriptions')
.preload('user', (builder) => {
builder.select('id', 'login');
})
.firstOrFail();
const validStates = ['approved'];
if (!validStates.includes(dataset.server_state)) {
// session.flash('errors', 'Invalid server state!');
return response
.flash(
'warning',
`Invalid server state. Dataset with id ${id} cannot be reviewed. Datset has server state ${dataset.server_state}.`,
)
.redirect()
.toRoute('reviewer.dataset.list');
}
const fieldnames: Array<string> = await dataset.describe();
const fields = {};
for (const fieldName of fieldnames) {
const field: Field = dataset.getField(fieldName) as Field;
const modelClass = field.getValueModelClass();
let fieldValues = field.getValue();
let value = '';
if (fieldValues === null || fieldValues == undefined) {
continue;
}
if (modelClass === null) {
if (typeof fieldValues === 'number') {
// If the field values are a number, use them as is
value = fieldValues.toString();
} else {
// If the field values are not a number, use the replace() function to remove non-printable characters
value = fieldValues.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '\xEF\xBF\xBD ');
}
} else {
if (!Array.isArray(fieldValues)) {
fieldValues = [fieldValues];
}
for (const fieldValue of fieldValues) {
if (fieldValue === null) {
continue;
}
if (modelClass.prototype instanceof BaseModel) {
// this.mapModelAttributes(fieldValue, childNode);
value = '<ul>';
Object.keys(fieldValue).forEach((prop) => {
let modelValue = fieldValue[prop];
// console.log(`${prop}: ${value}`);
if (modelValue != null) {
if (modelValue instanceof DateTime) {
modelValue = modelValue.toFormat('yyyy-MM-dd HH:mm:ss').trim();
} else {
modelValue = modelValue.toString().trim();
}
// Replace invalid XML-1.0-Characters by UTF-8 replacement character.
modelValue = modelValue.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '\xEF\xBF\xBD ');
value = value + '<li>' + prop + ' : ' + modelValue + '</li>';
}
});
value = value + '</ul>';
} else if (modelClass instanceof DateTime) {
// console.log('Value is a luxon date');
// this.mapDateAttributes(fieldValue, childNode);
value = value + ' Year ' + modelClass.year.toString();
value = value + ' Month ' + modelClass.month.toString();
value = value + ' Day ' + modelClass.day.toString();
value = value + ' Hour ' + modelClass.hour.toString();
value = value + ' Minute ' + modelClass.minute.toString();
value = value + ' Second ' + modelClass.second.toString();
value = value + ' UnixTimestamp ' + modelClass.toUnixInteger().toString();
let zoneName = modelClass.zoneName ? modelClass.zoneName : '';
value = value + ' Timezone ' + zoneName;
}
}
}
if (value != '') {
fields[fieldName] = value;
}
}
return inertia.render('Reviewer/Dataset/Review', {
dataset,
fields: fields,
});
}
public async reviewUpdate({ request, response }) {
const id = request.param('id');
// const { id } = params;
const dataset = await Dataset.findOrFail(id);
const validStates = ['approved'];
if (!validStates.includes(dataset.server_state)) {
// throw new Error('Invalid server state!');
// return response.flash('warning', 'Invalid server state. Dataset cannot be released to editor').redirect().back();
return response
.flash(
'warning',
`Invalid server state. Dataset with id ${id} cannot be reviewed. Datset has server state ${dataset.server_state}.`,
)
.redirect()
.toRoute('reviewer.dataset.list');
}
dataset.server_state = 'reviewed';
try {
// await dataset.related('editor').associate(user); // speichert schon ab
await dataset.save();
return response.toRoute('reviewer.dataset.list').flash('message', `You have successfully reviewed dataset ${dataset.id}!`);
} catch (error) {
// Handle any errors
console.error(error);
return response.status(500).json({ error: 'An error occurred while reviewing the data.' });
}
}
public async reject({ request, inertia, response }: HttpContextContract) {
const id = request.param('id');
const dataset = await Dataset.query()
.where('id', id)
// .preload('titles')
// .preload('descriptions')
.preload('user', (builder) => {
builder.select('id', 'login');
})
.firstOrFail();
const validStates = ['approved'];
if (!validStates.includes(dataset.server_state)) {
// session.flash('errors', 'Invalid server state!');
return response
.flash(
'warning',
`Invalid server state. Dataset with id ${id} cannot be rejected. Datset has server state ${dataset.server_state}.`,
)
.redirect()
.toRoute('reviewer.dataset.list');
}
return inertia.render('Reviewer/Dataset/Reject', {
dataset,
});
}
public async rejectUpdate({ request, response }) {
const id = request.param('id');
const dataset = await Dataset.query()
.where('id', id)
.preload('editor', (builder) => {
builder.select('id', 'login');
})
.firstOrFail();
const newSchema = schema.create({
server_state: schema.string({ trim: true }),
reject_reviewer_note: schema.string({ trim: true }, [rules.minLength(10), rules.maxLength(500)]),
});
try {
await request.validate({ schema: newSchema });
} catch (error) {
// return response.badRequest(error.messages);
throw error;
}
const validStates = ['approved'];
if (!validStates.includes(dataset.server_state)) {
// throw new Error('Invalid server state!');
// return response.flash('warning', 'Invalid server state. Dataset cannot be released to editor').redirect().back();
return response
.flash(
'warning',
`Invalid server state. Dataset with id ${id} cannot be rejected. Datset has server state ${dataset.server_state}.`,
)
.redirect()
.toRoute('reviewer.dataset.list');
}
// dataset.server_state = 'reviewed';
dataset.server_state = 'rejected_reviewer';
const rejectReviewerNote = request.input('reject_reviewer_note', '');
dataset.reject_reviewer_note = rejectReviewerNote;
try {
// await dataset.related('editor').associate(user); // speichert schon ab
await dataset.save();
return response
.toRoute('reviewer.dataset.list')
.flash('message', `You have rejected dataset ${dataset.id}! to editor ${dataset.editor.login}`);
} catch (error) {
// Handle any errors
console.error(error);
return response.status(500).json({ error: 'An error occurred while reviewing the data.' });
}
}
}