-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
1,297 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ coverage | |
.vscode | ||
.DS_STORE | ||
.env | ||
.idea | ||
tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,26 @@ | ||
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' | ||
import AuthValidator from 'App/Validators/AuthValidator' | ||
import Admin from 'App/Models/Admin' | ||
|
||
export default class AuthAdminController { | ||
public async index({ view }: HttpContextContract) { | ||
return view.render('auth/admin') | ||
} | ||
|
||
public async register({ request, response, auth }: HttpContextContract) { | ||
const data = await request.validate(AuthValidator) | ||
const admin = await Admin.create(data) | ||
|
||
await auth.use('admin').login(admin) | ||
|
||
return response.redirect('/') | ||
} | ||
|
||
public async login({ request, response, auth }: HttpContextContract) { | ||
const { email, password } = await request.validate(AuthValidator) | ||
|
||
await auth.use('admin').attempt(email, password) | ||
|
||
return response.redirect('/') | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,26 @@ | ||
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' | ||
import AuthValidator from 'App/Validators/AuthValidator' | ||
import User from 'App/Models/User' | ||
|
||
export default class AuthUserController { | ||
public async index({ view }: HttpContextContract) { | ||
return view.render('auth/user') | ||
} | ||
|
||
public async register({ request, response, auth }: HttpContextContract) { | ||
const data = await request.validate(AuthValidator) | ||
const user = await User.create(data) | ||
|
||
await auth.login(user) | ||
|
||
return response.redirect('/') | ||
} | ||
|
||
public async login({ request, response, auth }: HttpContextContract) { | ||
const { email, password } = await request.validate(AuthValidator) | ||
|
||
await auth.use('user').attempt(email, password) | ||
|
||
return response.redirect('/') | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { GuardsList } from '@ioc:Adonis/Addons/Auth' | ||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' | ||
import { AuthenticationException } from '@adonisjs/auth/build/standalone' | ||
|
||
/** | ||
* Auth middleware is meant to restrict un-authenticated access to a given route | ||
* or a group of routes. | ||
* | ||
* You must register this middleware inside `start/kernel.ts` file under the list | ||
* of named middleware. | ||
*/ | ||
export default class AuthMiddleware { | ||
/** | ||
* The URL to redirect to when request is Unauthorized | ||
*/ | ||
protected redirectTo = '/login' | ||
|
||
/** | ||
* Authenticates the current HTTP request against a custom set of defined | ||
* guards. | ||
* | ||
* The authentication loop stops as soon as the user is authenticated using any | ||
* of the mentioned guards and that guard will be used by the rest of the code | ||
* during the current request. | ||
*/ | ||
protected async authenticate(auth: HttpContextContract['auth'], guards: (keyof GuardsList)[]) { | ||
/** | ||
* Hold reference to the guard last attempted within the for loop. We pass | ||
* the reference of the guard to the "AuthenticationException", so that | ||
* it can decide the correct response behavior based upon the guard | ||
* driver | ||
*/ | ||
let guardLastAttempted: string | undefined | ||
|
||
for (let guard of guards) { | ||
guardLastAttempted = guard | ||
|
||
if (await auth.use(guard).check()) { | ||
/** | ||
* Instruct auth to use the given guard as the default guard for | ||
* the rest of the request, since the user authenticated | ||
* succeeded here | ||
*/ | ||
auth.defaultGuard = guard | ||
return true | ||
} | ||
} | ||
|
||
/** | ||
* Unable to authenticate using any guard | ||
*/ | ||
throw new AuthenticationException( | ||
'Unauthorized access', | ||
'E_UNAUTHORIZED_ACCESS', | ||
guardLastAttempted, | ||
this.redirectTo, | ||
) | ||
} | ||
|
||
/** | ||
* Handle request | ||
*/ | ||
public async handle ( | ||
{ auth }: HttpContextContract, | ||
next: () => Promise<void>, | ||
customGuards: (keyof GuardsList)[] | ||
) { | ||
/** | ||
* Uses the user defined guards or the default guard mentioned in | ||
* the config file | ||
*/ | ||
const guards = customGuards.length ? customGuards : [auth.name] | ||
await this.authenticate(auth, guards) | ||
await next() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' | ||
|
||
/** | ||
* Silent auth middleware can be used as a global middleware to silent check | ||
* if the user is logged-in or not. | ||
* | ||
* The request continues as usual, even when the user is not logged-in. | ||
*/ | ||
export default class SilentAuthMiddleware { | ||
/** | ||
* Handle request | ||
*/ | ||
public async handle({ auth }: HttpContextContract, next: () => Promise<void>) { | ||
/** | ||
* Check if user is logged-in or not. If yes, then `ctx.auth.user` will be | ||
* set to the instance of the currently logged in user. | ||
*/ | ||
|
||
if (await auth.use('admin').check()) { | ||
// admin is logged in | ||
auth.defaultGuard = 'admin' | ||
} | ||
|
||
await auth.check() | ||
await next() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { DateTime } from 'luxon' | ||
import Hash from '@ioc:Adonis/Core/Hash' | ||
import { column, beforeSave, BaseModel } from '@ioc:Adonis/Lucid/Orm' | ||
|
||
export default class Admin extends BaseModel { | ||
@column({ isPrimary: true }) | ||
public id: number | ||
|
||
@column() | ||
public email: string | ||
|
||
@column({ serializeAs: null }) | ||
public password: string | ||
|
||
@column() | ||
public rememberMeToken?: string | ||
|
||
@column.dateTime({ autoCreate: true }) | ||
public createdAt: DateTime | ||
|
||
@column.dateTime({ autoCreate: true, autoUpdate: true }) | ||
public updatedAt: DateTime | ||
|
||
@beforeSave() | ||
public static async hashPassword (admin: Admin) { | ||
if (admin.$dirty.password) { | ||
admin.password = await Hash.make(admin.password) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { DateTime } from 'luxon' | ||
import Hash from '@ioc:Adonis/Core/Hash' | ||
import { column, beforeSave, BaseModel } from '@ioc:Adonis/Lucid/Orm' | ||
|
||
export default class User extends BaseModel { | ||
@column({ isPrimary: true }) | ||
public id: number | ||
|
||
@column() | ||
public email: string | ||
|
||
@column({ serializeAs: null }) | ||
public password: string | ||
|
||
@column() | ||
public rememberMeToken?: string | ||
|
||
@column.dateTime({ autoCreate: true }) | ||
public createdAt: DateTime | ||
|
||
@column.dateTime({ autoCreate: true, autoUpdate: true }) | ||
public updatedAt: DateTime | ||
|
||
@beforeSave() | ||
public static async hashPassword (user: User) { | ||
if (user.$dirty.password) { | ||
user.password = await Hash.make(user.password) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator' | ||
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' | ||
|
||
export default class AuthValidator { | ||
constructor(protected ctx: HttpContextContract) {} | ||
|
||
/* | ||
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data. | ||
* | ||
* For example: | ||
* 1. The username must be of data type string. But then also, it should | ||
* not contain special characters or numbers. | ||
* ``` | ||
* schema.string({}, [ rules.alpha() ]) | ||
* ``` | ||
* | ||
* 2. The email must be of data type string, formatted as a valid | ||
* email. But also, not used by any other user. | ||
* ``` | ||
* schema.string({}, [ | ||
* rules.email(), | ||
* rules.unique({ table: 'users', column: 'email' }), | ||
* ]) | ||
* ``` | ||
*/ | ||
public schema = schema.create({ | ||
email: schema.string([rules.email()]), | ||
password: schema.string() | ||
}) | ||
|
||
/** | ||
* Custom messages for validation failures. You can make use of dot notation `(.)` | ||
* for targeting nested fields and array expressions `(*)` for targeting all | ||
* children of an array. For example: | ||
* | ||
* { | ||
* 'profile.username.required': 'Username is required', | ||
* 'scores.*.number': 'Define scores as valid numbers' | ||
* } | ||
* | ||
*/ | ||
public messages: CustomMessages = {} | ||
} |
Oops, something went wrong.