├── .editorconfig ├── .eslintrc ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── commands └── MakePolicy.js ├── instructions.js ├── instructions.md ├── package-lock.json ├── package.json ├── providers └── GuardProvider.js ├── src ├── Exceptions │ └── index.js ├── Middleware │ ├── Can.js │ └── GuardInit.js └── ViewBindings │ ├── Can.js │ └── Cannot.js ├── templates ├── Policy.mustache └── acl.js └── test └── unit └── view.spec.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 2 8 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@slynova", 3 | "env": { 4 | "node": true 5 | }, 6 | "globals": { 7 | "use": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | .editorconfig 3 | .eslintrc 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # [1.0.0-beta.5](https://github.com/RomainLanz/adonis-guard/compare/1.0.0-beta.4...1.0.0-beta.5) (2018-09-11) 3 | 4 | 5 | ### Bug Fixes 6 | 7 | * **tag:** allow to have only one arg ([d44b585](https://github.com/RomainLanz/adonis-guard/commit/d44b585)) 8 | 9 | 10 | 11 | 12 | # [1.0.0-beta.4](https://github.com/RomainLanz/adonis-guard/compare/1.0.0-beta.3...1.0.0-beta.4) (2018-07-20) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * **exception:** invoke correctly the exception ([c26d297](https://github.com/RomainLanz/adonis-guard/commit/c26d297)) 18 | * **instructions:** replace this by cli ([e032d09](https://github.com/RomainLanz/adonis-guard/commit/e032d09)) 19 | * **monkey-patch:** sometimes it happens to do bad code ([ef0eec9](https://github.com/RomainLanz/adonis-guard/commit/ef0eec9)) 20 | 21 | 22 | ### Features 23 | 24 | * monkey patch [@slynova](https://github.com/slynova)/fence to fetch resource ([3614db1](https://github.com/RomainLanz/adonis-guard/commit/3614db1)) 25 | 26 | 27 | 28 | 29 | # [1.0.0-beta.3](https://github.com/RomainLanz/adonis-guard/compare/1.0.0-beta.2...1.0.0-beta.3) (2018-07-05) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * **middleware:** condition is now inversed ([ff908ba](https://github.com/RomainLanz/adonis-guard/commit/ff908ba)) 35 | 36 | 37 | 38 | 39 | # [1.0.0-beta.2](https://github.com/RomainLanz/adonis-guard/compare/1.0.0-beta.1...1.0.0-beta.2) (2018-07-05) 40 | 41 | 42 | ### Bug Fixes 43 | 44 | * **view:** corrects export statment of [@cannot](https://github.com/cannot) tag ([f68fc2c](https://github.com/RomainLanz/adonis-guard/commit/f68fc2c)) 45 | 46 | 47 | ### Features 48 | 49 | * **middleware:** add can middleware ([d9cafda](https://github.com/RomainLanz/adonis-guard/commit/d9cafda)) 50 | 51 | 52 | 53 | 54 | # 1.0.0-beta.1 (2018-07-05) 55 | 56 | 57 | ### Bug Fixes 58 | 59 | * **instructions:** copy the file to the correct place ([98dd5ec](https://github.com/RomainLanz/adonis-guard/commit/98dd5ec)) 60 | * **middleware:** auth.user is accessible on ctx ([5f31ca2](https://github.com/RomainLanz/adonis-guard/commit/5f31ca2)) 61 | * **Middleware:** remove wrong import ([2be31c4](https://github.com/RomainLanz/adonis-guard/commit/2be31c4)) 62 | * **Middleware:** Use view from the context ([bf57e6b](https://github.com/RomainLanz/adonis-guard/commit/bf57e6b)) 63 | * **view-global:** send directly Guard object ([9446a08](https://github.com/RomainLanz/adonis-guard/commit/9446a08)) 64 | 65 | 66 | ### Features 67 | 68 | * **view:** add cannot tag ([60974a7](https://github.com/RomainLanz/adonis-guard/commit/60974a7)) 69 | * **view:** add Guard global ([fa22088](https://github.com/RomainLanz/adonis-guard/commit/fa22088)) 70 | * **view:** implement [@can](https://github.com/can) tag ([6ec3a00](https://github.com/RomainLanz/adonis-guard/commit/6ec3a00)) 71 | * **view:** start working on can tag ([e9c6fe6](https://github.com/RomainLanz/adonis-guard/commit/e9c6fe6)) 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Slynova 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adonis Guard 🔰 2 | 3 | This package is an **authorization provider** built on top of [@slynova/fence](https://github.com/Slynova-Org/fence). 4 | 5 | ## Getting Started 6 | 7 | Install the package using the `adonis` CLI. 8 | 9 | ```bash 10 | > adonis install adonis-guard 11 | ``` 12 | 13 | Follow instruction that are displayed ([or read them here](https://github.com/RomainLanz/adonis-guard/blob/master/instructions.md)). 14 | 15 | ## Defining your authorization 16 | 17 | ### Gate 18 | Gates must be defined inside the `start/acl.js` file. This file will be loaded only once when the server is launch. 19 | To define a gate, use the `Gate` facade. 20 | 21 | ```js 22 | // start/acl.js 23 | const Gate = use('Gate') 24 | 25 | Gate.define('gateName', (user, resource) => { 26 | // Payload 27 | // e.g. return user.id === resource.author_id 28 | }) 29 | ``` 30 | 31 | ### Policy 32 | You can generate a new policy by using the command `adonis make:policy {name}`. 33 | This will generate a file in `app/Policies/{Name}Policy.js`. 34 | To attach a policy to a resource, you need to call the `policy` method of the `Gate` facade. 35 | 36 | ```js 37 | // start/acl.js 38 | const Gate = use('Gate') 39 | 40 | Gate.policy('App/Models/MyResource', 'App/Policies/MyPolicy') 41 | ``` 42 | 43 | ## Usage 44 | 45 | Adonis Guard automaticaly share an instance of the `guard` in the context of each request. 46 | To validate the authorization of a user you simply need to extract it from the context and run the gate/policy. 47 | 48 | ```js 49 | // Controller 50 | async show ({ guard, params }) { 51 | const post = await Post.find(params.id) 52 | 53 | if (guard.denies('show', post)) { 54 | // abort 401 55 | } 56 | 57 | // ... 58 | } 59 | ``` 60 | 61 | ```js 62 | // RouteValidator 63 | async authorize () { 64 | const post = await Post.find(this.ctx.params.id) 65 | 66 | if (this.ctx.guard.denies('show', post)) { 67 | // abort 401 68 | } 69 | 70 | // ... 71 | } 72 | ``` 73 | 74 | You can also use it in your view to choose to display or not an element. 75 | 76 | ```html 77 | @if(guard.allows('edit', post)) 78 | Edit 79 | @endif 80 | 81 | @can('edit', post) 82 | Edit 83 | @endcan 84 | 85 | @cannot('edit', post) 86 |

Not allowed!

87 | @endcannot 88 | ``` 89 | 90 | The `@can` and `@cannot` tags have the same signature as `guard.allows()` and `guard.denies()`. 91 | 92 | You can also use the middleware `can` in your route.
93 | Notice that this middleware doesn't work with resource. It will execute a gate with the loggedIn user only. 94 | 95 | ```js 96 | Route.get('/admin/posts', 'Admin/PostController.index') 97 | .middleware('can:viewAdminPosts') 98 | ``` 99 | 100 | A second argument can be supplied that will replace a resource in your gate. This is useful when you want to have dynamic route rules. 101 | 102 | ```js 103 | Route.get('/admin/posts', 'Admin/PostController.index') 104 | .middleware('can:hasRole,admin,editor') 105 | ``` 106 | 107 | `admin,editor` will be extracted into an array that you can retrieve as the second parameter in your gate. 108 | 109 | **Public API** 110 | 111 | ```js 112 | guard.allows('gateName/Policy Method', resource) // It will use per default the authenticated user or return false if not authenticated 113 | guard.denies('gateName/Policy Method', resource) // It will use per default the authenticated user or return true if not authenticated 114 | guard.allows('gateName/Policy Method', resource, user) 115 | guard.denies('gateName/Policy Method', resource, user) 116 | guard.can(user).pass('gateName').for(resource) 117 | guard.can(user).callPolicy('Policy Method', resource) 118 | ``` 119 | -------------------------------------------------------------------------------- /commands/MakePolicy.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const _ = require('lodash') 11 | const { singular } = require('pluralize') 12 | const { Command } = require('@adonisjs/ace') 13 | const { basename, join, sep } = require('path') 14 | 15 | class MakePolicy extends Command { 16 | /** 17 | * Command signature required by ace. 18 | * 19 | * @return {string} 20 | */ 21 | static get signature () { 22 | return 'make:policy { name: Name of the policy }' 23 | } 24 | 25 | /** 26 | * Command description. 27 | * 28 | * @return {string} 29 | */ 30 | static get description () { 31 | return 'Make a new Policy' 32 | } 33 | 34 | /** 35 | * Returns file name for policy. 36 | * 37 | * 38 | * @param {String} name 39 | * 40 | * @return {String} 41 | */ 42 | $getFileName (name) { 43 | name = name.replace(/policy/ig, '') 44 | 45 | return `${singular(_.upperFirst(_.camelCase(name)))}Policy` 46 | } 47 | 48 | /** 49 | * Returns path to the policy file 50 | * 51 | * @param {String} name 52 | * 53 | * @return {String} 54 | */ 55 | $getFilePath (name) { 56 | const baseName = basename(name) 57 | const normalizedName = name.replace(baseName, this.$getFileName(baseName)) 58 | 59 | return `${join(process.cwd(), 'app/Policies', normalizedName)}.js` 60 | } 61 | 62 | /** 63 | * Returns name of resource from policy name. 64 | * 65 | * @param {String} name 66 | * 67 | * @return {String} 68 | */ 69 | $getResourceName (name) { 70 | return this.$getFileName(name).replace('Policy', '').toLowerCase() 71 | } 72 | 73 | /** 74 | * Method called when command is executed. This method will 75 | * require all files from the migrations directory 76 | * and execute all pending schema files. 77 | * 78 | * @param {object} args 79 | * 80 | * @return {void} 81 | */ 82 | async handle ({ name }) { 83 | const templatePath = join(__dirname, '../templates/Policy.mustache') 84 | const filePath = this.$getFilePath(name) 85 | const templateContent = await this.readFile(templatePath, 'utf-8') 86 | 87 | await this.generateFile(filePath, templateContent, { 88 | name: this.$getFileName(name), 89 | resource: this.$getResourceName(name), 90 | }) 91 | 92 | const createdFile = filePath.replace(process.cwd(), '').replace(sep, '') 93 | 94 | // eslint-disable-next-line no-console 95 | console.log(`${this.icon('success')} ${this.chalk.green('create')} ${createdFile}`) 96 | } 97 | } 98 | 99 | module.exports = MakePolicy 100 | -------------------------------------------------------------------------------- /instructions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const { join } = require('path') 11 | 12 | module.exports = async function (cli) { 13 | await cli.copy(join(__dirname, 'templates/acl.js'), join(cli.helpers.appRoot(), 'start/acl.js')) 14 | .catch((e) => {}) 15 | cli.command.completed('create', 'start/acl.js') 16 | } 17 | -------------------------------------------------------------------------------- /instructions.md: -------------------------------------------------------------------------------- 1 | ## Registering provider 2 | 3 | The provider is registered inside `start/app.js` file under `providers` array. 4 | 5 | ```js 6 | const providers = [ 7 | 'adonis-guard/providers/GuardProvider' 8 | ] 9 | ``` 10 | 11 | ## Registering middleware 12 | 13 | Add the middleware `Adonis/Middleware/GuardInit` in the `start/kernel.js` file **after** `AuthInit`. 14 | Add the middleware `Adonis/Middleware/Can` in the `start/kernel.js` file in `namedMiddleware` array. 15 | 16 | ```js 17 | // start/kernel.js 18 | const globalMiddleware = [ 19 | ... 20 | 'Adonis/Middleware/AuthInit', 21 | 'Adonis/Middleware/GuardInit', 22 | ... 23 | ] 24 | 25 | const namedMiddleware = { 26 | ... 27 | can: 'Adonis/Middleware/Can', 28 | ... 29 | } 30 | ``` 31 | 32 | 33 | ## Loading acl.js 34 | 35 | Add the `start/acl.js` file to your Ignitor starting script. 36 | 37 | ```js 38 | // server.js 39 | 40 | new Ignitor(require('@adonisjs/fold')) 41 | .appRoot(__dirname) 42 | .preLoad('start/acl') 43 | .fireHttpServer() 44 | .catch(console.error) 45 | ``` 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adonis-guard", 3 | "version": "1.0.0-beta.5", 4 | "main": "index.js", 5 | "repository": "git@github.com:RomainLanz/adonis-guard.git", 6 | "author": "Romain Lanz ", 7 | "license": "MIT", 8 | "scripts": { 9 | "lint": "eslint src providers" 10 | }, 11 | "dependencies": { 12 | "@adonisjs/generic-exceptions": "^3.0.1", 13 | "@slynova/fence": "^1.0.6", 14 | "lodash": "^4.17.21", 15 | "pluralize": "^8.0.0" 16 | }, 17 | "devDependencies": { 18 | "@adonisjs/ace": "^5.0.8", 19 | "@adonisjs/fold": "^4.0.9", 20 | "@slynova/eslint-config": "^1.0.5", 21 | "cz-conventional-changelog": "^3.3.0", 22 | "edge.js": "^1.1.4", 23 | "eslint": "^7.20.0" 24 | }, 25 | "config": { 26 | "commitizen": { 27 | "path": "./node_modules/cz-conventional-changelog" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /providers/GuardProvider.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const { Gate, Helpers } = require('@slynova/fence') 11 | const { ServiceProvider } = require('@adonisjs/fold') 12 | 13 | class GuardProvider extends ServiceProvider { 14 | /** 15 | * Registers providers for all the Guard related 16 | * commands. 17 | * 18 | * @return {void} 19 | */ 20 | $registerCommands () { 21 | this.app.bind('Guard/Commands/Make:Policy', () => require('../commands/MakePolicy')) // eslint-disable-line global-require 22 | } 23 | 24 | /** 25 | * Registers providers for all the Guard related 26 | * classes. 27 | * 28 | * @return {void} 29 | */ 30 | $registerAlias () { 31 | this.app.singleton('Adonis/Addons/Gate', () => Gate) 32 | this.app.alias('Adonis/Addons/Gate', 'Gate') 33 | 34 | this.app.bind('Adonis/Middleware/Can', () => { 35 | const Can = require('../src/Middleware/Can') // eslint-disable-line global-require 36 | return new Can() 37 | }) 38 | 39 | this.app.bind('Adonis/Middleware/GuardInit', () => { 40 | const GuardInit = require('../src/Middleware/GuardInit') // eslint-disable-line global-require 41 | return new GuardInit() 42 | }) 43 | } 44 | 45 | $monkeyPatch () { 46 | Helpers.formatResourceName = (resource) => { 47 | return resource.$gate.namespace 48 | } 49 | 50 | Gate.policy = (resourceName, policyName) => { 51 | const resource = this.app.use(resourceName) 52 | resource.prototype.$gate = { namespace: resourceName } 53 | 54 | const policy = this.app.make(policyName) 55 | 56 | Gate.$getStorage().storePolicy(resourceName, policy) 57 | } 58 | } 59 | 60 | /** 61 | * Register namespaces to the IoC container 62 | * 63 | * @method register 64 | * 65 | * @return {void} 66 | */ 67 | register () { 68 | this.$registerCommands() 69 | this.$registerAlias() 70 | this.$monkeyPatch() 71 | } 72 | 73 | boot () { 74 | const ace = require('@adonisjs/ace') // eslint-disable-line global-require 75 | ace.addCommand('Guard/Commands/Make:Policy') 76 | 77 | this.app.with('Adonis/Src/View', (View) => { 78 | const Can = require('../src/ViewBindings/Can') 79 | const Cannot = require('../src/ViewBindings/Cannot') 80 | 81 | View.tag(new Can()) 82 | View.tag(new Cannot()) 83 | }) 84 | } 85 | } 86 | 87 | module.exports = GuardProvider 88 | -------------------------------------------------------------------------------- /src/Exceptions/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const { RuntimeException } = require('@adonisjs/generic-exceptions') 11 | 12 | class AuthorizationException extends RuntimeException {} 13 | 14 | module.exports = { AuthorizationException } 15 | -------------------------------------------------------------------------------- /src/Middleware/Can.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const { AuthorizationException } = require('../Exceptions') 11 | 12 | class Can { 13 | async handle ({ auth, guard }, next, [method, ...argument]) { 14 | if (!guard.can(auth.user).pass(method).for(argument)) { 15 | throw AuthorizationException.invoke('Unauthorized', 401, 'E_UNAUTHORIZED') 16 | } 17 | 18 | await next() 19 | } 20 | } 21 | 22 | module.exports = Can 23 | -------------------------------------------------------------------------------- /src/Middleware/GuardInit.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const { Guard } = require('@slynova/fence') 11 | 12 | class GuardInit { 13 | async handle (ctx, next) { 14 | const guard = Guard.setDefaultUser(ctx.auth.user || null) 15 | 16 | /** 17 | * Adding guard in the context 18 | */ 19 | ctx.guard = guard 20 | 21 | /** 22 | * Sharing guard with the view 23 | */ 24 | if (ctx.view && typeof (ctx.view.share) === 'function') { 25 | ctx.view.share({ guard }) 26 | } 27 | 28 | await next() 29 | } 30 | } 31 | 32 | module.exports = GuardInit 33 | -------------------------------------------------------------------------------- /src/ViewBindings/Can.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const { BaseTag } = require('edge.js') 11 | 12 | class Can extends BaseTag { 13 | /** 14 | * The tag name. 15 | * 16 | * @return {String} 17 | */ 18 | get tagName () { 19 | return 'can' 20 | } 21 | 22 | /** 23 | * Tag is a block tag. 24 | * 25 | * @return {Boolean} 26 | */ 27 | get isBlock () { 28 | return true 29 | } 30 | 31 | /** 32 | * Compile the template. 33 | * 34 | * @param {Object} compiler 35 | * @param {Object} lexer 36 | * @param {Object} buffer 37 | * @param {String} options.body 38 | * @param {Number} options.lineno 39 | * 40 | * @return {void} 41 | */ 42 | compile (compiler, lexer, buffer, { body, childs, lineno }) { 43 | const args = this._compileStatement(lexer, body, lineno).toStatement() 44 | const [ability, resource, user] = Array.isArray(args) ? args : [args] 45 | 46 | buffer.writeLine(`if (this.context.resolve('guard').allows(${ability}, ${resource}, ${user})) {`) 47 | buffer.indent() 48 | 49 | childs.forEach(child => compiler.parseLine(child)) 50 | 51 | buffer.dedent() 52 | buffer.writeLine('}') 53 | } 54 | 55 | run () { 56 | } 57 | } 58 | 59 | module.exports = Can 60 | -------------------------------------------------------------------------------- /src/ViewBindings/Cannot.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const { BaseTag } = require('edge.js') 11 | 12 | class Cannot extends BaseTag { 13 | /** 14 | * The tag name. 15 | * 16 | * @return {String} 17 | */ 18 | get tagName () { 19 | return 'cannot' 20 | } 21 | 22 | /** 23 | * Tag is a block tag. 24 | * 25 | * @return {Boolean} 26 | */ 27 | get isBlock () { 28 | return true 29 | } 30 | 31 | /** 32 | * Compile the template. 33 | * 34 | * @param {Object} compiler 35 | * @param {Object} lexer 36 | * @param {Object} buffer 37 | * @param {String} options.body 38 | * @param {Number} options.lineno 39 | * 40 | * @return {void} 41 | */ 42 | compile (compiler, lexer, buffer, { body, childs, lineno }) { 43 | const args = this._compileStatement(lexer, body, lineno).toStatement() 44 | const [ability, resource, user] = Array.isArray(args) ? args : [args] 45 | 46 | buffer.writeLine(`if (this.context.resolve('guard').denies(${ability}, ${resource}, ${user})) {`) 47 | buffer.indent() 48 | 49 | childs.forEach(child => compiler.parseLine(child)) 50 | 51 | buffer.dedent() 52 | buffer.writeLine('}') 53 | } 54 | 55 | run () { 56 | } 57 | } 58 | 59 | module.exports = Cannot 60 | -------------------------------------------------------------------------------- /templates/Policy.mustache: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | class {{name}} { 4 | index (user) { 5 | // 6 | } 7 | 8 | store (user) { 9 | // 10 | } 11 | 12 | show (user, {{resource}}) { 13 | // 14 | } 15 | 16 | create (user) { 17 | // 18 | } 19 | 20 | update (user, {{resource}}) { 21 | // 22 | } 23 | 24 | edit (user) { 25 | // 26 | } 27 | 28 | destroy (user, {{resource}}) { 29 | // 30 | } 31 | } 32 | 33 | module.exports = {{name}} 34 | -------------------------------------------------------------------------------- /templates/acl.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Gate = use('Gate') 4 | 5 | // 6 | -------------------------------------------------------------------------------- /test/unit/view.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * adonis-guard 5 | * 6 | * @license MIT 7 | * @copyright Slynova - Romain Lanz 8 | */ 9 | 10 | const test = require('japa') 11 | const edge = require('edge.js') 12 | 13 | class View { 14 | constructor () { 15 | this.engine = edge 16 | this.tag = this.engine.tag.bind(this.engine) 17 | } 18 | } 19 | 20 | 21 | --------------------------------------------------------------------------------