├── .gitignore ├── README.md ├── assets └── banner.png ├── client ├── .editorconfig ├── .gitignore ├── .prettierignore ├── .prettierrc ├── README.md ├── config │ ├── Auth.ts │ ├── Axios.ts │ ├── BootstrapVue.ts │ ├── GoogleAnalytics.ts │ ├── Meta.ts │ ├── Robots.ts │ ├── Sitemap.ts │ ├── Toasts.ts │ ├── Translations.ts │ └── index.ts ├── contracts │ └── toast.ts ├── jsconfig.json ├── nuxt.config.ts ├── package.json ├── src │ ├── components │ │ └── LangSwitcher.vue │ ├── locales │ │ ├── en-US.ts │ │ └── fr-FR.ts │ ├── public │ │ ├── favicon.jpg │ │ └── images │ │ │ └── image.jpg │ ├── store │ │ └── index.ts │ └── template │ │ ├── layouts │ │ └── master.vue │ │ └── pages │ │ └── index.vue ├── tsconfig.json ├── vue-shim.d.ts └── yarn.lock ├── docker-compose.example.yaml ├── package.json └── server ├── .adonisrc.json ├── .editorconfig ├── .env ├── .env.example ├── .gitignore ├── ace ├── app ├── Controllers │ └── Http │ │ ├── AuthController.ts │ │ ├── CookiesController.ts │ │ └── UserController.ts ├── Exceptions │ └── Handler.ts ├── Middleware │ ├── Auth.ts │ └── SilentAuth.ts ├── Models │ ├── Cookie.ts │ └── User.ts └── Validators │ └── users │ ├── StoreValidator.ts │ └── UpdateValidator.ts ├── commands └── index.ts ├── config ├── app.ts ├── auth.ts ├── bodyparser.ts ├── cors.ts ├── database.ts ├── hash.ts ├── session.ts └── static.ts ├── contracts ├── auth.ts ├── env.ts ├── events.ts └── hash.ts ├── database ├── migrations │ ├── 1587988332388_user.ts │ ├── 1592489784670_api_tokens.ts │ ├── 1594403111129_add_fields_users.ts │ ├── 1594407141527_add_avatar_users.ts │ └── 1594422933992_cookies.ts └── seeders │ └── User.ts ├── env.ts ├── package-lock.json ├── package.json ├── providers └── AppProvider.ts ├── server.ts ├── start ├── kernel.ts └── routes.ts ├── tsconfig.json ├── yarn-error.log └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # App AdonisJS & NuxtJS 2 | []() 3 | []() 4 | []() 5 | 6 | 7 | An open source app for your personal website ! 8 | 9 | To use it refer you to the [documentation](#Guide). 10 | 11 | ## Features 12 | 13 | * Authentication system 14 | * Navbar included 15 | * Sidebar included 16 | * Header with Carousel 17 | * Multi-language 18 | 19 | ## Technologies used 20 | - [Bootstrap Vue](https://bootstrap-vue.org/docs/) 21 | - [SASS](https://sass-lang.com/) 22 | - [AdonisJS](https://preview.adonisjs.com/) 23 | - [VueJS](https://vuejs.org/) 24 | - [NuxtJS](https://nuxtjs.org/) 25 | 26 |  27 | 28 | ## Summary 29 | * [Installation](#Installation) 30 | * [Guide](#Guide) 31 | * [Contributors](#Contributors) 32 | * [License](#License) 33 | 34 | ### Installation 35 | 36 | 1. Clone the repository from `https://github.com/Izoxy/adonis-nuxt-template/` 37 | 2. Open a terminal in the folder 38 | 3. Type `yarn build-template` 39 | 4. For run the template in dev mode, you need to type `yarn api` to start the API and `yarn front` to start the frontend in different terminals. 40 | 5. For generate your site (in VPS), simply type `yarn run-template` 41 | 42 | It's already finished, it's really quick to set up. 43 | 44 | ### Guide 45 | #### Master - Sommaire 46 | 47 | * [Controllers](#Controllers) 48 | * [Models](#Models) 49 | * [Validators](#Validators) 50 | * [Layouts](#Layouts) 51 | * [Configurations](#Configurations) 52 | * [Middleware](#Middleware) 53 | - Routes 54 | * [Configurations](#Configurations) 55 | * [Auth](#Auth) 56 | * [Lang](#Lang) 57 | - Use the translation 58 | - Add a language 59 | * [Components](#Components) 60 | 61 | ##### For Adonis 62 | 63 | The API is in `/api/app` and manage the connection with database to execute queries. 64 | 65 | ##### For Nuxt 66 | 67 | You can also see the master of Nuxt in `/frontend` and see the main config in `/frontend/nuxt.config.js`. 68 | 69 | 70 | ###### Controllers 71 | 72 | The controllers are the main functions which manage the users, cookies and the authentication system. 73 | They are available in `/api/app/Controllers/Http`. 74 | 75 | ###### Models 76 | 77 | The models are `BaseModel`, they serve to represent the tables from the database. 78 | They are available in `/api/app/Models` 79 | 80 | ###### Validators 81 | 82 | The validators serve to catch many errors that the user may cause (wrong email, etc...) 83 | They are available in `/api/app/Validators/users` 84 | 85 | ##### Layouts 86 | 87 | Here you can find the master from the application. 88 | 89 | In `/layouts/master/master.vue`, you have the main layout. 90 | 91 | You have also the index in `/frontend/pages/index.vue` 92 | 93 | #### Configurations 94 | 95 | ##### For Adonis 96 | In `/api/config` you can see all configs which used by Adonis. 97 | 98 | ##### For Nuxt 99 | In `/frontend/configurations` you can see all modules which manage many functions (Build, Axios, Meta, Plugins, etc...). 100 | 101 | There are all registered in the main nuxt config `/frontend/nuxt.config.js`. 102 | 103 | #### Middleware 104 | 105 | For a perfect routing, we use the middleware suggested by Adonis and those of Nuxt. 106 | 107 | In `/api/app/Middleware` and in `/frontend/middleware`. 108 | 109 | ##### Routes 110 | 111 | The routes are registered in `/api/start/routes.ts`. 112 | 113 | #### Auth 114 | The authentication system is complexe. 115 | We have many files who manage the system. 116 | 117 | We use Adonis for the back-end, the part who manage the database is in `/api/app`. 118 | 119 | Moreover, we have a specific usage from the Cookie to save the data from the users. You can find it in `/front/store` 120 | 121 | #### Lang 122 | 123 | Here, we have the multi-language system. How to use it ? 124 | 125 | You need to add the [lang switcher](#LangSwitcher) in your layout for example. 126 | 127 | ##### Use the translation 128 | 129 | For use the translation and others, refer you to the nuxt-i18n [documentation](https://nuxt-community.github.io/nuxt-i18n/). 130 | 131 | Example : 132 | ``` 133 | {{ $t('welcome') }} 134 | ``` 135 | 136 | ##### Add a language 137 | 138 | We need to add your lang in `/frontend/configurations/Translations.js` in the locales field like that : 139 | ``` 140 | { 141 | code: 'en', 142 | name: 'English', 143 | file: 'en-US.js' 144 | } 145 | ``` 146 | And you need to create your lang file in `/frontend/locales` like that : 147 | 148 | ```javascript 149 | export default { 150 | welcome: 'Bienvenue', 151 | } 152 | ``` 153 | 154 | #### Components 155 | Here you can find the different add-ons available in our template. 156 | 157 | - [Navbar](#Navbar) 158 | - [Header](#Header) 159 | - [Sidebar](#Sidebar) 160 | - [Lang Switcher](#LangSwitcher) 161 | 162 | If you encounter difficulties with one or more components, do not hesitate to contact [us](https://github.com/Izoxy). 163 | 164 | ##### Navbar 165 | A simple navbar. You can see the documentation from Navbar [here](https://bootstrap-vue.org/docs/components/navbar). 166 | 167 | Just import `` from `/components/navbar/Navbar.vue` 168 | And need to do add this in `` 169 | ```javascript 170 | import Navbar from "~/components/navbar/Navbar"; 171 | export default { 172 | name: "YourComponentName", 173 | components: { Navbar } 174 | } 175 | ``` 176 | If you want to have it on all pages, putting it on the main `layout` is advisable. 177 | 178 | ##### Header 179 | A simple header with a Carousel. You can see the documentation from Carousel [here](https://bootstrap-vue.org/docs/components/carousel). 180 | 181 | Just import `` from `/components/header/Header.vue` 182 | And need to do add this in `` 183 | ```javascript 184 | import Header from "~/components/header/Header"; 185 | export default { 186 | name: "YourComponentName", 187 | components: { Header } 188 | } 189 | ``` 190 | 191 | ##### Sidebar 192 | A simple sidebar. 193 | 194 | Just import `` from `/components/sidebar/Sidebar.vue` 195 | And need to do add this in `` 196 | ```javascript 197 | import Sidebar from "~/components/sidebar/Sidebar"; 198 | export default { 199 | name: "YourComponentName", 200 | components: { Sidebar } 201 | } 202 | ``` 203 | 204 | ##### LangSwitcher 205 | It's a simple button with a dropdown to change the language. 206 | You only have to import `` from `/components/langswitcher/LangSwitcher.vue` 207 | And need to do add this in `` 208 | ```javascript 209 | import LangSwitcher from "~/components/langswitcher/LangSwitcher"; 210 | export default { 211 | name: "YourComponentName", 212 | components: { LangSwitcher } 213 | } 214 | ``` 215 | 216 | ### Contributors 217 | * [Baptiste Parmantier](https://github.com/LeadcodeDev) 218 | * [Alexandre Gossard](https://github.com/HakkaOfDev) 219 | 220 | ### License 221 | 222 | Distributed under the MIT License. See [License](https://github.com/Izoxy/adonis-nuxt-template/blob/master/LICENSE) for more information. 223 | 224 | ### Made with ❤ by Izoxy 225 | -------------------------------------------------------------------------------- /assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Izoxy/adonis-nuxt-template/fbf32a4c98cf0f454bef39cb31f08aed6f8200e6/assets/banner.png -------------------------------------------------------------------------------- /client/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tab 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | /logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | build/ 71 | 72 | # Nuxt generate 73 | dist 74 | 75 | # vuepress build output 76 | .vuepress/dist 77 | 78 | # Serverless directories 79 | .serverless 80 | 81 | # IDE / Editor 82 | .idea 83 | 84 | # Service worker 85 | sw.* 86 | 87 | # macOS 88 | .DS_Store 89 | 90 | # Vim swap files 91 | *.swp 92 | -------------------------------------------------------------------------------- /client/.prettierignore: -------------------------------------------------------------------------------- 1 | nuxt.config.ts -------------------------------------------------------------------------------- /client/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "tabWidth": 4, 5 | "useTabs": true, 6 | "printWidth": 250 7 | } 8 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | # frontend 2 | 3 | ## Build Setup 4 | 5 | ```bash 6 | # install dependencies 7 | $ yarn install 8 | 9 | # serve with hot reload at localhost:3000 10 | $ yarn dev 11 | 12 | # build for production and launch server 13 | $ yarn build 14 | $ yarn start 15 | 16 | # generate static project 17 | $ yarn generate 18 | ``` 19 | 20 | For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org). 21 | -------------------------------------------------------------------------------- /client/config/Auth.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | strategies: { 3 | local: { 4 | endpoints: { 5 | login: { url: '/authentication/web/login', method: 'post' }, 6 | logout: { url: '/authentication/web/logout', method: 'post' }, 7 | user: { url: '/authentication/user/me', method: 'get', propertyName: 'user' }, 8 | }, 9 | tokenRequired: false, 10 | tokenType: false, 11 | }, 12 | }, 13 | redirect: { 14 | login: '/authentication/login', 15 | logout: '/', 16 | callback: '/account', 17 | home: '/', 18 | }, 19 | resetOnError: true, 20 | } 21 | -------------------------------------------------------------------------------- /client/config/Axios.ts: -------------------------------------------------------------------------------- 1 | /* 2 | ** Axios module configuration 3 | ** See https://axios.nuxtjs.org/options 4 | */ 5 | export default { 6 | baseURL: 'http://localhost:3333/api', 7 | credentials: true, 8 | } 9 | -------------------------------------------------------------------------------- /client/config/BootstrapVue.ts: -------------------------------------------------------------------------------- 1 | /* 2 | ** Bootstrat-vue module configuration 3 | ** See https://bootstrap-vue.org/docs 4 | */ 5 | export default { 6 | icons: true, 7 | } 8 | -------------------------------------------------------------------------------- /client/config/GoogleAnalytics.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | id: 'UA-XXX-X', 3 | } 4 | -------------------------------------------------------------------------------- /client/config/Meta.ts: -------------------------------------------------------------------------------- 1 | /* 2 | ** Headers module configuration 3 | ** See https://nuxtjs.org/api/configuration-head 4 | ** See https://vue-meta.nuxtjs.org/api/#metainfo-properties 5 | */ 6 | export default { 7 | htmlAttrs: { 8 | lang: 'fr-FR', 9 | }, 10 | title: 'Welcome to adonis nuxt template', 11 | meta: [ 12 | { charset: 'utf-8' }, 13 | { lang: 'fr-FR' }, 14 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 15 | { hid: 'description', name: 'description', content: 'The description of the Adonis-Nuxt template to quickly start a project.' }, 16 | 17 | { hid: 'og:type', name: 'og:type', content: 'website' }, 18 | { hid: 'og:url', name: 'og:url', content: 'https://my-domain.com' }, 19 | { hid: 'og:title', name: 'og:title', content: 'Welcome to adonis nuxt template' }, 20 | { hid: 'og:site_name', name: 'og:site_name', content: 'Adonis-nuxt-template' }, 21 | { hid: 'og:locale', name: 'og:locale', content: 'fr' }, 22 | { hid: 'og:image', name: 'og:image', content: '/images/image.jpg' }, 23 | 24 | { name: 'msapplication-TileColor', content: '#0DA5FF' }, 25 | { name: 'theme-color', content: '#0DA5FF' }, 26 | ], 27 | link: [{ rel: 'icon', type: 'image/jpg', href: '/favicon.jpg' }], 28 | } 29 | -------------------------------------------------------------------------------- /client/config/Robots.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | // Disallow: [ 3 | // '/login', 4 | // '/admin' 5 | // ], 6 | Sitemap: process.env.baseUrl + '/sitemap.xml', 7 | } 8 | -------------------------------------------------------------------------------- /client/config/Sitemap.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | path: '/sitemap.xml', 3 | hostname: process.env.baseUrl, 4 | cacheTime: 720000, 5 | gzip: true, 6 | generate: false, 7 | // exclude: ['/login', '/admin/**'], 8 | } 9 | -------------------------------------------------------------------------------- /client/config/Toasts.ts: -------------------------------------------------------------------------------- 1 | /* 2 | ** Toasts module configuration 3 | ** See https://github.com/nuxt-community/modules/tree/master/packages/toast 4 | */ 5 | import { props, configuration } from '~/contracts/toast' 6 | 7 | const configuration: configuration = { 8 | position: 'bottom-left', 9 | duration: 5000, 10 | keepOnHover: true, 11 | } 12 | 13 | export default { 14 | position: 'top-center', 15 | register: [ 16 | { 17 | name: 'error', 18 | message: ({ message }: props) => message, 19 | options: { 20 | position: configuration.position, 21 | duration: configuration.duration, 22 | keepOnHover: configuration.keepOnHover, 23 | icon: 'do_not_disturb', 24 | type: 'error', 25 | action: { 26 | text: 'fermer', 27 | onClick: (e: any, toastObject: any) => { 28 | toastObject.goAway(0) 29 | }, 30 | }, 31 | }, 32 | }, 33 | { 34 | name: 'success', 35 | message: ({ message }: props) => message, 36 | options: { 37 | position: configuration.position, 38 | duration: configuration.duration, 39 | keepOnHover: configuration.keepOnHover, 40 | icon: 'check', 41 | type: 'success', 42 | action: { 43 | text: 'fermer', 44 | onClick: (e: any, toastObject: any) => { 45 | toastObject.goAway(0) 46 | }, 47 | }, 48 | }, 49 | }, 50 | { 51 | name: 'info', 52 | message: ({ message }: props) => message, 53 | options: { 54 | position: configuration.position, 55 | duration: configuration.duration, 56 | keepOnHover: configuration.keepOnHover, 57 | icon: 'info', 58 | type: 'info', 59 | action: { 60 | text: 'fermer', 61 | onClick: (e: any, toastObject: any) => { 62 | toastObject.goAway(0) 63 | }, 64 | }, 65 | }, 66 | }, 67 | ], 68 | } 69 | -------------------------------------------------------------------------------- /client/config/Translations.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | locales: [ 3 | { 4 | code: 'en', 5 | name: 'English', 6 | file: 'en-US.ts', 7 | }, 8 | { 9 | code: 'fr', 10 | name: 'Français', 11 | file: 'fr-FR.ts', 12 | }, 13 | ], 14 | strategy: 'no_prefix', 15 | defaultLocale: 'en', 16 | langDir: 'locales/', 17 | lazy: true, 18 | seo: true, 19 | vueI18n: { 20 | fallbackLocale: 'en', 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /client/config/index.ts: -------------------------------------------------------------------------------- 1 | import Auth from './Auth' 2 | import Axios from './Axios' 3 | import BootstrapVue from './BootstrapVue' 4 | import Meta from './Meta' 5 | import Robots from './Robots' 6 | import Sitemap from './Sitemap' 7 | import Toasts from './Toasts' 8 | import Translations from './Translations' 9 | import GoogleAnalytics from './GoogleAnalytics' 10 | 11 | export { Auth, Axios, BootstrapVue, Meta, Robots, Sitemap, Toasts, Translations, GoogleAnalytics } 12 | -------------------------------------------------------------------------------- /client/contracts/toast.ts: -------------------------------------------------------------------------------- 1 | /** 2 | ** Configuration of interface and toast types 3 | */ 4 | export type props = { 5 | message: string 6 | } 7 | 8 | export type configuration = { 9 | position: string 10 | duration: number 11 | keepOnHover: boolean 12 | } 13 | -------------------------------------------------------------------------------- /client/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "~/*": ["./*"], 6 | "@/*": ["./*"], 7 | "~~/*": ["./*"], 8 | "@@/*": ["./*"] 9 | } 10 | }, 11 | "exclude": ["node_modules", ".nuxt", "dist"] 12 | } 13 | -------------------------------------------------------------------------------- /client/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import { Auth, Axios, BootstrapVue, Meta, Robots, Sitemap, Toasts, Translations, GoogleAnalytics } from './config' 2 | 3 | export default { 4 | /* 5 | ** Nuxt rendering mode 6 | ** See https://nuxtjs.org/api/configuration-mode 7 | */ 8 | mode: 'universal', 9 | 10 | /* 11 | ** Nuxt target 12 | ** See https://nuxtjs.org/api/configuration-target 13 | */ 14 | target: 'server', 15 | 16 | debug: true, 17 | 18 | /* 19 | ** Auto import components 20 | ** See https://nuxtjs.org/api/configuration-components 21 | */ 22 | components: true, 23 | 24 | /* 25 | ** Nuxt.js dev-modules 26 | */ 27 | buildModules: ['@nuxt/typescript-build', '@nuxtjs/composition-api', ['@nuxtjs/google-analytics', GoogleAnalytics]], 28 | 29 | /** 30 | ** Nuxt build folder 31 | */ 32 | buildDir: 'build', 33 | 34 | /** 35 | ** Nuxt src folder 36 | */ 37 | srcDir: 'src', 38 | 39 | dir: { 40 | assets: 'assets', 41 | layouts: 'template/layouts', 42 | middleware: 'middleware', 43 | pages: 'template/pages', 44 | static: 'public', 45 | store: 'store', 46 | }, 47 | 48 | /* 49 | ** Nuxt.js modules 50 | ** See ~/configurations/* 51 | */ 52 | modules: [ 53 | // Doc: https://axios.nuxtjs.org/usage 54 | ['@nuxtjs/axios', Axios], 55 | 56 | // Doc: https://auth.nuxtjs.org/ 57 | ['@nuxtjs/auth', Auth], 58 | 59 | // Doc : https://github.com/nuxt-community/modules/tree/master/packages/toast 60 | ['@nuxtjs/toast', Toasts], 61 | 62 | // Doc : https://github.com/nuxt-community/sitemap-module 63 | ['@nuxtjs/sitemap', Sitemap], 64 | 65 | // Doc : https://i18n.nuxtjs.org/ 66 | ['nuxt-i18n', Translations], 67 | 68 | // Doc : https://github.com/nuxt-community/robots-module 69 | ['@nuxtjs/robots', Robots], 70 | ], 71 | 72 | /** 73 | ** Environnements variables settings 74 | ** Don't forget to specifie 'process.client' 75 | ** if you want to use 'window' or 'document' 76 | */ 77 | env: {}, 78 | 79 | /** 80 | ** Headers module settings 81 | ** See https://fr.nuxtjs.org/guides/configuration-glossary/configuration-head/ 82 | */ 83 | head: Meta, 84 | 85 | /** 86 | ** Global style module settings 87 | ** See https://fr.nuxtjs.org/guides/configuration-glossary/configuration-css 88 | */ 89 | css: ['material-icons/iconfont/material-icons.scss'], 90 | 91 | /* 92 | ** Plugins to load before mounting the App 93 | ** https://nuxtjs.org/guide/plugins 94 | */ 95 | plugins: [], 96 | 97 | /** 98 | ** Build settings 99 | ** See https://fr.nuxtjs.org/guides/configuration-glossary/configuration-build/ 100 | */ 101 | build: {}, 102 | 103 | /** 104 | ** Nuxt generation settings 105 | ** See https://fr.nuxtjs.org/api/configuration-generate/ 106 | */ 107 | generate: { 108 | minify: { 109 | collapseWhitespace: false, 110 | }, 111 | }, 112 | 113 | /** 114 | ** Nuxt transition settings 115 | ** See https://fr.nuxtjs.org/api/configuration-transition 116 | */ 117 | pageTransition: { 118 | name: 'page', 119 | mode: 'out-in', 120 | }, 121 | } 122 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "cross-env NODE_ENV=developpement nuxt-ts", 7 | "build": "nuxt-ts build", 8 | "start": "nuxt-ts start", 9 | "export": "nuxt-ts export" 10 | }, 11 | "dependencies": { 12 | "@nuxt/typescript-runtime": "^1.0.0", 13 | "@nuxtjs/auth": "^4.9.1", 14 | "@nuxtjs/axios": "^5.11.0", 15 | "@nuxtjs/composition-api": "^0.13.3", 16 | "@nuxtjs/robots": "^2.4.2", 17 | "@nuxtjs/sitemap": "^2.4.0", 18 | "@nuxtjs/toast": "^3.3.0", 19 | "cross-env": "^7.0.2", 20 | "js-cookie": "^2.2.1", 21 | "material-icons": "^0.3.1", 22 | "node-sass": "^4.14.1", 23 | "nuxt": "^2.13.3", 24 | "nuxt-i18n": "^6.13.1", 25 | "sass-loader": "^9.0.2", 26 | "vue": "^2.6.11", 27 | "vue-server-renderer": "^2.6.11", 28 | "vuex-persistedstate": "^3.0.1" 29 | }, 30 | "devDependencies": { 31 | "@nuxt/types": "^2.14.1", 32 | "@nuxt/typescript-build": "^2.0.2", 33 | "@nuxtjs/google-analytics": "^2.4.0", 34 | "eslint-config-prettier": "^6.11.0", 35 | "eslint-plugin-prettier": "^3.1.4", 36 | "prettier": "^2.0.5", 37 | "vue-template-compiler": "^2.6.11" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /client/src/components/LangSwitcher.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ $t('headerLangs') }} 5 | {{ lang.code.toUpperCase() }} 6 | 7 | 8 | 9 | 10 | 28 | 29 | 44 | -------------------------------------------------------------------------------- /client/src/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | welcome: 'Welcome to Adonis, Nuxt app !', 3 | headerLangs: 'Switch langage to', 4 | description: 'Create a fast, efficient and powerful application thanks to this model combining the best combination of technologies', 5 | } 6 | -------------------------------------------------------------------------------- /client/src/locales/fr-FR.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | welcome: 'Bienvenue dans l\'application Adonis, Nuxt !', 3 | headerLangs: 'Changer la langue à', 4 | description: 'Créer une application rapide, performante et puissante grâce à ce modèle associant la meilleure combinaison de technologies', 5 | } 6 | -------------------------------------------------------------------------------- /client/src/public/favicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Izoxy/adonis-nuxt-template/fbf32a4c98cf0f454bef39cb31f08aed6f8200e6/client/src/public/favicon.jpg -------------------------------------------------------------------------------- /client/src/public/images/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Izoxy/adonis-nuxt-template/fbf32a4c98cf0f454bef39cb31f08aed6f8200e6/client/src/public/images/image.jpg -------------------------------------------------------------------------------- /client/src/store/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Izoxy/adonis-nuxt-template/fbf32a4c98cf0f454bef39cb31f08aed6f8200e6/client/src/store/index.ts -------------------------------------------------------------------------------- /client/src/template/layouts/master.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 25 | -------------------------------------------------------------------------------- /client/src/template/pages/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ $t('description') }} 5 | 6 | 7 | 8 | 13 | 14 | 36 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | // tsconfig.json 2 | { 3 | "compilerOptions": { 4 | "target": "ES2018", 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "lib": ["ESNext", "ESNext.AsyncIterable", "DOM"], 8 | "esModuleInterop": true, 9 | "allowJs": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "noEmit": true, 13 | "baseUrl": ".", 14 | "paths": { 15 | "~/*": ["./*"], 16 | "@/*": ["./*"] 17 | }, 18 | "types": ["@types/node", "@nuxt/types", "nuxt-i18n"] 19 | }, 20 | "exclude": ["node_modules"] 21 | } 22 | -------------------------------------------------------------------------------- /client/vue-shim.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | -------------------------------------------------------------------------------- /docker-compose.example.yaml: -------------------------------------------------------------------------------- 1 | MACHINE_IP: 2 | 3 | client_name: 4 | client_image: 5 | 6 | server_name: 7 | server_image: 8 | 9 | network: 10 | network_name: 11 | 12 | database_user: 13 | database_password: 14 | 15 | version: '3' 16 | services: 17 | nginx: 18 | container_name: nginx 19 | image: nginx 20 | networks: 21 | - {{ network }} 22 | ports: 23 | - '80:80' 24 | volumes: 25 | - ./templates:/etc/nginx/templates 26 | 27 | 28 | mysql: 29 | container_name: mysql 30 | image: mariadb 31 | networks: 32 | - {{ network }} 33 | environment: 34 | MYSQL_USER: {{ database_user }} 35 | MYSQL_ROOT_PASSWORD: {{ database_password }} 36 | volumes: 37 | - mysql:/var/lib/mysql 38 | 39 | portfolio-server: 40 | container_name: {{ server_name }} 41 | build: . 42 | image: {{ server_image }} 43 | hostname: {{ server_name }} 44 | networks: 45 | - {{ network }} 46 | environment: 47 | DB_USER: {{ database_user }} 48 | DB_PASSWORD: {{ database_password }} 49 | 50 | portfolio-client: 51 | container_name: {{ client_name }} 52 | build: . 53 | image: {{ client_image }} 54 | networks: 55 | - {{ network }} 56 | ports: 57 | - '3000:3000' 58 | environment: 59 | PORTFOLIO_API: http://{{ MACHINE_IP }}:80/api 60 | 61 | networks: 62 | {{ network }}: 63 | name: {{ network_name }} 64 | 65 | volumes: 66 | mysql: 67 | driver: local 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adonis-nuxt-template", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "api": "cd ./server && yarn start", 7 | "front": "cd ./client && yarn dev", 8 | "build-template": "cd ./server && yarn install && yarn build && node ace migration:run && cd ../client && yarn install" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/Izoxy/adonis-nuxt-template.git" 13 | }, 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/Izoxy/adonis-nuxt-template/issues" 17 | }, 18 | "contributors": [ 19 | { 20 | "name": "Baptiste Parmantier", 21 | "email": "baptiste.parmantier.pro@gmail.com", 22 | "url": "https://github.com/LeadcodeDev" 23 | }, 24 | { 25 | "name": "Alexandre Gossard", 26 | "email": "frestytv@gmail.com", 27 | "url": "https://github.com/HakkaOfDev" 28 | } 29 | ], 30 | "homepage": "https://github.com/Izoxy/adonis-nuxt-template#readme" 31 | } 32 | -------------------------------------------------------------------------------- /server/.adonisrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript": true, 3 | "commands": [ 4 | "./commands", 5 | "@adonisjs/core/build/commands", 6 | "@adonisjs/lucid/build/commands" 7 | ], 8 | "exceptionHandlerNamespace": "App/Exceptions/Handler", 9 | "aliases": { 10 | "App": "app", 11 | "Contracts": "contracts", 12 | "Config": "config", 13 | "Database": "database" 14 | }, 15 | "preloads": [ 16 | "./start/routes", 17 | "./start/kernel" 18 | ], 19 | "providers": [ 20 | "./providers/AppProvider", 21 | "@adonisjs/core", 22 | "@adonisjs/lucid", 23 | "@adonisjs/auth", 24 | "@adonisjs/session" 25 | ], 26 | "metaFiles": [ 27 | ".env", 28 | ".adonisrc.json", 29 | "public/**" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /server/.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | [*] 3 | indent_style = tab 4 | indent_size = 4 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.json] 11 | insert_final_newline = ignore 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /server/.env: -------------------------------------------------------------------------------- 1 | PORT=3333 2 | HOST=0.0.0.0 3 | NODE_ENV=development 4 | APP_KEY=Raw-vAOdybthO6LAOZW-ADl9K3dLHr-S 5 | DB_CONNECTION=mysql 6 | DB_HOST=127.0.0.1 7 | DB_NAME=adonis-nuxt-template 8 | DB_USER=root 9 | DB_PASSWORD= 10 | SESSION_DRIVER=cookie -------------------------------------------------------------------------------- /server/.env.example: -------------------------------------------------------------------------------- 1 | PORT= 2 | HOST= 3 | NODE_ENV= 4 | APP_KEY= 5 | DB_CONNECTION= 6 | DB_HOST= 7 | DB_USER= 8 | DB_PASSWORD= 9 | DB_NAME= 10 | SESSION_DRIVER= -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | coverage 4 | .vscode 5 | .DS_STORE 6 | # .env 7 | tmp -------------------------------------------------------------------------------- /server/ace: -------------------------------------------------------------------------------- 1 | /* 2 | |-------------------------------------------------------------------------- 3 | | Ace Commands 4 | |-------------------------------------------------------------------------- 5 | | 6 | | This file is the entry point for running ace commands. For typescript 7 | | projects, the ace commands will fallback to the compiled code and 8 | | hence this file has to be executable by node directly. 9 | | 10 | */ 11 | 12 | require('reflect-metadata') 13 | require('source-map-support').install({ handleUncaughtExceptions: false }) 14 | 15 | const { Ignitor } = require('@adonisjs/core/build/src/Ignitor') 16 | new Ignitor(__dirname) 17 | .ace() 18 | .handle(process.argv.slice(2)) 19 | .catch(console.error) 20 | -------------------------------------------------------------------------------- /server/app/Controllers/Http/AuthController.ts: -------------------------------------------------------------------------------- 1 | import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' 2 | 3 | export default class AuthController { 4 | public async loginWeb({ request, auth }: HttpContextContract) { 5 | const email = request.input('email') 6 | const password = request.input('password') 7 | const remember_me = !!request.input('remember_me') 8 | try { 9 | await auth.attempt(email, password, remember_me) 10 | return { user: auth.user } 11 | } catch (error) { 12 | if (error.code === 'E_INVALID_AUTH_UID') return { error: "L'utilisateur n'a pas été trouvé" } 13 | if (error.code === 'E_INVALID_AUTH_PASSWORD') return { error: "L'identifiant ou le mot de passe est incorrecte" } 14 | } 15 | } 16 | 17 | public async logoutWeb({ auth }: HttpContextContract) { 18 | await auth.logout() 19 | return { message: 'Vous avez été déconnecté' } 20 | } 21 | 22 | public async loginApi({ request, auth }: HttpContextContract) { 23 | const email = request.input('email') 24 | const password = request.input('password') 25 | 26 | const token = await auth.use('api').attempt(email, password, { 27 | expiresIn: '10 days' 28 | }) 29 | return { token: token.toJSON() } 30 | } 31 | 32 | public async logoutApi({ auth }: HttpContextContract) { 33 | await auth.use('api').logout() 34 | return { message: 'Vous avez été déconnecté' } 35 | } 36 | 37 | public async user({ auth }: HttpContextContract) { 38 | console.log('auth') 39 | await auth.authenticate() 40 | return { user: auth.user } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /server/app/Controllers/Http/CookiesController.ts: -------------------------------------------------------------------------------- 1 | import Cookie from 'App/Models/Cookie' 2 | import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' 3 | import { DateTime } from 'luxon' 4 | 5 | export default class CookiesController { 6 | public async show({ params }: HttpContextContract) { 7 | const cookie = await Cookie.findBy('ip', params.ip) 8 | return { cookie } 9 | } 10 | 11 | public async store({ request }: HttpContextContract) { 12 | const date = new Date() 13 | const ip = request.input('ip') 14 | const expiration = DateTime.fromJSDate(new Date(date.setMonth(date.getMonth() + 6))) 15 | await Cookie.updateOrCreate({ ip }, { ip, expiration }) 16 | 17 | return { message: 'Cookies are allow for user : ' + ip } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/app/Controllers/Http/UserController.ts: -------------------------------------------------------------------------------- 1 | // import Application from '@ioc:Adonis/Core/Application' 2 | import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' 3 | import User from 'App/Models/User' 4 | import StoreValidator from 'App/Validators/users/StoreValidator' 5 | import UpdateValidator from 'App/Validators/users/UpdateValidator' 6 | 7 | export default class UsersController { 8 | public async index() { 9 | const users = await User.all() 10 | return { users } 11 | } 12 | 13 | public async show({ params }: HttpContextContract) { 14 | const user = await User.findOrFail(params.id) 15 | return { user } 16 | } 17 | 18 | public async store({ request }: HttpContextContract) { 19 | const data = await request.validate(StoreValidator) 20 | const user = await User.create(data) 21 | 22 | return { user } 23 | } 24 | 25 | public async update({ response, request, params, auth }: HttpContextContract) { 26 | const user = await User.findOrFail(params.id) 27 | 28 | if (user.id != auth.user!.id) { 29 | return response.unauthorized() 30 | } 31 | 32 | const data = await request.validate(UpdateValidator) 33 | 34 | /** 35 | * const avatar = request.file('avatar', { 36 | * extnames: ['jpg', 'jpeg', 'png', 'svg'] 37 | * }) 38 | * 39 | * if (avatar?.hasErrors) { 40 | * return avatar.errors 41 | * } 42 | 43 | * await avatar?.move(Application.publicPath(`/uploads/users/avatar`), { 44 | * name: `${params.id}.${avatar.extname}`, 45 | * overwrite: true 46 | * }) 47 | */ 48 | 49 | await auth.user!.merge({ ...data }).save() 50 | 51 | return { message: 'Le compte a été mis à jour' } 52 | } 53 | 54 | public async destroy({ response, params, auth }: HttpContextContract) { 55 | const user = await User.findOrFail(params.id) 56 | 57 | if (user.id != auth.user!.id) { 58 | return response.unauthorized() 59 | } 60 | 61 | auth.user!.delete() 62 | return { message: "L'utilisateur a bien été supprimé" } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /server/app/Exceptions/Handler.ts: -------------------------------------------------------------------------------- 1 | /* 2 | |-------------------------------------------------------------------------- 3 | | Http Exception Handler 4 | |-------------------------------------------------------------------------- 5 | | 6 | | AdonisJs will forward all exceptions occurred during an HTTP request to 7 | | the following class. You can learn more about exception handling by 8 | | reading docs. 9 | | 10 | | The exception handler extends a base `HttpExceptionHandler` which is not 11 | | mandatory, however it can do lot of heavy lifting to handle the errors 12 | | properly. 13 | | 14 | */ 15 | 16 | import Logger from '@ioc:Adonis/Core/Logger' 17 | import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler' 18 | 19 | export default class ExceptionHandler extends HttpExceptionHandler { 20 | constructor () { 21 | super(Logger) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /server/app/Middleware/Auth.ts: -------------------------------------------------------------------------------- 1 | import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' 2 | import { AuthenticationException } from '@adonisjs/auth/build/standalone' 3 | 4 | /** 5 | * Auth middleware is meant to restrict un-authenticated access to a given route 6 | * or a group of routes. 7 | * 8 | * You must register this middleware inside `start/kernel.ts` file under the list 9 | * of named middleware. 10 | */ 11 | export default class AuthMiddleware { 12 | /** 13 | * The URL to redirect to when request is Unauthorized 14 | */ 15 | protected redirectTo = '/login' 16 | 17 | /** 18 | * Authenticates the current HTTP request against a custom set of defined 19 | * guards. 20 | * 21 | * The authentication loop stops as soon as the user is authenticated using any 22 | * of the mentioned guards and that guard will be used by the rest of the code 23 | * during the current request. 24 | */ 25 | protected async authenticate (auth: HttpContextContract['auth'], guards: any[]) { 26 | /** 27 | * Hold reference to the guard last attempted within the for loop. We pass 28 | * the reference of the guard to the "AuthenticationException", so that 29 | * it can decide the correct response behavior based upon the guard 30 | * driver 31 | */ 32 | let guardLastAttempted: string | undefined 33 | 34 | for (let guard of guards) { 35 | guardLastAttempted = guard 36 | 37 | if (await auth.use(guard).check()) { 38 | /** 39 | * Instruct auth to use the given guard as the default guard for 40 | * the rest of the request, since the user authenticated 41 | * succeeded here 42 | */ 43 | auth.defaultGuard = guard 44 | return true 45 | } 46 | } 47 | 48 | /** 49 | * Unable to authenticate using any guard 50 | */ 51 | throw new AuthenticationException( 52 | 'Unauthorized access', 53 | 'E_UNAUTHORIZED_ACCESS', 54 | guardLastAttempted, 55 | this.redirectTo, 56 | ) 57 | } 58 | 59 | /** 60 | * Handle request 61 | */ 62 | public async handle ({ auth }: HttpContextContract, next: () => Promise, customGuards: string[]) { 63 | /** 64 | * Uses the user defined guards or the default guard mentioned in 65 | * the config file 66 | */ 67 | const guards = customGuards.length ? customGuards : [auth.name] 68 | await this.authenticate(auth, guards) 69 | await next() 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /server/app/Middleware/SilentAuth.ts: -------------------------------------------------------------------------------- 1 | import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' 2 | 3 | /** 4 | * Silent auth middleware can be used as a global middleware to silent check 5 | * if the user is logged-in or not. 6 | * 7 | * The request continues as usual, even when the user is not logged-in. 8 | */ 9 | export default class SilentAuthMiddleware { 10 | /** 11 | * Handle request 12 | */ 13 | public async handle ({ auth }: HttpContextContract, next: () => Promise) { 14 | /** 15 | * Check if user is logged-in or not. If yes, then `ctx.auth.user` will be 16 | * set to the instance of the currently logged in user. 17 | */ 18 | await auth.check() 19 | await next() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /server/app/Models/Cookie.ts: -------------------------------------------------------------------------------- 1 | import { DateTime } from 'luxon' 2 | import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm' 3 | 4 | export default class Cooky extends BaseModel { 5 | @column({ isPrimary: true }) 6 | public id: number 7 | 8 | @column() 9 | public ip: string 10 | 11 | @column.dateTime({ autoCreate: true }) 12 | public expiration: DateTime 13 | } 14 | -------------------------------------------------------------------------------- /server/app/Models/User.ts: -------------------------------------------------------------------------------- 1 | import { DateTime } from 'luxon' 2 | import Hash from '@ioc:Adonis/Core/Hash' 3 | import { column, beforeSave, BaseModel } from '@ioc:Adonis/Lucid/Orm' 4 | 5 | export default class User extends BaseModel { 6 | @column({ isPrimary: true }) 7 | public id: number 8 | 9 | @column() 10 | public email: string 11 | 12 | @column() 13 | public firstname: string 14 | 15 | @column() 16 | public lastname: string 17 | 18 | @column() 19 | public password: string 20 | 21 | @column() 22 | public rememberMeToken?: string 23 | 24 | @column.dateTime({ autoCreate: true }) 25 | public createdAt: DateTime 26 | 27 | @column.dateTime({ autoCreate: true, autoUpdate: true }) 28 | public updatedAt: DateTime 29 | 30 | @beforeSave() 31 | public static async hashPassword(user: User) { 32 | if (user.$dirty.password) { 33 | user.password = await Hash.make(user.password) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /server/app/Validators/users/StoreValidator.ts: -------------------------------------------------------------------------------- 1 | import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' 2 | import { schema, rules } from '@ioc:Adonis/Core/Validator' 3 | 4 | export default class StoreValidator { 5 | constructor(private ctx: HttpContextContract) {} 6 | 7 | /** 8 | * Defining a schema to validate the "shape", "type", "formatting" and "integrity" of data. 9 | * 10 | * For example: 11 | * 1. The username must be of data type string. But then also, it should 12 | * not contain special characters or numbers. 13 | * ``` 14 | * schema.string({}, [ rules.alpha() ]) 15 | * ``` 16 | * 17 | * 2. The email must be of data type string, formatted as a valid 18 | * email. But also, not used by any other user. 19 | * ``` 20 | * schema.string({}, [ 21 | * rules.email(), 22 | * rules.unique({ table: 'users', column: 'email' }), 23 | * ]) 24 | * ``` 25 | */ 26 | public schema = schema.create({ 27 | firstname: schema.string({ trim: true }), 28 | lastname: schema.string({ trim: true }), 29 | email: schema.string({ trim: true }, [rules.email(), rules.unique({ table: 'users', column: 'email' })]), 30 | password: schema.string({ trim: true }, [rules.confirmed()]) 31 | }) 32 | 33 | /** 34 | * The `schema` first gets compiled to a reusable function and then that compiled 35 | * function validates the data at runtime. 36 | * 37 | * Since, compiling the schema is an expensive operation, you must always cache it by 38 | * defining a unique cache key. The simplest way is to use the current request route 39 | * key, which is a combination of the route pattern and HTTP method. 40 | */ 41 | public cacheKey = this.ctx.routeKey 42 | 43 | /** 44 | * Custom messages for validation failures. You can make use of dot notation `(.)` 45 | * for targeting nested fields and array expressions `(*)` for targeting all 46 | * children of an array. For example: 47 | * 48 | * { 49 | * 'profile.username.required': 'Username is required', 50 | * 'scores.*.number': 'Define scores as valid numbers' 51 | * } 52 | */ 53 | public messages = { 54 | required: 'Le champ {{ field }} est obligatoire', 55 | 'firstname.required': 'Le prénom est obligatoire', 56 | 'lastname.required': 'Le nom est obligatoire', 57 | 'email.required': "L'email est obligatoire", 58 | 'email.email': "L'email doit-être une adresse email valide", 59 | 'email.unique': "L'email existe déjà, veuillez en choisir une autre", 60 | 'password_confirmation.confirmed': "Le mot de passe n'a pas été confirmé ou est invalide" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /server/app/Validators/users/UpdateValidator.ts: -------------------------------------------------------------------------------- 1 | import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' 2 | import { schema, rules } from '@ioc:Adonis/Core/Validator' 3 | 4 | export default class StoreValidator { 5 | constructor(private ctx: HttpContextContract) {} 6 | 7 | /** 8 | * Defining a schema to validate the "shape", "type", "formatting" and "integrity" of data. 9 | * 10 | * For example: 11 | * 1. The username must be of data type string. But then also, it should 12 | * not contain special characters or numbers. 13 | * ``` 14 | * schema.string({}, [ rules.alpha() ]) 15 | * ``` 16 | * 17 | * 2. The email must be of data type string, formatted as a valid 18 | * email. But also, not used by any other user. 19 | * ``` 20 | * schema.string({}, [ 21 | * rules.email(), 22 | * rules.unique({ table: 'users', column: 'email' }), 23 | * ]) 24 | * ``` 25 | */ 26 | public schema = schema.create({ 27 | firstname: schema.string.optional({ trim: true }), 28 | lastname: schema.string.optional({ trim: true }), 29 | email: schema.string.optional({ trim: true }, [rules.email(), rules.unique({ table: 'users', column: 'email' })]), 30 | password: schema.string.optional({ trim: true }, [rules.confirmed()]) 31 | }) 32 | 33 | /** 34 | * The `schema` first gets compiled to a reusable function and then that compiled 35 | * function validates the data at runtime. 36 | * 37 | * Since, compiling the schema is an expensive operation, you must always cache it by 38 | * defining a unique cache key. The simplest way is to use the current request route 39 | * key, which is a combination of the route pattern and HTTP method. 40 | */ 41 | public cacheKey = this.ctx.routeKey 42 | 43 | /** 44 | * Custom messages for validation failures. You can make use of dot notation `(.)` 45 | * for targeting nested fields and array expressions `(*)` for targeting all 46 | * children of an array. For example: 47 | * 48 | * { 49 | * 'profile.username.required': 'Username is required', 50 | * 'scores.*.number': 'Define scores as valid numbers' 51 | * } 52 | */ 53 | public messages = { 54 | required: 'Le champ {{ field }} est obligatoire', 55 | 'firstname.required': 'Le prénom est obligatoire', 56 | 'lastname.required': 'Le nom est obligatoire', 57 | 'email.required': "L'email est obligatoire", 58 | 'email.email': "L'email doit-être une adresse email valide", 59 | 'email.unique': "L'email existe déjà, veuillez en choisir une autre", 60 | 'password_confirmation.confirmed': "Le mot de passe n'a pas été confirmé ou est invalide" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /server/commands/index.ts: -------------------------------------------------------------------------------- 1 | import { listDirectoryFiles } from '@adonisjs/core/build/standalone' 2 | import Application from '@ioc:Adonis/Core/Application' 3 | 4 | /* 5 | |-------------------------------------------------------------------------- 6 | | Exporting an array of commands 7 | |-------------------------------------------------------------------------- 8 | | 9 | | Instead of manually exporting each file from this directory, we use the 10 | | helper `listDirectoryFiles` to recursively collect and export an array 11 | | of filenames. 12 | | 13 | | Couple of things to note: 14 | | 15 | | 1. The file path must be relative from the project root and not this directory. 16 | | 2. We must ignore this file. 17 | | 18 | */ 19 | export default listDirectoryFiles(__dirname, Application.appRoot, ['./commands/index']) 20 | -------------------------------------------------------------------------------- /server/config/app.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Config source: https://git.io/JfefZ 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this config 5 | * file. 6 | */ 7 | 8 | import proxyAddr from 'proxy-addr' 9 | import Env from '@ioc:Adonis/Core/Env' 10 | import { LoggerConfig } from '@ioc:Adonis/Core/Logger' 11 | import { RequestConfig } from '@ioc:Adonis/Core/Request' 12 | import { ResponseConfig } from '@ioc:Adonis/Core/Response' 13 | import { ProfilerConfig } from '@ioc:Adonis/Core/Profiler' 14 | 15 | type HttpConfig = RequestConfig & ResponseConfig 16 | 17 | /* 18 | |-------------------------------------------------------------------------- 19 | | Application secret key 20 | |-------------------------------------------------------------------------- 21 | | 22 | | The secret to encrypt and sign different values in your application. 23 | | Make sure to keep the `APP_KEY` as an environment variable and secure. 24 | | 25 | | Note: Changing the application key for an existing app will make all 26 | | the cookies invalid and also the existing encrypted data will not 27 | | be decrypted. 28 | | 29 | */ 30 | export const appKey: string = Env.get('APP_KEY') as string 31 | 32 | /* 33 | |-------------------------------------------------------------------------- 34 | | Http server configuration 35 | |-------------------------------------------------------------------------- 36 | | 37 | | The configuration for the HTTP(s) server. Make sure to go through all 38 | | the config properties to make keep server secure. 39 | | 40 | */ 41 | export const http: HttpConfig = { 42 | /* 43 | |-------------------------------------------------------------------------- 44 | | Allow method spoofing 45 | |-------------------------------------------------------------------------- 46 | | 47 | | Method spoofing enables defining custom HTTP methods using a query string 48 | | `_method`. This is usually required when you are making traditional 49 | | form requests and wants to use HTTP verbs like `PUT`, `DELETE` and 50 | | so on. 51 | | 52 | */ 53 | allowMethodSpoofing: false, 54 | 55 | /* 56 | |-------------------------------------------------------------------------- 57 | | Subdomain offset 58 | |-------------------------------------------------------------------------- 59 | */ 60 | subdomainOffset: 2, 61 | 62 | /* 63 | |-------------------------------------------------------------------------- 64 | | Request Ids 65 | |-------------------------------------------------------------------------- 66 | | 67 | | Setting this value to `true` will generate a unique request id for each 68 | | HTTP request and set it as `x-request-id` header. 69 | | 70 | */ 71 | generateRequestId: false, 72 | 73 | /* 74 | |-------------------------------------------------------------------------- 75 | | Trusting proxy servers 76 | |-------------------------------------------------------------------------- 77 | | 78 | | Define the proxy servers that AdonisJs must trust for reading `X-Forwarded` 79 | | headers. 80 | | 81 | */ 82 | trustProxy: proxyAddr.compile('loopback'), 83 | 84 | /* 85 | |-------------------------------------------------------------------------- 86 | | Generating Etag 87 | |-------------------------------------------------------------------------- 88 | | 89 | | Whether or not to generate an etag for every response. 90 | | 91 | */ 92 | etag: false, 93 | 94 | /* 95 | |-------------------------------------------------------------------------- 96 | | JSONP Callback 97 | |-------------------------------------------------------------------------- 98 | */ 99 | jsonpCallbackName: 'callback', 100 | 101 | /* 102 | |-------------------------------------------------------------------------- 103 | | Cookie settings 104 | |-------------------------------------------------------------------------- 105 | */ 106 | cookie: { 107 | domain: '', 108 | path: '/', 109 | maxAge: '2h', 110 | httpOnly: true, 111 | secure: false, 112 | sameSite: false 113 | }, 114 | 115 | /* 116 | |-------------------------------------------------------------------------- 117 | | Force content negotiation to JSON 118 | |-------------------------------------------------------------------------- 119 | | 120 | | The internals of the framework relies on the content negotiation to 121 | | detect the best possible response type for a given HTTP request. 122 | | 123 | | However, it is a very common these days that API servers always wants to 124 | | make response in JSON regardless of the existence of the `Accept` header. 125 | | 126 | | By setting `forceContentNegotiationToJSON = true`, you negotiate with the 127 | | server in advance to always return JSON without relying on the client 128 | | to set the header explicitly. 129 | | 130 | */ 131 | forceContentNegotiationToJSON: true 132 | } 133 | 134 | /* 135 | |-------------------------------------------------------------------------- 136 | | Logger 137 | |-------------------------------------------------------------------------- 138 | */ 139 | export const logger: LoggerConfig = { 140 | /* 141 | |-------------------------------------------------------------------------- 142 | | Application name 143 | |-------------------------------------------------------------------------- 144 | | 145 | | The name of the application you want to add to the log. It is recommended 146 | | to always have app name in every log line. 147 | | 148 | | The `APP_NAME` environment variable is automatically set by AdonisJS by 149 | | reading the `name` property from the `package.json` file. 150 | | 151 | */ 152 | name: Env.get('APP_NAME') as string, 153 | 154 | /* 155 | |-------------------------------------------------------------------------- 156 | | Toggle logger 157 | |-------------------------------------------------------------------------- 158 | | 159 | | Enable or disable logger application wide 160 | | 161 | */ 162 | enabled: true, 163 | 164 | /* 165 | |-------------------------------------------------------------------------- 166 | | Logging level 167 | |-------------------------------------------------------------------------- 168 | | 169 | | The level from which you want the logger to flush logs. It is recommended 170 | | to make use of the environment variable, so that you can define log levels 171 | | at deployment level and not code level. 172 | | 173 | */ 174 | level: Env.get('LOG_LEVEL', 'info') as string, 175 | 176 | /* 177 | |-------------------------------------------------------------------------- 178 | | Pretty print 179 | |-------------------------------------------------------------------------- 180 | | 181 | | It is highly advised NOT to use `prettyPrint` in production, since it 182 | | can have huge impact on performance. 183 | | 184 | */ 185 | prettyPrint: Env.get('NODE_ENV') === 'development' 186 | } 187 | 188 | /* 189 | |-------------------------------------------------------------------------- 190 | | Profiler 191 | |-------------------------------------------------------------------------- 192 | */ 193 | export const profiler: ProfilerConfig = { 194 | /* 195 | |-------------------------------------------------------------------------- 196 | | Toggle profiler 197 | |-------------------------------------------------------------------------- 198 | | 199 | | Enable or disable profiler 200 | | 201 | */ 202 | enabled: true, 203 | 204 | /* 205 | |-------------------------------------------------------------------------- 206 | | Blacklist actions/row labels 207 | |-------------------------------------------------------------------------- 208 | | 209 | | Define an array of actions or row labels that you want to disable from 210 | | getting profiled. 211 | | 212 | */ 213 | blacklist: [], 214 | 215 | /* 216 | |-------------------------------------------------------------------------- 217 | | Whitelist actions/row labels 218 | |-------------------------------------------------------------------------- 219 | | 220 | | Define an array of actions or row labels that you want to whitelist for 221 | | the profiler. When whitelist is defined, then `blacklist` is ignored. 222 | | 223 | */ 224 | whitelist: [] 225 | } 226 | -------------------------------------------------------------------------------- /server/config/auth.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Config source: https://git.io/JvyKy 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this config 5 | * file. 6 | */ 7 | 8 | import { AuthConfig } from '@ioc:Adonis/Addons/Auth' 9 | 10 | /* 11 | |-------------------------------------------------------------------------- 12 | | Authentication Mapping 13 | |-------------------------------------------------------------------------- 14 | | 15 | | List of available authentication mapping. You must first define them 16 | | inside the `contracts/auth.ts` file before mentioning them here. 17 | | 18 | */ 19 | const authConfig: AuthConfig = { 20 | guard: 'web', 21 | list: { 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Web Guard 25 | |-------------------------------------------------------------------------- 26 | | 27 | | Web guard uses classic old school sessions for authenticating users. 28 | | If you are building a standard web application, it is recommended to 29 | | use web guard with session driver 30 | | 31 | */ 32 | web: { 33 | driver: 'session', 34 | 35 | provider: { 36 | /* 37 | |-------------------------------------------------------------------------- 38 | | Driver 39 | |-------------------------------------------------------------------------- 40 | | 41 | | Name of the driver 42 | | 43 | */ 44 | driver: 'lucid', 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Identifier key 49 | |-------------------------------------------------------------------------- 50 | | 51 | | The identifier key is the unique key on the model. In most cases specifying 52 | | the primary key is the right choice. 53 | | 54 | */ 55 | identifierKey: 'id', 56 | 57 | /* 58 | |-------------------------------------------------------------------------- 59 | | Uids 60 | |-------------------------------------------------------------------------- 61 | | 62 | | Uids are used to search a user against one of the mentioned columns. During 63 | | login, the auth module will search the user mentioned value against one 64 | | of the mentioned columns to find their user record. 65 | | 66 | */ 67 | uids: ['email'], 68 | 69 | /* 70 | |-------------------------------------------------------------------------- 71 | | Model 72 | |-------------------------------------------------------------------------- 73 | | 74 | | The model to use for fetching or finding users 75 | | 76 | */ 77 | model: () => import('App/Models/User') 78 | } 79 | }, 80 | /* 81 | |-------------------------------------------------------------------------- 82 | | OAT Guard 83 | |-------------------------------------------------------------------------- 84 | | 85 | | OAT (Opaque access tokens) guard uses database backed tokens to authenticate 86 | | HTTP request. This guard DOES NOT rely on sessions or cookies and uses 87 | | Authorization header value for authentication. 88 | | 89 | | Use this guard to authenticate mobile apps or web clients that cannot rely 90 | | on cookies/sessions. 91 | | 92 | */ 93 | api: { 94 | driver: 'oat', 95 | 96 | /* 97 | |-------------------------------------------------------------------------- 98 | | Tokens provider 99 | |-------------------------------------------------------------------------- 100 | | 101 | | Uses SQL database for managing tokens. 102 | | 103 | */ 104 | tokenProvider: { 105 | driver: 'database', 106 | table: 'api_tokens' 107 | }, 108 | 109 | provider: { 110 | /* 111 | |-------------------------------------------------------------------------- 112 | | Driver 113 | |-------------------------------------------------------------------------- 114 | | 115 | | Name of the driver 116 | | 117 | */ 118 | driver: 'lucid', 119 | 120 | /* 121 | |-------------------------------------------------------------------------- 122 | | Identifier key 123 | |-------------------------------------------------------------------------- 124 | | 125 | | The identifier key is the unique key on the model. In most cases specifying 126 | | the primary key is the right choice. 127 | | 128 | */ 129 | identifierKey: 'id', 130 | 131 | /* 132 | |-------------------------------------------------------------------------- 133 | | Uids 134 | |-------------------------------------------------------------------------- 135 | | 136 | | Uids are used to search a user against one of the mentioned columns. During 137 | | login, the auth module will search the user mentioned value against one 138 | | of the mentioned columns to find their user record. 139 | | 140 | */ 141 | uids: ['email'], 142 | 143 | /* 144 | |-------------------------------------------------------------------------- 145 | | Model 146 | |-------------------------------------------------------------------------- 147 | | 148 | | The model to use for fetching or finding users 149 | | 150 | */ 151 | model: () => import('App/Models/User') 152 | } 153 | } 154 | } 155 | } 156 | 157 | export default authConfig 158 | -------------------------------------------------------------------------------- /server/config/bodyparser.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Config source: https://git.io/Jfefn 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this config 5 | * file. 6 | */ 7 | 8 | import { BodyParserConfig } from '@ioc:Adonis/Core/BodyParser' 9 | 10 | const bodyParserConfig: BodyParserConfig = { 11 | /* 12 | |-------------------------------------------------------------------------- 13 | | White listed methods 14 | |-------------------------------------------------------------------------- 15 | | 16 | | HTTP methods for which body parsing must be performed. It is a good practice 17 | | to avoid body parsing for `GET` requests. 18 | | 19 | */ 20 | whitelistedMethods: ['POST', 'PUT', 'PATCH', 'DELETE'], 21 | 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | JSON parser settings 25 | |-------------------------------------------------------------------------- 26 | | 27 | | The settings for the JSON parser. The types defines the request content 28 | | types which gets processed by the JSON parser. 29 | | 30 | */ 31 | json: { 32 | encoding: 'utf-8', 33 | limit: '1mb', 34 | strict: true, 35 | types: [ 36 | 'application/json', 37 | 'application/json-patch+json', 38 | 'application/vnd.api+json', 39 | 'application/csp-report', 40 | ], 41 | }, 42 | 43 | /* 44 | |-------------------------------------------------------------------------- 45 | | Form parser settings 46 | |-------------------------------------------------------------------------- 47 | | 48 | | The settings for the `application/x-www-form-urlencoded` parser. The types 49 | | defines the request content types which gets processed by the form parser. 50 | | 51 | */ 52 | form: { 53 | encoding: 'utf-8', 54 | limit: '1mb', 55 | queryString: {}, 56 | types: [ 57 | 'application/x-www-form-urlencoded', 58 | ], 59 | }, 60 | 61 | /* 62 | |-------------------------------------------------------------------------- 63 | | Raw body parser settings 64 | |-------------------------------------------------------------------------- 65 | | 66 | | Raw body just reads the request body stream as a plain text, which you 67 | | can process by hand. This must be used when request body type is not 68 | | supported by the body parser. 69 | | 70 | */ 71 | raw: { 72 | encoding: 'utf-8', 73 | limit: '1mb', 74 | queryString: {}, 75 | types: [ 76 | 'text/*', 77 | ], 78 | }, 79 | 80 | /* 81 | |-------------------------------------------------------------------------- 82 | | Multipart parser settings 83 | |-------------------------------------------------------------------------- 84 | | 85 | | The settings for the `multipart/form-data` parser. The types defines the 86 | | request content types which gets processed by the form parser. 87 | | 88 | */ 89 | multipart: { 90 | /* 91 | |-------------------------------------------------------------------------- 92 | | Auto process 93 | |-------------------------------------------------------------------------- 94 | | 95 | | The auto process option will process uploaded files and writes them to 96 | | the `tmp` folder. You can turn it off and then manually use the stream 97 | | to pipe stream to a different destination. 98 | | 99 | | It is recommended to keep `autoProcess=true`. Unless you are processing bigger 100 | | file sizes. 101 | | 102 | */ 103 | autoProcess: true, 104 | 105 | /* 106 | |-------------------------------------------------------------------------- 107 | | Files to be processed manually 108 | |-------------------------------------------------------------------------- 109 | | 110 | | You can turn off `autoProcess` for certain routes by defining 111 | | routes inside the following array. 112 | | 113 | | NOTE: Make sure the route pattern starts with a leading slash. 114 | | 115 | | Correct 116 | | ```js 117 | | /projects/:id/file 118 | | ``` 119 | | 120 | | Incorrect 121 | | ```js 122 | | projects/:id/file 123 | | ``` 124 | */ 125 | processManually: [], 126 | 127 | /* 128 | |-------------------------------------------------------------------------- 129 | | Temporary file name 130 | |-------------------------------------------------------------------------- 131 | | 132 | | When auto processing is on. We will use this method to compute the temporary 133 | | file name. AdonisJs will compute a unique `tmpPath` for you automatically, 134 | | However, you can also define your own custom method. 135 | | 136 | */ 137 | // tmpFileName () { 138 | // }, 139 | 140 | /* 141 | |-------------------------------------------------------------------------- 142 | | Encoding 143 | |-------------------------------------------------------------------------- 144 | | 145 | | Request body encoding 146 | | 147 | */ 148 | encoding: 'utf-8', 149 | 150 | /* 151 | |-------------------------------------------------------------------------- 152 | | Max Fields 153 | |-------------------------------------------------------------------------- 154 | | 155 | | The maximum number of fields allowed in the request body. The field includes 156 | | text inputs and files both. 157 | | 158 | */ 159 | maxFields: 1000, 160 | 161 | /* 162 | |-------------------------------------------------------------------------- 163 | | Request body limit 164 | |-------------------------------------------------------------------------- 165 | | 166 | | The total limit to the multipart body. This includes all request files 167 | | and fields data. 168 | | 169 | */ 170 | limit: '20mb', 171 | 172 | /* 173 | |-------------------------------------------------------------------------- 174 | | Types 175 | |-------------------------------------------------------------------------- 176 | | 177 | | The types that will be considered and parsed as multipart body. 178 | | 179 | */ 180 | types: [ 181 | 'multipart/form-data', 182 | ], 183 | }, 184 | } 185 | 186 | export default bodyParserConfig 187 | -------------------------------------------------------------------------------- /server/config/cors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Config source: https://git.io/JfefC 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this config 5 | * file. 6 | */ 7 | 8 | import { CorsConfig } from '@ioc:Adonis/Core/Cors' 9 | 10 | const corsConfig: CorsConfig = { 11 | /* 12 | |-------------------------------------------------------------------------- 13 | | Enabled 14 | |-------------------------------------------------------------------------- 15 | | 16 | | A boolean to enable or disable CORS integration from your AdonisJs 17 | | application. 18 | | 19 | | Setting the value to `true` will enable the CORS for all HTTP request. However, 20 | | you can define a function to enable/disable it on per request basis as well. 21 | | 22 | */ 23 | enabled: true, 24 | 25 | // You can also use a function that return true or false. 26 | // enabled: (request) => request.url().startsWith('/api') 27 | 28 | /* 29 | |-------------------------------------------------------------------------- 30 | | Origin 31 | |-------------------------------------------------------------------------- 32 | | 33 | | Set a list of origins to be allowed for `Access-Control-Allow-Origin`. 34 | | The value can be one of the following: 35 | | 36 | | https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin 37 | | 38 | | Boolean (true) - Allow current request origin. 39 | | Boolean (false) - Disallow all. 40 | | String - Comma seperated list of allowed origins. 41 | | Array - An array of allowed origins. 42 | | String (*) - A wildcard (*) to allow all request origins. 43 | | Function - Receives the current origin stirng and should return 44 | | one of the above values. 45 | | 46 | */ 47 | origin: true, 48 | 49 | /* 50 | |-------------------------------------------------------------------------- 51 | | Methods 52 | |-------------------------------------------------------------------------- 53 | | 54 | | An array of allowed HTTP methods for CORS. The `Access-Control-Request-Method` 55 | | is checked against the following list. 56 | | 57 | | Following is the list of default methods. Feel free to add more. 58 | */ 59 | methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE'], 60 | 61 | /* 62 | |-------------------------------------------------------------------------- 63 | | Headers 64 | |-------------------------------------------------------------------------- 65 | | 66 | | List of headers to be allowed for `Access-Control-Allow-Headers` header. 67 | | The value can be one of the following: 68 | | 69 | | https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers 70 | | 71 | | Boolean(true) - Allow all headers mentioned in `Access-Control-Request-Headers`. 72 | | Boolean(false) - Disallow all headers. 73 | | String - Comma seperated list of allowed headers. 74 | | Array - An array of allowed headers. 75 | | Function - Receives the current header and should return one of the above values. 76 | | 77 | */ 78 | headers: true, 79 | 80 | /* 81 | |-------------------------------------------------------------------------- 82 | | Expose Headers 83 | |-------------------------------------------------------------------------- 84 | | 85 | | A list of headers to be exposed by setting `Access-Control-Expose-Headers`. 86 | | header. By default following 6 simple response headers are exposed. 87 | | 88 | | Cache-Control 89 | | Content-Language 90 | | Content-Type 91 | | Expires 92 | | Last-Modified 93 | | Pragma 94 | | 95 | | In order to add more headers, simply define them inside the following array. 96 | | 97 | | https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers 98 | | 99 | */ 100 | exposeHeaders: ['cache-control', 'content-language', 'content-type', 'expires', 'last-modified', 'pragma'], 101 | 102 | /* 103 | |-------------------------------------------------------------------------- 104 | | Credentials 105 | |-------------------------------------------------------------------------- 106 | | 107 | | Toggle `Access-Control-Allow-Credentials` header. If value is set to `true`, 108 | | then header will be set, otherwise not. 109 | | 110 | | https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials 111 | | 112 | */ 113 | credentials: true, 114 | 115 | /* 116 | |-------------------------------------------------------------------------- 117 | | MaxAge 118 | |-------------------------------------------------------------------------- 119 | | 120 | | Define `Access-Control-Max-Age` header in seconds. 121 | | https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age 122 | | 123 | */ 124 | maxAge: 90 125 | } 126 | 127 | export default corsConfig 128 | -------------------------------------------------------------------------------- /server/config/database.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Config source: https://git.io/JesV9 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this config 5 | * file. 6 | */ 7 | 8 | import Env from '@ioc:Adonis/Core/Env' 9 | import { OrmConfig } from '@ioc:Adonis/Lucid/Orm' 10 | import Application from '@ioc:Adonis/Core/Application' 11 | import { DatabaseConfig } from '@ioc:Adonis/Lucid/Database' 12 | 13 | const databaseConfig: DatabaseConfig & { orm: Partial } = { 14 | /* 15 | |-------------------------------------------------------------------------- 16 | | Connection 17 | |-------------------------------------------------------------------------- 18 | | 19 | | The primary connection for making database queries across the application 20 | | You can use any key from the `connections` object defined in this same 21 | | file. 22 | | 23 | */ 24 | connection: Env.get('DB_CONNECTION', 'sqlite') as string, 25 | 26 | connections: { 27 | /* 28 | |-------------------------------------------------------------------------- 29 | | Sqlite 30 | |-------------------------------------------------------------------------- 31 | | 32 | | Configuration for the Sqlite database. Make sure to install the driver 33 | | from npm when using this connection 34 | | 35 | | npm i sqlite3 36 | | 37 | */ 38 | sqlite: { 39 | client: 'sqlite', 40 | connection: { 41 | filename: Application.tmpPath('db.sqlite3'), 42 | }, 43 | useNullAsDefault: true, 44 | healthCheck: false, 45 | }, 46 | 47 | /* 48 | |-------------------------------------------------------------------------- 49 | | Mysql config 50 | |-------------------------------------------------------------------------- 51 | | 52 | | Configuration for Mysql database. Make sure to install the driver 53 | | from npm when using this connection 54 | | 55 | | npm i mysql 56 | | 57 | */ 58 | mysql: { 59 | client: 'mysql', 60 | connection: { 61 | host: Env.get('DB_HOST', '127.0.0.1') as string, 62 | port: Number(Env.get('DB_PORT', 3306)), 63 | user: Env.get('DB_USER', 'lucid') as string, 64 | password: Env.get('DB_PASSWORD', 'lucid') as string, 65 | database: Env.get('DB_NAME', 'lucid') as string, 66 | }, 67 | healthCheck: false, 68 | }, 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | PostgreSQL config 73 | |-------------------------------------------------------------------------- 74 | | 75 | | Configuration for PostgreSQL database. Make sure to install the driver 76 | | from npm when using this connection 77 | | 78 | | npm i pg 79 | | 80 | */ 81 | pg: { 82 | client: 'pg', 83 | connection: { 84 | host: Env.get('DB_HOST', '127.0.0.1') as string, 85 | port: Number(Env.get('DB_PORT', 5432)), 86 | user: Env.get('DB_USER', 'lucid') as string, 87 | password: Env.get('DB_PASSWORD', 'lucid') as string, 88 | database: Env.get('DB_NAME', 'lucid') as string, 89 | }, 90 | healthCheck: false, 91 | }, 92 | }, 93 | 94 | /* 95 | |-------------------------------------------------------------------------- 96 | | Orm Configuration 97 | |-------------------------------------------------------------------------- 98 | | 99 | | Following are some of the configuration options to tweak the conventional 100 | | settings of the ORM. For example: 101 | | 102 | | - Define a custom function to compute the default table name for a given model. 103 | | - Or define a custom function to compute the primary key for a given model. 104 | | 105 | */ 106 | orm: { 107 | }, 108 | } 109 | 110 | export default databaseConfig 111 | -------------------------------------------------------------------------------- /server/config/hash.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Config source: https://git.io/JfefW 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this config 5 | * file. 6 | */ 7 | 8 | import Env from '@ioc:Adonis/Core/Env' 9 | import { HashConfig } from '@ioc:Adonis/Core/Hash' 10 | 11 | /* 12 | |-------------------------------------------------------------------------- 13 | | Hash Config 14 | |-------------------------------------------------------------------------- 15 | | 16 | | The `HashConfig` relies on the `HashList` interface which is 17 | | defined inside `contracts` directory. 18 | | 19 | */ 20 | const hashConfig: HashConfig = { 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Default hasher 24 | |-------------------------------------------------------------------------- 25 | | 26 | | By default we make use of the bcrypt hasher to hash values. However, feel 27 | | free to change the default value 28 | | 29 | */ 30 | default: Env.get('HASH_DRIVER', 'argon') as 'argon', 31 | 32 | list: { 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Argon 36 | |-------------------------------------------------------------------------- 37 | | 38 | | Argon mapping uses the `argon2` driver to hash values. 39 | | 40 | | Make sure you install the underlying dependency for this driver to work. 41 | | https://www.npmjs.com/package/phc-argon2. 42 | | 43 | | npm install phc-argon2 44 | | 45 | */ 46 | argon: { 47 | driver: 'argon2', 48 | variant: 'id', 49 | iterations: 3, 50 | memory: 4096, 51 | parallelism: 1, 52 | saltSize: 16, 53 | }, 54 | 55 | /* 56 | |-------------------------------------------------------------------------- 57 | | Bcrypt 58 | |-------------------------------------------------------------------------- 59 | | 60 | | Bcrypt mapping uses the `bcrypt` driver to hash values. 61 | | 62 | | Make sure you install the underlying dependency for this driver to work. 63 | | https://www.npmjs.com/package/phc-bcrypt. 64 | | 65 | | npm install phc-bcrypt 66 | | 67 | */ 68 | bcrypt: { 69 | driver: 'bcrypt', 70 | rounds: 10, 71 | }, 72 | }, 73 | } 74 | 75 | export default hashConfig 76 | -------------------------------------------------------------------------------- /server/config/session.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Config source: https://git.io/JeYHp 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this config 5 | * file. 6 | */ 7 | 8 | import Env from '@ioc:Adonis/Core/Env' 9 | import { SessionConfig } from '@ioc:Adonis/Addons/Session' 10 | 11 | const sessionConfig: SessionConfig = { 12 | /* 13 | |-------------------------------------------------------------------------- 14 | | Driver 15 | |-------------------------------------------------------------------------- 16 | | 17 | | The session driver to use. You can choose between one of the following 18 | | drivers. 19 | | 20 | | - cookie (Uses signed cookies to store session values) 21 | | - file (Uses filesystem to store session values) 22 | | - redis (Uses redis. Make sure to install "@adonisjs/redis" as well) 23 | | 24 | | Note: Switching drivers will make existing sessions invalid. 25 | | 26 | */ 27 | driver: Env.get('SESSION_DRIVER', 'cookie') as string, 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | Cookie name 32 | |-------------------------------------------------------------------------- 33 | | 34 | | The name of the cookie that will hold the session id. 35 | | 36 | */ 37 | cookieName: 'adonis-session', 38 | 39 | /* 40 | |-------------------------------------------------------------------------- 41 | | Clear session when browser closes 42 | |-------------------------------------------------------------------------- 43 | | 44 | | Whether or not you want to destroy the session when browser closes. Setting 45 | | this value to `true` will ignore the `age`. 46 | | 47 | */ 48 | clearWithBrowser: false, 49 | 50 | /* 51 | |-------------------------------------------------------------------------- 52 | | Session age 53 | |-------------------------------------------------------------------------- 54 | | 55 | | The duration for which session stays active after no activity. A new HTTP 56 | | request to the server is considered as activity. 57 | | 58 | | The value can be a number in milliseconds or a string that must be valid 59 | | as per https://npmjs.org/package/ms package. 60 | | 61 | | Example: `2 days`, `2.5 hrs`, `1y`, `5s` and so on. 62 | | 63 | */ 64 | age: '2h', 65 | 66 | /* 67 | |-------------------------------------------------------------------------- 68 | | Cookie values 69 | |-------------------------------------------------------------------------- 70 | | 71 | | The cookie settings are used to setup the session id cookie and also the 72 | | driver will use the same values. 73 | | 74 | */ 75 | cookie: { 76 | path: '/', 77 | httpOnly: true, 78 | sameSite: false, 79 | }, 80 | 81 | /* 82 | |-------------------------------------------------------------------------- 83 | | Configuration for file driver 84 | |-------------------------------------------------------------------------- 85 | | 86 | | The file driver needs absolute path to the directory in which sessions 87 | | must be stored. 88 | | 89 | */ 90 | file: { 91 | location: '', 92 | }, 93 | 94 | /* 95 | |-------------------------------------------------------------------------- 96 | | Redis driver 97 | |-------------------------------------------------------------------------- 98 | | 99 | | The redis connection you want session driver to use. The same connection 100 | | must be defined inside `config/redis.ts` file 101 | | 102 | */ 103 | redisConnection: 'session', 104 | } 105 | 106 | export default sessionConfig 107 | -------------------------------------------------------------------------------- /server/config/static.ts: -------------------------------------------------------------------------------- 1 | import { AssetsConfig } from '@ioc:Adonis/Core/Static' 2 | 3 | const staticConfig: AssetsConfig = { 4 | enabled: true, 5 | dotFiles: 'ignore', 6 | etag: true, 7 | lastModified: true 8 | } 9 | 10 | export default staticConfig 11 | -------------------------------------------------------------------------------- /server/contracts/auth.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Contract source: https://git.io/JvyKD 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this 5 | * file. 6 | */ 7 | 8 | import User from 'App/Models/User' 9 | 10 | declare module '@ioc:Adonis/Addons/Auth' { 11 | /* 12 | |-------------------------------------------------------------------------- 13 | | Providers 14 | |-------------------------------------------------------------------------- 15 | | 16 | | The providers are used to fetch users. The Auth module comes pre-bundled 17 | | with two providers that are `Lucid` and `Database`. Both uses database 18 | | to fetch user details. 19 | | 20 | | You can also create and register your own custom providers. 21 | | 22 | */ 23 | interface ProvidersList { 24 | /* 25 | |-------------------------------------------------------------------------- 26 | | User Provider 27 | |-------------------------------------------------------------------------- 28 | | 29 | | The following provider uses Lucid models as a driver for fetching user 30 | | details from the database for authentication. 31 | | 32 | | You can create multiple providers using the same underlying driver with 33 | | different Lucid models. 34 | | 35 | */ 36 | user: { 37 | implementation: LucidProviderContract, 38 | config: LucidProviderConfig, 39 | }, 40 | } 41 | 42 | /* 43 | |-------------------------------------------------------------------------- 44 | | Guards 45 | |-------------------------------------------------------------------------- 46 | | 47 | | The guards are used for authenticating users using different drivers. 48 | | The auth module comes with 4 different guards. 49 | | 50 | | - SessionGuardContract 51 | | - BasicAuthGuardContract 52 | | - JwtGuardContract 53 | | - OATGuardContract ( Opaque access token ) 54 | | 55 | | Every guard needs a provider for looking up users from the database. 56 | | 57 | */ 58 | interface GuardsList { 59 | /* 60 | |-------------------------------------------------------------------------- 61 | | Web Guard 62 | |-------------------------------------------------------------------------- 63 | | 64 | | The web guard uses sessions for maintaining user login state. It uses 65 | | the `user` provider for fetching user details. 66 | | 67 | */ 68 | web: { 69 | implementation: SessionGuardContract<'user', 'web'>, 70 | config: SessionGuardConfig<'user'>, 71 | }, 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | OAT Guard 75 | |-------------------------------------------------------------------------- 76 | | 77 | | OAT, stands for (Opaque access tokens) guard uses database backed tokens 78 | | to authenticate requests. 79 | | 80 | */ 81 | api: { 82 | implementation: OATGuardContract<'user', 'api'>, 83 | config: OATGuardConfig<'user'>, 84 | }, 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /server/contracts/env.ts: -------------------------------------------------------------------------------- 1 | declare module '@ioc:Adonis/Core/Env' { 2 | type CustomTypes = typeof import('../env').default 3 | interface EnvTypes extends CustomTypes {} 4 | } 5 | -------------------------------------------------------------------------------- /server/contracts/events.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Contract source: https://git.io/JfefG 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this contract 5 | * file. 6 | */ 7 | 8 | declare module '@ioc:Adonis/Core/Event' { 9 | /* 10 | |-------------------------------------------------------------------------- 11 | | Define typed events 12 | |-------------------------------------------------------------------------- 13 | | 14 | | You can define types for events inside the following interface and 15 | | AdonisJS will make sure that all listeners and emit calls adheres 16 | | to the defined types. 17 | | 18 | | For example: 19 | | 20 | | interface EventsList { 21 | | 'new:user': UserModel 22 | | } 23 | | 24 | | Now calling `Event.emit('new:user')` will statically ensure that passed value is 25 | | an instance of the the UserModel only. 26 | | 27 | */ 28 | interface EventsList { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/contracts/hash.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Contract source: https://git.io/Jfefs 3 | * 4 | * Feel free to let us know via PR, if you find something broken in this contract 5 | * file. 6 | */ 7 | 8 | declare module '@ioc:Adonis/Core/Hash' { 9 | interface HashersList { 10 | bcrypt: { 11 | config: BcryptConfig 12 | implementation: BcryptContract 13 | } 14 | argon: { 15 | config: ArgonConfig 16 | implementation: ArgonContract 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/database/migrations/1587988332388_user.ts: -------------------------------------------------------------------------------- 1 | import BaseSchema from '@ioc:Adonis/Lucid/Schema' 2 | 3 | export default class UsersSchema extends BaseSchema { 4 | protected tableName = 'users' 5 | 6 | public async up() { 7 | this.schema.createTable(this.tableName, (table) => { 8 | table.increments('id').primary() 9 | table.string('email', 255).notNullable() 10 | table.string('password', 180).notNullable() 11 | table.string('remember_me_token').nullable() 12 | table.dateTime('created_at').notNullable() 13 | table.dateTime('updated_at').notNullable() 14 | }) 15 | } 16 | 17 | public async down() { 18 | this.schema.dropTable(this.tableName) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /server/database/migrations/1592489784670_api_tokens.ts: -------------------------------------------------------------------------------- 1 | import BaseSchema from '@ioc:Adonis/Lucid/Schema' 2 | 3 | export default class ApiTokens extends BaseSchema { 4 | protected tableName = 'api_tokens' 5 | 6 | public async up() { 7 | this.schema.createTable(this.tableName, (table) => { 8 | table.increments('id').primary() 9 | table.integer('user_id').unsigned().references('id').inTable('users').onDelete('CASCADE') 10 | table.string('name').notNullable() 11 | table.string('type').notNullable() 12 | table.string('token', 64).notNullable() 13 | 14 | /** 15 | * "useTz: true" utilizes timezone option in PostgreSQL and MSSQL 16 | */ 17 | table.dateTime('expires_at', { useTz: true }).nullable() 18 | table.dateTime('created_at', { useTz: true }).notNullable() 19 | }) 20 | } 21 | 22 | public async down() { 23 | this.schema.dropTable(this.tableName) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /server/database/migrations/1594403111129_add_fields_users.ts: -------------------------------------------------------------------------------- 1 | import BaseSchema from '@ioc:Adonis/Lucid/Schema' 2 | 3 | export default class Users extends BaseSchema { 4 | protected tableName = 'users' 5 | 6 | public async up() { 7 | this.schema.table(this.tableName, (table) => { 8 | table.string('firstname', 255).notNullable() 9 | table.string('lastname', 255).notNullable() 10 | }) 11 | } 12 | 13 | public async down() { 14 | this.schema.table(this.tableName, (table) => { 15 | table.dropColumn('firstname') 16 | table.dropColumn('lastname') 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/database/migrations/1594407141527_add_avatar_users.ts: -------------------------------------------------------------------------------- 1 | import BaseSchema from '@ioc:Adonis/Lucid/Schema' 2 | 3 | export default class Users extends BaseSchema { 4 | protected tableName = 'users' 5 | 6 | public async up() { 7 | this.schema.table(this.tableName, (table) => { 8 | table.string('avatar') 9 | }) 10 | } 11 | 12 | public async down() { 13 | this.schema.table(this.tableName, (table) => { 14 | table.dropColumn('avatar') 15 | }) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /server/database/migrations/1594422933992_cookies.ts: -------------------------------------------------------------------------------- 1 | import BaseSchema from '@ioc:Adonis/Lucid/Schema' 2 | 3 | export default class Cookies extends BaseSchema { 4 | protected tableName = 'cookies' 5 | 6 | public async up() { 7 | this.schema.createTable(this.tableName, (table) => { 8 | table.increments('id') 9 | table.string('ip').notNullable() 10 | table.dateTime('expiration').notNullable() 11 | }) 12 | } 13 | 14 | public async down() { 15 | this.schema.dropTable(this.tableName) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /server/database/seeders/User.ts: -------------------------------------------------------------------------------- 1 | import BaseSeeder from '@ioc:Adonis/Lucid/Seeder' 2 | import User from 'App/Models/User' 3 | 4 | export default class UserSeeder extends BaseSeeder { 5 | public async run() { 6 | await User.create({ 7 | firstname: 'admin', 8 | lastname: 'admin', 9 | email: 'admin@admin.fr', 10 | password: 'admin' 11 | }) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server/env.ts: -------------------------------------------------------------------------------- 1 | import Env from '@ioc:Adonis/Core/Env' 2 | 3 | export default Env.rules({ 4 | HOST: Env.schema.string({ format: 'host' }), 5 | PORT: Env.schema.number(), 6 | APP_KEY: Env.schema.string() 7 | }) 8 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "node ace build", 7 | "start": "node ace serve --watch" 8 | }, 9 | "devDependencies": { 10 | "@adonisjs/assembler": "^3.1.0", 11 | "adonis-preset-ts": "^1.0.4", 12 | "pino-pretty": "^4.0.0", 13 | "typescript": "^4.0.5", 14 | "youch": "^2.0.10", 15 | "youch-terminal": "^1.0.0" 16 | }, 17 | "dependencies": { 18 | "@adonisjs/ace": "^7.1.6", 19 | "@adonisjs/auth": "^5.0.2", 20 | "@adonisjs/core": "^5.0.4-preview-rc-2", 21 | "@adonisjs/fold": "^7.0.8", 22 | "@adonisjs/lucid": "^9.0.3", 23 | "@adonisjs/session": "^4.0.5", 24 | "mysql": "^2.18.1", 25 | "phc-argon2": "^1.0.10", 26 | "proxy-addr": "^2.0.6", 27 | "reflect-metadata": "^0.1.13", 28 | "source-map-support": "^0.5.19" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/providers/AppProvider.ts: -------------------------------------------------------------------------------- 1 | import { IocContract } from '@adonisjs/fold' 2 | 3 | export default class AppProvider { 4 | constructor (protected $container: IocContract) { 5 | } 6 | 7 | public register () { 8 | // Register your own bindings 9 | } 10 | 11 | public boot () { 12 | // IoC container is ready 13 | } 14 | 15 | public shutdown () { 16 | // Cleanup, since app is going down 17 | } 18 | 19 | public ready () { 20 | // App is ready 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /server/server.ts: -------------------------------------------------------------------------------- 1 | /* 2 | |-------------------------------------------------------------------------- 3 | | AdonisJs Server 4 | |-------------------------------------------------------------------------- 5 | | 6 | | The contents in this file is meant to bootstrap the AdonisJs application 7 | | and start the HTTP server to accept incoming connections. You must avoid 8 | | making this file dirty and instead make use of `lifecycle hooks` provided 9 | | by AdonisJs service providers for custom code. 10 | | 11 | */ 12 | 13 | import 'reflect-metadata' 14 | import sourceMapSupport from 'source-map-support' 15 | import { Ignitor } from '@adonisjs/core/build/src/Ignitor' 16 | 17 | sourceMapSupport.install({ handleUncaughtExceptions: false }) 18 | 19 | new Ignitor(__dirname) 20 | .httpServer() 21 | .start() 22 | .catch(console.error) 23 | -------------------------------------------------------------------------------- /server/start/kernel.ts: -------------------------------------------------------------------------------- 1 | /* 2 | |-------------------------------------------------------------------------- 3 | | Application middleware 4 | |-------------------------------------------------------------------------- 5 | | 6 | | This file is used to define middleware for HTTP requests. You can register 7 | | middleware as a `closure` or an IoC container binding. The bindings are 8 | | preferred, since they keep this file clean. 9 | | 10 | */ 11 | 12 | import Server from '@ioc:Adonis/Core/Server' 13 | 14 | /* 15 | |-------------------------------------------------------------------------- 16 | | Global middleware 17 | |-------------------------------------------------------------------------- 18 | | 19 | | An array of global middleware, that will be executed in the order they 20 | | are defined for all HTTP requests. 21 | | 22 | */ 23 | Server.middleware.register(['Adonis/Core/BodyParserMiddleware']) 24 | 25 | /* 26 | |-------------------------------------------------------------------------- 27 | | Named middleware 28 | |-------------------------------------------------------------------------- 29 | | 30 | | Named middleware are defined a key-value pair. The value is the namespace 31 | | or middleware function and key is the alias. Later you can use these 32 | | alias on individual routes. For example: 33 | | 34 | | { auth: 'Adonis/Auth/Middleware' } 35 | | 36 | | and then use it as follows 37 | | 38 | | Route.get('dashboard', 'UserController.dashboard').middleware('auth') 39 | | 40 | */ 41 | Server.middleware.registerNamed({ 42 | auth: 'App/Middleware/Auth' 43 | }) 44 | -------------------------------------------------------------------------------- /server/start/routes.ts: -------------------------------------------------------------------------------- 1 | /* 2 | |-------------------------------------------------------------------------- 3 | | Routes 4 | |-------------------------------------------------------------------------- 5 | | 6 | | This file is dedicated for defining HTTP routes. A single file is enough 7 | | for majority of projects, however you can define routes in different 8 | | files and just make sure to import them inside this file. For example 9 | | 10 | | Define routes in following two files 11 | | ├── start/routes/cart.ts 12 | | ├── start/routes/customer.ts 13 | | 14 | | and then import them inside `start/routes/index.ts` as follows 15 | | 16 | | import './cart' 17 | | import './customer' 18 | | 19 | */ 20 | 21 | import Route from '@ioc:Adonis/Core/Route' 22 | 23 | Route.group(() => { 24 | Route.resource('users', 'UsersController').apiOnly().middleware({}) 25 | Route.get('/authentication/user/me', 'AuthController.user').middleware('auth') 26 | 27 | Route.post('/authentication/api/login', 'AuthController.loginApi') 28 | Route.post('/authentication/api/logout', 'AuthController.logoutApi').middleware('auth') 29 | 30 | Route.post('/authentication/web/login', 'AuthController.loginWeb') 31 | Route.post('/authentication/web/logout', 'AuthController.logoutWeb').middleware('auth') 32 | 33 | Route.resource('cookies', 'CookiesController').apiOnly().only(['show', 'store']) 34 | }).prefix('/api') 35 | -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "**/*" 4 | ], 5 | "exclude": [ 6 | "node_modules", 7 | "build" 8 | ], 9 | "extends": "./node_modules/adonis-preset-ts/tsconfig", 10 | "compilerOptions": { 11 | "outDir": "build", 12 | "rootDir": "./", 13 | "sourceMap": true, 14 | "paths": { 15 | "App/*": [ 16 | "./app/*" 17 | ], 18 | "Contracts/*": [ 19 | "./contracts/*" 20 | ], 21 | "Database/*": [ 22 | "./database/*" 23 | ] 24 | }, 25 | "types": [ 26 | "@adonisjs/core", 27 | "@adonisjs/auth", 28 | "@adonisjs/lucid", 29 | "@adonisjs/session" 30 | ] 31 | } 32 | } --------------------------------------------------------------------------------
{{ $t('description') }}