feat: add auth via google

This commit is contained in:
Sonny
2024-04-27 18:14:40 +02:00
committed by Sonny
parent 2531242615
commit df4185bd62
18 changed files with 450 additions and 46 deletions

View File

@@ -0,0 +1,7 @@
import type { HttpContext } from '@adonisjs/core/http';
export default class AppsController {
index({ inertia }: HttpContext) {
return inertia.render('home');
}
}

View File

@@ -0,0 +1,56 @@
import User from '#models/user';
import type { HttpContext } from '@adonisjs/core/http';
import logger from '@adonisjs/core/services/logger';
export default class UsersController {
private redirectTo = '/';
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.redirect(this.redirectTo);
}
if (google.stateMisMatch()) {
session.flash('flash', 'Request expired. Retry again');
return response.redirect(this.redirectTo);
}
if (google.hasError()) {
session.flash('flash', google.getError() || 'Something went wrong');
return response.redirect(this.redirectTo);
}
const { email, id: providerId, name, nickName, avatarUrl, token } = await google.user();
const user = await User.updateOrCreate(
{
email,
},
{
email,
providerId,
name,
nickName,
avatarUrl,
token,
}
);
await auth.use('web').login(user);
session.flash('flash', 'Successfully authenticated');
logger.info(`[${user.email}] auth success`);
response.redirect('/');
}
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('/');
}
}

View File

@@ -0,0 +1,5 @@
import { BaseModel, CamelCaseNamingStrategy } from '@adonisjs/lucid/orm';
export default class AppBaseModel extends BaseModel {
static namingStrategy = new CamelCaseNamingStrategy();
}

View File

@@ -1,30 +1,53 @@
import type { GoogleToken } from '@adonisjs/ally/types';
import { beforeCreate, column } from '@adonisjs/lucid/orm';
import { DateTime } from 'luxon';
import hash from '@adonisjs/core/services/hash';
import { compose } from '@adonisjs/core/helpers';
import { BaseModel, column } from '@adonisjs/lucid/orm';
import { withAuthFinder } from '@adonisjs/auth/mixins/lucid';
import { v4 as uuidv4 } from 'uuid';
import AppBaseModel from './app_base_model.js';
const AuthFinder = withAuthFinder(() => hash.use('scrypt'), {
uids: ['email'],
passwordColumnName: 'password',
});
export default class User extends AppBaseModel {
static selfAssignPrimaryKey = true;
export default class User extends compose(BaseModel, AuthFinder) {
@column({ isPrimary: true })
declare id: number;
@column()
declare fullName: string | null;
declare id: string; // UUID
@column()
declare email: string;
@column()
declare password: string;
declare name: string;
@column.dateTime({ autoCreate: true })
@column({ serializeAs: 'nickName' })
declare nickName: string; // public username
@column({ serializeAs: 'avatarUrl' })
declare avatarUrl: string;
declare isAdmin: boolean;
@column({ serializeAs: null })
declare token: GoogleToken;
@column({ serializeAs: null })
declare providerId: string;
@column.dateTime({
autoCreate: true,
serialize: (value: DateTime) => value.toISODate(),
serializeAs: 'createdAt',
})
declare createdAt: DateTime;
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime | null;
@column.dateTime({
autoCreate: true,
autoUpdate: true,
serialize: (value: DateTime) => value.toISODate(),
serializeAs: 'updatedAt',
})
declare updatedAt: DateTime;
@beforeCreate()
static assignUuid(user: User) {
user.id = uuidv4();
user.isAdmin = false;
}
}