mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-09 15:05:35 +00:00
refactor: split backend by context instead of type 'controllers/models/...'
This commit is contained in:
78
app/auth/controllers/auth_controller.ts
Normal file
78
app/auth/controllers/auth_controller.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import User from '#user/models/user';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import logger from '@adonisjs/core/services/logger';
|
||||
import db from '@adonisjs/lucid/services/db';
|
||||
import { RouteName } from '@izzyjs/route/types';
|
||||
|
||||
export default class AuthController {
|
||||
private redirectTo: RouteName = 'auth';
|
||||
|
||||
login({ inertia }: HttpContext) {
|
||||
return inertia.render('login');
|
||||
}
|
||||
|
||||
google = ({ ally }: HttpContext) => ally.use('google').redirect();
|
||||
|
||||
async callbackAuth({ ally, auth, response, session }: HttpContext) {
|
||||
const google = ally.use('google');
|
||||
if (google.accessDenied()) {
|
||||
// TODO: translate error messages + show them in UI
|
||||
session.flash('flash', 'Access was denied');
|
||||
return response.redirectToNamedRoute(this.redirectTo);
|
||||
}
|
||||
|
||||
if (google.stateMisMatch()) {
|
||||
session.flash('flash', 'Request expired. Retry again');
|
||||
return response.redirectToNamedRoute(this.redirectTo);
|
||||
}
|
||||
|
||||
if (google.hasError()) {
|
||||
session.flash('flash', google.getError() || 'Something went wrong');
|
||||
return response.redirectToNamedRoute(this.redirectTo);
|
||||
}
|
||||
|
||||
const userCount = await db.from('users').count('* as total');
|
||||
const {
|
||||
email,
|
||||
id: providerId,
|
||||
name,
|
||||
nickName,
|
||||
avatarUrl,
|
||||
token,
|
||||
} = await google.user();
|
||||
const user = await User.updateOrCreate(
|
||||
{
|
||||
email,
|
||||
},
|
||||
{
|
||||
email,
|
||||
providerId,
|
||||
name,
|
||||
nickName,
|
||||
avatarUrl,
|
||||
token,
|
||||
providerType: 'google',
|
||||
isAdmin: userCount[0].total === '0' ? true : undefined,
|
||||
}
|
||||
);
|
||||
|
||||
await auth.use('web').login(user);
|
||||
session.flash('flash', 'Successfully authenticated');
|
||||
logger.info(`[${user.email}] auth success`);
|
||||
|
||||
response.redirectToNamedRoute('dashboard');
|
||||
}
|
||||
|
||||
async logout({ auth, response, session }: HttpContext) {
|
||||
await auth.use('web').logout();
|
||||
session.flash('flash', 'Successfully disconnected');
|
||||
logger.info(`[${auth.user?.email}] disconnected successfully`);
|
||||
response.redirect('/');
|
||||
}
|
||||
|
||||
async getAllUsersWithTotalRelations() {
|
||||
return User.query()
|
||||
.withCount('collections', (q) => q.as('totalCollections'))
|
||||
.withCount('links', (q) => q.as('totalLinks'));
|
||||
}
|
||||
}
|
||||
28
app/auth/middlewares/auth_middleware.ts
Normal file
28
app/auth/middlewares/auth_middleware.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { Authenticators } from '@adonisjs/auth/types';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import type { NextFn } from '@adonisjs/core/types/http';
|
||||
import { route } from '@izzyjs/route/client';
|
||||
|
||||
/**
|
||||
* Auth middleware is used authenticate HTTP requests and deny
|
||||
* access to unauthenticated users.
|
||||
*/
|
||||
export default class AuthMiddleware {
|
||||
/**
|
||||
* The URL to redirect to, when authentication fails
|
||||
*/
|
||||
redirectTo = route('auth').path;
|
||||
|
||||
async handle(
|
||||
ctx: HttpContext,
|
||||
next: NextFn,
|
||||
options: {
|
||||
guards?: (keyof Authenticators)[];
|
||||
} = {}
|
||||
) {
|
||||
await ctx.auth.authenticateUsing(options.guards, {
|
||||
loginRoute: this.redirectTo,
|
||||
});
|
||||
return next();
|
||||
}
|
||||
}
|
||||
31
app/auth/middlewares/guest_middleware.ts
Normal file
31
app/auth/middlewares/guest_middleware.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import type { NextFn } from '@adonisjs/core/types/http';
|
||||
import type { Authenticators } from '@adonisjs/auth/types';
|
||||
|
||||
/**
|
||||
* Guest middleware is used to deny access to routes that should
|
||||
* be accessed by unauthenticated users.
|
||||
*
|
||||
* For example, the login page should not be accessible if the user
|
||||
* is already logged-in
|
||||
*/
|
||||
export default class GuestMiddleware {
|
||||
/**
|
||||
* The URL to redirect to when user is logged-in
|
||||
*/
|
||||
redirectTo = '/';
|
||||
|
||||
async handle(
|
||||
ctx: HttpContext,
|
||||
next: NextFn,
|
||||
options: { guards?: (keyof Authenticators)[] } = {}
|
||||
) {
|
||||
for (let guard of options.guards || [ctx.auth.defaultGuard]) {
|
||||
if (await ctx.auth.use(guard).check()) {
|
||||
return ctx.response.redirect(this.redirectTo, true);
|
||||
}
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
}
|
||||
9
app/auth/middlewares/silent_auth_middleware.ts
Normal file
9
app/auth/middlewares/silent_auth_middleware.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
import type { NextFn } from '@adonisjs/core/types/http';
|
||||
|
||||
export default class SilentAuthMiddleware {
|
||||
async handle(ctx: HttpContext, next: NextFn) {
|
||||
await ctx.auth.check();
|
||||
return next();
|
||||
}
|
||||
}
|
||||
27
app/auth/routes/auth_routes.ts
Normal file
27
app/auth/routes/auth_routes.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { middleware } from '#start/kernel';
|
||||
import router from '@adonisjs/core/services/router';
|
||||
const AuthController = () => import('#auth/controllers/auth_controller');
|
||||
|
||||
const ROUTES_PREFIX = '/auth';
|
||||
|
||||
/**
|
||||
* Auth routes for unauthicated users
|
||||
*/
|
||||
router
|
||||
.group(() => {
|
||||
router.get('/google', [AuthController, 'google']).as('auth');
|
||||
router
|
||||
.get('/callback', [AuthController, 'callbackAuth'])
|
||||
.as('auth.callback');
|
||||
})
|
||||
.prefix(ROUTES_PREFIX);
|
||||
|
||||
/**
|
||||
* Routes for authenticated users
|
||||
*/
|
||||
router
|
||||
.group(() => {
|
||||
router.get('/logout', [AuthController, 'logout']).as('auth.logout');
|
||||
})
|
||||
.middleware([middleware.auth()])
|
||||
.prefix(ROUTES_PREFIX);
|
||||
1
app/auth/routes/routes.ts
Normal file
1
app/auth/routes/routes.ts
Normal file
@@ -0,0 +1 @@
|
||||
import './auth_routes.js';
|
||||
Reference in New Issue
Block a user