This commit is contained in:
Rutra
2026-05-04 14:16:59 +02:00
commit 03a14da804
60 changed files with 10549 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
import env from '#start/env';
export default class AuthController {
async showLogin({ view, session, response }) {
if (session.get('is_authenticated')) {
return response.redirect().toPath('/');
}
return view.render('login');
}
async login({ request, session, response }) {
const { username, password } = request.only(['username', 'password']);
const validUsername = env.get('AUTH_USERNAME');
const validPassword = env.get('AUTH_PASSWORD');
if (username === validUsername && password === validPassword) {
session.put('is_authenticated', true);
session.put('username', username);
const intendedUrl = session.get('intended_url', '/');
session.forget('intended_url');
return response.redirect().toPath(intendedUrl);
}
session.flash('errors', { form: 'Invalid username or password.' });
session.flashOnly(['username']);
return response.redirect().toPath('/login');
}
async logout({ session, response }) {
session.clear();
return response.redirect().toPath('/login');
}
}
//# sourceMappingURL=auth_controller.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"auth_controller.js","sourceRoot":"","sources":["../../../app/controllers/auth_controller.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,YAAY,CAAA;AAE5B,MAAM,CAAC,OAAO,OAAO,cAAc;IAKjC,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAe;QACtD,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACpC,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACxC,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC7B,CAAC;IAQD,KAAK,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAe;QACrD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAA;QAErE,MAAM,aAAa,GAAG,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;QAC9C,MAAM,aAAa,GAAG,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;QAE9C,IAAI,QAAQ,KAAK,aAAa,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAA;YACrC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;YAEjC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;YACpD,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;YAC9B,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QAChD,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE,CAAC,CAAA;QAElE,OAAO,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;QAC/B,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC7C,CAAC;IAMD,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAe;QAC7C,OAAO,CAAC,KAAK,EAAE,CAAA;QACf,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC7C,CAAC;CACF"}

View File

@@ -0,0 +1,50 @@
import app from '@adonisjs/core/services/app';
import { readdirSync, existsSync, statSync } from 'node:fs';
import { extname, join } from 'node:path';
const IMAGE_EXTENSIONS = new Set(['.jpg', '.jpeg', '.png', '.gif', '.webp']);
const VIDEO_EXTENSIONS = new Set(['.mp4', '.mov', '.avi', '.webm']);
function getMediaType(filename) {
const ext = extname(filename).toLowerCase();
if (IMAGE_EXTENSIONS.has(ext))
return 'image';
if (VIDEO_EXTENSIONS.has(ext))
return 'video';
return 'unknown';
}
export default class MediaController {
async index({ view }) {
const uploadsDir = app.publicPath('uploads');
let files = [];
try {
const entries = readdirSync(uploadsDir, { withFileTypes: true });
files = entries
.filter((entry) => entry.isFile())
.map((entry) => {
const stat = statSync(join(uploadsDir, entry.name));
return {
filename: entry.name,
url: `/uploads/${entry.name}`,
type: getMediaType(entry.name),
size: stat.size,
};
})
.sort((a, b) => b.filename.localeCompare(a.filename));
}
catch {
files = [];
}
return view.render('dashboard', { files });
}
async serve({ params, response }) {
const { filename } = params;
if (!/^[\w\-. ]+$/.test(filename)) {
return response.status(400).json({ error: 'Invalid filename.' });
}
const filePath = join(app.publicPath('uploads'), filename);
if (!existsSync(filePath)) {
return response.status(404).json({ error: 'Media not found', filename });
}
return response.download(filePath);
}
}
//# sourceMappingURL=media_controller.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"media_controller.js","sourceRoot":"","sources":["../../../app/controllers/media_controller.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,40 @@
import app from '@adonisjs/core/services/app';
const ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'mp4', 'mov', 'avi', 'webm'];
const MAX_SIZE = '100mb';
export default class UploadController {
async store({ request, response }) {
const file = request.file('file', {
size: MAX_SIZE,
extnames: ALLOWED_EXTENSIONS,
});
if (!file) {
return response.badRequest({ success: false, message: 'No file provided.' });
}
if (!file.isValid) {
return response.unprocessableEntity({
success: false,
message: file.errors[0]?.message ?? 'File validation failed.',
errors: file.errors,
});
}
const safeName = file.clientName.replace(/[^a-zA-Z0-9._-]/g, '_');
const uniqueFilename = `${Date.now()}_${safeName}`;
await file.move(app.publicPath('uploads'), {
name: uniqueFilename,
overwrite: false,
});
if (file.hasErrors) {
return response.internalServerError({
success: false,
message: 'Could not save the file to disk.',
errors: file.errors,
});
}
return response.ok({
success: true,
filename: uniqueFilename,
url: `/uploads/${uniqueFilename}`,
});
}
}
//# sourceMappingURL=upload_controller.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"upload_controller.js","sourceRoot":"","sources":["../../../app/controllers/upload_controller.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,6BAA6B,CAAA;AAE7C,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;AAC7F,MAAM,QAAQ,GAAG,OAAO,CAAA;AAExB,MAAM,CAAC,OAAO,OAAO,gBAAgB;IAMnC,KAAK,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAe;QAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE;YAChC,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,kBAAkB;SAC7B,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAA;QAC9E,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,QAAQ,CAAC,mBAAmB,CAAC;gBAClC,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,yBAAyB;gBAC7D,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAA;QACJ,CAAC;QAGD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAA;QACjE,MAAM,cAAc,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAA;QAElD,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;YACzC,IAAI,EAAE,cAAc;YACpB,SAAS,EAAE,KAAK;SACjB,CAAC,CAAA;QAEF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,QAAQ,CAAC,mBAAmB,CAAC;gBAClC,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,kCAAkC;gBAC3C,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,EAAE,CAAC;YACjB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,cAAc;YACxB,GAAG,EAAE,YAAY,cAAc,EAAE;SAClC,CAAC,CAAA;IACJ,CAAC;CACF"}

21
app/exceptions/handler.js Normal file
View File

@@ -0,0 +1,21 @@
import app from '@adonisjs/core/services/app';
import { ExceptionHandler } from '@adonisjs/core/http';
export default class HttpExceptionHandler extends ExceptionHandler {
debug = !app.inProduction;
renderStatusPages = app.inProduction;
statusPages = {
'404': (error, { view }) => {
return view.render('pages/errors/not_found', { error });
},
'500..599': (error, { view }) => {
return view.render('pages/errors/server_error', { error });
},
};
async handle(error, ctx) {
return super.handle(error, ctx);
}
async report(error, ctx) {
return super.report(error, ctx);
}
}
//# sourceMappingURL=handler.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../app/exceptions/handler.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,6BAA6B,CAAA;AAC7C,OAAO,EAAe,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAGnE,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,gBAAgB;IAKtD,KAAK,GAAG,CAAC,GAAG,CAAC,YAAY,CAAA;IAOzB,iBAAiB,GAAG,GAAG,CAAC,YAAY,CAAA;IAMpC,WAAW,GAAgD;QACnE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YACzB,OAAO,IAAI,CAAC,MAAM,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACzD,CAAC;QACD,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QAC5D,CAAC;KACF,CAAA;IAMD,KAAK,CAAC,MAAM,CAAC,KAAc,EAAE,GAAgB;QAC3C,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IACjC,CAAC;IAQD,KAAK,CAAC,MAAM,CAAC,KAAc,EAAE,GAAgB;QAC3C,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IACjC,CAAC;CACF"}

View File

@@ -0,0 +1,11 @@
export default class AuthMiddleware {
async handle({ session, response, request }, next) {
const isAuthenticated = session.get('is_authenticated', false);
if (!isAuthenticated) {
session.put('intended_url', request.url());
return response.redirect().toPath('/login');
}
await next();
}
}
//# sourceMappingURL=auth_middleware.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"auth_middleware.js","sourceRoot":"","sources":["../../../app/middleware/auth_middleware.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAe,EAAE,IAAY;QACpE,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAA;QAE9D,IAAI,CAAC,eAAe,EAAE,CAAC;YAErB,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;YAC1C,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC7C,CAAC;QAED,MAAM,IAAI,EAAE,CAAA;IACd,CAAC;CACF"}

View File

@@ -0,0 +1,10 @@
import { Logger } from '@adonisjs/core/logger';
import { HttpContext } from '@adonisjs/core/http';
export default class ContainerBindingsMiddleware {
handle(ctx, next) {
ctx.containerResolver.bindValue(HttpContext, ctx);
ctx.containerResolver.bindValue(Logger, ctx.logger);
return next();
}
}
//# sourceMappingURL=container_bindings_middleware.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"container_bindings_middleware.js","sourceRoot":"","sources":["../../../app/middleware/container_bindings_middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAUjD,MAAM,CAAC,OAAO,OAAO,2BAA2B;IAC9C,MAAM,CAAC,GAAgB,EAAE,IAAY;QACnC,GAAG,CAAC,iBAAiB,CAAC,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;QACjD,GAAG,CAAC,iBAAiB,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QAEnD,OAAO,IAAI,EAAE,CAAA;IACf,CAAC;CACF"}