- added own provider for drive methods
Some checks failed
CI Pipeline / japa-tests (push) Failing after 1m13s
Some checks failed
CI Pipeline / japa-tests (push) Failing after 1m13s
- renamed middleware Role and Can to role_middleware and can_middleware - added some typing for inertia vue3 components - npm updates
This commit is contained in:
parent
cb51a4136f
commit
296c8fd46e
67 changed files with 2515 additions and 1913 deletions
|
@ -8,7 +8,8 @@ import UpdateUserValidator from '#app/Validators/UpdateUserValidator';
|
|||
// import Hash from '@ioc:Adonis/Core/Hash';
|
||||
// import { schema, rules } from '@ioc:Adonis/Core/Validator';
|
||||
|
||||
export default class AdminUserController {
|
||||
export default class AdminuserController {
|
||||
|
||||
public async index({ auth, request, inertia }: HttpContext) {
|
||||
const page = request.input('page', 1);
|
||||
// const limit = 10
|
|
@ -1,7 +1,7 @@
|
|||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
// import TotpSecret from 'App/Models/TotpSecret';
|
||||
import User from '#app/Models/User';
|
||||
import TwoFactorAuthProvider from '#app/Services/TwoFactorAuthProvider';
|
||||
import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider';
|
||||
import { StatusCodes } from 'http-status-codes';
|
||||
import { InvalidArgumentException } from 'node-exceptions';
|
||||
import { TotpState } from '#contracts/enums';
|
||||
|
|
|
@ -4,7 +4,7 @@ import User from '#models/User';
|
|||
// import InvalidCredentialException from 'App/Exceptions/InvalidCredentialException';
|
||||
import AuthValidator from '#app/Validators/AuthValidator';
|
||||
|
||||
import TwoFactorAuthProvider from '#app/Services/TwoFactorAuthProvider';
|
||||
import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider';
|
||||
// import { Authenticator } from '@adonisjs/auth';
|
||||
// import { LoginState } from 'Contracts/enums';
|
||||
// import { StatusCodes } from 'http-status-codes';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import User from '#app/Models/User';
|
||||
// import { RenderResponse } from '@ioc:EidelLev/Inertia';
|
||||
import TwoFactorAuthProvider from '#app/Services/TwoFactorAuthProvider';
|
||||
import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider';
|
||||
import hash from '@adonisjs/core/services/hash';
|
||||
import { schema, rules } from '@adonisjs/validator';
|
||||
|
||||
|
@ -88,7 +88,7 @@ export default class UserController {
|
|||
}
|
||||
|
||||
public async disableTwoFactorAuthentication({ auth, response, session }: HttpContext): Promise<void> {
|
||||
const user = auth?.user;
|
||||
const user = auth.user;
|
||||
|
||||
user.twoFactorSecret = null;
|
||||
user.twoFactorRecoveryCodes = null;
|
||||
|
|
|
@ -9,11 +9,11 @@ import Language from '#app/Models/Language';
|
|||
import Coverage from '#app/Models/Coverage';
|
||||
import Collection from '#app/Models/Collection';
|
||||
import { schema, rules } from '@adonisjs/validator';
|
||||
import { CustomMessages } from "@adonisjs/validator/types";
|
||||
import { CustomMessages } from '@adonisjs/validator/types';
|
||||
import dayjs from 'dayjs';
|
||||
import Person from '#app/Models/Person';
|
||||
import db from '@adonisjs/lucid/services/db';
|
||||
import { TransactionClientContract } from "@adonisjs/lucid/types/database";
|
||||
import { TransactionClientContract } from '@adonisjs/lucid/types/database';
|
||||
import Subject from '#app/Models/Subject';
|
||||
import CreateDatasetValidator from '#app/Validators/CreateDatasetValidator';
|
||||
import UpdateDatasetValidator from '#app/Validators/UpdateDatasetValidator';
|
||||
|
@ -27,14 +27,15 @@ import {
|
|||
DatasetTypes,
|
||||
SubjectTypes,
|
||||
} from '#contracts/enums';
|
||||
import { ModelQueryBuilderContract } from "@adonisjs/lucid/types/model";
|
||||
import { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';
|
||||
import DatasetReference from '#app/Models/DatasetReference';
|
||||
import { cuid } from '@adonisjs/core/helpers';
|
||||
import File from '#app/Models/File';
|
||||
import ClamScan from 'clamscan';
|
||||
import { ValidationException } from '@adonisjs/validator';
|
||||
// import Drive from '@ioc:Adonis/Core/Drive';
|
||||
import { Exception } from "@adonisjs/core/exceptions";
|
||||
import drive from '#services/drive';
|
||||
import { Exception } from '@adonisjs/core/exceptions';
|
||||
import { MultipartFile } from '@adonisjs/core/types/bodyparser';
|
||||
import * as crypto from 'crypto';
|
||||
import app from '@adonisjs/core/services/app';
|
||||
|
@ -428,7 +429,7 @@ export default class DatasetController {
|
|||
}
|
||||
|
||||
// save data files
|
||||
const uploadedFiles: MultipartFile[] = request.files('files');
|
||||
const uploadedFiles: MultipartFile[] = request.files('files');
|
||||
for (const [index, file] of uploadedFiles.entries()) {
|
||||
try {
|
||||
await this.scanFileForViruses(file.tmpPath); //, 'gitea.lan', 3310);
|
||||
|
@ -439,19 +440,16 @@ export default class DatasetController {
|
|||
}
|
||||
// clientName: 'Gehaltsschema.png'
|
||||
// extname: 'png'
|
||||
// fieldName: 'file'
|
||||
// fieldName: 'file'
|
||||
// const fileName = `file-${this.generateRandomString(32)}.${file.extname}`;
|
||||
const fileName = this.generateFilename(file.extname as string);
|
||||
const mimeType = file.headers['content-type'] || 'application/octet-stream'; // Fallback to a default MIME type
|
||||
const datasetFolder = `files/${dataset.id}`;
|
||||
// const size = file.size;
|
||||
await file.move(
|
||||
app.makePath( datasetFolder),
|
||||
{
|
||||
name: fileName,
|
||||
overwrite: true, // overwrite in case of conflict
|
||||
},
|
||||
);
|
||||
await file.move(app.makePath(datasetFolder), {
|
||||
name: fileName,
|
||||
overwrite: true, // overwrite in case of conflict
|
||||
});
|
||||
// save file metadata into db
|
||||
const newFile = new File();
|
||||
newFile.pathName = `${datasetFolder}/${fileName}`;
|
||||
|
@ -468,7 +466,10 @@ export default class DatasetController {
|
|||
}
|
||||
|
||||
private generateRandomString(length: number): string {
|
||||
return crypto.randomBytes(Math.ceil(length / 2)).toString('hex').slice(0, length);
|
||||
return crypto
|
||||
.randomBytes(Math.ceil(length / 2))
|
||||
.toString('hex')
|
||||
.slice(0, length);
|
||||
}
|
||||
|
||||
private generateFilename(extension: string): string {
|
||||
|
@ -477,9 +478,9 @@ export default class DatasetController {
|
|||
const randomString3 = this.generateRandomString(4);
|
||||
const randomString4 = this.generateRandomString(4);
|
||||
const randomString5 = this.generateRandomString(12);
|
||||
|
||||
|
||||
return `file-${randomString1}-${randomString2}-${randomString3}-${randomString4}-${randomString5}.${extension}`;
|
||||
}
|
||||
}
|
||||
|
||||
private async scanFileForViruses(filePath: string | undefined, host?: string, port?: number): Promise<void> {
|
||||
// const clamscan = await (new ClamScan().init());
|
||||
|
@ -660,7 +661,7 @@ export default class DatasetController {
|
|||
});
|
||||
|
||||
try {
|
||||
await request.validate({
|
||||
await request.validate({
|
||||
schema: newSchema,
|
||||
// reporter: validator.reporters.vanilla,
|
||||
});
|
||||
|
@ -919,11 +920,7 @@ export default class DatasetController {
|
|||
// move to disk:
|
||||
const fileName = `file-${cuid()}.${fileData.extname}`;
|
||||
const datasetFolder = `files/${dataset.id}`;
|
||||
await fileData.moveToDisk(
|
||||
datasetFolder,
|
||||
{ name: fileName, overwrite: true },
|
||||
'local'
|
||||
);
|
||||
await fileData.moveToDisk(datasetFolder, { name: fileName, overwrite: true }, 'local');
|
||||
// let path = coverImage.filePath;
|
||||
|
||||
//save to db:
|
||||
|
@ -1047,21 +1044,25 @@ export default class DatasetController {
|
|||
}
|
||||
}
|
||||
const datasetFolder = `files/${params.id}`;
|
||||
const folderExists = await Drive.exists(datasetFolder);
|
||||
const folderExists = await drive.exists(datasetFolder);
|
||||
if (folderExists) {
|
||||
const folderContents = await Drive.list(datasetFolder).toArray();
|
||||
const dirListing = drive.list(datasetFolder);
|
||||
const folderContents = await dirListing.toArray();
|
||||
if (folderContents.length === 0) {
|
||||
await Drive.delete(datasetFolder);
|
||||
await drive.delete(datasetFolder);
|
||||
}
|
||||
// delete dataset wirh relation in db
|
||||
await dataset.delete();
|
||||
session.flash({ message: 'You have deleted 1 dataset!' });
|
||||
return response.redirect().toRoute('dataset.list');
|
||||
} else {
|
||||
session.flash({
|
||||
warning: `You cannot delete this dataset! Invalid server_state: "${dataset.server_state}"!`,
|
||||
});
|
||||
return response.status(400).redirect().back();
|
||||
// session.flash({
|
||||
// warning: `You cannot delete this dataset! Invalid server_state: "${dataset.server_state}"!`,
|
||||
// });
|
||||
return response
|
||||
.flash({ warning: `You cannot delete this dataset! Dataset folder "${datasetFolder}" doesn't exist!` })
|
||||
.redirect()
|
||||
.back();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -1070,10 +1071,7 @@ export default class DatasetController {
|
|||
throw error;
|
||||
} else if (error instanceof Exception) {
|
||||
// General exception handling
|
||||
return response
|
||||
.flash('errors', { error: error.message })
|
||||
.redirect()
|
||||
.back();
|
||||
return response.flash('errors', { error: error.message }).redirect().back();
|
||||
} else {
|
||||
session.flash({ error: 'An error occurred while deleting the dataset.' });
|
||||
return response.redirect().back();
|
||||
|
|
|
@ -29,28 +29,38 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
|||
* codes. You might want to enable them in production only, but feel
|
||||
* free to enable them in development as well.
|
||||
*/
|
||||
protected renderStatusPages = true;
|
||||
|
||||
// protected statusPages = {
|
||||
// '401,403': 'errors/unauthorized',
|
||||
// '404': 'errors/not-found',
|
||||
// '500..599': 'errors/server-error',
|
||||
// };
|
||||
protected renderStatusPages = true; //app.inProduction;
|
||||
|
||||
/**
|
||||
* Status pages is a collection of error code range and a callback
|
||||
* to return the HTML contents to send as a response.
|
||||
*/
|
||||
// protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
|
||||
// '401..403': (error, { view }) => {
|
||||
// return view.render('./errors/unauthorized', { error });
|
||||
// },
|
||||
// '404': (error, { view }) => {
|
||||
// return view.render('./errors/not-found', { error });
|
||||
// },
|
||||
// '500..599': (error, { view }) => {
|
||||
// return view.render('./errors/server-error', { error });
|
||||
// },
|
||||
// };
|
||||
protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
|
||||
'401..403': (error, { view }) => {
|
||||
return view.render('./errors/unauthorized', { error });
|
||||
'404': (error, { inertia }) => {
|
||||
return inertia.render('Errors/ServerError', {
|
||||
error: error.message,
|
||||
code: error.status,
|
||||
});
|
||||
},
|
||||
'404': (error, { view }) => {
|
||||
return view.render('./errors/not-found', { error });
|
||||
},
|
||||
'500..599': (error, { view }) => {
|
||||
return view.render('./errors/server-error', { error });
|
||||
'401..403': async (error, { inertia }) => {
|
||||
// session.flash('errors', error.message);
|
||||
return inertia.render('Errors/ServerError', {
|
||||
error: error.message,
|
||||
code: error.status,
|
||||
});
|
||||
},
|
||||
'500..599': (error, { inertia }) => inertia.render('Errors/ServerError', { error: error.message, code: error.status }),
|
||||
};
|
||||
|
||||
// constructor() {
|
||||
|
@ -58,7 +68,7 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
|||
// }
|
||||
|
||||
public async handle(error: any, ctx: HttpContext) {
|
||||
const { response, request, session } = ctx;
|
||||
// const { response, request, session, inertia } = ctx;
|
||||
|
||||
/**
|
||||
* Handle failed authentication attempt
|
||||
|
@ -75,17 +85,26 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
|||
// https://github.com/inertiajs/inertia-laravel/issues/56
|
||||
// let test = response.getStatus(); //200
|
||||
// let header = request.header('X-Inertia'); // true
|
||||
if (request.header('X-Inertia') && [500, 503, 404, 403, 401, 200].includes(response.getStatus())) {
|
||||
// session.flash('errors', error.messages.errors);
|
||||
session.flash('errors', error.messages);
|
||||
return response.redirect().back();
|
||||
// return inertia.render('Error', {
|
||||
// status: response.getStatus(),
|
||||
// message: error.message,
|
||||
// });
|
||||
// ->toResponse($request)
|
||||
// ->setStatusCode($response->status());
|
||||
}
|
||||
// if (request.header('X-Inertia') && [500, 503, 404, 403, 401, 200].includes(response.getStatus())) {
|
||||
// // session.flash('errors', error.messages.errors);
|
||||
// session.flash('errors', error.messages);
|
||||
// return response.redirect().back();
|
||||
// // return inertia.render('errors/server_error', {
|
||||
// // return inertia.render('errors/server_error', {
|
||||
// // // status: response.getStatus(),
|
||||
// // error: error,
|
||||
// // });
|
||||
// // ->toResponse($request)
|
||||
// // ->setStatusCode($response->status());
|
||||
// }
|
||||
// Dynamically change the error templates based on the absence of X-Inertia header
|
||||
// if (!ctx.request.header('X-Inertia')) {
|
||||
// this.statusPages = {
|
||||
// '401..403': (error, { view }) => view.render('./errors/unauthorized', { error }),
|
||||
// '404': (error, { view }) => view.render('./errors/not-found', { error }),
|
||||
// '500..599': (error, { view }) => view.render('./errors/server-error', { error }),
|
||||
// };
|
||||
// }
|
||||
|
||||
/**
|
||||
* Forward rest of the exceptions to the parent class
|
||||
|
|
|
@ -7,7 +7,8 @@ import BaseModel from './BaseModel.js';
|
|||
import * as fs from 'fs';
|
||||
import crypto from 'crypto';
|
||||
// import Drive from '@ioc:Adonis/Core/Drive';
|
||||
import Drive from '@adonisjs/drive';
|
||||
// import Drive from '@adonisjs/drive';
|
||||
import drive from '#services/drive';
|
||||
|
||||
import type { HasMany } from "@adonisjs/lucid/types/relations";
|
||||
import type { BelongsTo } from "@adonisjs/lucid/types/relations";
|
||||
|
@ -164,7 +165,7 @@ export default class File extends BaseModel {
|
|||
public async delete() {
|
||||
if (this.pathName) {
|
||||
// Delete file from additional storage
|
||||
await Drive.delete(this.pathName);
|
||||
await drive.delete(this.pathName);
|
||||
}
|
||||
|
||||
// Call the original delete method of the BaseModel to remove the record from the database
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { DateTime } from 'luxon';
|
||||
import { withAuthFinder } from '@adonisjs/auth';
|
||||
import { column, beforeSave, manyToMany, hasMany } from '@adonisjs/lucid/orm';
|
||||
import { withAuthFinder } from '@adonisjs/auth/mixins/lucid'
|
||||
import { column, manyToMany, hasMany } from '@adonisjs/lucid/orm';
|
||||
import hash from '@adonisjs/core/services/hash';
|
||||
import Role from './Role.js';
|
||||
import db from '@adonisjs/lucid/services/db';
|
||||
// import Config from '@ioc:Adonis/Core/Config';
|
||||
import config from '@adonisjs/core/services/config';
|
||||
import Dataset from './Dataset.js';
|
||||
import BaseModel from './BaseModel.js';
|
||||
|
@ -84,12 +83,12 @@ export default class User extends compose(BaseModel, AuthFinder) {
|
|||
// })
|
||||
// public totp_secret: HasOne<typeof TotpSecret>;
|
||||
|
||||
@beforeSave()
|
||||
public static async hashPassword(user: User) {
|
||||
if (user.$dirty.password) {
|
||||
user.password = await hash.use('laravel').make(user.password);
|
||||
}
|
||||
}
|
||||
// @beforeSave()
|
||||
// public static async hashPassword(user: User) {
|
||||
// if (user.$dirty.password) {
|
||||
// user.password = await hash.use('laravel').make(user.password);
|
||||
// }
|
||||
// }
|
||||
|
||||
public get isTwoFactorEnabled(): boolean {
|
||||
return Boolean(this?.twoFactorSecret && this.state == TotpState.STATE_ENABLED);
|
||||
|
|
13
app/services/drive.ts
Normal file
13
app/services/drive.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
// import app from './app.js';
|
||||
import DriveManager from "#providers/drive/src/drive_manager";
|
||||
import app from "@adonisjs/core/services/app";
|
||||
|
||||
let drive: DriveManager;
|
||||
/**
|
||||
* Returns a singleton instance of the router class from
|
||||
* the container
|
||||
*/
|
||||
await app.booted(async () => {
|
||||
drive = await app.container.make(DriveManager);
|
||||
});
|
||||
export { drive as default };
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue