update
This commit is contained in:
@@ -1,102 +1,91 @@
|
||||
import type { HttpContext } from '@adonisjs/core/http'
|
||||
import {{pascalCaseName}} from '#modules/{{capName}}/model/{{snakeCaseName}}'
|
||||
import {{pascalCaseName}}Policy from '#modules/{{capName}}/policy/{{snakeCaseName}}_policy'
|
||||
import { create{{pascalCaseName}}ApiValidator } from '#modules/{{capName}}/api/validators/{{snakeCaseName}}_create_api_validator'
|
||||
import { update{{pascalCaseName}}ApiValidator } from '#modules/{{capName}}/api/validators/{{snakeCaseName}}_update_api_validator'
|
||||
|
||||
export default class {{pascalCaseName}}ApiController {
|
||||
/**
|
||||
* GET /api/{{name}}
|
||||
*/
|
||||
/**
|
||||
* @index
|
||||
* @operationId get{{pascalCaseName}}
|
||||
* @description Returns array of records
|
||||
* @responseBody 200 - [{{{swaggerModel}}}]
|
||||
* @responseHeader 200 - X-pages - A description of the header - @example(test)
|
||||
* @description Returns records visible to an authorized user.
|
||||
* @responseBody 200 - [{{{swaggerExample}}}]
|
||||
* @responseBody 401 - { "message": "Unauthorized" }
|
||||
* @responseBody 403 - { "message": "Forbidden" }
|
||||
*/
|
||||
async index({ response }: HttpContext) {
|
||||
const result = await {{pascalCaseName}}.all()
|
||||
return response.ok(result)
|
||||
async index({ response, bouncer }: HttpContext) {
|
||||
await bouncer.with({{pascalCaseName}}Policy).authorize('view{{pascalCaseName}}List')
|
||||
return response.ok(await {{pascalCaseName}}.all())
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/{{name}}/:id
|
||||
*/
|
||||
|
||||
/**
|
||||
* @show
|
||||
* @operationId show{{pascalCaseName}}
|
||||
* @description Returns record
|
||||
* @responseBody 200 - {{{swaggerModel}}}
|
||||
* @description Returns one record visible to an authorized user.
|
||||
* @paramPath id - Record ID - @required
|
||||
* @responseBody 200 - {{{swaggerExample}}}
|
||||
* @responseBody 401 - { "message": "Unauthorized" }
|
||||
* @responseBody 403 - { "message": "Forbidden" }
|
||||
* @responseBody 404 - { "message": "Not found" }
|
||||
* @responseHeader 200 - X-pages - A description of the header - @example(test)
|
||||
*/
|
||||
async show({ params, response }: HttpContext) {
|
||||
async show({ params, response, bouncer }: HttpContext) {
|
||||
await bouncer.with({{pascalCaseName}}Policy).authorize('view{{pascalCaseName}}')
|
||||
const record = await {{pascalCaseName}}.find(params.id)
|
||||
if (!record) return response.notFound({ message: 'Not found' })
|
||||
return response.ok(record)
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/{{name}}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @store
|
||||
* @operationId store{{pascalCaseName}}
|
||||
* @description Creates and Returns record
|
||||
* @description Creates and returns a record.
|
||||
* @requestBody <create{{pascalCaseName}}ApiValidator>
|
||||
* @responseBody 200 - {{{swaggerModel}}}
|
||||
* @responseBody 404 - { "message": "Not found" }
|
||||
* @responseBody 422 - <Error422> - Returns an error if the request body fails validation.
|
||||
* @responseHeader 200 - X-pages - A description of the header - @example(test)
|
||||
* @responseBody 201 - {{{swaggerExample}}}
|
||||
* @responseBody 401 - { "message": "Unauthorized" }
|
||||
* @responseBody 403 - { "message": "Forbidden" }
|
||||
* @responseBody 422 - { "errors": [{ "message": "Validation failed", "rule": "required", "field": "name" }] }
|
||||
*/
|
||||
async store({ request, response }: HttpContext) {
|
||||
async store({ request, response, bouncer }: HttpContext) {
|
||||
await bouncer.with({{pascalCaseName}}Policy).authorize('create{{pascalCaseName}}')
|
||||
const payload = await create{{pascalCaseName}}ApiValidator.validate(request.all())
|
||||
const record = await {{pascalCaseName}}.create(payload)
|
||||
return response.created(record)
|
||||
return response.created(await {{pascalCaseName}}.create(payload))
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT /api/{{name}}/:id
|
||||
*/
|
||||
|
||||
/**
|
||||
* @update
|
||||
* @operationId update{{pascalCaseName}}
|
||||
* @description Updates and Returns record
|
||||
* @description Updates and returns a record.
|
||||
* @paramPath id - Record ID - @required
|
||||
* @requestBody <update{{pascalCaseName}}ApiValidator>
|
||||
* @responseBody 200 - {{{swaggerModel}}}
|
||||
* @responseBody 200 - {{{swaggerExample}}}
|
||||
* @responseBody 401 - { "message": "Unauthorized" }
|
||||
* @responseBody 403 - { "message": "Forbidden" }
|
||||
* @responseBody 404 - { "message": "Not found" }
|
||||
* @responseBody 422 - <Error422> - Returns an error if the request body fails validation.
|
||||
* @responseHeader 200 - X-pages - A description of the header - @example(test)
|
||||
* @responseBody 422 - { "errors": [{ "message": "Validation failed", "rule": "required", "field": "name" }] }
|
||||
*/
|
||||
async update({ params, request, response }: HttpContext) {
|
||||
async update({ params, request, response, bouncer }: HttpContext) {
|
||||
await bouncer.with({{pascalCaseName}}Policy).authorize('update{{pascalCaseName}}')
|
||||
const record = await {{pascalCaseName}}.find(params.id)
|
||||
if (!record) return response.notFound({ message: 'Not found' })
|
||||
|
||||
const payload = await update{{pascalCaseName}}ApiValidator.validate(request.all())
|
||||
record.merge(payload)
|
||||
record.merge(await update{{pascalCaseName}}ApiValidator.validate(request.all()))
|
||||
await record.save()
|
||||
return response.ok(record)
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE /api/{{name}}/:id
|
||||
*/
|
||||
|
||||
/**
|
||||
* @destroy
|
||||
* @operationId destroy{{pascalCaseName}}
|
||||
* @description Destroys record
|
||||
* @paramPath id - The ID of the source - @required
|
||||
* @description Deletes a record.
|
||||
* @paramPath id - Record ID - @required
|
||||
* @responseBody 200 - { "message": "Deleted" }
|
||||
* @responseHeader 200 - X-pages - A description of the header - @example(test)
|
||||
* @responseBody 401 - { "message": "Unauthorized" }
|
||||
* @responseBody 403 - { "message": "Forbidden" }
|
||||
* @responseBody 404 - { "message": "Not found" }
|
||||
*/
|
||||
async destroy({ params, response }: HttpContext) {
|
||||
async destroy({ params, response, bouncer }: HttpContext) {
|
||||
await bouncer.with({{pascalCaseName}}Policy).authorize('delete{{pascalCaseName}}')
|
||||
const record = await {{pascalCaseName}}.find(params.id)
|
||||
if (!record) return response.notFound({ message: 'Not found' })
|
||||
|
||||
await record.delete()
|
||||
return response.ok({ message: 'Deleted' })
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import router from '@adonisjs/core/services/router'
|
||||
import { middleware } from '#start/kernel'
|
||||
|
||||
const {{pascalCaseName}}ApiController = () => import('#modules/{{moduleName}}/api/controllers/{{snakeCaseName}}_api_controller')
|
||||
|
||||
router
|
||||
@@ -10,3 +12,4 @@ router
|
||||
router.delete('/:id', [{{pascalCaseName}}ApiController, 'destroy'])
|
||||
})
|
||||
.prefix('/api/{{snakeCaseName}}')
|
||||
.use([middleware.auth()])
|
||||
|
||||
@@ -1,24 +1,104 @@
|
||||
import { test } from '@japa/runner'
|
||||
import db from '@adonisjs/lucid/services/db'
|
||||
import testUtils from '@adonisjs/core/services/test_utils'
|
||||
import { createAdminWithToken } from '#tests/utils/auth'
|
||||
|
||||
const ALL_PERMISSIONS = ['{{name}}s.view', '{{name}}s.create', '{{name}}s.update', '{{name}}s.delete']
|
||||
|
||||
const ROUTES = [
|
||||
['get', '/api/{{snakeCaseName}}'],
|
||||
['get', '/api/{{snakeCaseName}}/999999'],
|
||||
['post', '/api/{{snakeCaseName}}'],
|
||||
['put', '/api/{{snakeCaseName}}/999999'],
|
||||
['delete', '/api/{{snakeCaseName}}/999999'],
|
||||
] as const
|
||||
|
||||
test.group('API /api/{{snakeCaseName}}', (group) => {
|
||||
group.each.setup(async () => {
|
||||
await db.beginGlobalTransaction()
|
||||
return () => db.rollbackGlobalTransaction()
|
||||
group.each.setup(() => testUtils.db().wrapInGlobalTransaction())
|
||||
|
||||
test('rejects unauthenticated requests', async ({ client }) => {
|
||||
for (const [method, url] of ROUTES) {
|
||||
const response = await client[method](url)
|
||||
response.assertStatus(401)
|
||||
}
|
||||
})
|
||||
|
||||
test('rejects a token without the required permission', async ({ client }) => {
|
||||
const { token } = await createAdminWithToken([])
|
||||
for (const [method, url] of ROUTES) {
|
||||
const response = await client[method](url).bearerToken(token)
|
||||
response.assertStatus(403)
|
||||
}
|
||||
})
|
||||
|
||||
test('GET /api/{{snakeCaseName}} -> list', async ({ client }) => {
|
||||
const res = await client.get('/api/{{snakeCaseName}}')
|
||||
res.assertStatus(200)
|
||||
const { token } = await createAdminWithToken(ALL_PERMISSIONS)
|
||||
const response = await client.get('/api/{{snakeCaseName}}').bearerToken(token)
|
||||
response.assertStatus(200)
|
||||
})
|
||||
|
||||
test('POST /api/{{snakeCaseName}} -> create', async ({ client }) => {
|
||||
test('POST /api/{{snakeCaseName}} -> create', async ({ assert, client }) => {
|
||||
const { token } = await createAdminWithToken(ALL_PERMISSIONS)
|
||||
const payload = {
|
||||
{{#each createFields}}
|
||||
{{column_name}}: {{{sampleValue}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
}
|
||||
const res = await client.post('/api/{{snakeCaseName}}').json(payload)
|
||||
res.assertStatus(201)
|
||||
const response = await client.post('/api/{{snakeCaseName}}').bearerToken(token).json(payload)
|
||||
response.assertStatus(201)
|
||||
assert.exists(response.body().id)
|
||||
})
|
||||
|
||||
test('GET /api/{{snakeCaseName}}/:id -> show and 404', async ({ assert, client }) => {
|
||||
const { token } = await createAdminWithToken(ALL_PERMISSIONS)
|
||||
const created = await client.post('/api/{{snakeCaseName}}').bearerToken(token).json({
|
||||
{{#each createFields}}
|
||||
{{column_name}}: {{{sampleValue}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
})
|
||||
created.assertStatus(201)
|
||||
const id = created.body().id
|
||||
|
||||
const response = await client.get(`/api/{{snakeCaseName}}/${id}`).bearerToken(token)
|
||||
response.assertStatus(200)
|
||||
assert.equal(response.body().id, id)
|
||||
|
||||
const missing = await client.get('/api/{{snakeCaseName}}/999999').bearerToken(token)
|
||||
missing.assertStatus(404)
|
||||
})
|
||||
|
||||
test('PUT /api/{{snakeCaseName}}/:id -> update and 404', async ({ client }) => {
|
||||
const { token } = await createAdminWithToken(ALL_PERMISSIONS)
|
||||
const created = await client.post('/api/{{snakeCaseName}}').bearerToken(token).json({
|
||||
{{#each createFields}}
|
||||
{{column_name}}: {{{sampleValue}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
})
|
||||
created.assertStatus(201)
|
||||
|
||||
const updated = await client.put(`/api/{{snakeCaseName}}/${created.body().id}`).bearerToken(token).json({
|
||||
{{#each updateFields}}
|
||||
{{column_name}}: {{{sampleValue}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
})
|
||||
updated.assertStatus(200)
|
||||
|
||||
const missing = await client.put('/api/{{snakeCaseName}}/999999').bearerToken(token).json({})
|
||||
missing.assertStatus(404)
|
||||
})
|
||||
|
||||
test('DELETE /api/{{snakeCaseName}}/:id -> destroy and 404', async ({ client }) => {
|
||||
const { token } = await createAdminWithToken(ALL_PERMISSIONS)
|
||||
const created = await client.post('/api/{{snakeCaseName}}').bearerToken(token).json({
|
||||
{{#each createFields}}
|
||||
{{column_name}}: {{{sampleValue}}}{{#unless @last}},{{/unless}}
|
||||
{{/each}}
|
||||
})
|
||||
created.assertStatus(201)
|
||||
|
||||
const deleted = await client.delete(`/api/{{snakeCaseName}}/${created.body().id}`).bearerToken(token)
|
||||
deleted.assertStatus(200)
|
||||
|
||||
const missing = await client.delete('/api/{{snakeCaseName}}/999999').bearerToken(token)
|
||||
missing.assertStatus(404)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user