- now authenticated user can change password with check of old password and password confirmination
Some checks failed
CI Pipeline / japa-tests (push) Failing after 52s

- cchanged route app.dashboard to apps.dashboard
- add editor and reviewer relation to Dataset.ts
- added personal menu in asideMenu
- added Approve.vue for editor
- show warning in Index.vue  (editor), if no dataset is loaded
- user Receive.vue without inertia helper form
- npm updates
- added routes in routes.ts
This commit is contained in:
Kaimbacher 2023-12-12 15:22:25 +01:00
parent 0d51002903
commit ae0c471e93
14 changed files with 733 additions and 408 deletions

View file

@ -6,6 +6,8 @@ import CreateUserValidator from 'App/Validators/CreateUserValidator';
import UpdateUserValidator from 'App/Validators/UpdateUserValidator';
import { RenderResponse } from '@ioc:EidelLev/Inertia';
// import { schema, rules } from '@ioc:Adonis/Core/Validator';
import Hash from '@ioc:Adonis/Core/Hash';
import { schema, rules } from '@ioc:Adonis/Core/Validator';
export default class UsersController {
public async index({ auth, request, inertia }: HttpContextContract) {
@ -182,7 +184,7 @@ export default class UsersController {
* @param HttpContextContract ctx
* @return : RedirectContract
*/
public async accountInfoStore({ request, response, auth, session }: HttpContextContract) {
public async accountInfoStoreOld({ request, response, auth, session }: HttpContextContract) {
// validate update form
await request.validate(UpdateUserValidator);
@ -202,6 +204,46 @@ export default class UsersController {
//->with('message', __($message));
}
public async accountInfoStore({ auth, request, response, session }) {
const passwordSchema = schema.create({
old_password: schema.string({ trim: true }, [rules.required()]),
new_password: schema.string({ trim: true }, [rules.minLength(8), rules.maxLength(255), rules.confirmed('confirm_password')]),
confirm_password: schema.string({ trim: true }, [rules.required()]),
});
try {
await request.validate({ schema: passwordSchema });
} catch (error) {
// return response.badRequest(error.messages);
throw error;
}
try {
const user = await auth.user;
const { old_password, new_password } = request.only(['old_password', 'new_password']);
// if (!(old_password && new_password && confirm_password)) {
// return response.status(400).send({ message: 'Old password and new password are required.' });
// }
// Verify if the provided old password matches the user's current password
const isSame = await Hash.verify(user.password, old_password);
if (!isSame) {
return response.flash({ message: 'Old password is incorrect.' }).redirect().back();
}
// Hash the new password before updating the user's password
user.password = new_password;
await user.save();
// return response.status(200).send({ message: 'Password updated successfully.' });
session.flash('Password updated successfully.');
return response.redirect().toRoute('settings.user');
} catch (error) {
// return response.status(500).send({ message: 'Internal server error.' });
return response.flash('warning', `Invalid server state. Internal server error.`).redirect().back();
}
}
// private async syncRoles(userId: number, roleIds: Array<number>) {
// const user = await User.findOrFail(userId)
// // const roles: Role[] = await Role.query().whereIn('id', roleIds);

View file

@ -27,7 +27,7 @@ export default class AuthController {
}
// otherwise, redirect todashboard
response.redirect('/app/dashboard');
response.redirect('/apps/dashboard');
}
// logout function

View file

@ -8,12 +8,18 @@ import { create } from 'xmlbuilder2';
import { readFileSync } from 'fs';
import { transform } from 'saxon-js';
import type { ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm';
import { schema, CustomMessages } from '@ioc:Adonis/Core/Validator';
// Create a new instance of the client
const client = new Client({ node: 'http://localhost:9200' }); // replace with your OpenSearch endpoint
export default class DatasetsController {
private proc;
public messages: CustomMessages = {
// 'required': '{{ field }} is required',
// 'licenses.minLength': 'at least {{ options.minLength }} permission must be defined',
'reviewer_id.required': 'reviewer_id must be defined',
};
constructor() {
this.proc = readFileSync('public/assets2/solr.sef.json');
@ -60,6 +66,7 @@ export default class DatasetsController {
})
.preload('titles')
.preload('user', (query) => query.select('id', 'login'))
.preload('editor', (query) => query.select('id', 'login'))
.paginate(page, 10);
return inertia.render('Editor/Dataset/Index', {
@ -68,6 +75,7 @@ export default class DatasetsController {
can: {
// create: await auth.user?.can(['dataset-submit']),
receive: await auth.user?.can(['dataset-receive']),
approve: await auth.user?.can(['dataset-approve']),
edit: await auth.user?.can(['dataset-editor-edit']),
delete: await auth.user?.can(['dataset-editor-delete']),
},
@ -103,6 +111,106 @@ export default class DatasetsController {
});
}
public async receiveUpdate({ auth, request, response }) {
const id = request.param('id');
// const { id } = params;
const dataset = await Dataset.findOrFail(id);
const validStates = ['released'];
if (!validStates.includes(dataset.server_state)) {
// throw new Error('Invalid server state!');
// return response.flash('warning', 'Invalid server state. Dataset cannot be released to editor').redirect().back();
return response
.flash(
'warning',
`Invalid server state. Dataset with id ${id} cannot be received by editor. Datset has server state ${dataset.server_state}.`,
)
.redirect()
.toRoute('editor.dataset.list');
}
dataset.server_state = 'editor_accepted';
const user = (await User.find(auth.user?.id)) as User;
// dataset.editor().associate(user).save();
try {
await dataset.related('editor').associate(user); // speichert schon ab
// await dataset.save();
return response.toRoute('editor.dataset.list').flash('message', `You have accepted dataset ${dataset.id}!`);
} catch (error) {
// Handle any errors
console.error(error);
return response.status(500).json({ error: 'An error occurred while accepting the data.' });
}
}
public async approve({ request, inertia, response }) {
const id = request.param('id');
// $dataset = Dataset::with('user:id,login')->findOrFail($id);
const dataset = await Dataset.findOrFail(id);
const validStates = ['editor_accepted', 'rejected_reviewer'];
if (!validStates.includes(dataset.server_state)) {
// session.flash('errors', 'Invalid server state!');
return response
.flash(
'warning',
`Invalid server state. Dataset with id ${id} cannot be approved. Datset has server state ${dataset.server_state}.`,
)
.redirect()
.back();
}
const reviewers = await User.query()
.whereHas('roles', (builder) => {
builder.where('name', 'reviewer');
})
.pluck('login', 'id');
return inertia.render('Editor/Dataset/Approve', {
dataset,
reviewers,
});
}
public async approveUpdate({ request, response }) {
const approveDatasetSchema = schema.create({
reviewer_id: schema.number(),
});
try {
await request.validate({ schema: approveDatasetSchema, messages: this.messages });
} catch (error) {
// return response.badRequest(error.messages);
throw error;
}
const id = request.param('id');
const dataset = await Dataset.findOrFail(id);
const validStates = ['editor_accepted', 'rejected_reviewer'];
if (!validStates.includes(dataset.server_state)) {
// session.flash('errors', 'Invalid server state!');
return response
.flash(
'warning',
`Invalid server state. Dataset with id ${id} cannot be approved. Datset has server state ${dataset.server_state}.`,
)
.redirect()
.back();
}
dataset.server_state = 'approved';
if (dataset.reject_reviewer_note != null) {
dataset.reject_reviewer_note = null;
}
//save main and additional titles
const reviewer_id = request.input('reviewer_id', null);
dataset.reviewer_id = reviewer_id;
if (await dataset.save()) {
return response.toRoute('editor.dataset.list').flash('message', 'You have approved one dataset!');
}
}
public async create({}: HttpContextContract) {}
public async store({}: HttpContextContract) {}

View file

@ -230,6 +230,19 @@ export default class Dataset extends DatasetExtension {
})
public xmlCache: HasOne<typeof DocumentXmlCache>;
/**
* Get the account that the dataset belongs to
*/
@belongsTo(() => User, {
foreignKey: 'editor_id',
})
public editor: BelongsTo<typeof User>;
@belongsTo(() => User, {
foreignKey: 'reviewer_id',
})
public reviewer: BelongsTo<typeof User>;
static async earliestPublicationDate(): Promise<Dataset | null> {
const serverState = 'published';