- additional functionality for DatasetController.ts

- additional validation rules like 'uniqueArray'
- additional Lucid models like BaseModel.ts for filling attributes, Title.ts, Description.ts
- npm updates for @adonisjs/core
This commit is contained in:
Kaimbacher 2023-06-22 17:20:04 +02:00
parent c4f4eff0d9
commit e0ff71b117
44 changed files with 2002 additions and 1556 deletions

View File

@ -1,17 +1,17 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
export default class HomeController { export default class HomeController {
public async index({}: HttpContextContract) {} public async index({}: HttpContextContract) {}
public async create({}: HttpContextContract) {} public async create({}: HttpContextContract) {}
public async store({}: HttpContextContract) {} public async store({}: HttpContextContract) {}
public async show({}: HttpContextContract) {} public async show({}: HttpContextContract) {}
public async edit({}: HttpContextContract) {} public async edit({}: HttpContextContract) {}
public async update({}: HttpContextContract) {} public async update({}: HttpContextContract) {}
public async destroy({}: HttpContextContract) {} public async destroy({}: HttpContextContract) {}
} }

View File

@ -8,197 +8,207 @@ import { RenderResponse } from '@ioc:EidelLev/Inertia';
// import { schema, rules } from '@ioc:Adonis/Core/Validator'; // import { schema, rules } from '@ioc:Adonis/Core/Validator';
export default class UsersController { export default class UsersController {
public async index({ auth, request, inertia }: HttpContextContract) { public async index({ auth, request, inertia }: HttpContextContract) {
const page = request.input('page', 1); const page = request.input('page', 1);
// const limit = 10 // const limit = 10
let users: ModelQueryBuilderContract<typeof User, User> = User.query(); let users: ModelQueryBuilderContract<typeof User, User> = User.query();
if (request.input('search')) { if (request.input('search')) {
// users = users.whereRaw('name like %?%', [request.input('search')]) // users = users.whereRaw('name like %?%', [request.input('search')])
const searchTerm = request.input('search'); const searchTerm = request.input('search');
users.where('login', 'ilike', `%${searchTerm}%`); users.where('login', 'ilike', `%${searchTerm}%`);
} }
if (request.input('sort')) { if (request.input('sort')) {
type SortOrder = 'asc' | 'desc' | undefined; type SortOrder = 'asc' | 'desc' | undefined;
let attribute = request.input('sort'); let attribute = request.input('sort');
let sort_order: SortOrder = 'asc'; let sort_order: SortOrder = 'asc';
// if (strncmp($attribute, '-', 1) === 0) { // if (strncmp($attribute, '-', 1) === 0) {
if (attribute.substr(0, 1) == '-') { if (attribute.substr(0, 1) == '-') {
sort_order = 'desc'; sort_order = 'desc';
// attribute = substr(attribute, 1); // attribute = substr(attribute, 1);
attribute = attribute.substr(1); attribute = attribute.substr(1);
} }
// $users->orderBy($attribute, $sort_order); // $users->orderBy($attribute, $sort_order);
users.orderBy(attribute, sort_order); users.orderBy(attribute, sort_order);
} else { } else {
// users.orderBy('created_at', 'desc'); // users.orderBy('created_at', 'desc');
users.orderBy('id', 'asc'); users.orderBy('id', 'asc');
} }
// const users = await User.query().orderBy('login').paginate(page, limit); // const users = await User.query().orderBy('login').paginate(page, limit);
let usersResult = await users // User.query() let usersResult = await users // User.query()
// .orderBy('login') // .orderBy('login')
// .filter(qs) // .filter(qs)
// .preload('focusInterests') // .preload('focusInterests')
// .preload('role') // .preload('role')
.paginate(page, 5); .paginate(page, 5);
// var test = request.all(); // var test = request.all();
return inertia.render('Admin/User/Index', { return inertia.render('Admin/User/Index', {
// testing: 'this is a test', // testing: 'this is a test',
users: usersResult.toJSON(), users: usersResult.toJSON(),
filters: request.all(), filters: request.all(),
can: { can: {
create: await auth.user?.can(['user-create']), create: await auth.user?.can(['user-create']),
edit: await auth.user?.can(['user-edit']), edit: await auth.user?.can(['user-edit']),
delete: await auth.user?.can(['user-delete']), delete: await auth.user?.can(['user-delete']),
}, },
}); });
} }
public async create({ inertia }: HttpContextContract) { public async create({ inertia }: HttpContextContract) {
// let rolesPluck = {}; // let rolesPluck = {};
// (await Role.query().select('id', 'name')).forEach((user) => { // (await Role.query().select('id', 'name')).forEach((user) => {
// rolesPluck[user.id] = user.name; // rolesPluck[user.id] = user.name;
// }); // });
const roles = await Role.query().select('id', 'name').pluck('name', 'id'); const roles = await Role.query().select('id', 'name').pluck('name', 'id');
return inertia.render('Admin/User/Create', { return inertia.render('Admin/User/Create', {
roles: roles, roles: roles,
}); });
} }
public async store({ request, response, session }: HttpContextContract) { public async store({ request, response, session }: HttpContextContract) {
// node ace make:validator CreateUser // node ace make:validator CreateUser
try { try {
// Step 2 - Validate request body against the schema // Step 2 - Validate request body against the schema
await request.validate(CreateUserValidator); await request.validate(CreateUserValidator);
// console.log({ payload }); // console.log({ payload });
} catch (error) { } catch (error) {
// Step 3 - Handle errors // Step 3 - Handle errors
// return response.badRequest(error.messages); // return response.badRequest(error.messages);
throw error; throw error;
} }
const input = request.only(['login', 'email', 'password']); const input = request.only(['login', 'email', 'password']);
const user = await User.create(input); const user = await User.create(input);
if (request.input('roles')) { if (request.input('roles')) {
const roles: Array<number> = request.input('roles'); const roles: Array<number> = request.input('roles');
await user.related('roles').attach(roles); await user.related('roles').attach(roles);
} }
session.flash('message', 'User has been created successfully'); session.flash('message', 'User has been created successfully');
return response.redirect().toRoute('user.index'); return response.redirect().toRoute('user.index');
} }
public async show({ request, inertia }: HttpContextContract) { public async show({ request, inertia }: HttpContextContract) {
const id = request.param('id'); const id = request.param('id');
const user = await User.query().where('id', id).firstOrFail(); const user = await User.query().where('id', id).firstOrFail();
const roles = await Role.query().pluck('name', 'id'); const roles = await Role.query().pluck('name', 'id');
// const userHasRoles = user.roles; // const userHasRoles = user.roles;
const userRoles = await user.related('roles').query().orderBy('name').pluck('id'); const userRoles = await user.related('roles').query().orderBy('name').pluck('id');
return inertia.render('Admin/User/Show', { return inertia.render('Admin/User/Show', {
roles: roles, roles: roles,
user: user, user: user,
userHasRoles: userRoles, userHasRoles: userRoles,
}); });
} }
public async edit({ request, inertia }: HttpContextContract) { public async edit({ request, inertia }: HttpContextContract) {
const id = request.param('id'); const id = request.param('id');
const user = await User.query().where('id', id).firstOrFail(); const user = await User.query().where('id', id).firstOrFail();
const roles = await Role.query().pluck('name', 'id'); const roles = await Role.query().pluck('name', 'id');
// const userHasRoles = user.roles; // const userHasRoles = user.roles;
const userHasRoles = await user.related('roles').query().orderBy('name').pluck('id'); const userHasRoles = await user.related('roles').query().orderBy('name').pluck('id');
// let test = Object.keys(userHasRoles).map((key) => userHasRoles[key]); // let test = Object.keys(userHasRoles).map((key) => userHasRoles[key]);
return inertia.render('Admin/User/Edit', { return inertia.render('Admin/User/Edit', {
roles: roles, roles: roles,
user: user, user: user,
userHasRoles: Object.keys(userHasRoles).map((key) => userHasRoles[key]), //convert object to array with role ids userHasRoles: Object.keys(userHasRoles).map((key) => userHasRoles[key]), //convert object to array with role ids
}); });
} }
public async update({ request, response, session }: HttpContextContract) { public async update({ request, response, session }: HttpContextContract) {
// node ace make:validator UpdateUser // node ace make:validator UpdateUser
const id = request.param('id'); const id = request.param('id');
const user = await User.query().where('id', id).firstOrFail(); const user = await User.query().where('id', id).firstOrFail();
// validate update form // validate update form
await request.validate(UpdateUserValidator); await request.validate(UpdateUserValidator);
// password is optional // password is optional
let input; let input;
if (request.input('password')) { if (request.input('password')) {
input = request.only(['login', 'email', 'password']); input = request.only(['login', 'email', 'password']);
} else { } else {
input = request.only(['login', 'email']); input = request.only(['login', 'email']);
} }
await user.merge(input).save(); await user.merge(input).save();
// await user.save(); // await user.save();
if (request.input('roles')) { if (request.input('roles')) {
const roles: Array<number> = request.input('roles'); const roles: Array<number> = request.input('roles');
await user.related('roles').sync(roles); await user.related('roles').sync(roles);
} }
session.flash('message', 'User has been updated successfully'); session.flash('message', 'User has been updated successfully');
return response.redirect().toRoute('user.index'); return response.redirect().toRoute('user.index');
} }
public async destroy({ request, response, session }: HttpContextContract) { public async destroy({ request, response, session }: HttpContextContract) {
const id = request.param('id'); const id = request.param('id');
const user = await User.findOrFail(id); const user = await User.findOrFail(id);
await user.delete(); await user.delete();
session.flash('message', `User ${user.login} has been deleted.`); session.flash('message', `User ${user.login} has been deleted.`);
return response.redirect().toRoute('user.index'); return response.redirect().toRoute('user.index');
} }
/** /**
* Show the user a form to change their personal information & password. * Show the user a form to change their personal information & password.
* *
* @return \Inertia\Response * @return \Inertia\Response
*/ */
public accountInfo({ inertia, auth }: HttpContextContract): RenderResponse { public accountInfo({ inertia, auth }: HttpContextContract): RenderResponse {
const user = auth.user; const user = auth.user;
// const id = request.param('id'); // const id = request.param('id');
// const user = await User.query().where('id', id).firstOrFail(); // const user = await User.query().where('id', id).firstOrFail();
return inertia.render('Admin/User/AccountInfo', { return inertia.render('Admin/User/AccountInfo', {
user: user, user: user,
}); });
} }
/** /**
* Save the modified personal information for a user. * Save the modified personal information for a user.
* *
* @param HttpContextContract ctx * @param HttpContextContract ctx
* @return : RedirectContract * @return : RedirectContract
*/ */
public async accountInfoStore({ request, response, auth, session }: HttpContextContract) { public async accountInfoStore({ request, response, auth, session }: HttpContextContract) {
// validate update form // validate update form
await request.validate(UpdateUserValidator); await request.validate(UpdateUserValidator);
const payload = request.only(['login', 'email']); const payload = request.only(['login', 'email']);
auth.user?.merge(payload); auth.user?.merge(payload);
const user = await auth.user?.save(); const user = await auth.user?.save();
// $user = \Auth::user()->update($request->except(['_token'])); // $user = \Auth::user()->update($request->except(['_token']));
let message; let message;
if (user) { if (user) {
message = 'Account updated successfully.'; message = 'Account updated successfully.';
} else { } else {
message = 'Error while saving. Please try again.'; message = 'Error while saving. Please try again.';
} }
session.flash(message); session.flash(message);
return response.redirect().toRoute('admin.account.info'); return response.redirect().toRoute('admin.account.info');
//->with('message', __($message)); //->with('message', __($message));
} }
// private async syncRoles(userId: number, roleIds: Array<number>) {
// const user = await User.findOrFail(userId)
// // const roles: Role[] = await Role.query().whereIn('id', roleIds);
// // await user.roles().sync(roles.rows.map(role => role.id))
// await user.related("roles").sync(roleIds);
// return user
// }
} }

View File

@ -25,10 +25,8 @@ export default class AuthorsController {
if (request.input('filter')) { if (request.input('filter')) {
// users = users.whereRaw('name like %?%', [request.input('search')]) // users = users.whereRaw('name like %?%', [request.input('search')])
const searchTerm = request.input('filter'); const searchTerm = request.input('filter');
authors authors.whereILike('first_name', `%${searchTerm}%`).orWhereILike('last_name', `%${searchTerm}%`);
.whereILike('first_name', `%${searchTerm}%`) // .orWhere('email', 'like', `%${searchTerm}%`);
.orWhereILike('last_name', `%${searchTerm}%`);
// .orWhere('email', 'like', `%${searchTerm}%`);
} }
let persons = await authors; let persons = await authors;

View File

@ -4,20 +4,12 @@ import Dataset from 'App/Models/Dataset';
// node ace make:controller Author // node ace make:controller Author
export default class DatasetController { export default class DatasetController {
public async index({}: HttpContextContract) {
// select * from gba.persons
// where exists (select * from gba.documents inner join gba.link_documents_persons on "documents"."id" = "link_documents_persons"."document_id"
// where ("link_documents_persons"."role" = 'author') and ("persons"."id" = "link_documents_persons"."person_id"));
const datasets = await Dataset.query().where('server_state', 'published').orWhere('server_state', 'deleted');
public async index({}: HttpContextContract) { return datasets;
// select * from gba.persons }
// where exists (select * from gba.documents inner join gba.link_documents_persons on "documents"."id" = "link_documents_persons"."document_id"
// where ("link_documents_persons"."role" = 'author') and ("persons"."id" = "link_documents_persons"."person_id"));
const datasets = await Dataset
.query()
.where('server_state', 'published')
.orWhere('server_state', 'deleted');
return datasets;
}
} }

View File

@ -5,38 +5,36 @@ import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import AuthValidator from 'App/Validators/AuthValidator'; import AuthValidator from 'App/Validators/AuthValidator';
export default class AuthController { export default class AuthController {
// login function // login function
public async login({ request, response, auth, session }: HttpContextContract) { public async login({ request, response, auth, session }: HttpContextContract) {
// console.log({ // console.log({
// registerBody: request.body(), // registerBody: request.body(),
// }); // });
await request.validate(AuthValidator); await request.validate(AuthValidator);
const plainPassword = await request.input('password'); const plainPassword = await request.input('password');
const email = await request.input('email'); const email = await request.input('email');
// grab uid and password values off request body // grab uid and password values off request body
// const { email, password } = request.only(['email', 'password']) // const { email, password } = request.only(['email', 'password'])
try {
// attempt to login
await auth.use('web').attempt(email, plainPassword);
} catch (error) {
// if login fails, return vague form message and redirect back
session.flash('message', 'Your username, email, or password is incorrect');
return response.redirect().back();
}
// otherwise, redirect todashboard
response.redirect('/dashboard');
}
try { // logout function
// attempt to login public async logout({ auth, response }: HttpContextContract) {
await auth.use("web").attempt(email, plainPassword); // await auth.logout();
} catch (error) { await auth.use('web').logout();
// if login fails, return vague form message and redirect back response.redirect('/app/login');
session.flash('message', 'Your username, email, or password is incorrect') // return response.status(200);
return response.redirect().back() }
}
// otherwise, redirect todashboard
response.redirect('/dashboard');
}
// logout function
public async logout({ auth, response }: HttpContextContract) {
// await auth.logout();
await auth.use('web').logout();
response.redirect('/app/login');
// return response.status(200);
}
} }

View File

@ -1,33 +1,22 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
// import User from 'App/Models/User'; import User from 'App/Models/User';
import Dataset from 'App/Models/Dataset';
// import Role from 'App/Models/Role'; // import Role from 'App/Models/Role';
// import Database from '@ioc:Adonis/Lucid/Database'; // import Database from '@ioc:Adonis/Lucid/Database';
import License from 'App/Models/License'; import License from 'App/Models/License';
import Project from 'App/Models/Project'; import Project from 'App/Models/Project';
// import type { ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm'; import Title from 'App/Models/Title';
import Description from 'App/Models/Description';
// import CreateUserValidator from 'App/Validators/CreateUserValidator'; // import CreateUserValidator from 'App/Validators/CreateUserValidator';
// import UpdateUserValidator from 'App/Validators/UpdateUserValidator'; // import UpdateUserValidator from 'App/Validators/UpdateUserValidator';
// import { RenderResponse } from '@ioc:EidelLev/Inertia';
import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator'; import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
// import Application from '@ioc:Adonis/Core/Application'; import Person from 'App/Models/Person';
import Database from '@ioc:Adonis/Lucid/Database';
enum TitleTypes { import { TransactionClientContract } from '@ioc:Adonis/Lucid/Database';
Main = 'Main', import Subject from 'App/Models/Subject';
Sub = 'Sub', import CreateDatasetValidator from 'App/Validators/CreateDatasetValidator';
Alternative = 'Alternative', import { TitleTypes, DescriptionTypes } from 'Contracts/enums';
Translated = 'Translated',
Other = 'Other',
}
enum DescriptionTypes {
Abstract = 'Abstract',
Methods = 'Methods',
Series_information = 'Series_information',
Technical_info = 'Technical_info',
Translated = 'Translated',
Other = 'Other',
}
export default class DatasetController { export default class DatasetController {
public async create({ inertia }: HttpContextContract) { public async create({ inertia }: HttpContextContract) {
@ -190,7 +179,7 @@ export default class DatasetController {
depth_min: schema.number.optional([rules.requiredIfExists('depth_max')]), depth_min: schema.number.optional([rules.requiredIfExists('depth_max')]),
depth_max: schema.number.optional([rules.requiredIfExists('depth_min')]), depth_max: schema.number.optional([rules.requiredIfExists('depth_min')]),
}), }),
subjects: schema.array([rules.minLength(3)]).members( subjects: schema.array([rules.minLength(3), rules.uniqueArray('value')]).members(
schema.object().members({ schema.object().members({
value: schema.string({ trim: true }, [ value: schema.string({ trim: true }, [
rules.minLength(3), rules.minLength(3),
@ -214,98 +203,161 @@ export default class DatasetController {
} }
return response.redirect().back(); return response.redirect().back();
} }
public async store({ request, response, session }: HttpContextContract) { public async store({ auth, request, response, session }: HttpContextContract) {
const newDatasetSchema = schema.create({ // node ace make:validator CreateDataset
// first step
language: schema.string({ trim: true }, [
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
]),
licenses: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one license for the new dataset
rights: schema.string([rules.equalTo('true')]),
// second step
type: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
creating_corporation: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
titles: schema.array([rules.minLength(1)]).members(
schema.object().members({
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
type: schema.enum(Object.values(TitleTypes)),
language: schema.string({ trim: true }, [
rules.minLength(2),
rules.maxLength(255),
rules.translatedLanguage('/language', 'type'),
]),
}),
),
descriptions: schema.array([rules.minLength(1)]).members(
schema.object().members({
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
type: schema.enum(Object.values(DescriptionTypes)),
language: schema.string({ trim: true }, [
rules.minLength(2),
rules.maxLength(255),
rules.translatedLanguage('/language', 'type'),
]),
}),
),
authors: schema.array([rules.minLength(1)]).members(schema.object().members({ email: schema.string({ trim: true }) })),
// third step
project_id: schema.number.optional(),
embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]),
coverage: schema.object().members({
x_min: schema.number(),
x_max: schema.number(),
y_min: schema.number(),
y_max: schema.number(),
elevation_absolut: schema.number.optional(),
elevation_min: schema.number.optional([rules.requiredIfExists('elevation_max')]),
elevation_max: schema.number.optional([rules.requiredIfExists('elevation_min')]),
depth_absolut: schema.number.optional(),
depth_min: schema.number.optional([rules.requiredIfExists('depth_max')]),
depth_max: schema.number.optional([rules.requiredIfExists('depth_min')]),
}),
subjects: schema.array([rules.minLength(3)]).members(
schema.object().members({
value: schema.string({ trim: true }, [
rules.minLength(3),
rules.maxLength(255),
// rules.unique({ table: 'dataset_subjects', column: 'value' }),
]),
// type: schema.enum(Object.values(TitleTypes)),
language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
}),
),
// file: schema.file({
// size: '100mb',
// extnames: ['jpg', 'gif', 'png'],
// }),
files: schema.array([rules.minLength(1)]).members(
schema.file({
size: '100mb',
extnames: ['jpg', 'gif', 'png'],
}),
),
// upload: schema.object().members({
// label: schema.string({ trim: true }, [rules.maxLength(255)]),
// // label: schema.string({ trim: true }, [
// // // rules.minLength(3),
// // // rules.maxLength(255),
// // ]),
// }),
});
// const coverImages = request.file('files');
// node ace make:validator CreateUser
try { try {
// Step 2 - Validate request body against the schema // Step 2 - Validate request body against the schema
// await request.validate(CreateUserValidator); // await request.validate(CreateUserValidator);
await request.validate({ schema: newDatasetSchema, messages: this.messages }); // await request.validate({ schema: newDatasetSchema, messages: this.messages });
await request.validate(CreateDatasetValidator);
// console.log({ payload }); // console.log({ payload });
} catch (error) { } catch (error) {
// Step 3 - Handle errors // Step 3 - Handle errors
// return response.badRequest(error.messages); // return response.badRequest(error.messages);
throw error; throw error;
} }
// const user = new User();
// user.email = 'example@example.com';
// user.password = 'password';
// await user.useTransaction(trx).save();
let trx: TransactionClientContract | null = null;
try {
trx = await Database.transaction();
const user = (await User.find(auth.user?.id)) as User;
// const dataset = await user.related('datasets').create({
// type: request.input('type'),
// creatingCorporation: request.input('creating_corporation'),
// language: request.input('language'),
// });
// Create a new instance of the Dataset model:
const dataset = new Dataset();
dataset.type = request.input('type');
dataset.creatingCorporation = request.input('creating_corporation');
dataset.language = request.input('language');
dataset.embargoDate = request.input('embargo_date');
//await dataset.related('user').associate(user); // speichert schon ab
// Dataset.$getRelation('user').boot();
// Dataset.$getRelation('user').setRelated(dataset, user);
// dataset.$setRelated('user', user);
await user.useTransaction(trx).related('datasets').save(dataset);
//store licenses:
const licenses: number[] = request.input('licenses', []);
dataset.useTransaction(trx).related('licenses').sync(licenses);
const authors = request.input('authors', []);
for (const [key, person] of authors.entries()) {
const pivotData = { role: 'author', sort_order: key + 1 };
if (person.id !== undefined) {
await dataset
.useTransaction(trx)
.related('persons')
.attach({
[person.id]: {
role: pivotData.role,
sort_order: pivotData.sort_order,
allow_email_contact: false,
},
});
} else {
const dataPerson = new Person();
// use overwritten fill method
dataPerson.fill(person);
await dataset.useTransaction(trx).related('persons').save(dataPerson, false, {
role: pivotData.role,
sort_order: pivotData.sort_order,
allow_email_contact: false,
});
}
}
const contributors = request.input('contributors', []);
for (const [key, person] of contributors.entries()) {
const pivotData = { role: 'contributor', sort_order: key + 1 };
if (person.id !== undefined) {
await dataset
.useTransaction(trx)
.related('persons')
.attach({
[person.id]: {
role: pivotData.role,
sort_order: pivotData.sort_order,
allow_email_contact: false,
},
});
} else {
const dataPerson = new Person();
// use overwritten fill method
dataPerson.fill(person);
await dataset.useTransaction(trx).related('persons').save(dataPerson, false, {
role: pivotData.role,
sort_order: pivotData.sort_order,
allow_email_contact: false,
});
}
}
//save main and additional titles
const titles = request.input('titles', []);
for (const titleData of titles) {
const title = new Title();
title.value = titleData.value;
title.language = titleData.language;
title.type = titleData.type;
await dataset.useTransaction(trx).related('titles').save(title);
}
//save abstract and additional descriptions
const descriptions = request.input('descriptions', []);
for (const descriptionData of descriptions) {
// $descriptionReference = new Description($description);
// $dataset->abstracts()->save($descriptionReference);
const description = new Description();
description.value = descriptionData.value;
description.language = descriptionData.language;
description.type = descriptionData.type;
await dataset.useTransaction(trx).related('descriptions').save(description);
}
//save keywords
const keywords = request.input('subjects', []);
for (const keywordData of keywords) {
// $dataKeyword = new Subject($keyword);
// $dataset->subjects()->save($dataKeyword);
const keyword = await Subject.firstOrNew({ value: keywordData.value, type: keywordData.type }, keywordData);
if (keyword.$isNew == true) {
await dataset.useTransaction(trx).related('subjects').save(keyword);
} else {
await dataset.useTransaction(trx).related('subjects').attach([keyword.id]);
}
}
// Dataset.$getRelation('persons').boot();
// Dataset.$getRelation('persons').pushRelated(dataset, person)
// dataset.$pushRelated('persons', person);
await trx.commit();
console.log('Users and posts created successfully');
} catch (error) {
if (trx !== null) {
await trx.rollback();
}
console.error('Failed to create dataset and related models:', error);
// Handle the error and exit the controller code accordingly
// session.flash('message', 'Failed to create dataset and relaed models');
// return response.redirect().back();
throw error;
}
// save data files:
const coverImage = request.files('files')[0]; const coverImage = request.files('files')[0];
if (coverImage) { if (coverImage) {
// clientName: 'Gehaltsschema.png' // clientName: 'Gehaltsschema.png'
@ -326,11 +378,6 @@ export default class DatasetController {
); );
// let path = coverImage.filePath; // let path = coverImage.filePath;
} }
// const user = await User.create(input);
// if (request.input('roles')) {
// const roles: Array<number> = request.input('roles');
// await user.related('roles').attach(roles);
// }
session.flash('message', 'Dataset has been created successfully'); session.flash('message', 'Dataset has been created successfully');
// return response.redirect().toRoute('user.index'); // return response.redirect().toRoute('user.index');
@ -367,6 +414,7 @@ export default class DatasetController {
'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`, 'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,
'subjects.minLength': 'at least {{ options.minLength }} keywords must be defined', 'subjects.minLength': 'at least {{ options.minLength }} keywords must be defined',
'subjects.uniqueArray': 'The {{ options.array }} array must have unique values based on the {{ options.field }} attribute.',
'subjects.*.value.required': 'keyword value is required', 'subjects.*.value.required': 'keyword value is required',
'subjects.*.value.minLength': 'keyword value must be at least {{ options.minLength }} characters long', 'subjects.*.value.minLength': 'keyword value must be at least {{ options.minLength }} characters long',
'subjects.*.type.required': 'keyword type is required', 'subjects.*.type.required': 'keyword type is required',

View File

@ -18,44 +18,44 @@ import Logger from '@ioc:Adonis/Core/Logger';
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'; import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler';
export default class ExceptionHandler extends HttpExceptionHandler { export default class ExceptionHandler extends HttpExceptionHandler {
protected statusPages = { protected statusPages = {
'401,403': 'errors/unauthorized', '401,403': 'errors/unauthorized',
'404': 'errors/not-found', '404': 'errors/not-found',
'500..599': 'errors/server-error', '500..599': 'errors/server-error',
}; };
constructor() { constructor() {
super(Logger); super(Logger);
} }
public async handle(error: any, ctx: HttpContextContract) { public async handle(error: any, ctx: HttpContextContract) {
const { response, request, inertia } = ctx; const { response, request, inertia } = ctx;
/** /**
* Handle failed authentication attempt * Handle failed authentication attempt
*/ */
// if (['E_INVALID_AUTH_PASSWORD', 'E_INVALID_AUTH_UID'].includes(error.code)) { // if (['E_INVALID_AUTH_PASSWORD', 'E_INVALID_AUTH_UID'].includes(error.code)) {
// session.flash('errors', { login: error.message }); // session.flash('errors', { login: error.message });
// return response.redirect('/login'); // return response.redirect('/login');
// } // }
// if ([401].includes(error.status)) { // if ([401].includes(error.status)) {
// session.flash('errors', { login: error.message }); // session.flash('errors', { login: error.message });
// return response.redirect('/dashboard'); // return response.redirect('/dashboard');
// } // }
// https://github.com/inertiajs/inertia-laravel/issues/56 // https://github.com/inertiajs/inertia-laravel/issues/56
if (request.header('X-Inertia') && [500, 503, 404, 403, 401].includes(response.getStatus())) { if (request.header('X-Inertia') && [500, 503, 404, 403, 401].includes(response.getStatus())) {
return inertia.render('Error', { return inertia.render('Error', {
status: response.getStatus(), status: response.getStatus(),
message: error.message message: error.message,
}); });
// ->toResponse($request) // ->toResponse($request)
// ->setStatusCode($response->status()); // ->setStatusCode($response->status());
} }
/** /**
* Forward rest of the exceptions to the parent class * Forward rest of the exceptions to the parent class
*/ */
return super.handle(error, ctx); return super.handle(error, ctx);
} }
} }

View File

@ -1,4 +1,4 @@
import { Exception } from "@adonisjs/core/build/standalone"; import { Exception } from '@adonisjs/core/build/standalone';
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -23,14 +23,14 @@ export default class InvalidCredentialException extends Exception {
* Unable to find user * Unable to find user
*/ */
static invalidUid() { static invalidUid() {
const error = new this("User not found", 400, "E_INVALID_AUTH_UID"); const error = new this('User not found', 400, 'E_INVALID_AUTH_UID');
return error; return error;
} }
/** /**
* Invalid user password * Invalid user password
*/ */
static invalidPassword() { static invalidPassword() {
const error = new this("Password mis-match", 400, "E_INVALID_AUTH_PASSWORD"); const error = new this('Password mis-match', 400, 'E_INVALID_AUTH_PASSWORD');
return error; return error;
} }
@ -41,18 +41,18 @@ export default class InvalidCredentialException extends Exception {
// if (!ctx.session) { // if (!ctx.session) {
// return ctx.response.status(this.status).send(this.responseText); // return ctx.response.status(this.status).send(this.responseText);
// } // }
ctx.session.flashExcept(["_csrf"]); ctx.session.flashExcept(['_csrf']);
ctx.session.flash("auth", { ctx.session.flash('auth', {
error: error, error: error,
/** /**
* Will be removed in the future * Will be removed in the future
*/ */
errors: { errors: {
uid: this.code === "E_INVALID_AUTH_UID" ? ["Invalid login id"] : null, uid: this.code === 'E_INVALID_AUTH_UID' ? ['Invalid login id'] : null,
password: this.code === "E_INVALID_AUTH_PASSWORD" ? ["Invalid password"] : null, password: this.code === 'E_INVALID_AUTH_PASSWORD' ? ['Invalid password'] : null,
}, },
}); });
ctx.response.redirect("back", true); ctx.response.redirect('back', true);
} }
/** /**

View File

@ -1,6 +1,6 @@
import { AuthenticationException } from '@adonisjs/auth/build/standalone' import { AuthenticationException } from '@adonisjs/auth/build/standalone';
import type { GuardsList } from '@ioc:Adonis/Addons/Auth' import type { GuardsList } from '@ioc:Adonis/Addons/Auth';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
/** /**
* Auth middleware is meant to restrict un-authenticated access to a given route * Auth middleware is meant to restrict un-authenticated access to a given route
@ -10,67 +10,58 @@ import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
* of named middleware. * of named middleware.
*/ */
export default class AuthMiddleware { export default class AuthMiddleware {
/**
* The URL to redirect to when request is Unauthorized
*/
protected redirectTo = '/app/login'
/**
* Authenticates the current HTTP request against a custom set of defined
* guards.
*
* The authentication loop stops as soon as the user is authenticated using any
* of the mentioned guards and that guard will be used by the rest of the code
* during the current request.
*/
protected async authenticate(auth: HttpContextContract['auth'], guards: (keyof GuardsList)[]) {
/** /**
* Hold reference to the guard last attempted within the for loop. We pass * The URL to redirect to when request is Unauthorized
* the reference of the guard to the "AuthenticationException", so that
* it can decide the correct response behavior based upon the guard
* driver
*/ */
let guardLastAttempted: string | undefined protected redirectTo = '/app/login';
for (let guard of guards) { /**
guardLastAttempted = guard * Authenticates the current HTTP request against a custom set of defined
* guards.
if (await auth.use(guard).check()) { *
* The authentication loop stops as soon as the user is authenticated using any
* of the mentioned guards and that guard will be used by the rest of the code
* during the current request.
*/
protected async authenticate(auth: HttpContextContract['auth'], guards: (keyof GuardsList)[]) {
/** /**
* Instruct auth to use the given guard as the default guard for * Hold reference to the guard last attempted within the for loop. We pass
* the rest of the request, since the user authenticated * the reference of the guard to the "AuthenticationException", so that
* succeeded here * it can decide the correct response behavior based upon the guard
* driver
*/ */
auth.defaultGuard = guard let guardLastAttempted: string | undefined;
return true
} for (let guard of guards) {
guardLastAttempted = guard;
if (await auth.use(guard).check()) {
/**
* Instruct auth to use the given guard as the default guard for
* the rest of the request, since the user authenticated
* succeeded here
*/
auth.defaultGuard = guard;
return true;
}
}
/**
* Unable to authenticate using any guard
*/
throw new AuthenticationException('Unauthorized access', 'E_UNAUTHORIZED_ACCESS', guardLastAttempted, this.redirectTo);
} }
/** /**
* Unable to authenticate using any guard * Handle request
*/ */
throw new AuthenticationException( public async handle({ auth }: HttpContextContract, next: () => Promise<void>, customGuards: (keyof GuardsList)[]) {
'Unauthorized access', /**
'E_UNAUTHORIZED_ACCESS', * Uses the user defined guards or the default guard mentioned in
guardLastAttempted, * the config file
this.redirectTo, */
) const guards = customGuards.length ? customGuards : [auth.name];
} await this.authenticate(auth, guards);
await next();
/** }
* Handle request
*/
public async handle (
{ auth }: HttpContextContract,
next: () => Promise<void>,
customGuards: (keyof GuardsList)[]
) {
/**
* Uses the user defined guards or the default guard mentioned in
* the config file
*/
const guards = customGuards.length ? customGuards : [auth.name]
await this.authenticate(auth, guards)
await next()
}
} }

View File

@ -15,48 +15,44 @@ const userRoleTable = Config.get('rolePermission.user_role_table', 'link_account
* Should be called after auth middleware * Should be called after auth middleware
*/ */
export default class Can { export default class Can {
/** /**
* Handle request * Handle request
*/ */
public async handle( public async handle({ auth, response }: HttpContextContract, next: () => Promise<void>, permissionNames: string[]) {
{ auth, response }: HttpContextContract, /**
next: () => Promise<void>, * Check if user is logged-in
permissionNames: string[] */
) { let user = await auth.user;
/** if (!user) {
* Check if user is logged-in return response.unauthorized({ error: 'Must be logged in' });
*/ }
let user = await auth.user; let hasPermission = await this.checkHasPermissions(user, permissionNames);
if (!user) { if (!hasPermission) {
return response.unauthorized({ error: 'Must be logged in' }); // return response.unauthorized({
} // error: `Doesn't have required role(s): ${permissionNames.join(',')}`,
let hasPermission = await this.checkHasPermissions(user, permissionNames); // });
if (!hasPermission) { throw new Exception(`Doesn't have required permission(s): ${permissionNames.join(',')}`, 401);
// return response.unauthorized({ }
// error: `Doesn't have required role(s): ${permissionNames.join(',')}`, await next();
// }); }
throw new Exception(`Doesn't have required permission(s): ${permissionNames.join(',')}`, 401);
}
await next();
}
private async checkHasPermissions(user: User, permissionNames: Array<string>): Promise<boolean> { private async checkHasPermissions(user: User, permissionNames: Array<string>): Promise<boolean> {
let rolePlaceHolder = '('; let rolePlaceHolder = '(';
let placeholders = new Array(permissionNames.length).fill('?'); let placeholders = new Array(permissionNames.length).fill('?');
rolePlaceHolder += placeholders.join(','); rolePlaceHolder += placeholders.join(',');
rolePlaceHolder += ')'; rolePlaceHolder += ')';
// let test = user // let test = user
// .related('roles') // .related('roles')
// .query() // .query()
// .count('permissions.name') // .count('permissions.name')
// .innerJoin('gba.role_has_permissions', function () { // .innerJoin('gba.role_has_permissions', function () {
// this.on('gba.role_has_permissions.role_id', 'roles.id'); // this.on('gba.role_has_permissions.role_id', 'roles.id');
// }) // })
// .innerJoin('gba.permissions', function () { // .innerJoin('gba.permissions', function () {
// this.on('role_has_permissions.permission_id', 'permissions.id'); // this.on('role_has_permissions.permission_id', 'permissions.id');
// }) // })
// .andWhereIn('permissions.name', permissionNames); // .andWhereIn('permissions.name', permissionNames);
// select "permissions"."name" // select "permissions"."name"
// from "gba"."roles" // from "gba"."roles"
@ -66,20 +62,27 @@ export default class Can {
// where ("permissions"."name" in ('dataset-list', 'dataset-publish')) // where ("permissions"."name" in ('dataset-list', 'dataset-publish'))
// and ("link_accounts_roles"."account_id" = 1) // and ("link_accounts_roles"."account_id" = 1)
let { let {
rows: { rows: {
0: { permissioncount }, 0: { permissioncount },
}, },
} = await Database.rawQuery( } = await Database.rawQuery(
'SELECT count("p"."name") as permissionCount FROM ' + roleTable + 'SELECT count("p"."name") as permissionCount FROM ' +
' r INNER JOIN ' + userRoleTable + ' ur ON ur.role_id=r.id AND "ur"."account_id"=? ' + roleTable +
' INNER JOIN ' + rolePermissionTable + ' rp ON rp.role_id=r.id ' + ' r INNER JOIN ' +
' INNER JOIN ' + permissionTable + ' p ON rp.permission_id=p.id AND "p"."name" in ' + userRoleTable +
rolePlaceHolder + ' ur ON ur.role_id=r.id AND "ur"."account_id"=? ' +
' LIMIT 1', ' INNER JOIN ' +
[user.id, ...permissionNames] rolePermissionTable +
); ' rp ON rp.role_id=r.id ' +
' INNER JOIN ' +
permissionTable +
' p ON rp.permission_id=p.id AND "p"."name" in ' +
rolePlaceHolder +
' LIMIT 1',
[user.id, ...permissionNames],
);
return permissioncount > 0; return permissioncount > 0;
} }
} }

View File

@ -1,11 +1,11 @@
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import Config from '@ioc:Adonis/Core/Config' import Config from '@ioc:Adonis/Core/Config';
import Database from '@ioc:Adonis/Lucid/Database' import Database from '@ioc:Adonis/Lucid/Database';
import User from 'App/Models/User' import User from 'App/Models/User';
// import { Exception } from '@adonisjs/core/build/standalone' // import { Exception } from '@adonisjs/core/build/standalone'
const roleTable = Config.get('rolePermission.role_table', 'roles') const roleTable = Config.get('rolePermission.role_table', 'roles');
const userRoleTable = Config.get('rolePermission.user_role_table', 'user_roles') const userRoleTable = Config.get('rolePermission.user_role_table', 'user_roles');
/** /**
* Role authentication to check if user has any of the specified roles * Role authentication to check if user has any of the specified roles
@ -13,54 +13,50 @@ const userRoleTable = Config.get('rolePermission.user_role_table', 'user_roles')
* Should be called after auth middleware * Should be called after auth middleware
*/ */
export default class Is { export default class Is {
/**
* Handle request
*/
public async handle(
{ auth, response }: HttpContextContract,
next: () => Promise<void>,
roleNames: string[]
) {
/** /**
* Check if user is logged-in or not. * Handle request
*/ */
let user = await auth.user public async handle({ auth, response }: HttpContextContract, next: () => Promise<void>, roleNames: string[]) {
if (!user) { /**
return response.unauthorized({ error: 'Must be logged in' }) * Check if user is logged-in or not.
*/
let user = await auth.user;
if (!user) {
return response.unauthorized({ error: 'Must be logged in' });
}
let hasRole = await this.checkHasRoles(user, roleNames);
if (!hasRole) {
return response.unauthorized({
error: `Doesn't have required role(s): ${roleNames.join(',')}`,
});
// return new Exception(`Doesn't have required role(s): ${roleNames.join(',')}`,
// 401,
// "E_INVALID_AUTH_UID");
}
await next();
} }
let hasRole = await this.checkHasRoles(user, roleNames)
if (!hasRole) { private async checkHasRoles(user: User, roleNames: Array<string>): Promise<boolean> {
return response.unauthorized({ let rolePlaceHolder = '(';
error: `Doesn't have required role(s): ${roleNames.join(',')}`, let placeholders = new Array(roleNames.length).fill('?');
}) rolePlaceHolder += placeholders.join(',');
// return new Exception(`Doesn't have required role(s): ${roleNames.join(',')}`, rolePlaceHolder += ')';
// 401,
// "E_INVALID_AUTH_UID"); let {
0: {
0: { roleCount },
},
} = await Database.rawQuery(
'SELECT count(`ur`.`id`) as roleCount FROM ' +
userRoleTable +
' ur INNER JOIN ' +
roleTable +
' r ON ur.role_id=r.id WHERE `ur`.`user_id`=? AND `r`.`name` in ' +
rolePlaceHolder +
' LIMIT 1',
[user.id, ...roleNames],
);
return roleCount > 0;
} }
await next()
}
private async checkHasRoles(user: User, roleNames: Array<string>): Promise<boolean> {
let rolePlaceHolder = '('
let placeholders = new Array(roleNames.length).fill('?')
rolePlaceHolder += placeholders.join(',')
rolePlaceHolder += ')'
let {
0: {
0: { roleCount },
},
} = await Database.rawQuery(
'SELECT count(`ur`.`id`) as roleCount FROM ' +
userRoleTable +
' ur INNER JOIN ' +
roleTable +
' r ON ur.role_id=r.id WHERE `ur`.`user_id`=? AND `r`.`name` in ' +
rolePlaceHolder +
' LIMIT 1',
[user.id, ...roleNames]
)
return roleCount > 0
}
} }

View File

@ -7,77 +7,72 @@ import { Exception } from '@adonisjs/core/build/standalone';
const roleTable = Config.get('rolePermission.role_table', 'roles'); const roleTable = Config.get('rolePermission.role_table', 'roles');
const userRoleTable = Config.get('rolePermission.user_role_table', 'link_accounts_roles'); const userRoleTable = Config.get('rolePermission.user_role_table', 'link_accounts_roles');
// node ace make:middleware role // node ace make:middleware role
export default class Role { export default class Role {
// .middleware(['auth', 'role:admin,moderator']) // .middleware(['auth', 'role:admin,moderator'])
public async handle( public async handle({ auth, response }: HttpContextContract, next: () => Promise<void>, userRoles: string[]) {
{ auth, response }: HttpContextContract, // Check if user is logged-in or not.
next: () => Promise<void>, // let expression = "";
userRoles: string[] // if (Array.isArray(args)) {
) { // expression = args.join(" || ");
// Check if user is logged-in or not. // }
// let expression = "";
// if (Array.isArray(args)) {
// expression = args.join(" || ");
// }
let user = await auth.user; let user = await auth.user;
if (!user) { if (!user) {
return response.unauthorized({ error: 'Must be logged in' }); return response.unauthorized({ error: 'Must be logged in' });
} }
let hasRole = await this.checkHasRoles(user, userRoles); let hasRole = await this.checkHasRoles(user, userRoles);
if (!hasRole) { if (!hasRole) {
// return response.unauthorized({ // return response.unauthorized({
// error: `Doesn't have required role(s): ${userRoles.join(',')}`, // error: `Doesn't have required role(s): ${userRoles.join(',')}`,
// // error: `Doesn't have required role(s)`, // // error: `Doesn't have required role(s)`,
// }); // });
throw new Exception(`Doesn't have required role(s): ${userRoles.join(',')}`, 401); throw new Exception(`Doesn't have required role(s): ${userRoles.join(',')}`, 401);
} }
// code for middleware goes here. ABOVE THE NEXT CALL // code for middleware goes here. ABOVE THE NEXT CALL
await next(); await next();
} }
private async checkHasRoles(user: User, userRoles: string[]): Promise<boolean> { private async checkHasRoles(user: User, userRoles: string[]): Promise<boolean> {
// await user.load("roles"); // await user.load("roles");
// const ok = user.roles.map((role) => role.name); // const ok = user.roles.map((role) => role.name);
// const roles = await user.getRoles(); // const roles = await user.getRoles();
let rolePlaceHolder = '('; let rolePlaceHolder = '(';
let placeholders = new Array(userRoles.length).fill('?'); let placeholders = new Array(userRoles.length).fill('?');
rolePlaceHolder += placeholders.join(','); rolePlaceHolder += placeholders.join(',');
rolePlaceHolder += ')'; rolePlaceHolder += ')';
// const roles = await user // const roles = await user
// .related('roles') // .related('roles')
// .query() // .query()
// .count('*') // .select('name') // .count('*') // .select('name')
// .whereIn('name', userRoles); // .whereIn('name', userRoles);
// // .groupBy('name'); // // .groupBy('name');
// select count(*) as roleCount // select count(*) as roleCount
// from gba.roles // from gba.roles
// inner join gba.link_accounts_roles // inner join gba.link_accounts_roles
// on "roles"."id" = "link_accounts_roles"."role_id" // on "roles"."id" = "link_accounts_roles"."role_id"
// where ("name" in ('administrator', 'editor')) and ("link_accounts_roles"."account_id" = 1) // where ("name" in ('administrator', 'editor')) and ("link_accounts_roles"."account_id" = 1)
let { let {
rows: { rows: {
0: { rolecount }, 0: { rolecount },
}, },
} = await Database.rawQuery( } = await Database.rawQuery(
'SELECT count("r"."id") as roleCount FROM ' + 'SELECT count("r"."id") as roleCount FROM ' +
roleTable + roleTable +
' r INNER JOIN ' + ' r INNER JOIN ' +
userRoleTable + userRoleTable +
' ur ON r.id=ur.role_id WHERE "ur"."account_id"=? AND "r"."name" in ' + ' ur ON r.id=ur.role_id WHERE "ur"."account_id"=? AND "r"."name" in ' +
rolePlaceHolder + rolePlaceHolder +
' LIMIT 1', ' LIMIT 1',
[user.id, ...userRoles] [user.id, ...userRoles],
); );
return rolecount > 0; return rolecount > 0;
} }
} }

View File

@ -1,4 +1,4 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
/** /**
* Silent auth middleware can be used as a global middleware to silent check * Silent auth middleware can be used as a global middleware to silent check
@ -7,15 +7,15 @@ import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
* The request continues as usual, even when the user is not logged-in. * The request continues as usual, even when the user is not logged-in.
*/ */
export default class SilentAuthMiddleware { export default class SilentAuthMiddleware {
/**
* Handle request
*/
public async handle({ auth }: HttpContextContract, next: () => Promise<void>) {
/** /**
* Check if user is logged-in or not. If yes, then `ctx.auth.user` will be * Handle request
* set to the instance of the currently logged in user.
*/ */
await auth.check() public async handle({ auth }: HttpContextContract, next: () => Promise<void>) {
await next() /**
} * Check if user is logged-in or not. If yes, then `ctx.auth.user` will be
* set to the instance of the currently logged in user.
*/
await auth.check();
await next();
}
} }

119
app/Models/BaseModel.ts Normal file
View File

@ -0,0 +1,119 @@
import { BaseModel as LucidBaseModel } from '@ioc:Adonis/Lucid/Orm';
// import { ManyToManyQueryClient } from '@ioc:Adonis/Lucid/Orm';
// export class CustomManyToManyQueryClient extends ManyToManyQueryClient {
// public attach(
// relatedIds: any | any[],
// pivotAttributes: any = {},
// trx?: ReturnType<typeof this.model.transaction>
// ) {
// return super.attach(relatedIds, (row) => {
// row.pivot.fill(pivotAttributes);
// }, trx);
// }
// }
/**
* Helper to find if value is a valid Object or
* not
*/
export function isObject(value: any): boolean {
return value !== null && typeof value === 'object' && !Array.isArray(value);
}
export default class BaseModel extends LucidBaseModel {
/**
* When `fill` method is called, then we may have a situation where it
* removed the values which exists in `original` and hence the dirty
* diff has to do a negative diff as well
*/
// private fillInvoked: boolean = false;
public static fillable: string[] = [];
public fill(attributes: any, allowExtraProperties: boolean = false): this {
this.$attributes = {};
// const Model = this.constructor as typeof BaseModel;
// for (const key in attributes) {
// if (Model.fillable.includes(key)) {
// const value = attributes[key];
// if (Model.$hasColumn(key)) {
// this[key] = value;
// }
// }
// }
this.mergeFillableAttributes(attributes, allowExtraProperties);
// this.fillInvoked = true;
return this;
}
/**
* Merge bulk attributes with existing attributes.
*
* 1. If key is unknown, it will be added to the `extras` object.
* 2. If key is defined as a relationship, it will be ignored and one must call `$setRelated`.
*/
public mergeFillableAttributes(values: any, allowExtraProperties: boolean = false): this {
const Model = this.constructor as typeof BaseModel;
/**
* Merge values with the attributes
*/
if (isObject(values)) {
// Object.keys(values).forEach((key) => {
for (const key in values) {
if (Model.fillable.includes(key)) {
const value = values[key];
/**
* Set as column
*/
if (Model.$hasColumn(key)) {
this[key] = value;
continue;
}
/**
* Resolve the attribute name from the column names. Since people
* usaully define the column names directly as well by
* accepting them directly from the API.
*/
const attributeName = Model.$keys.columnsToAttributes.get(key);
if (attributeName) {
this[attributeName] = value;
continue;
}
/**
* If key is defined as a relation, then ignore it, since one
* must pass a qualified model to `this.$setRelated()`
*/
if (Model.$relationsDefinitions.has(key)) {
continue;
}
/**
* If the property already exists on the model, then set it
* as it is vs defining it as an extra property
*/
if (this.hasOwnProperty(key)) {
this[key] = value;
continue;
}
/**
* Raise error when not instructed to ignore non-existing properties.
*/
if (!allowExtraProperties) {
throw new Error(`Cannot define "${key}" on "${Model.name}" model, since it is not defined as a model property`);
}
this.$extras[key] = value;
}
}
}
return this;
}
}

View File

@ -1,52 +1,108 @@
import { import {
column, column,
BaseModel, BaseModel,
SnakeCaseNamingStrategy, SnakeCaseNamingStrategy,
// computed, manyToMany,
manyToMany, ManyToMany,
ManyToMany, belongsTo,
BelongsTo,
hasMany,
HasMany,
} from '@ioc:Adonis/Lucid/Orm'; } from '@ioc:Adonis/Lucid/Orm';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import Person from './Person'; import Person from './Person';
import User from './User';
import Title from './Title';
import Description from './Description';
import License from './License';
import Subject from './Subject';
export default class Dataset extends BaseModel { export default class Dataset extends BaseModel {
public static namingStrategy = new SnakeCaseNamingStrategy(); public static namingStrategy = new SnakeCaseNamingStrategy();
public static primaryKey = 'id'; public static primaryKey = 'id';
public static table = 'documents'; public static table = 'documents';
public static selfAssignPrimaryKey = false; public static selfAssignPrimaryKey = false;
@column({ isPrimary: true }) @column({ isPrimary: true })
public id: number; public id: number;
@column({}) @column({})
public server_state: boolean; public server_state: boolean;
@column({}) @column({})
public publisherName: string; public publisherName: string;
@column({ columnName: 'creating_corporation' })
public creatingCorporation: string;
@column.dateTime({ columnName: 'embargo_date' }) @column.dateTime({ columnName: 'embargo_date' })
public embargoDate: DateTime; public embargoDate: DateTime;
@column({}) @column({})
public type: string; public type: string;
@column({})
public language: string;
@column.dateTime({ columnName: 'server_date_published' }) @column({})
public serverDatePublished: DateTime; public account_id: number | null = null;
@column.dateTime({ autoCreate: true, columnName: 'created_at' }) @column.dateTime({ columnName: 'server_date_published' })
public createdAt: DateTime; public serverDatePublished: DateTime;
@column.dateTime({ autoCreate: true, autoUpdate: true }) @column.dateTime({ autoCreate: true, columnName: 'created_at' })
public updatedAt: DateTime; public createdAt: DateTime;
@column.dateTime({ autoCreate: true, autoUpdate: true, columnName: 'server_date_modified' })
public updatedAt: DateTime;
@manyToMany(() => Person, { @manyToMany(() => Person, {
pivotForeignKey: 'document_id', pivotForeignKey: 'document_id',
pivotRelatedForeignKey: 'person_id', pivotRelatedForeignKey: 'person_id',
pivotTable: 'link_documents_persons', pivotTable: 'link_documents_persons',
pivotColumns: ['role', 'sort_order', 'allow_email_contact'] pivotColumns: ['role', 'sort_order', 'allow_email_contact'],
}) })
public persons: ManyToMany<typeof Person>; public persons: ManyToMany<typeof Person>;
/**
* Get the account that the dataset belongs to
*/
@belongsTo(() => User, {
foreignKey: 'account_id',
})
public user: BelongsTo<typeof User>;
@hasMany(() => Title, {
foreignKey: 'document_id',
})
public titles: HasMany<typeof Title>;
@hasMany(() => Description, {
foreignKey: 'document_id',
})
public descriptions: HasMany<typeof Description>;
@manyToMany(() => License, {
pivotForeignKey: 'document_id',
pivotRelatedForeignKey: 'licence_id',
pivotTable: 'link_documents_licences',
})
public licenses: ManyToMany<typeof License>;
// public function subjects()
// {
// return $this->belongsToMany(\App\Models\Subject::class, 'link_dataset_subjects', 'document_id', 'subject_id');
// }
@manyToMany(() => Subject, {
pivotForeignKey: 'document_id',
pivotRelatedForeignKey: 'subject_id',
pivotTable: 'link_dataset_subjects',
})
public subjects: ManyToMany<typeof Subject>;
// async save(): Promise<this> {
// // Call the parent save method to persist changes to the database
// await super.save();
// return this;
// }
} }

28
app/Models/Description.ts Normal file
View File

@ -0,0 +1,28 @@
import { column, belongsTo, BelongsTo } from '@ioc:Adonis/Lucid/Orm';
import Dataset from './Dataset';
import BaseModel from './BaseModel';
export default class Description extends BaseModel {
public static primaryKey = 'id';
public static table = 'dataset_abstracts';
public static selfAssignPrimaryKey = false;
public static timestamps = false;
public static fillable: string[] = ['value', 'type', 'language'];
@column({})
public document_id: number;
@column()
public type: string;
@column()
public value: string;
@column()
public language: string;
@belongsTo(() => Dataset, {
foreignKey: 'document_id',
})
public dataset: BelongsTo<typeof Dataset>;
}

View File

@ -1,54 +1,55 @@
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { import {
column, column,
BaseModel, BaseModel,
hasMany, HasMany, hasMany,
// manyToMany, HasMany,
// ManyToMany, // manyToMany,
SnakeCaseNamingStrategy, // ManyToMany,
SnakeCaseNamingStrategy,
} from '@ioc:Adonis/Lucid/Orm'; } from '@ioc:Adonis/Lucid/Orm';
import HashValue from './HashValue'; import HashValue from './HashValue';
export default class File extends BaseModel { export default class File extends BaseModel {
public static namingStrategy = new SnakeCaseNamingStrategy(); public static namingStrategy = new SnakeCaseNamingStrategy();
public static primaryKey = 'id'; public static primaryKey = 'id';
public static table = 'document_files'; public static table = 'document_files';
public static selfAssignPrimaryKey = false; public static selfAssignPrimaryKey = false;
@column({ @column({
isPrimary: true, isPrimary: true,
}) })
public id: number; public id: number;
@column({}) @column({})
public pathName: string; public pathName: string;
@column()
public label: string;
@column() @column()
public comment: string; public label: string;
@column() @column()
public mimetype: string; public comment: string;
@column() @column()
public language: string; public mimetype: string;
@column() @column()
public fileSize: bigint; public language: string;
@column() @column()
public visibleInOai: boolean; public fileSize: bigint;
@column() @column()
public sortOrder: number; public visibleInOai: boolean;
@column()
public sortOrder: number;
@column.dateTime({ autoCreate: true }) @column.dateTime({ autoCreate: true })
public createdAt: DateTime; public createdAt: DateTime;
@column.dateTime({ autoCreate: true, autoUpdate: true }) @column.dateTime({ autoCreate: true, autoUpdate: true })
public updatedAt: DateTime; public updatedAt: DateTime;
// public function hashvalues() // public function hashvalues()
// { // {
@ -58,5 +59,5 @@ export default class File extends BaseModel {
@hasMany(() => HashValue, { @hasMany(() => HashValue, {
foreignKey: 'file_id', foreignKey: 'file_id',
}) })
public hashvalues: HasMany<typeof HashValue>; public hashvalues: HasMany<typeof HashValue>;
} }

View File

@ -1,41 +1,34 @@
import { import { column, BaseModel, belongsTo, BelongsTo, SnakeCaseNamingStrategy } from '@ioc:Adonis/Lucid/Orm';
column,
BaseModel,
belongsTo,
BelongsTo,
SnakeCaseNamingStrategy,
} from '@ioc:Adonis/Lucid/Orm';
import File from './File'; import File from './File';
export default class HashValue extends BaseModel { export default class HashValue extends BaseModel {
public static namingStrategy = new SnakeCaseNamingStrategy(); public static namingStrategy = new SnakeCaseNamingStrategy();
public static primaryKey = 'file_id, type'; public static primaryKey = 'file_id, type';
public static table = 'file_hashvalues'; public static table = 'file_hashvalues';
// static get primaryKey () { // static get primaryKey () {
// return 'type, value' // return 'type, value'
// } // }
static get incrementing () { static get incrementing() {
return false return false;
} }
// @column({ // @column({
// isPrimary: true, // isPrimary: true,
// }) // })
// public id: number; // public id: number;
// Foreign key is still on the same model // Foreign key is still on the same model
@column({}) @column({})
public file_id: number; public file_id: number;
@column({}) @column({})
public type: string; public type: string;
@column() @column()
public value: string; public value: string;
@belongsTo(() => File) @belongsTo(() => File)
public file: BelongsTo<typeof File> public file: BelongsTo<typeof File>;
} }

View File

@ -5,6 +5,22 @@ export default class License extends BaseModel {
public static primaryKey = 'id'; public static primaryKey = 'id';
public static table = 'document_licences'; public static table = 'document_licences';
public static selfAssignPrimaryKey = false; public static selfAssignPrimaryKey = false;
public static timestamps = false;
public static fillable: string[] = [
'name_long',
'name',
'language',
'link_licence',
'link_logo',
'desc_text',
'desc_markup',
'comment_internal',
'mime_type',
'sort_order',
'language',
'active',
'pod_allowed',
];
@column({ @column({
isPrimary: true, isPrimary: true,

View File

@ -1,100 +1,92 @@
import { import { column, BaseModel, manyToMany, ManyToMany, SnakeCaseNamingStrategy, beforeUpdate, beforeCreate } from '@ioc:Adonis/Lucid/Orm';
column,
BaseModel,
manyToMany,
ManyToMany,
SnakeCaseNamingStrategy,
beforeUpdate,
beforeCreate,
} from '@ioc:Adonis/Lucid/Orm';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import Role from 'App/Models/Role'; import Role from 'App/Models/Role';
export default class Permission extends BaseModel { export default class Permission extends BaseModel {
public static namingStrategy = new SnakeCaseNamingStrategy(); public static namingStrategy = new SnakeCaseNamingStrategy();
public static primaryKey = 'id'; public static primaryKey = 'id';
public static table = 'permissions'; public static table = 'permissions';
public static selfAssignPrimaryKey = false; public static selfAssignPrimaryKey = false;
@column({ @column({
isPrimary: true, isPrimary: true,
}) })
public id: number; public id: number;
@column({}) @column({})
public role_id: number; public role_id: number;
@column({}) @column({})
public display_name: string; public display_name: string;
@column({}) @column({})
public name: string; public name: string;
@column({}) @column({})
public description: string; public description: string;
@column.dateTime({ @column.dateTime({
serialize: (value: Date | null) => { serialize: (value: Date | null) => {
return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value; return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value;
}, },
autoCreate: true, autoCreate: true,
}) })
public created_at: DateTime; public created_at: DateTime;
@column.dateTime({ @column.dateTime({
serialize: (value: Date | null) => { serialize: (value: Date | null) => {
return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value; return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value;
}, },
autoCreate: true, autoCreate: true,
autoUpdate: true, autoUpdate: true,
}) })
public updated_at: DateTime; public updated_at: DateTime;
@beforeCreate() @beforeCreate()
@beforeUpdate() @beforeUpdate()
public static async resetDate(role) { public static async resetDate(role) {
role.created_at = this.formatDateTime(role.created_at); role.created_at = this.formatDateTime(role.created_at);
role.updated_at = this.formatDateTime(role.updated_at); role.updated_at = this.formatDateTime(role.updated_at);
} }
// public static boot() { // public static boot() {
// super.boot() // super.boot()
// this.before('create', async (_modelInstance) => { // this.before('create', async (_modelInstance) => {
// _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at) // _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at)
// _modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at) // _modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at)
// }) // })
// this.before('update', async (_modelInstance) => { // this.before('update', async (_modelInstance) => {
// _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at) // _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at)
// _modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at) // _modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at)
// }) // })
// } // }
private static formatDateTime(datetime) { private static formatDateTime(datetime) {
let value = new Date(datetime); let value = new Date(datetime);
return datetime return datetime
? value.getFullYear() + ? value.getFullYear() +
'-' + '-' +
(value.getMonth() + 1) + (value.getMonth() + 1) +
'-' + '-' +
value.getDate() + value.getDate() +
' ' + ' ' +
value.getHours() + value.getHours() +
':' + ':' +
value.getMinutes() + value.getMinutes() +
':' + ':' +
value.getSeconds() value.getSeconds()
: datetime; : datetime;
} }
// @belongsTo(() => Role) // @belongsTo(() => Role)
// public role: BelongsTo<typeof Role>; // public role: BelongsTo<typeof Role>;
@manyToMany(() => Role, { @manyToMany(() => Role, {
pivotForeignKey: 'permission_id', pivotForeignKey: 'permission_id',
pivotRelatedForeignKey: 'role_id', pivotRelatedForeignKey: 'role_id',
pivotTable: 'role_has_permissions', pivotTable: 'role_has_permissions',
}) })
public roles: ManyToMany<typeof Role>; public roles: ManyToMany<typeof Role>;
} }

View File

@ -1,83 +1,79 @@
import { import { column, SnakeCaseNamingStrategy, computed, manyToMany, ManyToMany } from '@ioc:Adonis/Lucid/Orm';
column,
BaseModel,
SnakeCaseNamingStrategy,
computed,
manyToMany,
ManyToMany,
} from '@ioc:Adonis/Lucid/Orm';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import Dataset from './Dataset'; import Dataset from './Dataset';
import BaseModel from './BaseModel';
export default class Person extends BaseModel { export default class Person extends BaseModel {
public static namingStrategy = new SnakeCaseNamingStrategy(); public static namingStrategy = new SnakeCaseNamingStrategy();
public static primaryKey = 'id'; public static primaryKey = 'id';
public static table = 'persons'; public static table = 'persons';
public static selfAssignPrimaryKey = false; public static selfAssignPrimaryKey = false;
// only the academic_title, email, first_name, identifier_orcid, last_name and name_type attributes are allowed to be mass assigned.
public static fillable: string[] = ['academic_title', 'email', 'first_name', 'identifier_orcid', 'last_name', 'name_type'];
@column({ @column({
isPrimary: true, isPrimary: true,
})
public id: number;
@column({})
public academicTitle: string;
@column()
public email: string;
@column({})
public firstName: string;
@column({})
public lastName: string;
@column({})
public identifierOrcid: string;
@column({})
public status: boolean;
@column({})
public nameType: string;
@column.dateTime({
serialize: (value: Date | null) => {
return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value;
},
autoCreate: true,
})
public createdAt: DateTime;
@computed({
serializeAs: 'name'
}) })
public get fullName() { public id: number;
return `${this.firstName} ${this.lastName}`;
} @column({ columnName: 'academic_title' })
public academicTitle: string;
@column()
public email: string;
@column({})
public firstName: string;
@column({})
public lastName: string;
@column({})
public identifierOrcid: string;
@column({})
public status: boolean;
@column({})
public nameType: string;
@column.dateTime({
serialize: (value: Date | null) => {
return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value;
},
autoCreate: true,
})
public createdAt: DateTime;
@computed({
serializeAs: 'name',
})
public get fullName() {
return `${this.firstName} ${this.lastName}`;
}
// @computed() // @computed()
// public get progress(): number { // public get progress(): number {
// return 50; // return 50;
// } // }
// @computed() // @computed()
// public get created_at() { // public get created_at() {
// return '2023-03-21 08:45:00'; // return '2023-03-21 08:45:00';
// } // }
@computed() @computed()
public get datasetCount() { public get datasetCount() {
const stock = this.$extras.datasets_count //my pivot column name was "stock" const stock = this.$extras.datasets_count; //my pivot column name was "stock"
return stock return stock;
} }
@manyToMany(() => Dataset, { @manyToMany(() => Dataset, {
pivotForeignKey: 'person_id', pivotForeignKey: 'person_id',
pivotRelatedForeignKey: 'document_id', pivotRelatedForeignKey: 'document_id',
pivotTable: 'link_documents_persons', pivotTable: 'link_documents_persons',
pivotColumns: ['role', 'sort_order', 'allow_email_contact'] pivotColumns: ['role', 'sort_order', 'allow_email_contact'],
}) })
public datasets: ManyToMany<typeof Dataset>; public datasets: ManyToMany<typeof Dataset>;
} }

View File

@ -12,7 +12,6 @@ export default class Project extends BaseModel {
}) })
public id: number; public id: number;
@column({}) @column({})
public label: string; public label: string;
@ -24,14 +23,12 @@ export default class Project extends BaseModel {
@column.dateTime({ @column.dateTime({
autoCreate: true, autoCreate: true,
}) })
public created_at: DateTime; public created_at: DateTime;
@column.dateTime({ @column.dateTime({
autoCreate: true, autoCreate: true,
autoUpdate: true autoUpdate: true,
}) })
public updated_at: DateTime; public updated_at: DateTime;
} }

View File

@ -1,12 +1,4 @@
import { import { column, BaseModel, SnakeCaseNamingStrategy, manyToMany, ManyToMany, beforeCreate, beforeUpdate } from '@ioc:Adonis/Lucid/Orm';
column,
BaseModel,
SnakeCaseNamingStrategy,
manyToMany,
ManyToMany,
beforeCreate,
beforeUpdate,
} from '@ioc:Adonis/Lucid/Orm';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
// import moment from 'moment'; // import moment from 'moment';
@ -15,91 +7,91 @@ import User from './User';
import Permission from 'App/Models/Permission'; import Permission from 'App/Models/Permission';
export default class Role extends BaseModel { export default class Role extends BaseModel {
public static namingStrategy = new SnakeCaseNamingStrategy(); public static namingStrategy = new SnakeCaseNamingStrategy();
public static primaryKey = 'id'; public static primaryKey = 'id';
public static table = 'roles'; public static table = 'roles';
public static selfAssignPrimaryKey = false; public static selfAssignPrimaryKey = false;
@column({ @column({
isPrimary: true, isPrimary: true,
}) })
public id: number; public id: number;
@column({}) @column({})
public display_name: string; public display_name: string;
@column({}) @column({})
public name: string; public name: string;
@column({}) @column({})
public description: string; public description: string;
@column.dateTime({ @column.dateTime({
serialize: (value: Date | null) => { serialize: (value: Date | null) => {
// return value ? moment(value).format('MMMM Do YYYY, HH:mm:ss') : value; // return value ? moment(value).format('MMMM Do YYYY, HH:mm:ss') : value;
return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value; return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value;
}, },
autoCreate: true, autoCreate: true,
}) })
public created_at: DateTime; public created_at: DateTime;
@column.dateTime({ @column.dateTime({
serialize: (value: Date | null) => { serialize: (value: Date | null) => {
return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value; return value ? dayjs(value).format('MMMM D YYYY HH:mm a') : value;
}, },
autoCreate: true, autoCreate: true,
autoUpdate: true autoUpdate: true,
}) })
public updated_at: DateTime; public updated_at: DateTime;
@beforeCreate() @beforeCreate()
@beforeUpdate() @beforeUpdate()
public static async resetDate(role) { public static async resetDate(role) {
role.created_at = this.formatDateTime(role.created_at); role.created_at = this.formatDateTime(role.created_at);
role.updated_at = this.formatDateTime(role.updated_at); role.updated_at = this.formatDateTime(role.updated_at);
} }
// public static boot() { // public static boot() {
// super.boot(); // super.boot();
// this.before('create', async (_modelInstance) => { // this.before('create', async (_modelInstance) => {
// _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at); // _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at);
// _modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at); // _modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at);
// }); // });
// this.before('update', async (_modelInstance) => { // this.before('update', async (_modelInstance) => {
// _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at); // _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at);
// _modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at); // _modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at);
// }); // });
// } // }
private static formatDateTime(datetime) { private static formatDateTime(datetime) {
let value = new Date(datetime); let value = new Date(datetime);
return datetime return datetime
? value.getFullYear() + ? value.getFullYear() +
'-' + '-' +
(value.getMonth() + 1) + (value.getMonth() + 1) +
'-' + '-' +
value.getDate() + value.getDate() +
' ' + ' ' +
value.getHours() + value.getHours() +
':' + ':' +
value.getMinutes() + value.getMinutes() +
':' + ':' +
value.getSeconds() value.getSeconds()
: datetime; : datetime;
} }
@manyToMany(() => User, { @manyToMany(() => User, {
pivotForeignKey: 'role_id', pivotForeignKey: 'role_id',
pivotRelatedForeignKey: 'account_id', pivotRelatedForeignKey: 'account_id',
pivotTable: 'link_accounts_roles', pivotTable: 'link_accounts_roles',
}) })
public users: ManyToMany<typeof User>; public users: ManyToMany<typeof User>;
@manyToMany(() => Permission, { @manyToMany(() => Permission, {
pivotForeignKey: 'role_id', pivotForeignKey: 'role_id',
pivotRelatedForeignKey: 'permission_id', pivotRelatedForeignKey: 'permission_id',
pivotTable: 'role_has_permissions', pivotTable: 'role_has_permissions',
}) })
public permissions: ManyToMany<typeof Permission>; public permissions: ManyToMany<typeof Permission>;
} }

28
app/Models/Title.ts Normal file
View File

@ -0,0 +1,28 @@
import { column, belongsTo, BelongsTo } from '@ioc:Adonis/Lucid/Orm';
import Dataset from './Dataset';
import BaseModel from './BaseModel';
export default class Title extends BaseModel {
public static primaryKey = 'id';
public static table = 'dataset_titles';
public static selfAssignPrimaryKey = false;
public static timestamps = false;
public static fillable: string[] = ['value', 'type', 'language'];
@column({})
public document_id: number;
@column()
public type: string;
@column()
public value: string;
@column()
public language: string;
@belongsTo(() => Dataset, {
foreignKey: 'document_id',
})
public dataset: BelongsTo<typeof Dataset>;
}

View File

@ -1,9 +1,10 @@
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { BaseModel, column, beforeSave, manyToMany, ManyToMany } from '@ioc:Adonis/Lucid/Orm'; import { BaseModel, column, beforeSave, manyToMany, ManyToMany, hasMany, HasMany } from '@ioc:Adonis/Lucid/Orm';
import Hash from '@ioc:Adonis/Core/Hash'; import Hash from '@ioc:Adonis/Core/Hash';
import Role from './Role'; import Role from './Role';
import Database from '@ioc:Adonis/Lucid/Database'; import Database from '@ioc:Adonis/Lucid/Database';
import Config from '@ioc:Adonis/Core/Config'; import Config from '@ioc:Adonis/Core/Config';
import Dataset from './Dataset';
// export default interface IUser { // export default interface IUser {
// id: number; // id: number;
@ -22,82 +23,87 @@ const roleTable = Config.get('rolePermission.role_table', 'roles');
const userRoleTable = Config.get('rolePermission.user_role_table', 'link_accounts_roles'); const userRoleTable = Config.get('rolePermission.user_role_table', 'link_accounts_roles');
export default class User extends BaseModel { export default class User extends BaseModel {
public static table = 'accounts'; public static table = 'accounts';
@column({ isPrimary: true }) @column({ isPrimary: true })
public id: number; public id: number;
@column() @column()
public login: string; public login: string;
@column() @column()
public email: string; public email: string;
@column({ serializeAs: null }) @column({ serializeAs: null })
public password: string; public password: string;
@column.dateTime({ autoCreate: true }) @column.dateTime({ autoCreate: true })
public createdAt: DateTime; public createdAt: DateTime;
@column.dateTime({ autoCreate: true, autoUpdate: true }) @column.dateTime({ autoCreate: true, autoUpdate: true })
public updatedAt: DateTime; public updatedAt: DateTime;
@beforeSave() @beforeSave()
public static async hashPassword(user) { public static async hashPassword(user) {
if (user.$dirty.password) { if (user.$dirty.password) {
user.password = await Hash.make(user.password); user.password = await Hash.make(user.password);
} }
} }
@manyToMany(() => Role, { @manyToMany(() => Role, {
pivotForeignKey: 'account_id', pivotForeignKey: 'account_id',
pivotRelatedForeignKey: 'role_id', pivotRelatedForeignKey: 'role_id',
pivotTable: 'link_accounts_roles', pivotTable: 'link_accounts_roles',
}) })
public roles: ManyToMany<typeof Role>; public roles: ManyToMany<typeof Role>;
// https://github.com/adonisjs/core/discussions/1872#discussioncomment-132289 @hasMany(() => Dataset, {
public async getRoles(this: User): Promise<string[]> { foreignKey: 'account_id',
const test = await this.related('roles').query(); })
return test.map((role) => role.name); public datasets: HasMany<typeof Dataset>;
}
public async can(permissionNames: Array<string>): Promise<boolean> { // https://github.com/adonisjs/core/discussions/1872#discussioncomment-132289
// const permissions = await this.getPermissions() public async getRoles(this: User): Promise<string[]> {
// return Acl.check(expression, operand => _.includes(permissions, operand)) const test = await this.related('roles').query();
const hasPermission = await this.checkHasPermissions(this, permissionNames); return test.map((role) => role.name);
return hasPermission; }
}
private async checkHasPermissions(user: User, permissionNames: Array<string>): Promise<boolean> { public async can(permissionNames: Array<string>): Promise<boolean> {
let permissionPlaceHolder = '('; // const permissions = await this.getPermissions()
let placeholders = new Array(permissionNames.length).fill('?'); // return Acl.check(expression, operand => _.includes(permissions, operand))
permissionPlaceHolder += placeholders.join(','); const hasPermission = await this.checkHasPermissions(this, permissionNames);
permissionPlaceHolder += ')'; return hasPermission;
}
let { private async checkHasPermissions(user: User, permissionNames: Array<string>): Promise<boolean> {
rows: { let permissionPlaceHolder = '(';
0: { permissioncount }, let placeholders = new Array(permissionNames.length).fill('?');
}, permissionPlaceHolder += placeholders.join(',');
} = await Database.rawQuery( permissionPlaceHolder += ')';
'SELECT count("p"."name") as permissionCount FROM ' +
roleTable +
' r INNER JOIN ' +
userRoleTable +
' ur ON ur.role_id=r.id AND "ur"."account_id"=? ' +
' INNER JOIN ' +
rolePermissionTable +
' rp ON rp.role_id=r.id ' +
' INNER JOIN ' +
permissionTable +
' p ON rp.permission_id=p.id AND "p"."name" in ' +
permissionPlaceHolder +
' LIMIT 1',
[user.id, ...permissionNames]
);
return permissioncount > 0; let {
} rows: {
0: { permissioncount },
},
} = await Database.rawQuery(
'SELECT count("p"."name") as permissionCount FROM ' +
roleTable +
' r INNER JOIN ' +
userRoleTable +
' ur ON ur.role_id=r.id AND "ur"."account_id"=? ' +
' INNER JOIN ' +
rolePermissionTable +
' rp ON rp.role_id=r.id ' +
' INNER JOIN ' +
permissionTable +
' p ON rp.permission_id=p.id AND "p"."name" in ' +
permissionPlaceHolder +
' LIMIT 1',
[user.id, ...permissionNames],
);
return permissioncount > 0;
}
} }
// export default User; // export default User;

View File

@ -1,74 +1,74 @@
import {column, BaseModel, belongsTo, BelongsTo, SnakeCaseNamingStrategy} from '@ioc:Adonis/Lucid/Orm' import { column, BaseModel, belongsTo, BelongsTo, SnakeCaseNamingStrategy } from '@ioc:Adonis/Lucid/Orm';
import User from 'App/Models/User' import User from 'App/Models/User';
import Role from 'App/Models/Role' import Role from 'App/Models/Role';
import { DateTime } from 'luxon' import { DateTime } from 'luxon';
// import moment from 'moment' // import moment from 'moment'
export default class UserRole extends BaseModel { export default class UserRole extends BaseModel {
public static namingStrategy = new SnakeCaseNamingStrategy() public static namingStrategy = new SnakeCaseNamingStrategy();
public static primaryKey = 'id' public static primaryKey = 'id';
public static table = 'user_roles' public static table = 'user_roles';
public static selfAssignPrimaryKey = false public static selfAssignPrimaryKey = false;
@column({ @column({
isPrimary: true, isPrimary: true,
})
public id: number
@column({})
public user_id: number
@column({})
public role_id: number
@column({
// serialize: (value: DateTime | null) => {
// return value ? moment(value).format('lll') : value
// },
})
public created_at: DateTime
@column({
// serialize: (value: DateTime | null) => {
// return value ? moment(value).format('lll') : value
// },
})
public updated_at: DateTime
public static boot() {
super.boot()
this.before('create', async (_modelInstance) => {
_modelInstance.created_at = this.formatDateTime(_modelInstance.created_at)
_modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at)
}) })
this.before('update', async (_modelInstance) => { public id: number;
_modelInstance.created_at = this.formatDateTime(_modelInstance.created_at)
_modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at) @column({})
public user_id: number;
@column({})
public role_id: number;
@column({
// serialize: (value: DateTime | null) => {
// return value ? moment(value).format('lll') : value
// },
}) })
} public created_at: DateTime;
private static formatDateTime(datetime) { @column({
let value = new Date(datetime) // serialize: (value: DateTime | null) => {
return datetime // return value ? moment(value).format('lll') : value
? value.getFullYear() + // },
'-' + })
(value.getMonth() + 1) + public updated_at: DateTime;
'-' +
value.getDate() +
' ' +
value.getHours() +
':' +
value.getMinutes() +
':' +
value.getSeconds()
: datetime
}
@belongsTo(() => User) public static boot() {
public user: BelongsTo<typeof User> super.boot();
@belongsTo(() => Role) this.before('create', async (_modelInstance) => {
public role: BelongsTo<typeof Role> _modelInstance.created_at = this.formatDateTime(_modelInstance.created_at);
_modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at);
});
this.before('update', async (_modelInstance) => {
_modelInstance.created_at = this.formatDateTime(_modelInstance.created_at);
_modelInstance.updated_at = this.formatDateTime(_modelInstance.updated_at);
});
}
private static formatDateTime(datetime) {
let value = new Date(datetime);
return datetime
? value.getFullYear() +
'-' +
(value.getMonth() + 1) +
'-' +
value.getDate() +
' ' +
value.getHours() +
':' +
value.getMinutes() +
':' +
value.getSeconds()
: datetime;
}
@belongsTo(() => User)
public user: BelongsTo<typeof User>;
@belongsTo(() => Role)
public role: BelongsTo<typeof Role>;
} }

View File

@ -2,45 +2,45 @@ import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
export default class AuthValidator { export default class AuthValidator {
constructor(protected ctx: HttpContextContract) {} constructor(protected ctx: HttpContextContract) {}
/* /*
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data. * Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
* *
* For example: * For example:
* 1. The username must be of data type string. But then also, it should * 1. The username must be of data type string. But then also, it should
* not contain special characters or numbers. * not contain special characters or numbers.
* ``` * ```
* schema.string({}, [ rules.alpha() ]) * schema.string({}, [ rules.alpha() ])
* ``` * ```
* *
* 2. The email must be of data type string, formatted as a valid * 2. The email must be of data type string, formatted as a valid
* email. But also, not used by any other user. * email. But also, not used by any other user.
* ``` * ```
* schema.string({}, [ * schema.string({}, [
* rules.email(), * rules.email(),
* rules.unique({ table: 'users', column: 'email' }), * rules.unique({ table: 'users', column: 'email' }),
* ]) * ])
* ``` * ```
*/ */
public schema = schema.create({ public schema = schema.create({
email: schema.string({ trim: true }, [ email: schema.string({ trim: true }, [
rules.email(), rules.email(),
// rules.unique({ table: 'accounts', column: 'email' }) // rules.unique({ table: 'accounts', column: 'email' })
]), ]),
password: schema.string({}, [rules.minLength(6)]), password: schema.string({}, [rules.minLength(6)]),
}); });
/** /**
* Custom messages for validation failures. You can make use of dot notation `(.)` * Custom messages for validation failures. You can make use of dot notation `(.)`
* for targeting nested fields and array expressions `(*)` for targeting all * for targeting nested fields and array expressions `(*)` for targeting all
* children of an array. For example: * children of an array. For example:
* *
* { * {
* 'profile.username.required': 'Username is required', * 'profile.username.required': 'Username is required',
* 'scores.*.number': 'Define scores as valid numbers' * 'scores.*.number': 'Define scores as valid numbers'
* } * }
* *
*/ */
public messages: CustomMessages = {}; public messages: CustomMessages = {};
} }

View File

@ -0,0 +1,157 @@
import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import dayjs from 'dayjs';
import { TitleTypes, DescriptionTypes } from 'Contracts/enums';
export default class CreateDatasetValidator {
constructor(protected ctx: HttpContextContract) {}
/*
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
*
* For example:
* 1. The username must be of data type string. But then also, it should
* not contain special characters or numbers.
* ```
* schema.string({}, [ rules.alpha() ])
* ```
*
* 2. The email must be of data type string, formatted as a valid
* email. But also, not used by any other user.
* ```
* schema.string({}, [
* rules.email(),
* rules.unique({ table: 'users', column: 'email' }),
* ])
* ```
*/
public schema = schema.create({
// first step
language: schema.string({ trim: true }, [
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
]),
licenses: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one license for the new dataset
rights: schema.string([rules.equalTo('true')]),
// second step
type: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
creating_corporation: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
titles: schema.array([rules.minLength(1)]).members(
schema.object().members({
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
type: schema.enum(Object.values(TitleTypes)),
language: schema.string({ trim: true }, [
rules.minLength(2),
rules.maxLength(255),
rules.translatedLanguage('/language', 'type'),
]),
}),
),
descriptions: schema.array([rules.minLength(1)]).members(
schema.object().members({
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
type: schema.enum(Object.values(DescriptionTypes)),
language: schema.string({ trim: true }, [
rules.minLength(2),
rules.maxLength(255),
rules.translatedLanguage('/language', 'type'),
]),
}),
),
authors: schema.array([rules.minLength(1)]).members(schema.object().members({ email: schema.string({ trim: true }) })),
// third step
project_id: schema.number.optional(),
embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]),
coverage: schema.object().members({
x_min: schema.number(),
x_max: schema.number(),
y_min: schema.number(),
y_max: schema.number(),
elevation_absolut: schema.number.optional(),
elevation_min: schema.number.optional([rules.requiredIfExists('elevation_max')]),
elevation_max: schema.number.optional([rules.requiredIfExists('elevation_min')]),
depth_absolut: schema.number.optional(),
depth_min: schema.number.optional([rules.requiredIfExists('depth_max')]),
depth_max: schema.number.optional([rules.requiredIfExists('depth_min')]),
}),
subjects: schema.array([rules.minLength(3), rules.uniqueArray('value')]).members(
schema.object().members({
value: schema.string({ trim: true }, [
rules.minLength(3),
rules.maxLength(255),
// rules.unique({ table: 'dataset_subjects', column: 'value' }),
]),
// type: schema.enum(Object.values(TitleTypes)),
language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
}),
),
// file: schema.file({
// size: '100mb',
// extnames: ['jpg', 'gif', 'png'],
// }),
files: schema.array([rules.minLength(1)]).members(
schema.file({
size: '100mb',
extnames: ['jpg', 'gif', 'png'],
}),
),
// upload: schema.object().members({
// label: schema.string({ trim: true }, [rules.maxLength(255)]),
// // label: schema.string({ trim: true }, [
// // // rules.minLength(3),
// // // rules.maxLength(255),
// // ]),
// }),
});
/**
* Custom messages for validation failures. You can make use of dot notation `(.)`
* for targeting nested fields and array expressions `(*)` for targeting all
* children of an array. For example:
*
* {
* 'profile.username.required': 'Username is required',
* 'scores.*.number': 'Define scores as valid numbers'
* }
*
*/
public messages: CustomMessages = {
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
'required': '{{ field }} is required',
'unique': '{{ field }} must be unique, and this value is already taken',
// 'confirmed': '{{ field }} is not correct',
'licences.minLength': 'at least {{ options.minLength }} permission must be defined',
'licences.*.number': 'Define roles as valid numbers',
'rights.equalTo': 'you must agree to continue',
'titles.0.value.minLength': 'Main Title must be at least {{ options.minLength }} characters long',
'titles.0.value.required': 'Main Title is required',
'titles.*.value.required': 'Additional title is required, if defined',
'titles.*.type.required': 'Additional title type is required',
'titles.*.language.required': 'Additional title language is required',
'titles.*.language.translatedLanguage': 'The language of the translated title must be different from the language of the dataset',
'descriptions.0.value.minLength': 'Main Abstract must be at least {{ options.minLength }} characters long',
'descriptions.0.value.required': 'Main Abstract is required',
'descriptions.*.value.required': 'Additional description is required, if defined',
'descriptions.*.type.required': 'Additional description type is required',
'descriptions.*.language.required': 'Additional description language is required',
'descriptions.*.language.translatedLanguage':
'The language of the translated description must be different from the language of the dataset',
'authors.minLength': 'at least {{ options.minLength }} author must be defined',
'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,
'subjects.minLength': 'at least {{ options.minLength }} keywords must be defined',
'subjects.uniqueArray': 'The {{ options.array }} array must have unique values based on the {{ options.field }} attribute.',
'subjects.*.value.required': 'keyword value is required',
'subjects.*.value.minLength': 'keyword value must be at least {{ options.minLength }} characters long',
'subjects.*.type.required': 'keyword type is required',
'subjects.*.language.required': 'language of keyword is required',
'files.*.size': 'file size is to big',
'files.extnames': 'file extension is not supported',
};
}

View File

@ -2,68 +2,68 @@ import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
export default class CreateRoleValidator { export default class CreateRoleValidator {
constructor(protected ctx: HttpContextContract) {} constructor(protected ctx: HttpContextContract) {}
/* /*
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data. * Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
* *
* For example: * For example:
* 1. The username must be of data type string. But then also, it should * 1. The username must be of data type string. But then also, it should
* not contain special characters or numbers. * not contain special characters or numbers.
* ``` * ```
* schema.string({}, [ rules.alpha() ]) * schema.string({}, [ rules.alpha() ])
* ``` * ```
* *
* 2. The email must be of data type string, formatted as a valid * 2. The email must be of data type string, formatted as a valid
* email. But also, not used by any other user. * email. But also, not used by any other user.
* ``` * ```
* schema.string({}, [ * schema.string({}, [
* rules.email(), * rules.email(),
* rules.unique({ table: 'users', column: 'email' }), * rules.unique({ table: 'users', column: 'email' }),
* ]) * ])
* ``` * ```
*/ */
public schema = schema.create({ public schema = schema.create({
name: schema.string({ trim: true }, [ name: schema.string({ trim: true }, [
rules.minLength(3), rules.minLength(3),
rules.maxLength(255), rules.maxLength(255),
rules.unique({ table: 'roles', column: 'name' }), rules.unique({ table: 'roles', column: 'name' }),
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
]), ]),
display_name: schema.string.optional({ trim: true }, [ display_name: schema.string.optional({ trim: true }, [
rules.minLength(3), rules.minLength(3),
rules.maxLength(255), rules.maxLength(255),
rules.unique({ table: 'roles', column: 'name' }), rules.unique({ table: 'roles', column: 'name' }),
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
]), ]),
description: schema.string.optional({}, [rules.minLength(3), rules.maxLength(255)]), description: schema.string.optional({}, [rules.minLength(3), rules.maxLength(255)]),
permissions: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new role permissions: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new role
}); });
// emails: schema // emails: schema
// .array([rules.minLength(1)]) // .array([rules.minLength(1)])
// .members( // .members(
// schema.object().members({ email: schema.string({}, [rules.email()]) }) // schema.object().members({ email: schema.string({}, [rules.email()]) })
// ), // ),
/** /**
* Custom messages for validation failures. You can make use of dot notation `(.)` * Custom messages for validation failures. You can make use of dot notation `(.)`
* for targeting nested fields and array expressions `(*)` for targeting all * for targeting nested fields and array expressions `(*)` for targeting all
* children of an array. For example: * children of an array. For example:
* *
* { * {
* 'profile.username.required': 'Username is required', * 'profile.username.required': 'Username is required',
* 'scores.*.number': 'Define scores as valid numbers' * 'scores.*.number': 'Define scores as valid numbers'
* } * }
* *
*/ */
public messages: CustomMessages = { public messages: CustomMessages = {
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long', 'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long', 'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
'required': '{{ field }} is required', 'required': '{{ field }} is required',
'unique': '{{ field }} must be unique, and this value is already taken', 'unique': '{{ field }} must be unique, and this value is already taken',
'confirmed': '{{ field }} is not correct', 'confirmed': '{{ field }} is not correct',
'permissions.minLength': 'at least {{ options.minLength }} permission must be defined', 'permissions.minLength': 'at least {{ options.minLength }} permission must be defined',
'permissions.*.number': 'Define roles as valid numbers', 'permissions.*.number': 'Define roles as valid numbers',
}; };
} }

View File

@ -2,63 +2,63 @@ import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
export default class CreateUserValidator { export default class CreateUserValidator {
constructor(protected ctx: HttpContextContract) {} constructor(protected ctx: HttpContextContract) {}
/* /*
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data. * Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
* *
* For example: * For example:
* 1. The username must be of data type string. But then also, it should * 1. The username must be of data type string. But then also, it should
* not contain special characters or numbers. * not contain special characters or numbers.
* ``` * ```
* schema.string({}, [ rules.alpha() ]) * schema.string({}, [ rules.alpha() ])
* ``` * ```
* *
* 2. The email must be of data type string, formatted as a valid * 2. The email must be of data type string, formatted as a valid
* email. But also, not used by any other user. * email. But also, not used by any other user.
* ``` * ```
* schema.string({}, [ * schema.string({}, [
* rules.email(), * rules.email(),
* rules.unique({ table: 'users', column: 'email' }), * rules.unique({ table: 'users', column: 'email' }),
* ]) * ])
* ``` * ```
*/ */
public schema = schema.create({ public schema = schema.create({
login: schema.string({ trim: true }, [ login: schema.string({ trim: true }, [
rules.minLength(3), rules.minLength(3),
rules.maxLength(50), rules.maxLength(50),
rules.unique({ table: 'accounts', column: 'login' }), rules.unique({ table: 'accounts', column: 'login' }),
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
]), ]),
email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]), email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]),
password: schema.string([rules.confirmed(), rules.minLength(6)]), password: schema.string([rules.confirmed(), rules.minLength(6)]),
roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user
}); });
// emails: schema // emails: schema
// .array([rules.minLength(1)]) // .array([rules.minLength(1)])
// .members( // .members(
// schema.object().members({ email: schema.string({}, [rules.email()]) }) // schema.object().members({ email: schema.string({}, [rules.email()]) })
// ), // ),
/** /**
* Custom messages for validation failures. You can make use of dot notation `(.)` * Custom messages for validation failures. You can make use of dot notation `(.)`
* for targeting nested fields and array expressions `(*)` for targeting all * for targeting nested fields and array expressions `(*)` for targeting all
* children of an array. For example: * children of an array. For example:
* *
* { * {
* 'profile.username.required': 'Username is required', * 'profile.username.required': 'Username is required',
* 'scores.*.number': 'Define scores as valid numbers' * 'scores.*.number': 'Define scores as valid numbers'
* } * }
* *
*/ */
public messages: CustomMessages = { public messages: CustomMessages = {
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long', 'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long', 'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
'required': '{{ field }} is required', 'required': '{{ field }} is required',
'unique': '{{ field }} must be unique, and this value is already taken', 'unique': '{{ field }} must be unique, and this value is already taken',
'confirmed': '{{ field }} is not correct', 'confirmed': '{{ field }} is not correct',
'roles.minLength': 'at least {{ options.minLength }} role must be defined', 'roles.minLength': 'at least {{ options.minLength }} role must be defined',
'roles.*.number': 'Define roles as valid numbers' 'roles.*.number': 'Define roles as valid numbers',
}; };
} }

View File

@ -3,95 +3,95 @@ import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
// import { Request } from '@adonisjs/core/build/standalone'; // import { Request } from '@adonisjs/core/build/standalone';
export default class UpdateRoleValidator { export default class UpdateRoleValidator {
protected ctx: HttpContextContract; protected ctx: HttpContextContract;
public schema; public schema;
constructor(ctx: HttpContextContract) { constructor(ctx: HttpContextContract) {
this.ctx = ctx; this.ctx = ctx;
this.schema = this.createSchema(); this.schema = this.createSchema();
} }
// public get schema() { // public get schema() {
// return this._schema; // return this._schema;
// } // }
private createSchema() { private createSchema() {
return schema.create({ return schema.create({
name: schema.string({ trim: true }, [ name: schema.string({ trim: true }, [
rules.minLength(3), rules.minLength(3),
rules.maxLength(50), rules.maxLength(50),
rules.unique({ rules.unique({
table: 'roles', table: 'roles',
column: 'name', column: 'name',
whereNot: { id: this.ctx?.params.id }, whereNot: { id: this.ctx?.params.id },
}), }),
rules.regex(/^[a-zA-Z0-9-_]+$/), rules.regex(/^[a-zA-Z0-9-_]+$/),
//Must be alphanumeric with hyphens or underscores //Must be alphanumeric with hyphens or underscores
]), ]),
description: schema.string.optional({}, [rules.minLength(3), rules.maxLength(255)]), description: schema.string.optional({}, [rules.minLength(3), rules.maxLength(255)]),
permissions: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one permission for the new role permissions: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one permission for the new role
}); });
} }
/* /*
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data. * Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
* *
* For example: * For example:
* 1. The username must be of data type string. But then also, it should * 1. The username must be of data type string. But then also, it should
* not contain special characters or numbers. * not contain special characters or numbers.
* ``` * ```
* schema.string({}, [ rules.alpha() ]) * schema.string({}, [ rules.alpha() ])
* ``` * ```
* *
* 2. The email must be of data type string, formatted as a valid * 2. The email must be of data type string, formatted as a valid
* email. But also, not used by any other user. * email. But also, not used by any other user.
* ``` * ```
* schema.string({}, [ * schema.string({}, [
* rules.email(), * rules.email(),
* rules.unique({ table: 'users', column: 'email' }), * rules.unique({ table: 'users', column: 'email' }),
* ]) * ])
* ``` * ```
*/ */
// public refs = schema.refs({ // public refs = schema.refs({
// id: this.ctx.params.id // id: this.ctx.params.id
// }) // })
// public schema = schema.create({ // public schema = schema.create({
// login: schema.string({ trim: true }, [ // login: schema.string({ trim: true }, [
// rules.minLength(3), // rules.minLength(3),
// rules.maxLength(50), // rules.maxLength(50),
// rules.unique({ // rules.unique({
// table: 'accounts', // table: 'accounts',
// column: 'login', // column: 'login',
// // whereNot: { id: this.refs.id } // // whereNot: { id: this.refs.id }
// whereNot: { id: this.ctx?.params.id }, // whereNot: { id: this.ctx?.params.id },
// }), // }),
// // rules.regex(/^[a-zA-Z0-9-_]+$/), // // rules.regex(/^[a-zA-Z0-9-_]+$/),
// //Must be alphanumeric with hyphens or underscores // //Must be alphanumeric with hyphens or underscores
// ]), // ]),
// email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]), // email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]),
// password: schema.string.optional([rules.confirmed(), rules.minLength(6)]), // password: schema.string.optional([rules.confirmed(), rules.minLength(6)]),
// roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user // roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user
// }); // });
/** /**
* Custom messages for validation failures. You can make use of dot notation `(.)` * Custom messages for validation failures. You can make use of dot notation `(.)`
* for targeting nested fields and array expressions `(*)` for targeting all * for targeting nested fields and array expressions `(*)` for targeting all
* children of an array. For example: * children of an array. For example:
* *
* { * {
* 'profile.username.required': 'Username is required', * 'profile.username.required': 'Username is required',
* 'scores.*.number': 'Define scores as valid numbers' * 'scores.*.number': 'Define scores as valid numbers'
* } * }
* *
*/ */
public messages: CustomMessages = { public messages: CustomMessages = {
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long', 'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long', 'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
'required': '{{ field }} is required', 'required': '{{ field }} is required',
'unique': '{{ field }} must be unique, and this value is already taken', 'unique': '{{ field }} must be unique, and this value is already taken',
'permissions.minLength': 'at least {{ options.minLength }} permission must be defined', 'permissions.minLength': 'at least {{ options.minLength }} permission must be defined',
'permissions.*.number': 'Define permissions as valid numbers', 'permissions.*.number': 'Define permissions as valid numbers',
}; };
} }

View File

@ -1,5 +1,6 @@
declare module '@ioc:Adonis/Core/Validator' { declare module '@ioc:Adonis/Core/Validator' {
interface Rules { interface Rules {
translatedLanguage(mainLanguageField: string, typeField: string): Rule; translatedLanguage(mainLanguageField: string, typeField: string): Rule;
uniqueArray(field: string): Rule;
} }
} }

View File

@ -12,7 +12,7 @@ export default class DatasetTitles extends BaseSchema {
.foreign('document_id', 'dataset_titles_document_id_foreign') .foreign('document_id', 'dataset_titles_document_id_foreign')
.references('id') .references('id')
.inTable('documents') .inTable('documents')
.onDelete('CASCADE') // delete this titke when document is deleted .onDelete('CASCADE') // delete this title when document is deleted
.onUpdate('CASCADE'); .onUpdate('CASCADE');
// table.string('type', 255).notNullable(); // table.string('type', 255).notNullable();
table.enum('type', Object.values(TitleTypes)).notNullable(); table.enum('type', Object.values(TitleTypes)).notNullable();

View File

@ -20,6 +20,7 @@ export default class Persons extends BaseSchema {
table.integer('registered_at'); table.integer('registered_at');
// table.string('name_type', 255); // table.string('name_type', 255);
table.enum('name_type', Object.values(PersonNameTypes)).notNullable(); table.enum('name_type', Object.values(PersonNameTypes)).notNullable();
table.timestamp('created_at', { useTz: false }).nullable();
}); });
} }

8
index.d.ts vendored
View File

@ -1,5 +1,5 @@
declare module '*.vue' { declare module '*.vue' {
import type { DefineComponent } from "vue" import type { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any> const component: DefineComponent<{}, {}, any>;
export default component export default component;
} }

166
package-lock.json generated
View File

@ -9,7 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@adonisjs/auth": "^8.2.3", "@adonisjs/auth": "^8.2.3",
"@adonisjs/core": "^5.8.3", "@adonisjs/core": "^5.9.0",
"@adonisjs/lucid": "^18.3.0", "@adonisjs/lucid": "^18.3.0",
"@adonisjs/repl": "^3.1.11", "@adonisjs/repl": "^3.1.11",
"@adonisjs/session": "^6.4.0", "@adonisjs/session": "^6.4.0",
@ -571,9 +571,9 @@
} }
}, },
"node_modules/@adonisjs/shield": { "node_modules/@adonisjs/shield": {
"version": "7.1.0", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/@adonisjs/shield/-/shield-7.1.0.tgz", "resolved": "https://registry.npmjs.org/@adonisjs/shield/-/shield-7.1.1.tgz",
"integrity": "sha512-+a4Z+LBcWd46gMh99Wf0+iJMowq4aKuD04kvYB4AgTV78ffn21AXq3bsnoklFACkidEJwZ3FlRfQfKE+z1vg+g==", "integrity": "sha512-y1YzXwravcS/A1yxcyfSD/UrRi2+H9v0ntX9NgVhLYvBF5eHuPzQKgv9sICVjmj2z7n94HzcTAio0Rc32EX51Q==",
"dependencies": { "dependencies": {
"@poppinss/utils": "^4.0.4", "@poppinss/utils": "^4.0.4",
"csrf": "^3.1.0", "csrf": "^3.1.0",
@ -2765,9 +2765,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "8.42.0", "version": "8.43.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
"integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -4094,15 +4094,15 @@
"dev": true "dev": true
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.59.11", "version": "5.60.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.11.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz",
"integrity": "sha512-XxuOfTkCUiOSyBWIvHlUraLw/JT/6Io1365RO6ZuI88STKMavJZPNMU0lFcUTeQXEhHiv64CbxYxBNoDVSmghg==", "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.4.0", "@eslint-community/regexpp": "^4.4.0",
"@typescript-eslint/scope-manager": "5.59.11", "@typescript-eslint/scope-manager": "5.60.0",
"@typescript-eslint/type-utils": "5.59.11", "@typescript-eslint/type-utils": "5.60.0",
"@typescript-eslint/utils": "5.59.11", "@typescript-eslint/utils": "5.60.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"grapheme-splitter": "^1.0.4", "grapheme-splitter": "^1.0.4",
"ignore": "^5.2.0", "ignore": "^5.2.0",
@ -4128,14 +4128,14 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "5.59.11", "version": "5.60.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.11.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz",
"integrity": "sha512-s9ZF3M+Nym6CAZEkJJeO2TFHHDsKAM3ecNkLuH4i4s8/RCPnF5JRip2GyviYkeEAcwGMJxkqG9h2dAsnA1nZpA==", "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.59.11", "@typescript-eslint/scope-manager": "5.60.0",
"@typescript-eslint/types": "5.59.11", "@typescript-eslint/types": "5.60.0",
"@typescript-eslint/typescript-estree": "5.59.11", "@typescript-eslint/typescript-estree": "5.60.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -4155,13 +4155,13 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "5.59.11", "version": "5.60.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.11.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz",
"integrity": "sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q==", "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.59.11", "@typescript-eslint/types": "5.60.0",
"@typescript-eslint/visitor-keys": "5.59.11" "@typescript-eslint/visitor-keys": "5.60.0"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -4172,13 +4172,13 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "5.59.11", "version": "5.60.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.11.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz",
"integrity": "sha512-LZqVY8hMiVRF2a7/swmkStMYSoXMFlzL6sXV6U/2gL5cwnLWQgLEG8tjWPpaE4rMIdZ6VKWwcffPlo1jPfk43g==", "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "5.59.11", "@typescript-eslint/typescript-estree": "5.60.0",
"@typescript-eslint/utils": "5.59.11", "@typescript-eslint/utils": "5.60.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"tsutils": "^3.21.0" "tsutils": "^3.21.0"
}, },
@ -4199,9 +4199,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "5.59.11", "version": "5.60.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.11.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz",
"integrity": "sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA==", "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -4212,13 +4212,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "5.59.11", "version": "5.60.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.11.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz",
"integrity": "sha512-YupOpot5hJO0maupJXixi6l5ETdrITxeo5eBOeuV7RSKgYdU3G5cxO49/9WRnJq9EMrB7AuTSLH/bqOsXi7wPA==", "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.59.11", "@typescript-eslint/types": "5.60.0",
"@typescript-eslint/visitor-keys": "5.59.11", "@typescript-eslint/visitor-keys": "5.60.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -4289,17 +4289,17 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "5.59.11", "version": "5.60.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.11.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz",
"integrity": "sha512-didu2rHSOMUdJThLk4aZ1Or8IcO3HzCw/ZvEjTTIfjIrcdd5cvSIwwDy2AOlE7htSNp7QIZ10fLMyRCveesMLg==", "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@types/json-schema": "^7.0.9", "@types/json-schema": "^7.0.9",
"@types/semver": "^7.3.12", "@types/semver": "^7.3.12",
"@typescript-eslint/scope-manager": "5.59.11", "@typescript-eslint/scope-manager": "5.60.0",
"@typescript-eslint/types": "5.59.11", "@typescript-eslint/types": "5.60.0",
"@typescript-eslint/typescript-estree": "5.59.11", "@typescript-eslint/typescript-estree": "5.60.0",
"eslint-scope": "^5.1.1", "eslint-scope": "^5.1.1",
"semver": "^7.3.7" "semver": "^7.3.7"
}, },
@ -4337,12 +4337,12 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "5.59.11", "version": "5.60.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.11.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz",
"integrity": "sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA==", "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.59.11", "@typescript-eslint/types": "5.60.0",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
}, },
"engines": { "engines": {
@ -4723,9 +4723,9 @@
} }
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.8.2", "version": "8.9.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -5741,9 +5741,9 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.21.8", "version": "4.21.9",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.8.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
"integrity": "sha512-j+7xYe+v+q2Id9qbBeCI8WX5NmZSRe8es1+0xntD/+gaWXznP8tFEkv5IgSaHf5dS1YwVMbX/4W6m937mj+wQw==", "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -5760,8 +5760,8 @@
} }
], ],
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001502", "caniuse-lite": "^1.0.30001503",
"electron-to-chromium": "^1.4.428", "electron-to-chromium": "^1.4.431",
"node-releases": "^2.0.12", "node-releases": "^2.0.12",
"update-browserslist-db": "^1.0.11" "update-browserslist-db": "^1.0.11"
}, },
@ -5943,9 +5943,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001503", "version": "1.0.30001506",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001506.tgz",
"integrity": "sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==", "integrity": "sha512-6XNEcpygZMCKaufIcgpQNZNf00GEqc7VQON+9Rd0K1bMYo8xhMZRAo5zpbnbMNizi4YNgIDAFrdykWsvY3H4Hw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -7498,9 +7498,9 @@
} }
}, },
"node_modules/dotenv": { "node_modules/dotenv": {
"version": "16.1.4", "version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==", "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@ -7648,9 +7648,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.431", "version": "1.4.436",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.431.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.436.tgz",
"integrity": "sha512-m232JTVmCawA2vG+1azVxhKZ9Sv1Q//xxNv5PkP5rWxGgQE8c3CiZFrh8Xnp+d1NmNxlu3QQrGIfdeW5TtXX5w==", "integrity": "sha512-aktOxo8fnrMC8vOIBMVS3PXbT1nrPQ+SouUuN7Y0a+Rw3pOMrvIV92Ybnax7x4tugA+ZpYA5fOHTby7ama8OQQ==",
"dev": true "dev": true
}, },
"node_modules/emittery": { "node_modules/emittery": {
@ -7729,9 +7729,9 @@
} }
}, },
"node_modules/envinfo": { "node_modules/envinfo": {
"version": "7.8.1", "version": "7.9.0",
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.9.0.tgz",
"integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", "integrity": "sha512-RODB4txU+xImYDemN5DqaKC0CHk05XSVkOX4pq0hK26Qx+1LChkuOyUDlGEjYb3ACr0n9qBhFjg37hQuJvpkRQ==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"bin": { "bin": {
@ -7798,15 +7798,15 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.42.0", "version": "8.43.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
"integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.4.0", "@eslint-community/regexpp": "^4.4.0",
"@eslint/eslintrc": "^2.0.3", "@eslint/eslintrc": "^2.0.3",
"@eslint/js": "8.42.0", "@eslint/js": "8.43.0",
"@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
@ -12641,9 +12641,9 @@
} }
}, },
"node_modules/pirates": { "node_modules/pirates": {
"version": "4.0.5", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
"integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
@ -14206,9 +14206,9 @@
} }
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "7.5.1", "version": "7.5.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
"integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"dependencies": { "dependencies": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
}, },
@ -15477,9 +15477,9 @@
} }
}, },
"node_modules/terser": { "node_modules/terser": {
"version": "5.18.0", "version": "5.18.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.18.0.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.18.1.tgz",
"integrity": "sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==", "integrity": "sha512-j1n0Ao919h/Ai5r43VAnfV/7azUYW43GPxK7qSATzrsERfW7+y2QW9Cp9ufnRF5CQUWbnLSo7UJokSWCqg4tsQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@jridgewell/source-map": "^0.3.3", "@jridgewell/source-map": "^0.3.3",
@ -16408,9 +16408,9 @@
} }
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.87.0", "version": "5.88.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.87.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.0.tgz",
"integrity": "sha512-GOu1tNbQ7p1bDEoFRs2YPcfyGs8xq52yyPBZ3m2VGnXGtV9MxjrkABHm4V9Ia280OefsSLzvbVoXcfLxjKY/Iw==", "integrity": "sha512-O3jDhG5e44qIBSi/P6KpcCcH7HD+nYIHVBhdWFxcLOcIGN8zGo5nqF3BjyNCxIh4p1vFdNnreZv2h2KkoAw3lw==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {

View File

@ -9,7 +9,7 @@
"start": "node server.js", "start": "node server.js",
"lint": "eslint . --ext=.ts", "lint": "eslint . --ext=.ts",
"format": "prettier --write .", "format": "prettier --write .",
"format-check": "prettier --check ./**/*.ts", "format-check": "prettier --check ./**/*.{ts,js}",
"test": "node ace test" "test": "node ace test"
}, },
"eslintConfig": { "eslintConfig": {
@ -74,7 +74,7 @@
}, },
"dependencies": { "dependencies": {
"@adonisjs/auth": "^8.2.3", "@adonisjs/auth": "^8.2.3",
"@adonisjs/core": "^5.8.3", "@adonisjs/core": "^5.9.0",
"@adonisjs/lucid": "^18.3.0", "@adonisjs/lucid": "^18.3.0",
"@adonisjs/repl": "^3.1.11", "@adonisjs/repl": "^3.1.11",
"@adonisjs/session": "^6.4.0", "@adonisjs/session": "^6.4.0",

View File

@ -1,6 +1,6 @@
module.exports = { module.exports = {
plugins: { plugins: {
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },
} };

View File

@ -1,34 +1,43 @@
import { Ref } from 'vue'; import { Ref } from 'vue';
export interface Dataset { export interface Dataset {
[key: string]: string | Ref<string>| boolean | Array<Title> | Array<Description>| Array<Person> | number | (IErrorMessage | undefined) | Coverage | Array<File>; [key: string]:
language: Ref<string>; | string
// licenses: Array<number>; | Ref<string>
rights: boolean; | boolean
type: string; | Array<Title>
creating_corporation: string; | Array<Description>
| Array<Person>
| number
| (IErrorMessage | undefined)
| Coverage
| Array<File>;
language: Ref<string>;
// licenses: Array<number>;
rights: boolean;
type: string;
creating_corporation: string;
titles: Array<Title>; titles: Array<Title>;
descriptions: Array<Description>; descriptions: Array<Description>;
authors: Array<Person>; authors: Array<Person>;
contributors: Array<Person>; contributors: Array<Person>;
project_id?: number; project_id?: number;
embargo_date?: string, embargo_date?: string;
coverage: Coverage, coverage: Coverage;
errors?: IErrorMessage; errors?: IErrorMessage;
// async (user): Promise<void>; // async (user): Promise<void>;
subjects: Array<Subject>, subjects: Array<Subject>;
files: Array<TestFile> | undefined, files: Array<TestFile> | undefined;
// upload: TethysFile // upload: TethysFile
} }
/** Provides information about files and allows JavaScript in a web page to access their content. */ /** Provides information about files and allows JavaScript in a web page to access their content. */
export interface TestFile extends Blob { export interface TestFile extends Blob {
readonly lastModified: number; readonly lastModified: number;
readonly name: string; readonly name: string;
readonly webkitRelativePath: string; readonly webkitRelativePath: string;
label: string, label: string;
sorting: number, sorting: number;
} }
// export interface TethysFile { // export interface TethysFile {
@ -39,7 +48,7 @@ export interface TestFile extends Blob {
export interface Subject { export interface Subject {
// id: number; // id: number;
language: string language: string;
type: string; type: string;
value: string; value: string;
external_key?: string; external_key?: string;
@ -68,7 +77,7 @@ export interface Person {
} }
interface IErrorMessage { interface IErrorMessage {
[key: string]: Array<string>; [key: string]: Array<string>;
} }
export interface Coverage { export interface Coverage {
@ -84,7 +93,7 @@ export interface Coverage {
depth_max?: number; depth_max?: number;
depth_absolut?: number; depth_absolut?: number;
time_min?: number, time_min?: number;
time_max?: number, time_max?: number;
time_absolut?: number time_absolut?: number;
} }

View File

@ -1,25 +1,25 @@
export const basic = { export const basic = {
aside: "bg-gray-800", aside: 'bg-gray-800',
asideScrollbars: "aside-scrollbars-gray", asideScrollbars: 'aside-scrollbars-gray',
asideBrand: "bg-gray-900 text-white", asideBrand: 'bg-gray-900 text-white',
asideMenuItem: "text-gray-300 hover:text-white", asideMenuItem: 'text-gray-300 hover:text-white',
asideMenuItemActive: "font-bold text-white", asideMenuItemActive: 'font-bold text-white',
asideMenuDropdown: "bg-gray-700/50", asideMenuDropdown: 'bg-gray-700/50',
navBarItemLabel: "text-black", navBarItemLabel: 'text-black',
navBarItemLabelHover: "hover:text-blue-500", navBarItemLabelHover: 'hover:text-blue-500',
navBarItemLabelActiveColor: "text-blue-600", navBarItemLabelActiveColor: 'text-blue-600',
overlay: "from-gray-700 via-gray-900 to-gray-700", overlay: 'from-gray-700 via-gray-900 to-gray-700',
}; };
export const white = { export const white = {
aside: "bg-white", aside: 'bg-white',
asideScrollbars: "aside-scrollbars-light", asideScrollbars: 'aside-scrollbars-light',
asideBrand: "", asideBrand: '',
asideMenuItem: "text-blue-600 hover:text-black dark:text-white", asideMenuItem: 'text-blue-600 hover:text-black dark:text-white',
asideMenuItemActive: "font-bold text-black dark:text-white", asideMenuItemActive: 'font-bold text-black dark:text-white',
asideMenuDropdown: "bg-gray-100/75", asideMenuDropdown: 'bg-gray-100/75',
navBarItemLabel: "text-blue-600", navBarItemLabel: 'text-blue-600',
navBarItemLabelHover: "hover:text-black", navBarItemLabelHover: 'hover:text-black',
navBarItemLabelActiveColor: "text-black", navBarItemLabelActiveColor: 'text-black',
overlay: "from-white via-gray-100 to-white", overlay: 'from-white via-gray-100 to-white',
}; };

View File

@ -2,18 +2,18 @@ import Route from '@ioc:Adonis/Core/Route';
// API // API
Route.group(() => { Route.group(() => {
// Route.post("register", "AuthController.register"); // Route.post("register", "AuthController.register");
// Route.post("login", "AuthController.login"); // Route.post("login", "AuthController.login");
Route.group(() => { Route.group(() => {
Route.get('authors', 'AuthorsController.index').as('author.index'); Route.get('authors', 'AuthorsController.index').as('author.index');
Route.get('datasets', 'DatasetController.index').as('dataset.index'); Route.get('datasets', 'DatasetController.index').as('dataset.index');
Route.get('persons', 'AuthorsController.persons').as('author.persons'); Route.get('persons', 'AuthorsController.persons').as('author.persons');
// Route.get("author/:id", "TodosController.show"); // Route.get("author/:id", "TodosController.show");
// Route.put("author/update", "TodosController.update"); // Route.put("author/update", "TodosController.update");
// Route.post("author", "TodosController.store"); // Route.post("author", "TodosController.store");
}); });
// .middleware("auth:api"); // .middleware("auth:api");
}) })
.namespace('App/Controllers/Http/Api') .namespace('App/Controllers/Http/Api')
.prefix('api'); .prefix('api');

View File

@ -11,6 +11,34 @@ https://issuehunt.io/r/adonisjs/validator/issues/84
// import { string } from '@ioc:Adonis/Core/Helpers'; // import { string } from '@ioc:Adonis/Core/Helpers';
import { validator } from '@ioc:Adonis/Core/Validator'; import { validator } from '@ioc:Adonis/Core/Validator';
validator.rule('uniqueArray', (dataArray, [field], { pointer, arrayExpressionPointer, errorReporter }) => {
const array = dataArray; //validator.helpers.getFieldValue(data, field, tip);
if (!Array.isArray(array)) {
throw new Error(`The ${pointer} must be an array.`);
}
const uniqueValues = new Set();
for (let i = 0; i < array.length; i++) {
const item = array[i];
const attributeValue = item[field]; // Extract the attribute value for uniqueness check
if (uniqueValues.has(attributeValue)) {
// throw new Error(`The ${field} array contains duplicate values for the ${field} attribute.`)
errorReporter.report(
pointer,
'uniqueArray', // Keep an eye on this
`The ${pointer} array contains duplicate values for the ${field} attribute.`,
arrayExpressionPointer,
{ field, array: pointer },
);
return;
}
uniqueValues.add(attributeValue);
}
});
validator.rule( validator.rule(
'translatedLanguage', 'translatedLanguage',
(value, [mainLanguageField, typeField], { root, tip, pointer, arrayExpressionPointer, errorReporter }) => { (value, [mainLanguageField, typeField], { root, tip, pointer, arrayExpressionPointer, errorReporter }) => {

View File

@ -15,10 +15,10 @@ module.exports = {
'primary': '#22C55E', 'primary': '#22C55E',
'primary-dark': '#DCFCE7', 'primary-dark': '#DCFCE7',
}, },
// fontFamily: { fontFamily: {
// sans: ['Inter', ...defaultTheme.fontFamily.sans], sans: ['Inter', ...defaultTheme.fontFamily.sans],
// logo: ['Archivo Black', ...defaultTheme.fontFamily.sans], logo: ['Archivo Black', ...defaultTheme.fontFamily.sans],
// }, },
zIndex: { zIndex: {
'-1': '-1', '-1': '-1',
}, },
@ -61,9 +61,7 @@ module.exports = {
return { return {
'scrollbarWidth': 'thin', 'scrollbarWidth': 'thin',
'scrollbarColor': `${theme(`colors.${color}.${thumb}`)} ${theme( 'scrollbarColor': `${theme(`colors.${color}.${thumb}`)} ${theme(`colors.${color}.${track}`)}`,
`colors.${color}.${track}`,
)}`,
'&::-webkit-scrollbar': { '&::-webkit-scrollbar': {
width: '8px', width: '8px',
height: '8px', height: '8px',

View File

@ -3,39 +3,39 @@ const Encore = require('@symfony/webpack-encore');
const { VueLoaderPlugin } = require('vue-loader'); const { VueLoaderPlugin } = require('vue-loader');
const babelLoader = { const babelLoader = {
// test: /\.js$/, // test: /\.js$/,
test: /\.(js|jsx|ts|tsx)$/, test: /\.(js|jsx|ts|tsx)$/,
// exclude: /(node_modules|bower_components)/, // exclude: /(node_modules|bower_components)/,
// exclude: file => ( // exclude: file => (
// /node_modules/.test(file) && // /node_modules/.test(file) &&
// !/\.vue\.js/.test(file) // !/\.vue\.js/.test(file)
// ), // ),
exclude: /node_modules/, exclude: /node_modules/,
use: { use: {
loader: 'babel-loader', loader: 'babel-loader',
options: { options: {
presets: [ presets: [
// ['@babel/preset-env', { // ['@babel/preset-env', {
// "targets": "> 0.25%, not dead" // "targets": "> 0.25%, not dead"
// // "targets": { // // "targets": {
// // "edge": "17", // // "edge": "17",
// // "firefox": "60", // // "firefox": "60",
// // "chrome": "67", // // "chrome": "67",
// // "safari": "11.1" // // "safari": "11.1"
// // } // // }
// }], // }],
['@babel/preset-env', {}], ['@babel/preset-env', {}],
'babel-preset-typescript-vue3', //because of new vue setup method 'babel-preset-typescript-vue3', //because of new vue setup method
// "@babel/preset-typescript" // "@babel/preset-typescript"
], ],
plugins: [ plugins: [
// "@babel/plugin-transform-runtime", // "@babel/plugin-transform-runtime",
['@babel/plugin-proposal-decorators', { legacy: true }], ['@babel/plugin-proposal-decorators', { legacy: true }],
'@babel/proposal-class-properties', '@babel/proposal-class-properties',
], ],
}, },
}, },
}; };
// const Components = require('unplugin-vue-components/webpack') // const Components = require('unplugin-vue-components/webpack')
@ -47,7 +47,7 @@ const babelLoader = {
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
if (!Encore.isRuntimeEnvironmentConfigured()) { if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev'); Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
} }
/* /*
@ -168,23 +168,23 @@ Encore.enableVersioning(Encore.isProduction());
| |
*/ */
Encore.configureDevServerOptions((options) => { Encore.configureDevServerOptions((options) => {
/** /**
* Normalize "options.static" property to an array * Normalize "options.static" property to an array
*/ */
if (!options.static) { if (!options.static) {
options.static = []; options.static = [];
} else if (!Array.isArray(options.static)) { } else if (!Array.isArray(options.static)) {
options.static = [options.static]; options.static = [options.static];
} }
/** /**
* Enable live reload and add views directory * Enable live reload and add views directory
*/ */
options.liveReload = true; options.liveReload = true;
options.static.push({ options.static.push({
directory: join(__dirname, './resources/views'), directory: join(__dirname, './resources/views'),
watch: true, watch: true,
}); });
}); });
/* /*
@ -268,42 +268,41 @@ Encore.enablePostCssLoader();
// // } // // }
// }) // })
Encore.addLoader({ Encore.addLoader({
test: /\.vue$/, test: /\.vue$/,
loader: 'vue-loader', loader: 'vue-loader',
options: { options: {
// loaders: { // loaders: {
// ts: 'ts-loader', // ts: 'ts-loader',
// }, // },
cacheDirectory: 'C:\\Users\\kaiarn\\Documents\\Software\\tethys.viewer\\node_modules\\.cache\\vue-loader', cacheDirectory: 'C:\\Users\\kaiarn\\Documents\\Software\\tethys.viewer\\node_modules\\.cache\\vue-loader',
cacheIdentifier: 'f930df3e', cacheIdentifier: 'f930df3e',
babelParserPlugins: ['jsx', 'classProperties', 'decorators-legacy'], babelParserPlugins: ['jsx', 'classProperties', 'decorators-legacy'],
}, },
}) }).addPlugin(new VueLoaderPlugin());
.addPlugin(new VueLoaderPlugin()) // .addAliases({
// .addAliases({ // vue$: 'vue/dist/vue.runtime.esm-bundler.js',
// vue$: 'vue/dist/vue.runtime.esm-bundler.js', // });
// });
Encore.addLoader(babelLoader) Encore.addLoader(babelLoader)
// Encore.enableTypeScriptLoader(config => { // Encore.enableTypeScriptLoader(config => {
// // Loader-specific options // // Loader-specific options
// config.configFile = 'tsconfig.vue.json'; // config.configFile = 'tsconfig.vue.json';
// config.appendTsSuffixTo = [/\.vue$/]; // config.appendTsSuffixTo = [/\.vue$/];
// config.transpileOnly = true; // config.transpileOnly = true;
// config.happyPackMode = false; // config.happyPackMode = false;
// }, { // }, {
// // Directly change the exclude rule // // Directly change the exclude rule
// exclude: /node_modules/, // exclude: /node_modules/,
// }) // })
.addAliases({ .addAliases({
'@': join(__dirname, 'resources/js'), '@': join(__dirname, 'resources/js'),
vue$: 'vue/dist/vue.runtime.esm-bundler.js' 'vue$': 'vue/dist/vue.runtime.esm-bundler.js',
}) })
.configureDefinePlugin((options) => { .configureDefinePlugin((options) => {
options['__VUE_OPTIONS_API__'] = true; options['__VUE_OPTIONS_API__'] = true;
options['__VUE_PROD_DEVTOOLS__'] = false; options['__VUE_PROD_DEVTOOLS__'] = false;
}); });
// Encore.addAliases({ // Encore.addAliases({
// '@': resolve(__dirname, 'resources/js') // '@': resolve(__dirname, 'resources/js')
@ -364,7 +363,7 @@ Encore.addLoader(babelLoader)
*/ */
const config = Encore.getWebpackConfig(); const config = Encore.getWebpackConfig();
config.infrastructureLogging = { config.infrastructureLogging = {
level: 'warn', level: 'warn',
}; };
config.stats = 'errors-warnings'; config.stats = 'errors-warnings';
// config.resolve.extensions.push('.vue'); // config.resolve.extensions.push('.vue');
@ -381,7 +380,7 @@ config.stats = 'errors-warnings';
// // // '@': path.resolve(__dirname, 'resources/js'), // // // '@': path.resolve(__dirname, 'resources/js'),
// // } // // }
// }; // };
config.resolve.extensions = [ '.tsx', '.ts', '.mjs', '.js', '.jsx', '.vue', '.json', '.wasm']; config.resolve.extensions = ['.tsx', '.ts', '.mjs', '.js', '.jsx', '.vue', '.json', '.wasm'];
// config.resolve = { // config.resolve = {
// // vue: 'vue/dist/vue.js' // // vue: 'vue/dist/vue.js'
@ -390,8 +389,6 @@ config.resolve.extensions = [ '.tsx', '.ts', '.mjs', '.js', '.jsx', '.vue', '.js
// } // }
// } // }
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Export config | Export config