initital commit
32
.adonisrc.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"typescript": true,
|
||||
"commands": [
|
||||
"./commands",
|
||||
"@adonisjs/core/build/commands",
|
||||
"@adonisjs/repl/build/commands",
|
||||
"@adonisjs/lucid/build/commands"
|
||||
],
|
||||
"exceptionHandlerNamespace": "App/Exceptions/Handler",
|
||||
"aliases": {
|
||||
"App": "app",
|
||||
"Config": "config",
|
||||
"Database": "database",
|
||||
"Contracts": "contracts"
|
||||
},
|
||||
"preloads": [
|
||||
"./start/routes",
|
||||
"./start/kernel"
|
||||
],
|
||||
"providers": [
|
||||
"./providers/AppProvider",
|
||||
"@adonisjs/core",
|
||||
"@adonisjs/redis",
|
||||
"@adonisjs/session",
|
||||
"@adonisjs/mail",
|
||||
"@adonisjs/auth",
|
||||
"@adonisjs/lucid"
|
||||
],
|
||||
"aceProviders": [
|
||||
"@adonisjs/repl"
|
||||
]
|
||||
}
|
||||
14
.editorconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.json]
|
||||
insert_final_newline = ignore
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
28
.env.example
Normal file
@@ -0,0 +1,28 @@
|
||||
PORT=
|
||||
HOST=
|
||||
NODE_ENV=
|
||||
APP_KEY=
|
||||
APP_NAME=
|
||||
|
||||
DB_CONNECTION=
|
||||
|
||||
MYSQL_HOST=
|
||||
MYSQL_PORT=
|
||||
MYSQL_USER=
|
||||
MYSQL_PASSWORD=
|
||||
MYSQL_DB_NAME=
|
||||
|
||||
SESSION_DRIVER=
|
||||
|
||||
REDIS_CONNECTION=
|
||||
REDIS_PORT=
|
||||
REDIS_DB=
|
||||
REDIS_HOST=
|
||||
REDIS_PASSWORD=
|
||||
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
SMTP_USERNAME=
|
||||
SMTP_PASSWORD=
|
||||
|
||||
MAILGUN_API_KEY=
|
||||
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
node_modules
|
||||
build
|
||||
coverage
|
||||
.vscode
|
||||
.DS_STORE
|
||||
.env
|
||||
tmp
|
||||
database/seeders
|
||||
|
||||
5
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
12
.idea/artapi.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/artapi.iml" filepath="$PROJECT_DIR$/.idea/artapi.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
21
Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
||||
FROM node:lts-alpine
|
||||
|
||||
RUN mkdir -p /home/node/app/node_modules
|
||||
|
||||
WORKDIR /home/node/app
|
||||
|
||||
COPY package.json yarn.* ./
|
||||
|
||||
RUN apk add --no-cache git
|
||||
|
||||
COPY . /home/node/app/
|
||||
|
||||
RUN chown -R node:node /home/node
|
||||
|
||||
RUN yarn
|
||||
|
||||
USER node
|
||||
|
||||
EXPOSE 3333
|
||||
|
||||
ENTRYPOINT ["node","ace","serve","--watch"]
|
||||
15
ace
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Ace Commands
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is the entry point for running ace commands.
|
||||
|
|
||||
*/
|
||||
|
||||
require('reflect-metadata')
|
||||
|
||||
const { Ignitor } = require('@adonisjs/core/build/standalone')
|
||||
new Ignitor(__dirname)
|
||||
.ace()
|
||||
.handle(process.argv.slice(2))
|
||||
1
ace-manifest.json
Normal file
@@ -0,0 +1 @@
|
||||
{"dump:rcfile":{"settings":{},"commandPath":"@adonisjs/core/build/commands/DumpRc","commandName":"dump:rcfile","description":"Dump contents of .adonisrc.json file along with defaults","args":[],"flags":[]},"list:routes":{"settings":{"loadApp":true},"commandPath":"@adonisjs/core/build/commands/ListRoutes","commandName":"list:routes","description":"List application routes","args":[],"flags":[{"name":"json","propertyName":"json","type":"boolean","description":"Output as JSON"}]},"generate:key":{"settings":{},"commandPath":"@adonisjs/core/build/commands/GenerateKey","commandName":"generate:key","description":"Generate a new APP_KEY secret","args":[],"flags":[]},"repl":{"settings":{"loadApp":true,"environment":"repl","stayAlive":true},"commandPath":"@adonisjs/repl/build/commands/AdonisRepl","commandName":"repl","description":"Start a new REPL session","args":[],"flags":[]},"db:seed":{"settings":{"loadApp":true},"commandPath":"@adonisjs/lucid/build/commands/DbSeed","commandName":"db:seed","description":"Execute database seeder files","args":[],"flags":[{"name":"connection","propertyName":"connection","type":"string","description":"Define a custom database connection for the seeders","alias":"c"},{"name":"interactive","propertyName":"interactive","type":"boolean","description":"Run seeders in interactive mode","alias":"i"},{"name":"files","propertyName":"files","type":"array","description":"Define a custom set of seeders files names to run","alias":"f"}]},"make:model":{"settings":{},"commandPath":"@adonisjs/lucid/build/commands/MakeModel","commandName":"make:model","description":"Make a new Lucid model","args":[{"type":"string","propertyName":"name","name":"name","required":true,"description":"Name of the model class"}],"flags":[{"name":"migration","propertyName":"migration","type":"boolean","alias":"m","description":"Generate the migration for the model"},{"name":"controller","propertyName":"controller","type":"boolean","alias":"c","description":"Generate the controller for the model"}]},"make:migration":{"settings":{"loadApp":true},"commandPath":"@adonisjs/lucid/build/commands/MakeMigration","commandName":"make:migration","description":"Make a new migration file","args":[{"type":"string","propertyName":"name","name":"name","required":true,"description":"Name of the migration file"}],"flags":[{"name":"connection","propertyName":"connection","type":"string","description":"Define a custom database connection for the migration"},{"name":"folder","propertyName":"folder","type":"string","description":"Pre-select a migration directory"},{"name":"create","propertyName":"create","type":"string","description":"Define the table name for creating a new table"},{"name":"table","propertyName":"table","type":"string","description":"Define the table name for altering an existing table"}]},"make:seeder":{"settings":{},"commandPath":"@adonisjs/lucid/build/commands/MakeSeeder","commandName":"make:seeder","description":"Make a new Seeder file","args":[{"type":"string","propertyName":"name","name":"name","required":true,"description":"Name of the seeder class"}],"flags":[]},"migration:run":{"settings":{"loadApp":true},"commandPath":"@adonisjs/lucid/build/commands/Migration/Run","commandName":"migration:run","description":"Run pending migrations","args":[],"flags":[{"name":"connection","propertyName":"connection","type":"string","description":"Define a custom database connection","alias":"c"},{"name":"force","propertyName":"force","type":"boolean","description":"Explicitly force to run migrations in production"},{"name":"dry-run","propertyName":"dryRun","type":"boolean","description":"Print SQL queries, instead of running the migrations"}]},"migration:rollback":{"settings":{"loadApp":true},"commandPath":"@adonisjs/lucid/build/commands/Migration/Rollback","commandName":"migration:rollback","description":"Rollback migrations to a given batch number","args":[],"flags":[{"name":"connection","propertyName":"connection","type":"string","description":"Define a custom database connection","alias":"c"},{"name":"force","propertyName":"force","type":"boolean","description":"Explictly force to run migrations in production"},{"name":"dry-run","propertyName":"dryRun","type":"boolean","description":"Print SQL queries, instead of running the migrations"},{"name":"batch","propertyName":"batch","type":"number","description":"Define custom batch number for rollback. Use 0 to rollback to initial state"}]},"migration:status":{"settings":{"loadApp":true},"commandPath":"@adonisjs/lucid/build/commands/Migration/Status","commandName":"migration:status","description":"Check migrations current status.","args":[],"flags":[{"name":"connection","propertyName":"connection","type":"string","description":"Define a custom database connection","alias":"c"}]}}
|
||||
56
app/Controllers/Http/AuthController.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import {HttpContextContract} from '@ioc:Adonis/Core/HttpContext'
|
||||
import User from "App/Models/User";
|
||||
import AuthValidator from "App/Validators/AuthValidator";
|
||||
|
||||
export default class AuthController {
|
||||
|
||||
public async loginWeb ({request, auth}: HttpContextContract) {
|
||||
const data = await request.validate(AuthValidator)
|
||||
const {email, password, remember_me } = data
|
||||
|
||||
try {
|
||||
await auth.attempt(email, password, remember_me)
|
||||
const user = await User.query()
|
||||
.where('id', auth.user!.id)
|
||||
.firstOrFail()
|
||||
if (!remember_me) {
|
||||
await user.merge({
|
||||
rememberMeToken: ''
|
||||
}).save()
|
||||
}
|
||||
return { user }
|
||||
} catch (error) {
|
||||
if (error.code === 'E_INVALID_AUTH_UID') return { error: "L'utilisateur n'a pas été trouvé" }
|
||||
if (error.code === 'E_INVALID_AUTH_PASSWORD') return { error: "L'identifiant ou le mot de passe est incorrect" }
|
||||
}
|
||||
}
|
||||
|
||||
public async loginApi ({request, auth}: HttpContextContract) {
|
||||
const email = request.input('email')
|
||||
const password = request.input('password')
|
||||
|
||||
const token = await auth.use('api').attempt(email, password, {
|
||||
expiresIn: '10 days'
|
||||
})
|
||||
return token.toJSON()
|
||||
}
|
||||
|
||||
public async logoutWeb ({auth}: HttpContextContract) {
|
||||
await auth.logout()
|
||||
return { message: 'Vous avez été déconnecté' }
|
||||
}
|
||||
|
||||
public async logoutApi ({auth}: HttpContextContract) {
|
||||
await auth.use('api').logout()
|
||||
return { message: 'Vous avez été déconnecté' }
|
||||
}
|
||||
|
||||
public async user ({auth}: HttpContextContract) {
|
||||
await auth.authenticate()
|
||||
const user = await User.query()
|
||||
.where('id', auth.user!.id)
|
||||
.firstOrFail()
|
||||
return { user }
|
||||
}
|
||||
|
||||
}
|
||||
40
app/Controllers/Http/FileController.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import Application from "@ioc:Adonis/Core/Application";
|
||||
import File from "App/Models/File";
|
||||
|
||||
export default class FileController {
|
||||
|
||||
public async index () {
|
||||
return File.query()
|
||||
}
|
||||
|
||||
public async store ({request}: HttpContextContract) {
|
||||
const file = await request.file('file', {
|
||||
extnames: ['jpg', 'png', 'jpeg']
|
||||
})
|
||||
const label = request.input('label')
|
||||
|
||||
if (!file) {
|
||||
return 'Please upload file'
|
||||
}
|
||||
if (file.hasErrors) {
|
||||
return file.errors
|
||||
}
|
||||
|
||||
await file.move(Application.makePath('storage'), {
|
||||
name: `${label}.${file.extname}`
|
||||
})
|
||||
|
||||
return await File.create({
|
||||
fileName: `${label}.${file.extname}`,
|
||||
label: label
|
||||
})
|
||||
}
|
||||
|
||||
public async destroy({ params }: HttpContextContract) {
|
||||
const file = await File.findOrFail(params.id)
|
||||
await file.delete()
|
||||
return { message: "Le fichier a bien été supprimée" }
|
||||
}
|
||||
|
||||
}
|
||||
74
app/Controllers/Http/PostsController.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import {HttpContextContract} from '@ioc:Adonis/Core/HttpContext'
|
||||
import Post from "App/Models/Post";
|
||||
import Redis from "@ioc:Adonis/Addons/Redis";
|
||||
|
||||
export default class PostsController {
|
||||
|
||||
public async getLikes ({params}: HttpContextContract) {
|
||||
let post = await Post.findBy('slug', params.slug)
|
||||
|
||||
if (!post) {
|
||||
post = await Post.create({
|
||||
slug: params.slug,
|
||||
likes: 0
|
||||
})
|
||||
}
|
||||
|
||||
return post.likes
|
||||
}
|
||||
|
||||
public async unlike ({request, params}: HttpContextContract) {
|
||||
const post = await Post.findByOrFail('slug', params.slug)
|
||||
const ip = await request.ip()
|
||||
|
||||
const getLikes = post.likes - 1
|
||||
const isLiked = await Redis.exists(`artapi/posts/${post.slug}/${ip}`)
|
||||
|
||||
if (isLiked) {
|
||||
await Redis.del(`artapi/posts/${post.slug}/${ip}`)
|
||||
await post.merge({
|
||||
likes: getLikes
|
||||
}).save()
|
||||
return {
|
||||
code: 200,
|
||||
post
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async isLiked ({params, request}: HttpContextContract) {
|
||||
const post = await Post.findBy('slug', params.slug)
|
||||
if (post) {
|
||||
const ip = request.ip()
|
||||
return Redis.exists(`artapi/posts/${post.slug}/${ip}`);
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public async like ({request, params}: HttpContextContract) {
|
||||
let post = await Post.findBy('slug', params.slug)
|
||||
const ip = await request.ip()
|
||||
|
||||
if (!post) {
|
||||
post = await Post.create({
|
||||
slug: params.slug,
|
||||
likes: 0
|
||||
})
|
||||
}
|
||||
|
||||
const getLikes = post.likes + 1
|
||||
const isLiked = await Redis.exists(`artapi/posts/${post.slug}/${ip}`)
|
||||
|
||||
if (!isLiked) {
|
||||
await Redis.set(`artapi/posts/${post.slug}/${ip}`, Date.now())
|
||||
await post.merge({
|
||||
likes: getLikes
|
||||
}).save()
|
||||
return {
|
||||
code: 200,
|
||||
post
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
41
app/Controllers/Http/SubscribersController.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import {HttpContextContract} from "@ioc:Adonis/Core/HttpContext";
|
||||
import Subscriber from "App/Models/Subscriber";
|
||||
import StoreValidator from "App/Validators/subscriber/StoreValidator";
|
||||
import UpdateValidator from "App/Validators/subscriber/UpdateValidator";
|
||||
|
||||
export default class SubscribersController {
|
||||
|
||||
public async index ({request}: HttpContextContract) {
|
||||
const limit = request.input('limit')
|
||||
const page = request.input('page')
|
||||
if (limit && page) {
|
||||
return Subscriber.query().orderBy('id', 'asc').paginate(page, limit);
|
||||
} else {
|
||||
return Subscriber.query().orderBy('id', 'asc');
|
||||
}
|
||||
}
|
||||
|
||||
public async store ({request}: HttpContextContract) {
|
||||
const data = await request.validate(StoreValidator)
|
||||
return await Subscriber.create(data)
|
||||
}
|
||||
|
||||
public async show ({params}: HttpContextContract) {
|
||||
return await Subscriber.findOrFail(params.id)
|
||||
}
|
||||
|
||||
public async update({ request, params }: HttpContextContract) {
|
||||
const subscriber = await Subscriber.findOrFail(params.id)
|
||||
const data = await request.validate(UpdateValidator)
|
||||
await subscriber.merge(data).save()
|
||||
|
||||
return { message: 'L\'abonné a été mis à jour' }
|
||||
}
|
||||
|
||||
public async destroy({ params }: HttpContextContract) {
|
||||
const subscriber = await Subscriber.findOrFail(params.id)
|
||||
await subscriber.delete()
|
||||
return { message: "L\'abonné a bien été supprimé" }
|
||||
}
|
||||
|
||||
}
|
||||
50
app/Controllers/Http/UsersController.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import {HttpContextContract} from '@ioc:Adonis/Core/HttpContext'
|
||||
import User from "App/Models/User";
|
||||
import StoreValidator from "App/Validators/users/StoreValidator";
|
||||
import UpdateValidator from "App/Validators/users/UpdateValidator";
|
||||
|
||||
export default class UsersController {
|
||||
|
||||
public async index () {
|
||||
return User.query()
|
||||
}
|
||||
|
||||
public async store ({request}: HttpContextContract) {
|
||||
const data = await request.validate(StoreValidator)
|
||||
return await User.create(data)
|
||||
}
|
||||
|
||||
public async show ({params}: HttpContextContract) {
|
||||
return await User.findOrFail(params.id)
|
||||
}
|
||||
|
||||
public async update({ request, params, response }: HttpContextContract) {
|
||||
const user = await User.findOrFail(params.id)
|
||||
const data = await request.validate(UpdateValidator)
|
||||
const { email } = data
|
||||
const user2 = await User.findBy('email', email)
|
||||
|
||||
if (user2 !== null && user.email !== email) {
|
||||
return response.abort({
|
||||
message: 'L\' adresse mail n\'est pas unique !'
|
||||
})
|
||||
}
|
||||
|
||||
await user.merge(data).save()
|
||||
|
||||
return { message: 'Le compte a été mis à jour' }
|
||||
}
|
||||
|
||||
public async destroy({ response, params, auth }: HttpContextContract) {
|
||||
const user = await User.findOrFail(params.id)
|
||||
const admin = await User.findBy('email', 'arthurdanjou@outlook.fr')
|
||||
|
||||
if (auth.user?.id != admin?.id) {
|
||||
return response.unauthorized()
|
||||
}
|
||||
|
||||
await user.delete()
|
||||
return { message: "L'utilisateur a bien été supprimé" }
|
||||
}
|
||||
|
||||
}
|
||||
23
app/Exceptions/Handler.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Http Exception Handler
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| AdonisJs will forward all exceptions occurred during an HTTP request to
|
||||
| the following class. You can learn more about exception handling by
|
||||
| reading docs.
|
||||
|
|
||||
| The exception handler extends a base `HttpExceptionHandler` which is not
|
||||
| mandatory, however it can do lot of heavy lifting to handle the errors
|
||||
| properly.
|
||||
|
|
||||
*/
|
||||
|
||||
import Logger from '@ioc:Adonis/Core/Logger'
|
||||
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'
|
||||
|
||||
export default class ExceptionHandler extends HttpExceptionHandler {
|
||||
constructor () {
|
||||
super(Logger)
|
||||
}
|
||||
}
|
||||
71
app/Middleware/Auth.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
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: any[]) {
|
||||
/**
|
||||
* 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: string[]) {
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
}
|
||||
21
app/Middleware/SilentAuth.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
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.
|
||||
*/
|
||||
await auth.check()
|
||||
await next()
|
||||
}
|
||||
}
|
||||
19
app/Models/File.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DateTime } from 'luxon'
|
||||
import {BaseModel, column} from '@ioc:Adonis/Lucid/Orm'
|
||||
|
||||
export default class File extends BaseModel {
|
||||
@column({ isPrimary: true })
|
||||
public id: number
|
||||
|
||||
@column()
|
||||
public label: string
|
||||
|
||||
@column()
|
||||
public fileName: string
|
||||
|
||||
@column.dateTime({ autoCreate: true })
|
||||
public createdAt: DateTime
|
||||
|
||||
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
||||
public updatedAt: DateTime
|
||||
}
|
||||
19
app/Models/Post.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DateTime } from 'luxon'
|
||||
import {BaseModel, column} from '@ioc:Adonis/Lucid/Orm'
|
||||
|
||||
export default class Post extends BaseModel {
|
||||
@column({ isPrimary: true })
|
||||
public id: number
|
||||
|
||||
@column()
|
||||
public slug: string
|
||||
|
||||
@column()
|
||||
public likes: number
|
||||
|
||||
@column.dateTime({ autoCreate: true })
|
||||
public createdAt: DateTime
|
||||
|
||||
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
||||
public updatedAt: DateTime
|
||||
}
|
||||
19
app/Models/Subscriber.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DateTime } from 'luxon'
|
||||
import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm'
|
||||
|
||||
export default class Subscriber extends BaseModel {
|
||||
@column({ isPrimary: true })
|
||||
public id: number
|
||||
|
||||
@column()
|
||||
public name: string
|
||||
|
||||
@column()
|
||||
public email: string
|
||||
|
||||
@column.dateTime({ autoCreate: true })
|
||||
public createdAt: DateTime
|
||||
|
||||
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
||||
public updatedAt: DateTime
|
||||
}
|
||||
40
app/Models/User.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
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()
|
||||
public password: string
|
||||
|
||||
@column()
|
||||
public confirmationToken: string
|
||||
|
||||
@column()
|
||||
public isConfirmed: boolean
|
||||
|
||||
@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)
|
||||
}
|
||||
}
|
||||
}
|
||||
26
app/Validators/AuthValidator.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {rules, schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class AuthValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
email: schema.string({ trim: true }, [
|
||||
rules.email(),
|
||||
rules.required()
|
||||
]),
|
||||
password: schema.string({ trim: true }, [
|
||||
rules.required()
|
||||
]),
|
||||
remember_me: schema.boolean()
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
'email.email': 'L\'adresse mail n\'est pas valide !',
|
||||
'email.required': 'Veuillez renseigner une adresse mail !',
|
||||
'password.required': 'Veuillez renseigner un mot de passe !',
|
||||
}
|
||||
}
|
||||
19
app/Validators/locations/StoreValidator.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class StoreValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
place: schema.string(),
|
||||
since: schema.date(),
|
||||
left: schema.string(),
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
required: 'Le champ {{field}} doit être valide !',
|
||||
}
|
||||
}
|
||||
19
app/Validators/locations/UpdateValidator.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class UpdateValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
place: schema.string.optional(),
|
||||
since: schema.date.optional(),
|
||||
left: schema.string.optional(),
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
required: 'Le champ {{field}} doit être valide !'
|
||||
}
|
||||
}
|
||||
25
app/Validators/posts/StoreValidator.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {rules, schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class StoreValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
title: schema.string(),
|
||||
content: schema.string(),
|
||||
description: schema.string(),
|
||||
readingTime: schema.number(),
|
||||
coverId: schema.number([rules.exists({ table: 'files', column: 'id' })]),
|
||||
tags: schema.array().members(
|
||||
schema.number()
|
||||
),
|
||||
lightBackGround: schema.boolean()
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
required: 'Le champ {{field}} doit être valide !',
|
||||
}
|
||||
}
|
||||
25
app/Validators/posts/UpdateValidator.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {rules, schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class UpdateValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
title: schema.string.optional(),
|
||||
content: schema.string.optional(),
|
||||
description: schema.string.optional(),
|
||||
readingTime: schema.number.optional(),
|
||||
coverId: schema.number.optional([rules.exists({ table: 'files', column: 'id' })]),
|
||||
tags: schema.array.optional().members(
|
||||
schema.number()
|
||||
),
|
||||
lightBackGround: schema.boolean.optional()
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
required: 'Le champ {{field}} doit être valide !'
|
||||
}
|
||||
}
|
||||
21
app/Validators/subscriber/StoreValidator.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {rules, schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class StoreValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
email: schema.string({ trim: true }, [
|
||||
rules.email(),
|
||||
rules.unique({table: 'subscribers', column: 'email'})
|
||||
]),
|
||||
name: schema.string()
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
required: 'Le champ {{field}} doit être valide !',
|
||||
}
|
||||
}
|
||||
21
app/Validators/subscriber/UpdateValidator.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {rules, schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class UpdateValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
email: schema.string({ trim: true }, [
|
||||
rules.email(),
|
||||
rules.unique({table: 'subscribers', column: 'email'})
|
||||
]),
|
||||
name: schema.string.optional()
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
required: 'Le champ {{field}} doit être valide !'
|
||||
}
|
||||
}
|
||||
22
app/Validators/users/StoreValidator.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {rules, schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class StoreValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
email: schema.string({ trim: true, escape: true }, [
|
||||
rules.email(),
|
||||
rules.required(),
|
||||
rules.unique({table: 'users', column: 'email'})
|
||||
])
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
required: 'Le champ {{field}} doit être valide !',
|
||||
'email.email': 'L\'adresse mail doit être valide !',
|
||||
}
|
||||
}
|
||||
23
app/Validators/users/UpdateValidator.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import {rules, schema} from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class UpdateValidator {
|
||||
constructor (private ctx: HttpContextContract) {
|
||||
}
|
||||
|
||||
public schema = schema.create({
|
||||
email: schema.string.optional({ trim: true, escape: true }, [rules.email()]),
|
||||
password: schema.string.optional({ trim: true, escape: true }, [rules.confirmed()]),
|
||||
is_confirmed: schema.boolean.optional(),
|
||||
confirmation_token: schema.string.optional({ trim: true, escape: true }),
|
||||
remember_me: schema.string.optional({ trim: true, escape: true }),
|
||||
})
|
||||
|
||||
public cacheKey = this.ctx.routeKey
|
||||
|
||||
public messages = {
|
||||
required: 'Le champ {{field}} doit être valide !',
|
||||
'email.email': 'L\'adresse mail doit être valide !',
|
||||
'password.confirmation': 'Les mots de passe ne correspondent pas !'
|
||||
}
|
||||
}
|
||||
19
commands/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { listDirectoryFiles } from '@adonisjs/core/build/standalone'
|
||||
import Application from '@ioc:Adonis/Core/Application'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Exporting an array of commands
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Instead of manually exporting each file from this directory, we use the
|
||||
| helper `listDirectoryFiles` to recursively collect and export an array
|
||||
| of filenames.
|
||||
|
|
||||
| Couple of things to note:
|
||||
|
|
||||
| 1. The file path must be relative from the project root and not this directory.
|
||||
| 2. We must ignore this file to avoid getting into an infinite loop
|
||||
|
|
||||
*/
|
||||
export default listDirectoryFiles(__dirname, Application.appRoot, ['./commands/index'])
|
||||
235
config/app.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* Config source: https://git.io/JfefZ
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
import proxyAddr from 'proxy-addr'
|
||||
import Env from '@ioc:Adonis/Core/Env'
|
||||
import { ServerConfig } from '@ioc:Adonis/Core/Server'
|
||||
import { LoggerConfig } from '@ioc:Adonis/Core/Logger'
|
||||
import { ProfilerConfig } from '@ioc:Adonis/Core/Profiler'
|
||||
import { ValidatorConfig } from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application secret key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The secret to encrypt and sign different values in your application.
|
||||
| Make sure to keep the `APP_KEY` as an environment variable and secure.
|
||||
|
|
||||
| Note: Changing the application key for an existing app will make all
|
||||
| the cookies invalid and also the existing encrypted data will not
|
||||
| be decrypted.
|
||||
|
|
||||
*/
|
||||
export const appKey: string = Env.get('APP_KEY')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Http server configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The configuration for the HTTP(s) server. Make sure to go through all
|
||||
| the config properties to make keep server secure.
|
||||
|
|
||||
*/
|
||||
export const http: ServerConfig = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Allow method spoofing
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Method spoofing enables defining custom HTTP methods using a query string
|
||||
| `_method`. This is usually required when you are making traditional
|
||||
| form requests and wants to use HTTP verbs like `PUT`, `DELETE` and
|
||||
| so on.
|
||||
|
|
||||
*/
|
||||
allowMethodSpoofing: false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Subdomain offset
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
subdomainOffset: 2,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Request Ids
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to `true` will generate a unique request id for each
|
||||
| HTTP request and set it as `x-request-id` header.
|
||||
|
|
||||
*/
|
||||
generateRequestId: false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Trusting proxy servers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define the proxy servers that AdonisJs must trust for reading `X-Forwarded`
|
||||
| headers.
|
||||
|
|
||||
*/
|
||||
trustProxy: proxyAddr.compile('loopback'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Generating Etag
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Whether or not to generate an etag for every response.
|
||||
|
|
||||
*/
|
||||
etag: false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| JSONP Callback
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
jsonpCallbackName: 'callback',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cookie settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
cookie: {
|
||||
domain: '',
|
||||
path: '/',
|
||||
maxAge: '2h',
|
||||
httpOnly: true,
|
||||
secure: false,
|
||||
sameSite: false,
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Force content negotiation to JSON
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The internals of the framework relies on the content negotiation to
|
||||
| detect the best possible response type for a given HTTP request.
|
||||
|
|
||||
| However, it is a very common these days that API servers always wants to
|
||||
| make response in JSON regardless of the existence of the `Accept` header.
|
||||
|
|
||||
| By setting `forceContentNegotiationToJSON = true`, you negotiate with the
|
||||
| server in advance to always return JSON without relying on the client
|
||||
| to set the header explicitly.
|
||||
|
|
||||
*/
|
||||
forceContentNegotiationToJSON: true,
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logger
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
export const logger: LoggerConfig = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The name of the application you want to add to the log. It is recommended
|
||||
| to always have app name in every log line.
|
||||
|
|
||||
| The `APP_NAME` environment variable is automatically set by AdonisJS by
|
||||
| reading the `name` property from the `package.json` file.
|
||||
|
|
||||
*/
|
||||
name: Env.get('APP_NAME'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Toggle logger
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enable or disable logger application wide
|
||||
|
|
||||
*/
|
||||
enabled: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logging level
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The level from which you want the logger to flush logs. It is recommended
|
||||
| to make use of the environment variable, so that you can define log levels
|
||||
| at deployment level and not code level.
|
||||
|
|
||||
*/
|
||||
level: Env.get('LOG_LEVEL', 'info'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pretty print
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| It is highly advised NOT to use `prettyPrint` in production, since it
|
||||
| can have huge impact on performance.
|
||||
|
|
||||
*/
|
||||
prettyPrint: Env.get('NODE_ENV') === 'development',
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Profiler
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
export const profiler: ProfilerConfig = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Toggle profiler
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enable or disable profiler
|
||||
|
|
||||
*/
|
||||
enabled: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Blacklist actions/row labels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define an array of actions or row labels that you want to disable from
|
||||
| getting profiled.
|
||||
|
|
||||
*/
|
||||
blacklist: [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Whitelist actions/row labels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define an array of actions or row labels that you want to whitelist for
|
||||
| the profiler. When whitelist is defined, then `blacklist` is ignored.
|
||||
|
|
||||
*/
|
||||
whitelist: [],
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validator
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Configure the global configuration for the validator. Here's the reference
|
||||
| to the default config https://git.io/JT0WE
|
||||
|
|
||||
*/
|
||||
export const validator: ValidatorConfig = {
|
||||
}
|
||||
166
config/auth.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Config source: https://git.io/JvyKy
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
import { AuthConfig } from '@ioc:Adonis/Addons/Auth'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Mapping
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| List of available authentication mapping. You must first define them
|
||||
| inside the `contracts/auth.ts` file before mentioning them here.
|
||||
|
|
||||
*/
|
||||
const authConfig: AuthConfig = {
|
||||
guard: 'web',
|
||||
list: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Guard
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Web guard uses classic old school sessions for authenticating users.
|
||||
| If you are building a standard web application, it is recommended to
|
||||
| use web guard with session driver
|
||||
|
|
||||
*/
|
||||
web: {
|
||||
driver: 'session',
|
||||
|
||||
provider: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Name of the driver
|
||||
|
|
||||
*/
|
||||
driver: 'lucid',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Identifier key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The identifier key is the unique key on the model. In most cases specifying
|
||||
| the primary key is the right choice.
|
||||
|
|
||||
*/
|
||||
identifierKey: 'id',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Uids
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Uids are used to search a user against one of the mentioned columns. During
|
||||
| login, the auth module will search the user mentioned value against one
|
||||
| of the mentioned columns to find their user record.
|
||||
|
|
||||
*/
|
||||
uids: ['email'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Model
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The model to use for fetching or finding users. The model is imported
|
||||
| lazily since the config files are read way earlier in the lifecycle
|
||||
| of booting the app and the models may not be in a usable state at
|
||||
| that time.
|
||||
|
|
||||
*/
|
||||
model: () => import('App/Models/User'),
|
||||
},
|
||||
},
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| OAT Guard
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| OAT (Opaque access tokens) guard uses database backed tokens to authenticate
|
||||
| HTTP request. This guard DOES NOT rely on sessions or cookies and uses
|
||||
| Authorization header value for authentication.
|
||||
|
|
||||
| Use this guard to authenticate mobile apps or web clients that cannot rely
|
||||
| on cookies/sessions.
|
||||
|
|
||||
*/
|
||||
api: {
|
||||
driver: 'oat',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Tokens provider
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Uses SQL database config for managing tokens. The foreignKey column is used
|
||||
| to make the relationship between the user and the token. You are free to
|
||||
| use any column name here.
|
||||
|
|
||||
*/
|
||||
tokenProvider: {
|
||||
driver: 'database',
|
||||
table: 'api_tokens',
|
||||
foreignKey: 'user_id',
|
||||
},
|
||||
|
||||
provider: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Name of the driver
|
||||
|
|
||||
*/
|
||||
driver: 'lucid',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Identifier key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The identifier key is the unique key on the model. In most cases specifying
|
||||
| the primary key is the right choice.
|
||||
|
|
||||
*/
|
||||
identifierKey: 'id',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Uids
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Uids are used to search a user against one of the mentioned columns. During
|
||||
| login, the auth module will search the user mentioned value against one
|
||||
| of the mentioned columns to find their user record.
|
||||
|
|
||||
*/
|
||||
uids: ['email'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Model
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The model to use for fetching or finding users. The model is imported
|
||||
| lazily since the config files are read way earlier in the lifecycle
|
||||
| of booting the app and the models may not be in a usable state at
|
||||
| that time.
|
||||
|
|
||||
*/
|
||||
model: () => import('App/Models/User'),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default authConfig
|
||||
186
config/bodyparser.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Config source: https://git.io/Jfefn
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
import { BodyParserConfig } from '@ioc:Adonis/Core/BodyParser'
|
||||
|
||||
const bodyParserConfig: BodyParserConfig = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| White listed methods
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| HTTP methods for which body parsing must be performed. It is a good practice
|
||||
| to avoid body parsing for `GET` requests.
|
||||
|
|
||||
*/
|
||||
whitelistedMethods: ['POST', 'PUT', 'PATCH', 'DELETE', 'GET'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| JSON parser settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The settings for the JSON parser. The types defines the request content
|
||||
| types which gets processed by the JSON parser.
|
||||
|
|
||||
*/
|
||||
json: {
|
||||
encoding: 'utf-8',
|
||||
limit: '1mb',
|
||||
strict: true,
|
||||
types: [
|
||||
'application/json',
|
||||
'application/json-patch+json',
|
||||
'application/vnd.api+json',
|
||||
'application/csp-report',
|
||||
],
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Form parser settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The settings for the `application/x-www-form-urlencoded` parser. The types
|
||||
| defines the request content types which gets processed by the form parser.
|
||||
|
|
||||
*/
|
||||
form: {
|
||||
encoding: 'utf-8',
|
||||
limit: '1mb',
|
||||
queryString: {},
|
||||
types: [
|
||||
'application/x-www-form-urlencoded',
|
||||
],
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Raw body parser settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Raw body just reads the request body stream as a plain text, which you
|
||||
| can process by hand. This must be used when request body type is not
|
||||
| supported by the body parser.
|
||||
|
|
||||
*/
|
||||
raw: {
|
||||
encoding: 'utf-8',
|
||||
limit: '1mb',
|
||||
queryString: {},
|
||||
types: [
|
||||
'text/*',
|
||||
],
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Multipart parser settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The settings for the `multipart/form-data` parser. The types defines the
|
||||
| request content types which gets processed by the form parser.
|
||||
|
|
||||
*/
|
||||
multipart: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Auto process
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The auto process option will process uploaded files and writes them to
|
||||
| the `tmp` folder. You can turn it off and then manually use the stream
|
||||
| to pipe stream to a different destination.
|
||||
|
|
||||
| It is recommended to keep `autoProcess=true`. Unless you are processing bigger
|
||||
| file sizes.
|
||||
|
|
||||
*/
|
||||
autoProcess: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Files to be processed manually
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You can turn off `autoProcess` for certain routes by defining
|
||||
| routes inside the following array.
|
||||
|
|
||||
| NOTE: Make sure the route pattern starts with a leading slash.
|
||||
|
|
||||
| Correct
|
||||
| ```js
|
||||
| /projects/:id/file
|
||||
| ```
|
||||
|
|
||||
| Incorrect
|
||||
| ```js
|
||||
| projects/:id/file
|
||||
| ```
|
||||
*/
|
||||
processManually: [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Temporary file name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When auto processing is on. We will use this method to compute the temporary
|
||||
| file name. AdonisJs will compute a unique `tmpPath` for you automatically,
|
||||
| However, you can also define your own custom method.
|
||||
|
|
||||
*/
|
||||
// tmpFileName () {
|
||||
// },
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encoding
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Request body encoding
|
||||
|
|
||||
*/
|
||||
encoding: 'utf-8',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Max Fields
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The maximum number of fields allowed in the request body. The field includes
|
||||
| text inputs and files both.
|
||||
|
|
||||
*/
|
||||
maxFields: 1000,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Request body limit
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The total limit to the multipart body. This includes all request files
|
||||
| and fields data.
|
||||
|
|
||||
*/
|
||||
limit: '20mb',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Types
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The types that will be considered and parsed as multipart body.
|
||||
|
|
||||
*/
|
||||
types: [
|
||||
'multipart/form-data',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export default bodyParserConfig
|
||||
142
config/cors.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* Config source: https://git.io/JfefC
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
import { CorsConfig } from '@ioc:Adonis/Core/Cors'
|
||||
|
||||
const corsConfig: CorsConfig = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enabled
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| A boolean to enable or disable CORS integration from your AdonisJs
|
||||
| application.
|
||||
|
|
||||
| Setting the value to `true` will enable the CORS for all HTTP request. However,
|
||||
| you can define a function to enable/disable it on per request basis as well.
|
||||
|
|
||||
*/
|
||||
enabled: true,
|
||||
|
||||
// You can also use a function that return true or false.
|
||||
// enabled: (request) => request.url().startsWith('/api')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Origin
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set a list of origins to be allowed for `Access-Control-Allow-Origin`.
|
||||
| The value can be one of the following:
|
||||
|
|
||||
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
|
||||
|
|
||||
| Boolean (true) - Allow current request origin.
|
||||
| Boolean (false) - Disallow all.
|
||||
| String - Comma separated list of allowed origins.
|
||||
| Array - An array of allowed origins.
|
||||
| String (*) - A wildcard (*) to allow all request origins.
|
||||
| Function - Receives the current origin string and should return
|
||||
| one of the above values.
|
||||
|
|
||||
*/
|
||||
origin: (origin) => {
|
||||
// Allow all connection on dev mode
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Production : allow only from your domain
|
||||
return origin.includes('arthurdanjou.fr');
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Methods
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| An array of allowed HTTP methods for CORS. The `Access-Control-Request-Method`
|
||||
| is checked against the following list.
|
||||
|
|
||||
| Following is the list of default methods. Feel free to add more.
|
||||
*/
|
||||
methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Headers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| List of headers to be allowed for `Access-Control-Allow-Headers` header.
|
||||
| The value can be one of the following:
|
||||
|
|
||||
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers
|
||||
|
|
||||
| Boolean(true) - Allow all headers mentioned in `Access-Control-Request-Headers`.
|
||||
| Boolean(false) - Disallow all headers.
|
||||
| String - Comma separated list of allowed headers.
|
||||
| Array - An array of allowed headers.
|
||||
| Function - Receives the current header and should return one of the above values.
|
||||
|
|
||||
*/
|
||||
headers: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Expose Headers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| A list of headers to be exposed by setting `Access-Control-Expose-Headers`.
|
||||
| header. By default following 6 simple response headers are exposed.
|
||||
|
|
||||
| Cache-Control
|
||||
| Content-Language
|
||||
| Content-Type
|
||||
| Expires
|
||||
| Last-Modified
|
||||
| Pragma
|
||||
|
|
||||
| In order to add more headers, simply define them inside the following array.
|
||||
|
|
||||
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
|
||||
|
|
||||
*/
|
||||
exposeHeaders: [
|
||||
'cache-control',
|
||||
'content-language',
|
||||
'content-type',
|
||||
'expires',
|
||||
'last-modified',
|
||||
'pragma',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Credentials
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Toggle `Access-Control-Allow-Credentials` header. If value is set to `true`,
|
||||
| then header will be set, otherwise not.
|
||||
|
|
||||
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
|
||||
|
|
||||
*/
|
||||
credentials: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| MaxAge
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define `Access-Control-Max-Age` header in seconds.
|
||||
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
|
||||
|
|
||||
*/
|
||||
maxAge: 90,
|
||||
}
|
||||
|
||||
export default corsConfig
|
||||
69
config/database.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Config source: https://git.io/JesV9
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
import Env from '@ioc:Adonis/Core/Env'
|
||||
import { OrmConfig } from '@ioc:Adonis/Lucid/Orm'
|
||||
import { DatabaseConfig } from '@ioc:Adonis/Lucid/Database'
|
||||
|
||||
const databaseConfig: DatabaseConfig & { orm: Partial<OrmConfig> } = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The primary connection for making database queries across the application
|
||||
| You can use any key from the `connections` object defined in this same
|
||||
| file.
|
||||
|
|
||||
*/
|
||||
connection: Env.get('DB_CONNECTION'),
|
||||
|
||||
connections: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| MySQL config
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Configuration for MySQL database. Make sure to install the driver
|
||||
| from npm when using this connection
|
||||
|
|
||||
| npm i mysql
|
||||
|
|
||||
*/
|
||||
mysql: {
|
||||
client: 'mysql',
|
||||
connection: {
|
||||
host: Env.get('MYSQL_HOST'),
|
||||
port: Env.get('MYSQL_PORT'),
|
||||
user: Env.get('MYSQL_USER'),
|
||||
password: Env.get('MYSQL_PASSWORD', ''),
|
||||
database: Env.get('MYSQL_DB_NAME'),
|
||||
charset: 'utf8mb4'
|
||||
},
|
||||
healthCheck: true,
|
||||
debug: false,
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| ORM Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Following are some of the configuration options to tweak the conventional
|
||||
| settings of the ORM. For example:
|
||||
|
|
||||
| - Define a custom function to compute the default table name for a given model.
|
||||
| - Or define a custom function to compute the primary key for a given model.
|
||||
|
|
||||
*/
|
||||
orm: {
|
||||
},
|
||||
}
|
||||
|
||||
export default databaseConfig
|
||||
75
config/hash.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Config source: https://git.io/JfefW
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
import Env from '@ioc:Adonis/Core/Env'
|
||||
import { HashConfig } from '@ioc:Adonis/Core/Hash'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Hash Config
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The `HashConfig` relies on the `HashList` interface which is
|
||||
| defined inside `contracts` directory.
|
||||
|
|
||||
*/
|
||||
const hashConfig: HashConfig = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default hasher
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default we make use of the bcrypt hasher to hash values. However, feel
|
||||
| free to change the default value
|
||||
|
|
||||
*/
|
||||
default: Env.get('HASH_DRIVER', 'argon'),
|
||||
|
||||
list: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Argon
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Argon mapping uses the `argon2` driver to hash values.
|
||||
|
|
||||
| Make sure you install the underlying dependency for this driver to work.
|
||||
| https://www.npmjs.com/package/phc-argon2.
|
||||
|
|
||||
| npm install phc-argon2
|
||||
|
|
||||
*/
|
||||
argon: {
|
||||
driver: 'argon2',
|
||||
variant: 'id',
|
||||
iterations: 3,
|
||||
memory: 4096,
|
||||
parallelism: 1,
|
||||
saltSize: 16,
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bcrypt
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Bcrypt mapping uses the `bcrypt` driver to hash values.
|
||||
|
|
||||
| Make sure you install the underlying dependency for this driver to work.
|
||||
| https://www.npmjs.com/package/phc-bcrypt.
|
||||
|
|
||||
| npm install phc-bcrypt
|
||||
|
|
||||
*/
|
||||
bcrypt: {
|
||||
driver: 'bcrypt',
|
||||
rounds: 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default hashConfig
|
||||
73
config/mail.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Config source: https://git.io/JvgAf
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this contract
|
||||
* file.
|
||||
*/
|
||||
|
||||
import Env from '@ioc:Adonis/Core/Env'
|
||||
import { MailConfig } from '@ioc:Adonis/Addons/Mail'
|
||||
|
||||
const mailConfig: MailConfig = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default mailer
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following mailer will be used to send emails, when you don't specify
|
||||
| a mailer
|
||||
|
|
||||
*/
|
||||
mailer: 'smtp',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mailers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You can define or more mailers to send emails from your application. A
|
||||
| single `driver` can be used to define multiple mailers with different
|
||||
| config.
|
||||
|
|
||||
| For example: Postmark driver can be used to have different mailers for
|
||||
| sending transactional and promotional emails
|
||||
|
|
||||
*/
|
||||
mailers: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Smtp
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Uses SMTP protocol for sending email
|
||||
|
|
||||
*/
|
||||
smtp: {
|
||||
driver: 'smtp',
|
||||
host: Env.get('SMTP_HOST'),
|
||||
port: Env.get('SMTP_PORT'),
|
||||
auth: {
|
||||
user: Env.get('SMTP_USERNAME'),
|
||||
pass: Env.get('SMTP_PASSWORD'),
|
||||
type: 'login',
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mailgun
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Uses Mailgun service for sending emails.
|
||||
|
|
||||
*/
|
||||
mailgun: {
|
||||
driver: 'mailgun',
|
||||
baseUrl: 'https://api.mailgun.net/v3',
|
||||
key: Env.get('MAILGUN_API_KEY'),
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
export default mailConfig
|
||||
48
config/redis.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Config source: https://git.io/JemcF
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
import Env from '@ioc:Adonis/Core/Env'
|
||||
import { RedisConfig } from '@ioc:Adonis/Addons/Redis'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Following is the configuration used by the Redis provider to connect to
|
||||
| the redis server and execute redis commands.
|
||||
|
|
||||
| Do make sure to pre-define the connections type inside `contracts/redis.ts`
|
||||
| file for AdonisJs to recognize connections.
|
||||
|
|
||||
| Make sure to check `contracts/redis.ts` file for defining extra connections
|
||||
*/
|
||||
const redisConfig: RedisConfig = {
|
||||
connection: Env.get('REDIS_CONNECTION'),
|
||||
|
||||
connections: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| The default connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The main connection you want to use to execute redis commands. The same
|
||||
| connection will be used by the session provider, if you rely on the
|
||||
| redis driver.
|
||||
|
|
||||
*/
|
||||
local: {
|
||||
host: Env.get('REDIS_HOST'),
|
||||
port: Env.get('REDIS_PORT'),
|
||||
password: Env.get('REDIS_PASSWORD', ''),
|
||||
db: Env.get('REDIS_DB', 0),
|
||||
keyPrefix: '',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default redisConfig
|
||||
106
config/session.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Config source: https://git.io/JeYHp
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
import Env from '@ioc:Adonis/Core/Env'
|
||||
import { SessionConfig } from '@ioc:Adonis/Addons/Session'
|
||||
|
||||
const sessionConfig: SessionConfig = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session driver to use. You can choose between one of the following
|
||||
| drivers.
|
||||
|
|
||||
| - cookie (Uses signed cookies to store session values)
|
||||
| - file (Uses filesystem to store session values)
|
||||
| - redis (Uses redis. Make sure to install "@adonisjs/redis" as well)
|
||||
|
|
||||
| Note: Switching drivers will make existing sessions invalid.
|
||||
|
|
||||
*/
|
||||
driver: Env.get('SESSION_DRIVER'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cookie name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The name of the cookie that will hold the session id.
|
||||
|
|
||||
*/
|
||||
cookieName: 'adonis-session',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Clear session when browser closes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Whether or not you want to destroy the session when browser closes. Setting
|
||||
| this value to `true` will ignore the `age`.
|
||||
|
|
||||
*/
|
||||
clearWithBrowser: false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session age
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The duration for which session stays active after no activity. A new HTTP
|
||||
| request to the server is considered as activity.
|
||||
|
|
||||
| The value can be a number in milliseconds or a string that must be valid
|
||||
| as per https://npmjs.org/package/ms package.
|
||||
|
|
||||
| Example: `2 days`, `2.5 hrs`, `1y`, `5s` and so on.
|
||||
|
|
||||
*/
|
||||
age: '2h',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cookie values
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The cookie settings are used to setup the session id cookie and also the
|
||||
| driver will use the same values.
|
||||
|
|
||||
*/
|
||||
cookie: {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: false,
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Configuration for the file driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The file driver needs absolute path to the directory in which sessions
|
||||
| must be stored.
|
||||
|
|
||||
*/
|
||||
file: {
|
||||
location: '',
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The redis connection you want session driver to use. The same connection
|
||||
| must be defined inside `config/redis.ts` file as well.
|
||||
|
|
||||
*/
|
||||
redisConnection: 'local',
|
||||
}
|
||||
|
||||
export default sessionConfig
|
||||
86
contracts/auth.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Contract source: https://git.io/JvyKD
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this
|
||||
* file.
|
||||
*/
|
||||
|
||||
import User from 'App/Models/User'
|
||||
|
||||
declare module '@ioc:Adonis/Addons/Auth' {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The providers are used to fetch users. The Auth module comes pre-bundled
|
||||
| with two providers that are `Lucid` and `Database`. Both uses database
|
||||
| to fetch user details.
|
||||
|
|
||||
| You can also create and register your own custom providers.
|
||||
|
|
||||
*/
|
||||
interface ProvidersList {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| User Provider
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following provider uses Lucid models as a driver for fetching user
|
||||
| details from the database for authentication.
|
||||
|
|
||||
| You can create multiple providers using the same underlying driver with
|
||||
| different Lucid models.
|
||||
|
|
||||
*/
|
||||
user: {
|
||||
implementation: LucidProviderContract<typeof User>,
|
||||
config: LucidProviderConfig<typeof User>,
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The guards are used for authenticating users using different drivers.
|
||||
| The auth module comes with 4 different guards.
|
||||
|
|
||||
| - SessionGuardContract
|
||||
| - BasicAuthGuardContract
|
||||
| - JwtGuardContract
|
||||
| - OATGuardContract ( Opaque access token )
|
||||
|
|
||||
| Every guard needs a provider for looking up users from the database.
|
||||
|
|
||||
*/
|
||||
interface GuardsList {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Guard
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The web guard uses sessions for maintaining user login state. It uses
|
||||
| the `user` provider for fetching user details.
|
||||
|
|
||||
*/
|
||||
web: {
|
||||
implementation: SessionGuardContract<'user', 'web'>,
|
||||
config: SessionGuardConfig<'user'>,
|
||||
},
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| OAT Guard
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| OAT, stands for (Opaque access tokens) guard uses database backed tokens
|
||||
| to authenticate requests.
|
||||
|
|
||||
*/
|
||||
api: {
|
||||
implementation: OATGuardContract<'user', 'api'>,
|
||||
config: OATGuardConfig<'user'>,
|
||||
},
|
||||
}
|
||||
}
|
||||
24
contracts/env.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Contract source: https://git.io/JTm6U
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this contract
|
||||
* file.
|
||||
*/
|
||||
|
||||
declare module '@ioc:Adonis/Core/Env' {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Getting types for validated environment variables
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The `default` export from the "../env.ts" file exports types for the
|
||||
| validated environment variables. Here we merge them with the `EnvTypes`
|
||||
| interface so that you can enjoy intellisense when using the "Env"
|
||||
| module.
|
||||
|
|
||||
*/
|
||||
|
||||
type CustomTypes = typeof import("../env").default;
|
||||
interface EnvTypes extends CustomTypes {
|
||||
}
|
||||
}
|
||||
30
contracts/events.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Contract source: https://git.io/JfefG
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this contract
|
||||
* file.
|
||||
*/
|
||||
|
||||
declare module '@ioc:Adonis/Core/Event' {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Define typed events
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You can define types for events inside the following interface and
|
||||
| AdonisJS will make sure that all listeners and emit calls adheres
|
||||
| to the defined types.
|
||||
|
|
||||
| For example:
|
||||
|
|
||||
| interface EventsList {
|
||||
| 'new:user': UserModel
|
||||
| }
|
||||
|
|
||||
| Now calling `Event.emit('new:user')` will statically ensure that passed value is
|
||||
| an instance of the the UserModel only.
|
||||
|
|
||||
*/
|
||||
interface EventsList {
|
||||
}
|
||||
}
|
||||
21
contracts/hash.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Contract source: https://git.io/Jfefs
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this contract
|
||||
* file.
|
||||
*/
|
||||
|
||||
declare module '@ioc:Adonis/Core/Hash' {
|
||||
import { HashDrivers } from '@ioc:Adonis/Core/Hash'
|
||||
|
||||
interface HashersList {
|
||||
bcrypt: {
|
||||
config: BcryptConfig,
|
||||
implementation: BcryptContract,
|
||||
},
|
||||
argon: {
|
||||
config: ArgonConfig,
|
||||
implementation: ArgonContract,
|
||||
},
|
||||
}
|
||||
}
|
||||
15
contracts/mail.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Contract source: https://git.io/JvgAT
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this contract
|
||||
* file.
|
||||
*/
|
||||
|
||||
declare module '@ioc:Adonis/Addons/Mail' {
|
||||
import { MailDrivers } from '@ioc:Adonis/Addons/Mail'
|
||||
|
||||
interface MailersList {
|
||||
smtp: MailDrivers['smtp'],
|
||||
mailgun: MailDrivers['mailgun'],
|
||||
}
|
||||
}
|
||||
12
contracts/redis.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Contract source: https://git.io/JemcN
|
||||
*
|
||||
* Feel free to let us know via PR, if you find something broken in this config
|
||||
* file.
|
||||
*/
|
||||
|
||||
declare module '@ioc:Adonis/Addons/Redis' {
|
||||
interface RedisConnectionsList {
|
||||
local: RedisConnectionConfig,
|
||||
}
|
||||
}
|
||||
1
database/factories/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
// import Factory from '@ioc:Adonis/Lucid/Factory'
|
||||
18
database/migrations/1603020084373_subscribers.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
|
||||
|
||||
export default class Subscribers extends BaseSchema {
|
||||
protected tableName = 'subscribers'
|
||||
|
||||
public async up () {
|
||||
this.schema.createTable(this.tableName, (table) => {
|
||||
table.increments('id').primary()
|
||||
table.string('name')
|
||||
table.string('email').notNullable()
|
||||
table.timestamps(true)
|
||||
})
|
||||
}
|
||||
|
||||
public async down () {
|
||||
this.schema.dropTable(this.tableName)
|
||||
}
|
||||
}
|
||||
34
database/migrations/1605093034793_users.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
|
||||
|
||||
export default class UsersSchema extends BaseSchema {
|
||||
protected tableName = 'users'
|
||||
|
||||
public async up () {
|
||||
this.schema.createTable(this.tableName, (table) => {
|
||||
table.increments('id').primary()
|
||||
table.string('email', 255).notNullable()
|
||||
table.string('password', 180).defaultTo(this.randomPassword()).notNullable()
|
||||
table.boolean('is_confirmed').defaultTo(false).notNullable()
|
||||
table.string('remember_me_token').defaultTo(null).nullable()
|
||||
table.string('confirmation_token').defaultTo(null).nullable()
|
||||
table.timestamps(true)
|
||||
})
|
||||
}
|
||||
|
||||
private randomPassword () {
|
||||
let chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
let password = ''
|
||||
let passwordLength = 12
|
||||
|
||||
for (let i = 0; i < passwordLength; i++) {
|
||||
let rnum = Math.floor(Math.random() * chars.length);
|
||||
password += chars.substring(rnum,rnum+1);
|
||||
}
|
||||
|
||||
return password
|
||||
}
|
||||
|
||||
public async down () {
|
||||
this.schema.dropTable(this.tableName)
|
||||
}
|
||||
}
|
||||
25
database/migrations/1605093087010_api_tokens.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
|
||||
|
||||
export default class ApiTokens extends BaseSchema {
|
||||
protected tableName = 'api_tokens'
|
||||
|
||||
public async up () {
|
||||
this.schema.createTable(this.tableName, (table) => {
|
||||
table.increments('id').primary()
|
||||
table.integer('user_id').unsigned().references('id').inTable('users').onDelete('CASCADE')
|
||||
table.string('name').notNullable()
|
||||
table.string('type').notNullable()
|
||||
table.string('token', 64).notNullable()
|
||||
|
||||
/**
|
||||
* "useTz: true" utilizes timezone option in PostgreSQL and MSSQL
|
||||
*/
|
||||
table.timestamp('expires_at', { useTz: true }).nullable()
|
||||
table.timestamp('created_at', { useTz: true }).notNullable()
|
||||
})
|
||||
}
|
||||
|
||||
public async down () {
|
||||
this.schema.dropTable(this.tableName)
|
||||
}
|
||||
}
|
||||
18
database/migrations/1605956543449_files.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
|
||||
|
||||
export default class Pictures extends BaseSchema {
|
||||
protected tableName = 'files'
|
||||
|
||||
public async up () {
|
||||
this.schema.createTable(this.tableName, (table) => {
|
||||
table.increments('id').primary()
|
||||
table.string('label').notNullable()
|
||||
table.string('file_name').notNullable()
|
||||
table.timestamps(true)
|
||||
})
|
||||
}
|
||||
|
||||
public async down () {
|
||||
this.schema.dropTable(this.tableName)
|
||||
}
|
||||
}
|
||||
18
database/migrations/1605956711010_posts.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
|
||||
|
||||
export default class Posts extends BaseSchema {
|
||||
protected tableName = 'posts'
|
||||
|
||||
public async up () {
|
||||
this.schema.createTable(this.tableName, (table) => {
|
||||
table.increments('id').primary()
|
||||
table.string('slug').notNullable()
|
||||
table.integer('likes').notNullable()
|
||||
table.timestamps(true)
|
||||
})
|
||||
}
|
||||
|
||||
public async down () {
|
||||
this.schema.dropTable(this.tableName)
|
||||
}
|
||||
}
|
||||
21
docker-compose.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
version: "3"
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: password
|
||||
MYSQL_USER: root
|
||||
MYSQL_PASSWORD: password
|
||||
MYSQL_DATABASE: artapi
|
||||
adonisjs:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- .:/home/node/app
|
||||
- /home/node/app/node_modules
|
||||
ports:
|
||||
- 80:3333
|
||||
depends_on:
|
||||
- mariadb
|
||||
51
env.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validating Environment Variables
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| In this file we define the rules for validating environment variables.
|
||||
| By performing validation we ensure that your application is running in
|
||||
| a stable environment with correct configuration values.
|
||||
|
|
||||
| This file is read automatically by the framework during the boot lifecycle
|
||||
| and hence do not rename or move this file to a different location.
|
||||
|
|
||||
*/
|
||||
|
||||
import Env from '@ioc:Adonis/Core/Env'
|
||||
|
||||
export default Env.rules({
|
||||
//App
|
||||
HOST: Env.schema.string({ format: 'host' }),
|
||||
PORT: Env.schema.number(),
|
||||
APP_KEY: Env.schema.string(),
|
||||
APP_NAME: Env.schema.string(),
|
||||
NODE_ENV: Env.schema.enum(['development', 'production', 'testing'] as const),
|
||||
|
||||
//Redis
|
||||
REDIS_CONNECTION: Env.schema.enum(['local'] as const),
|
||||
REDIS_HOST: Env.schema.string({ format: 'host' }),
|
||||
REDIS_PORT: Env.schema.number(),
|
||||
REDIS_DB: Env.schema.number(),
|
||||
REDIS_PASSWORD: Env.schema.string.optional(),
|
||||
|
||||
//Mysql
|
||||
MYSQL_HOST: Env.schema.string({ format: 'host' }),
|
||||
MYSQL_PORT: Env.schema.number(),
|
||||
MYSQL_USER: Env.schema.string(),
|
||||
MYSQL_PASSWORD: Env.schema.string.optional(),
|
||||
MYSQL_DB_NAME: Env.schema.string(),
|
||||
|
||||
//Session
|
||||
SESSION_DRIVER: Env.schema.string(),
|
||||
|
||||
//SMTP
|
||||
SMTP_HOST: Env.schema.string({ format: 'host' }),
|
||||
SMTP_PORT: Env.schema.number(),
|
||||
SMTP_USERNAME: Env.schema.string(),
|
||||
SMTP_PASSWORD: Env.schema.string(),
|
||||
|
||||
//Mailgun
|
||||
MAILGUN_API_KEY: Env.schema.string(),
|
||||
|
||||
})
|
||||
36
package.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "artapi",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "node ace build --production",
|
||||
"start": "node server.js",
|
||||
"dev": "node ace serve --watch",
|
||||
"seed": "node ace db:seed",
|
||||
"mig": "node ace migration:run",
|
||||
"lr": "node ace list:routes"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@adonisjs/assembler": "^3.0.0",
|
||||
"adonis-preset-ts": "^1.1.0",
|
||||
"pino-pretty": "^4.3.0",
|
||||
"typescript": "^4.0.5",
|
||||
"youch": "^2.1.1",
|
||||
"youch-terminal": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@adonisjs/auth": "^5.0.2",
|
||||
"@adonisjs/core": "^5.0.4-preview-rc",
|
||||
"@adonisjs/lucid": "^9.0.3",
|
||||
"@adonisjs/mail": "^5.1.0",
|
||||
"@adonisjs/redis": "^5.0.8",
|
||||
"@adonisjs/repl": "^1.0.0",
|
||||
"@adonisjs/session": "^4.0.5",
|
||||
"luxon": "^1.25.0",
|
||||
"mysql": "^2.18.1",
|
||||
"phc-argon2": "^1.0.11",
|
||||
"proxy-addr": "^2.0.6",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
}
|
||||
24
providers/AppProvider.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ApplicationContract } from '@ioc:Adonis/Core/Application'
|
||||
|
||||
export default class AppProvider {
|
||||
public static needsApplication = true
|
||||
|
||||
constructor (protected app: ApplicationContract) {
|
||||
}
|
||||
|
||||
public register () {
|
||||
// Register your own bindings
|
||||
}
|
||||
|
||||
public async boot () {
|
||||
// IoC container is ready
|
||||
}
|
||||
|
||||
public async ready () {
|
||||
// App is ready
|
||||
}
|
||||
|
||||
public async shutdown () {
|
||||
// Cleanup, since app is going down
|
||||
}
|
||||
}
|
||||
18
server.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| AdonisJs Server
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The contents in this file is meant to bootstrap the AdonisJs application
|
||||
| and start the HTTP server to accept incoming connections. You must avoid
|
||||
| making this file dirty and instead make use of `lifecycle hooks` provided
|
||||
| by AdonisJs service providers for custom code.
|
||||
|
|
||||
*/
|
||||
|
||||
import 'reflect-metadata'
|
||||
import { Ignitor } from '@adonisjs/core/build/standalone'
|
||||
|
||||
new Ignitor(__dirname)
|
||||
.httpServer()
|
||||
.start()
|
||||
46
start/kernel.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is used to define middleware for HTTP requests. You can register
|
||||
| middleware as a `closure` or an IoC container binding. The bindings are
|
||||
| preferred, since they keep this file clean.
|
||||
|
|
||||
*/
|
||||
|
||||
import Server from '@ioc:Adonis/Core/Server'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| An array of global middleware, that will be executed in the order they
|
||||
| are defined for all HTTP requests.
|
||||
|
|
||||
*/
|
||||
Server.middleware.register([
|
||||
'Adonis/Core/BodyParserMiddleware',
|
||||
'App/Middleware/SilentAuth',
|
||||
])
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Named middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Named middleware are defined a key-value pair. The value is the namespace
|
||||
| or middleware function and key is the alias. Later you can use these
|
||||
| alias on individual routes. For example:
|
||||
|
|
||||
| { auth: 'App/Auth/Middleware' }
|
||||
|
|
||||
| and then use it as follows
|
||||
|
|
||||
| Route.get('dashboard', 'UserController.dashboard').middleware('auth')
|
||||
|
|
||||
*/
|
||||
Server.middleware.registerNamed({
|
||||
auth: 'App/Middleware/Auth',
|
||||
})
|
||||
32
start/routes.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import Route from '@ioc:Adonis/Core/Route'
|
||||
import Application from "@ioc:Adonis/Core/Application";
|
||||
|
||||
Route.resource('users', 'UsersController').only(['index', 'show'])
|
||||
Route.get('/posts/:slug', 'PostsController.getLikes')
|
||||
Route.get('/posts/is/:slug', 'PostsController.isLiked')
|
||||
Route.post('/posts/:slug/like', 'PostsController.like')
|
||||
Route.post('/posts/:slug/unlike', 'PostsController.unlike')
|
||||
Route.resource('subscribers', 'SubscribersController').only(['index', 'show'])
|
||||
Route.resource('files', 'FileController').only(['index'])
|
||||
|
||||
Route.get('/files/:filename', async ({ response, params }) => {
|
||||
response.download(Application.makePath('storage', params.filename))
|
||||
})
|
||||
|
||||
Route.group(() => {
|
||||
Route.resource('users', 'UsersController').only(['store', 'update', 'destroy'])
|
||||
Route.resource('posts', 'PostsController').only(['store', 'update', 'destroy'])
|
||||
Route.resource('subscribers', 'SubscribersController').only(['store', 'update', 'destroy'])
|
||||
Route.resource('files', 'FileController').only(['store', 'update', 'destroy'])
|
||||
|
||||
}).middleware('auth')
|
||||
|
||||
Route.group(() => {
|
||||
Route.get('/me', 'AuthController.user').middleware('auth')
|
||||
|
||||
Route.post('/web/login', 'AuthController.loginWeb')
|
||||
Route.post('/web/logout', 'AuthController.logoutWeb')
|
||||
|
||||
Route.post('/api/login', 'AuthController.loginApi')
|
||||
Route.post('/api/logout', 'AuthController.logoutApi')
|
||||
}).prefix('auth')
|
||||
BIN
storage/ElectronJs.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
storage/GoLang.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
storage/Java.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
storage/JavaScript.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
storage/Logo.jpg
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
storage/MariaDB.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
storage/NuxtJs.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
storage/TwitterBanner.png
Normal file
|
After Width: | Height: | Size: 396 KiB |
BIN
storage/TypeScript.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
storage/VueJs.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
storage/cercle-cv.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
BIN
storage/website.png
Normal file
|
After Width: | Height: | Size: 270 KiB |
38
tsconfig.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"extends": "./node_modules/adonis-preset-ts/tsconfig",
|
||||
"include": [
|
||||
"**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"build"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"outDir": "build",
|
||||
"rootDir": "./",
|
||||
"sourceMap": true,
|
||||
"paths": {
|
||||
"App/*": [
|
||||
"./app/*"
|
||||
],
|
||||
"Config/*": [
|
||||
"./config/*"
|
||||
],
|
||||
"Contracts/*": [
|
||||
"./contracts/*"
|
||||
],
|
||||
"Database/*": [
|
||||
"./database/*"
|
||||
]
|
||||
},
|
||||
"types": [
|
||||
"@adonisjs/core",
|
||||
"@adonisjs/repl",
|
||||
"@adonisjs/redis",
|
||||
"@adonisjs/session",
|
||||
"@adonisjs/mail",
|
||||
"@adonisjs/auth",
|
||||
"@adonisjs/lucid"
|
||||
]
|
||||
}
|
||||
}
|
||||