Skip to content

Commit

Permalink
feat: finish configure command
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Oct 25, 2023
1 parent db93550 commit e2f20fc
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 66 deletions.
15 changes: 15 additions & 0 deletions configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,19 @@ export async function configure(command: Configure) {
await codemods.updateRcFile((rcFile) => {
rcFile.addProvider('@adonisjs/auth/auth_provider')
})

/**
* Register middleware
*/
await codemods.registerMiddleware('router', [
{
path: '@adonisjs/auth/initialize_auth_middleware',
},
])
await codemods.registerMiddleware('named', [
{
name: 'auth',
path: '@adonisjs/auth/auth_middleware',
},
])
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
"./core/token_providers/*": "./build/src/core/token_providers/*.js",
"./types/core": "./build/src/core/types.js",
"./session": "./build/src/guards/session/main.js",
"./initialize_auth_middleware": "./build/src/auth/middleware/initialize_auth_middleware.js",
"./auth_middleware": "./build/src/auth/middleware/auth_middleware.js",
"./types/session": "./build/src/guards/session/types.js"
},
"scripts": {
Expand Down
3 changes: 2 additions & 1 deletion src/auth/authenticator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export class Authenticator<KnownGuards extends Record<string, GuardFactory>> {
*
* Otherwise, "AuthenticationException" will be raised.
*/
async authenticateUsing(guards?: (keyof KnownGuards)[]) {
async authenticateUsing(guards?: (keyof KnownGuards)[], options?: { redirectTo?: string }) {
const guardsToUse = guards || [this.defaultGuard]
let lastUsedGuardDriver: string | undefined

Expand All @@ -144,6 +144,7 @@ export class Authenticator<KnownGuards extends Record<string, GuardFactory>> {
throw new AuthenticationException('Unauthorized access', {
code: 'E_UNAUTHORIZED_ACCESS',
guardDriverName: lastUsedGuardDriver!,
redirectTo: options?.redirectTo,
})
}
}
18 changes: 18 additions & 0 deletions src/auth/middleware/auth_middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { HttpContext } from '@adonisjs/core/http'
import type { NextFn } from '@adonisjs/core/types/http'
import type { Authenticators } from '@adonisjs/auth/types'

/**
* Options accepted by the middleware options
*/
export type AuthMiddlewareOptions = {
guards?: (keyof Authenticators)[]
redirectTo?: string
}

export default class AuthMiddleware {
async handle(ctx: HttpContext, next: NextFn, options: AuthMiddlewareOptions = {}) {
await ctx.auth.authenticateUsing(options.guards, options)
return next()
}
}
37 changes: 37 additions & 0 deletions src/auth/middleware/initialize_auth_middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/// <reference types="@adonisjs/core/providers/edge_provider" />

import auth from '@adonisjs/auth/services/main'
import type { HttpContext } from '@adonisjs/core/http'
import type { NextFn } from '@adonisjs/core/types/http'

/**
* The "InitializeAuthMiddleware" is used to create a request
* specific authenticator instance for every HTTP request.
*
* This middleware does not protect routes from unauthenticated
* users. Please use the "auth" middleware for that.
*/
export default class InitializeAuthMiddleware {
async handle(ctx: HttpContext, next: NextFn) {
/**
* Initialize the authenticator for the current HTTP
* request
*/
ctx.auth = auth.createAuthenticator(ctx)

/**
* Sharing authenticator with templates
*/
if ('view' in ctx) {
ctx.view.share({ auth: ctx.auth })
}

return next()
}
}

declare module '@adonisjs/core/http' {
export interface HttpContext {
auth: ReturnType<(typeof auth)['createAuthenticator']>
}
}
2 changes: 1 addition & 1 deletion stubs/config.stub
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const userProvider = providers.db({
table: 'users',
passwordColumnName: 'password',
id: 'id',
uids: ['email']
uids: ['email'],
})
{{/if}}

Expand Down
12 changes: 0 additions & 12 deletions stubs/config/auth_middleware.stub

This file was deleted.

206 changes: 154 additions & 52 deletions tests/auth/configure.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,157 @@
* file that was distributed with this source code.
*/

// import { test } from '@japa/runner'
// import { fileURLToPath } from 'node:url'
// import { IgnitorFactory } from '@adonisjs/core/factories'
// import Configure from '@adonisjs/core/commands/configure'

// const BASE_URL = new URL('./tmp/', import.meta.url)

// test.group('Configure', (group) => {
// group.each.setup(({ context }) => {
// context.fs.baseUrl = BASE_URL
// context.fs.basePath = fileURLToPath(BASE_URL)
// })

// test('create config file and register provider', async ({ fs, assert }) => {
// const ignitor = new IgnitorFactory()
// .withCoreProviders()
// .withCoreConfig()
// .create(BASE_URL, {
// importer: (filePath) => {
// if (filePath.startsWith('./') || filePath.startsWith('../')) {
// return import(new URL(filePath, BASE_URL).href)
// }

// return import(filePath)
// },
// })

// // await fs.create('.env', '')
// // await fs.createJson('tsconfig.json', {})
// // await fs.create('start/env.ts', `export default Env.create(new URL('./'), {})`)
// // await fs.create('start/kernel.ts', `router.use([])`)
// // await fs.create('adonisrc.ts', `export default defineConfig({}) {}`)

// const app = ignitor.createApp('web')
// await app.init()
// await app.boot()

// const ace = await app.container.make('ace')
// const command = await ace.create(Configure, ['../../../index.js'])
// await command.exec()

// // await assert.fileExists('config/session.ts')
// // await assert.fileExists('adonisrc.ts')
// // await assert.fileContains('adonisrc.ts', '@adonisjs/session/session_provider')
// // await assert.fileContains('config/session.ts', 'defineConfig')
// // await assert.fileContains('.env', 'SESSION_DRIVER=cookie')
// // await assert.fileContains(
// // 'start/env.ts',
// // `SESSION_DRIVER: Env.schema.enum(['cookie', 'redis', 'file', 'memory'] as const)`
// // )
// }).timeout(60 * 1000)
// })
import { test } from '@japa/runner'
import { fileURLToPath } from 'node:url'
import { IgnitorFactory } from '@adonisjs/core/factories'
import Configure from '@adonisjs/core/commands/configure'

const BASE_URL = new URL('./tmp/', import.meta.url)

test.group('Configure', (group) => {
group.each.setup(({ context }) => {
context.fs.baseUrl = BASE_URL
context.fs.basePath = fileURLToPath(BASE_URL)
})

test('create config file and register provider', async ({ fs, assert }) => {
const ignitor = new IgnitorFactory()
.withCoreProviders()
.withCoreConfig()
.create(BASE_URL, {
importer: (filePath) => {
if (filePath.startsWith('./') || filePath.startsWith('../')) {
return import(new URL(filePath, BASE_URL).href)
}

return import(filePath)
},
})

await fs.create('start/kernel.ts', `router.use([])`)
await fs.createJson('tsconfig.json', {})
await fs.create('adonisrc.ts', `export default defineConfig({}) {}`)

const app = ignitor.createApp('web')
await app.init()
await app.boot()

const ace = await app.container.make('ace')
const command = await ace.create(Configure, ['../../../index.js'])
command.prompt.trap('Select the user provider you want to use').replyWith('lucid')
await command.exec()

await assert.fileExists('config/auth.ts')
await assert.fileExists('adonisrc.ts')
await assert.fileContains('adonisrc.ts', '@adonisjs/auth/auth_provider')
await assert.fileContains(
'config/auth.ts',
`const userProvider = providers.lucid({
model: () => import('#models/user'),
uids: ['email'],
})`
)
await assert.fileContains(
'config/auth.ts',
`declare module '@adonisjs/auth/types' {
interface Authenticators extends InferAuthenticators<typeof authConfig> {}
}`
)
}).timeout(60 * 1000)

test('create config file with db user provider', async ({ fs, assert }) => {
const ignitor = new IgnitorFactory()
.withCoreProviders()
.withCoreConfig()
.create(BASE_URL, {
importer: (filePath) => {
if (filePath.startsWith('./') || filePath.startsWith('../')) {
return import(new URL(filePath, BASE_URL).href)
}

return import(filePath)
},
})

await fs.create('start/kernel.ts', `router.use([])`)
await fs.createJson('tsconfig.json', {})
await fs.create('adonisrc.ts', `export default defineConfig({}) {}`)

const app = ignitor.createApp('web')
await app.init()
await app.boot()

const ace = await app.container.make('ace')
const command = await ace.create(Configure, ['../../../index.js'])
command.prompt.trap('Select the user provider you want to use').replyWith('db')
await command.exec()

await assert.fileExists('config/auth.ts')
await assert.fileExists('adonisrc.ts')
await assert.fileContains('adonisrc.ts', '@adonisjs/auth/auth_provider')
await assert.fileContains(
'config/auth.ts',
`const userProvider = providers.db({
table: 'users',
passwordColumnName: 'password',
id: 'id',
uids: ['email'],
})`
)
await assert.fileContains(
'config/auth.ts',
`declare module '@adonisjs/auth/types' {
interface Authenticators extends InferAuthenticators<typeof authConfig> {}
}`
)
}).timeout(60 * 1000)

test('register middleware', async ({ fs, assert }) => {
const ignitor = new IgnitorFactory()
.withCoreProviders()
.withCoreConfig()
.create(BASE_URL, {
importer: (filePath) => {
if (filePath.startsWith('./') || filePath.startsWith('../')) {
return import(new URL(filePath, BASE_URL).href)
}

return import(filePath)
},
})

await fs.create(
'start/kernel.ts',
`
router.use([])
export const { middleware } = router.named({
})
`
)
await fs.createJson('tsconfig.json', {})
await fs.create('adonisrc.ts', `export default defineConfig({}) {}`)

const app = ignitor.createApp('web')
await app.init()
await app.boot()

const ace = await app.container.make('ace')
const command = await ace.create(Configure, ['../../../index.js'])
command.prompt.trap('Select the user provider you want to use').replyWith('db')
await command.exec()

await assert.fileExists('config/auth.ts')
await assert.fileExists('adonisrc.ts')

await assert.fileContains(
'start/kernel.ts',
`export const { middleware } = router.named({
auth: () => import('@adonisjs/auth/auth_middleware')
})`
)
await assert.fileContains(
'start/kernel.ts',
`router.use([() => import('@adonisjs/auth/initialize_auth_middleware')])`
)
}).timeout(60 * 1000)
})

0 comments on commit e2f20fc

Please sign in to comment.