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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||