├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── docs ├── assets │ └── gatema.jpeg └── out │ ├── AllowOperations.html │ ├── AllowOperations.js.html │ ├── DisallowOperations.html │ ├── DisallowOperations.js.html │ ├── GateMan.html │ ├── GateMan.js.html │ ├── HasRolesAndClaims.html │ ├── HasRolesAndClaims.js.html │ ├── RoleOperations.html │ ├── RoleOperations.js.html │ ├── index.html │ ├── scripts │ ├── app.min.js │ └── linenumber.js │ └── styles │ ├── app.min.css │ ├── iframe.css │ ├── prettify-jsdoc.css │ ├── prettify-tomorrow.css │ └── reset.css ├── index.js ├── package-lock.json ├── package.json └── src ├── AllowOperations.js ├── DisallowOperations.js ├── GateMan.js ├── HasRolesAndClaims.js ├── Models ├── Claim.js ├── Role.js ├── RoleClaim.js ├── UserClaim.js └── UserRole.js ├── RoleOperations.js └── Tests ├── Gateman.spec.js └── HasRolesAndAbilities.spec.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at ibesoft11@gmail.com. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Gatemanjs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Gateman.js 4 | 5 | Gatemanjs is an authorization system designed to manage roles and claims in node applications that use mongodb for data storage. It works together with mongoose to provide a fluent approach to managing roles and claims. 6 | 7 | ## Installation 8 | 9 | You can install gateman using npm package manager. 10 | 11 | ``` 12 | npm install gatemanjs 13 | ``` 14 | 15 | ## Usage 16 | 17 | Before using gateman in your node application, you'll have to import the gateman package and setup the gateman class by passing in a valid mongoose connection object 18 | 19 | ``` 20 | var mongoose = require('mongoose'); 21 | var gateman = require("gatemanjs").GateMan(mongoose); 22 | ``` 23 | 24 | ### Creating roles & claims 25 | You have to create a role before using it in your application, Gateman provides an easy way of doing that. 26 | 27 | ``` 28 | //Syntax 29 | gateman.createRole(roleName); 30 | 31 | //Example 32 | let role = await gateman.createRole("rolename"); 33 | ``` 34 | Creating claims is similar to creating roles 35 | 36 | ``` 37 | //Syntax 38 | gateman.createClaim(claimName); 39 | 40 | //Example 41 | let role = await gateman.createRole("claimname"); 42 | ``` 43 | 44 | ##### Note: To get a collection of existing roles, you can use 45 | ``` 46 | //Syntax 47 | gateman.getRoles(callback); 48 | 49 | //Example 50 | let roles = await gateman.getRoles(); 51 | ``` 52 | 53 | ### Allowing members of a role to perform a claim 54 | Adding claims to roles is made extremely easy. You do not have to create a claim in advance. Simply pass the name of the claim, and Gateman will create it if it doesn't exist. 55 | 56 | ``` 57 | gateman.allow('role').to('claim'); //for an existing role 58 | ``` 59 | You can also assign a claim to a role immediately after creating it 60 | 61 | ``` 62 | let role = await gateman.createRole("admin"); 63 | await gateman.allow("admin").to("delete"); 64 | 65 | //this provides every member of the admin role the claim to delete 66 | ``` 67 | 68 | ### Disallowing members of a role from performing a claim 69 | Retracting claims from a role is very easy, you just need the rolename and claimname 70 | 71 | ``` 72 | await gateman.disallow('role').from('claim'); 73 | 74 | //Gateman does nothing if the role doesn't possess the claim 75 | ``` 76 | 77 | ### Checking for Role claims 78 | Checking if a Claim has been assigned to a Role can be done this way 79 | 80 | ``` 81 | let result = await gateman.role('rolename').can('claimname'); 82 | //result is true if the claim has been assigned, else it will be false 83 | 84 | ``` 85 | 86 | ### Using gateman with user models 87 | 88 | It is important to set up your User model to extend the HasRolesAndClaims class from the gateman package. 89 | 90 | ``` 91 | const mongoose = require('mongoose'); 92 | const hasRolesAndClaims = require('gatemanjs').hasRolesAndClaims(mongoose); 93 | 94 | var UserSchema = mongoose.Schema({ 95 | name: String, 96 | email: String 97 | }); 98 | 99 | UserSchema.loadClass(hasRolesAndClaims); 100 | module.exports = mongoose.model('User', UserSchema) 101 | ``` 102 | 103 | After setting up your user model, you can call gateman methods on your mongoose user model. 104 | 105 | ### Allowing users to perform a claim 106 | ``` 107 | //Example 108 | 109 | let user = await UserModel.findOne({name: "chioma"}); 110 | await user.allow("claim"); 111 | 112 | /* 113 | The Gateman hasRolesAndClaims class is loaded into a valid mongoose model which means that the methods are only accessible to valid user objects. 114 | */ 115 | 116 | //Disallowing a user from performing a claim 117 | 118 | let user = await UserModel.findOne({name: "chioma"}); 119 | await user.disallow("claim"); 120 | 121 | ``` 122 | 123 | ### Assigning a role to a user 124 | Before assigning a role to a user, make sure it has been created. 125 | ``` 126 | //Example 127 | 128 | let user = await UserModel.findOne({name: "chioma"}); 129 | await user.assign("role"); 130 | 131 | /* 132 | The Gateman hasRolesAndClaims class is loaded into a valid mongoose model which means that the methods are only accessible to valid user objects. 133 | */ 134 | 135 | //Retracting a role from a user 136 | 137 | let user = await UserModel.findOne({name: "chioma"}); 138 | await user.retract("role"); 139 | 140 | ``` 141 | 142 | ### Checking for User claims and Roles 143 | Gateman provides an easy way of verifying if a user belongs to a role or can perform a claim 144 | 145 | ``` 146 | //To verify if a User belongs to a Role 147 | 148 | let user = await User.findOne({name: "chioma"}); 149 | let userHasRole = await user.isA("role"); 150 | if (userHasRole){ 151 | //user belongs to role 152 | } 153 | 154 | //To verify if a User can perform a claim 155 | 156 | let user = await User.findOne({name: "chioma"}); 157 | let userHasClaim = await user.can("claim"); 158 | if (userHasClaim){ 159 | //user can perform claim 160 | } 161 | ``` 162 | 163 | ### Retrieving User Roles and Claims 164 | Gateman provides an easy way of retrieving a User's roles and/or claims 165 | 166 | ``` 167 | //Returns a collection of Roles assigned to a User 168 | 169 | let user = await User.findOne({name: "chioma"}); 170 | let roles = await user.getRolesForUser(); 171 | console.log(roles); 172 | 173 | //Returns a collection of Claims a User can perform 174 | 175 | let user = await User.findOne({name: "chioma"}, (err, user)=>{ 176 | let claims = await user.getClaimsForUser(); 177 | console.log(claims); 178 | ``` 179 | 180 | ## Documentation 181 | * [Usage](http://htmlpreview.github.com/?https://github.com/NwangwuOsitadinma/gateman/master/docs/out/index.html): Gateman methods 182 | 183 | 184 | ## Contributing 185 | 186 | Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. 187 | 188 | 189 | ## Authors 190 | 191 | * **Ositadinma Nwangwu** - [NwangwuOsitadinma](https://github.com/NwangwuOsitadinma) 192 | * **Ibe Ogele** - [Ibesoft11](https://github.com/Ibesoft11) 193 | 194 | ## License 195 | 196 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 197 | 198 | ## Acknowledgments 199 | * This project was inspired by Joseph Silber's [Bouncer](https://github.com/JosephSilber/bouncer) 200 | * Mongoose was used to build this 201 | -------------------------------------------------------------------------------- /docs/assets/gatema.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NwangwuOsitadinma/gateman/75bb7dcc9a2d3edf5e8417a136086628656d6d70/docs/assets/gatema.jpeg -------------------------------------------------------------------------------- /docs/out/AllowOperations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JSDoc: AllowOperations 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 43 |
44 |
45 |
46 |
47 |
48 | 63 |
64 |
65 |
66 |
67 |

Class

68 |

AllowOperations

69 |
70 | 71 |
72 | 73 |
74 | 75 |

AllowOperations()

77 |
78 | 79 |
80 |
81 |
82 |

Constructor

83 |
84 |
85 |

86 | # 87 | 88 | 89 | new AllowOperations() 91 | 92 |

93 |
94 | Contains methods for managing application roles and claims 95 |
96 |
97 |

98 | View Source 99 | 100 | AllowOperations.js, line 10 102 | 103 |

104 |
105 |
106 |
107 |
108 | 109 | 110 |
111 |
112 |

Methods

113 |
114 | 115 |
116 | 117 | 118 | 119 |

120 | # 121 | 122 | 123 | async 124 | 125 | 126 | 127 | 128 | to(claimName) 130 | 131 | 132 |

133 | 134 | 135 | 136 | 137 |
138 | pass in the claim to be assigned to a role 139 |
140 |
Parameters:
141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 155 | 156 | 159 | 160 | 161 | 162 |
NameTypeDescription
claimName 153 | String 154 | pass a claim as a string if you called 157 | allow 158 |
163 |
164 | 165 |

166 | View Source 167 | 168 | AllowOperations.js, line 24 170 | 171 |

172 |
Usage
173 |

174 |
await gateman.allow("rolename").to("claim");
175 |
176 |
177 | 178 |
179 |
180 |
181 | 182 |
183 | 184 |
185 |
186 |
187 |
188 | 189 | 190 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /docs/out/AllowOperations.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | JSDoc: AllowOperations.js 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 42 |
43 |
44 |
45 |
46 | 53 |
54 |
55 |
56 |

Source

57 |

AllowOperations.js

58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 |
var role, claim, roleClaim;
 68 | 
 69 | class AllowOperations {
 70 | 
 71 |     /**
 72 |      * Contains methods for managing application roles and claims
 73 |      * * Provide a valid mongoose connection object that will be used to store application credentials
 74 |      * @mongoose a mongoose connection object
 75 |      */
 76 |     constructor(rol, clm, roleClm){
 77 |         role = rol;
 78 |         claim = clm;
 79 |         roleClaim = roleClm;
 80 |     }
 81 | 
 82 |     /**
 83 |      * pass in the claim to be assigned to a role
 84 |      * @param claimName {String} pass a claim as a string if you called allow
 85 |      * #### Usage
 86 |      ```
 87 |      await gateman.allow("rolename").to("claim");
 88 |      ```
 89 |      */
 90 |     async to(claimName) {
 91 |         try {
 92 |             if (this.operation === 'allow') {
 93 |                 //find the role, allow was meant to do this
 94 |                 let dbRole = await role.findOne({ name: this.roler });
 95 |                 if (dbRole) {
 96 |                     //assign role here
 97 |                     let c = await claim.where('name', claimName).limit(1).exec();
 98 |                     if (c.length > 0) {
 99 |                         let rlclm = await roleClaim.findOne({ role: dbRole._id, claim: c[0]._id });
100 |                         if (rlclm) {
101 |                             return "Claim has already been assigned to Role";
102 |                         } else {
103 |                             await roleClaim.create({ role: dbRole._id, claim: c[0]._id });
104 |                             return;
105 |                         }
106 |                     } else {
107 |                         claim.create({ name: claimName }, (err, claimE) => {
108 |                             if (err) throw new Error(err);
109 |                             roleClaim.create({ role: dbRole._id, claim: claimE._id }, function (err, roleClaim) {
110 |                                 if (err) throw err;
111 |                                 return;
112 |                             });
113 |                         });
114 |                     }
115 |                 } else {
116 |                     throw new Error("role not found");
117 |                 }
118 |             }
119 |         } catch (error) {
120 |             throw error;
121 |         }
122 |     }
123 | 
124 | }
125 | module.exports = AllowOperations;
126 |
127 |
128 | 129 | 130 | 131 | 132 |
133 |
134 |
135 |
136 | 137 | 138 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /docs/out/DisallowOperations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JSDoc: DisallowOperations 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 43 |
44 |
45 |
46 |
47 |
48 | 63 |
64 |
65 |
66 |
67 |

Class

68 |

DisallowOperations

69 |
70 |
71 |
72 | 73 |

DisallowOperations()

75 | 76 |
77 | 78 |
79 |
80 | 81 |
82 |

Constructor

83 |
84 |
85 | 86 |

87 | # 88 | 89 | 90 | 91 | new DisallowOperations() 93 | 94 | 95 |

96 |
97 | Contains methods for managing application roles and claims 98 |
99 |
100 |

101 | View Source 102 | 103 | DisallowOperations.js, 104 | line 10 105 | 106 |

107 | 108 |
109 |
110 |
111 |
112 | 113 |
114 | 115 |
116 |

Methods

117 |
118 | 119 |
120 | 121 | 122 | 123 |

124 | # 125 | 126 | 127 | async 128 | 129 | from(claimName) 131 | 132 |

133 | 134 |
135 | pass in the claim to be retracted from a role 136 |
137 |
Parameters:
138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 159 | 160 | 161 | 162 |
NameTypeDescription
claimName 155 | 156 | String 157 | 158 | the claim to retract from a role
163 |
164 | 165 |

166 | View Source 167 | 168 | DisallowOperations.js, line 26 170 | 171 |

172 |
Usage
173 |

174 |
await gateman.disallow("rolename").from("claim");
175 |
176 | 177 |
178 | 179 |
180 |
181 | 182 |
183 | 184 |
185 | 186 |
187 |
188 |
189 |
190 | 191 | 192 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /docs/out/DisallowOperations.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | JSDoc: DisallowOperations.js 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 42 |
43 |
44 |
45 |
46 | 53 |
54 |
55 |
56 |

Source

57 |

DisallowOperations.js

58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 |
var role, claim, roleClaim;
 68 | 
 69 | class DisallowOperations {
 70 | 
 71 |     /**
 72 |      * Contains methods for managing application roles and claims
 73 |      * * Provide a valid mongoose connection object that will be used to store application credentials
 74 |      * @mongoose a mongoose connection object
 75 |      */
 76 |     constructor(rol, clm, roleClm){
 77 |         role = rol;
 78 |         claim = clm;
 79 |         roleClaim = roleClm;
 80 |     }
 81 | 
 82 |    
 83 |     /**
 84 |      * pass in the claim to be retracted from a role
 85 |      * @param claimName {String} the claim to retract from a role
 86 |      * #### Usage
 87 |      ```
 88 |      await gateman.disallow('rolename').from('claim')
 89 |      //Gateman does nothing if the role doesn't possess the claim
 90 |      ```
 91 |      */
 92 |     async from(claimName) {
 93 |         try {
 94 |             if (this.operation === 'dissallow') {
 95 |                 let dbRole = await role.findOne({ name: this.roler });
 96 |                 if (dbRole) {
 97 |                     let dbClaim = await claim.findOne({ name: claimName });
 98 |                     await roleClaim.findOneAndDelete({ role: dbRole, claim: dbClaim });
 99 |                     return;
100 |                 }
101 |             }
102 |         } catch (error) {
103 |             throw error;
104 |         }
105 |     }
106 | 
107 | }
108 | module.exports = DisallowOperations;
109 |
110 |
111 | 112 | 113 | 114 | 115 |
116 |
117 |
118 |
119 | 120 | 121 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /docs/out/GateMan.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | JSDoc: GateMan 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 40 |
41 |
42 |
43 |
44 | 51 |
52 |
53 |
54 |

Class

55 |

GateMan

56 |
57 | 58 | 59 | 60 | 61 | 62 | 63 |
64 | 65 |
66 | 67 |

GateMan()

68 | 69 | 70 |
71 | 72 |
73 |
74 | 75 | 76 |
77 |

Constructor

78 |
79 |
80 | 81 | 82 | 83 |

84 | # 85 | 86 | 87 | 88 | new GateMan() 89 | 90 | 91 |

92 | 93 |
94 | Contains methods for managing application roles and claims
95 | Provide a valid mongoose connection object that will be used to store application credentials 96 |
97 | 98 |
99 | 100 | 101 |

102 | View Source 103 | 104 | GateMan.js, line 15 105 | 106 |

107 | 108 |
109 | 110 |
111 |
112 |
113 | 114 | 115 |
116 | 117 |
118 |

Methods

119 |
120 | 121 |
122 | 123 |

124 | # 125 | 126 | 127 | 128 | allow(rolename) 129 | 130 | 131 |

132 | 133 |
134 | Allows members of a role to perform a claim 135 |
136 | 137 |
Parameters:
138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 159 | 160 | 161 | 162 | 163 |
NameTypeDescription
rolename 157 | String 158 | the rolename
164 | 165 |
166 | 167 |

168 | View Source 169 | 170 | GateMan.js, line 86 171 | 172 |

173 |
Usage
174 |

175 |
await gateman.allow("rolename").to("claim");
176 | 177 |
178 | 179 |
180 | 181 |
182 | 183 | 184 | 185 |

186 | # 187 | 188 | 189 | async 190 | 191 | 192 | 193 | 194 | createClaim(claimName) 195 | 196 | 197 |

198 |
199 | Creates a new claim 200 |
201 | 202 |
Parameters:
203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 |
NameTypeDescription
claimName 223 | 224 | String 225 | 226 | A string that represents the name of the claim
235 | 236 | 237 |
238 | 239 |

240 | View Source 241 | 242 | GateMan.js, line 138 243 | 244 |

245 |
Usage
246 |

await gateman.createClaim("claimname");
247 | 248 |
249 |
250 | 251 |
252 | 253 |

254 | # 255 | 256 | async 257 | 258 | 259 | 260 | 261 | createRole(roleName) 262 | 263 | 264 |

265 | 266 |
267 | creates a new gateman role and returns the role 268 |
269 | 270 |
Parameters:
271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 297 | 298 | 299 | 300 | 301 | 302 |
NameTypeDescription
roleName 292 | 293 | 294 | String 295 | 296 | A string that represents the name of the role to be created
303 | 304 |
305 | 306 |

307 | View Source 308 | 309 | GateMan.js, line 29 310 | 311 |

312 |
Usage
313 |

await gateman.createRole("rolename");
314 | 315 |
316 | 317 |
318 | 319 |
320 | 321 |

322 | # 323 | 324 | 325 | 326 | disallow(rolename) 327 | 328 | 329 |

330 | 331 |
332 | Dissallows a member of a role from performing a claim 333 |
334 |
Parameters:
335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 357 | 358 | 359 | 360 | 361 | 362 |
NameTypeDescription
rolename 353 | 354 | String 355 | 356 | the rolename
363 |
364 | 365 |

366 | View Source 367 | 368 | GateMan.js, line 104 369 | 370 |

371 |
Usage
372 |

await gateman.disallow("rolename").from("claim");
373 | 374 | 375 |
376 | 377 |
378 | 379 |
380 | 381 |

382 | # 383 | 384 | async 385 | 386 | 387 | 388 | getClaim(claimName) 389 | 390 | 391 |

392 |
393 | Returns one claim that matches the claimName given 394 |
395 |
Parameters:
396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 426 | 427 | 428 | 429 | 430 |
NameTypeDescription
claimName 419 | 420 | 421 | String 422 | 423 | 424 | 425 | The name of the claim to find
431 | 432 |
433 | 434 |

435 | View Source 436 | 437 | GateMan.js, line 186 438 | 439 |

440 |
Usage
441 |

let claim = await gateman.getClaim("claimname");
442 | 443 |
444 | 445 |
446 | 447 |
448 | 449 |

450 | # 451 | 452 | 453 | async 454 | 455 | 456 | 457 | 458 | getClaims() 459 | 460 | 461 |

462 | 463 | 464 | 465 | 466 |
467 | Returns all claims existing in the system 468 |
469 |
470 | 471 |

472 | View Source 473 | 474 | GateMan.js, line 174 475 | 476 |

477 |
Usage
478 |

let claims = await gateman.getClaims();
479 | 480 |
481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 |
503 | 504 |
505 | 506 | 507 | 508 |

509 | # 510 | 511 | 512 | async 513 | 514 | 515 | 516 | 517 | getRole(roleName) 518 | 519 | 520 |

521 | 522 |
523 | returns a gateman role specified by the name given 524 |
525 | 526 |
Parameters:
527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 556 | 557 | 558 | 559 | 560 | 561 |
NameTypeDescription
roleName 549 | 550 | 551 | String 552 | 553 | 554 | 555 | A string that represents the name of the role to be returned
562 | 563 |
564 |

565 | View Source 566 | 567 | GateMan.js, line 67 568 | 569 |

570 |
Usage
571 |

let result = await gateman.getRole("rolename");
572 | 573 |
574 | 575 |
576 | 577 |
578 | 579 |

580 | # 581 | 582 | 583 | async 584 | 585 | 586 | 587 | 588 | getRoleClaims(roleName) 589 | 590 | 591 |

592 | 593 |
594 | Returns an array of claims a role can perform 595 |
596 | 597 |
Parameters:
598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 626 | 627 | 628 | 629 | 630 | 631 |
NameTypeDescription
roleName 621 | 622 | 623 | String 624 | 625 | represents the name of the role
632 | 633 |
634 | 635 |

636 | View Source 637 | 638 | GateMan.js, line 198 639 | 640 |

641 |
Usage
642 |

let roleClaims = await gateman.getRoleClaims("rolename");
643 | 644 |
645 | 646 |
647 | 648 |
649 | 650 |

651 | # 652 | 653 | 654 | async 655 | 656 | 657 | 658 | 659 | getRoles() 660 | 661 | 662 |

663 | 664 |
665 | Returns existing roles in the system 666 |
667 | 668 |
669 | 670 |

671 | View Source 672 | 673 | GateMan.js, line 121 674 | 675 |

676 |
Usage
677 |

let roles = await gateman.getRoles();
678 | 679 |
680 |
681 | 682 |
683 | 684 |

685 | # 686 | async 687 | 688 | 689 | removeClaim(claimName) 690 | 691 | 692 |

693 |
694 | Deletes an existing claim 695 |
696 |
Parameters:
697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 720 | 721 | 722 | 723 | 724 | 725 |
NameTypeDescription
claimName 714 | 715 | String 716 | 717 | 718 | 719 | A string that represents the name of the claim to be deleted
726 | 727 |
728 |

729 | View Source 730 | 731 | GateMan.js, line 162 732 | 733 |

734 |
Usage
735 |

await gateman.removeClaim("claimname");
736 | 737 |
738 | 739 |
740 |
741 | 742 |

743 | # 744 | 745 | async 746 | 747 | 748 | 749 | removeRole(roleName) 750 | 751 | 752 |

753 | 754 |
755 | deletes an existing gateman role, does nothing if role does not exist 756 |
757 |
Parameters:
758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 781 | 782 | 783 | 784 | 785 |
NameTypeDescription
roleName 777 | 778 | String 779 | 780 | A string that represents the name of the role to be removed
786 |
787 |

788 | View Source 789 | 790 | GateMan.js, line 50 791 | 792 |

793 |
Usage
794 |

await gateman.removeRole("rolename");
795 | 796 |
797 | 798 |
799 |
800 | 801 |

802 | # 803 | 804 | 805 | 806 | role(roleName) 807 | 808 | 809 |

810 |
811 | Checks if a Role can perform a Claim, must be used with `can` 812 |
813 |
Parameters:
814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 839 | 840 | 841 | 842 | 843 | 844 |
NameTypeDescription
roleName 834 | 835 | 836 | String 837 | 838 | A string that represents the name of the role
845 | 846 |
847 | 848 |

849 | View Source 850 | 851 | GateMan.js, line 226 852 | 853 |

854 |
Usage
855 |

let result = await gateman.role("rolename").can("claim");
856 | 857 |
858 | 859 |
860 | 861 |
862 |
863 | 864 | 865 |
866 | 867 |
868 | 869 | 870 | 871 | 872 |
873 |
874 |
875 |
876 | 877 | 878 | 887 | 888 | 889 | 890 | 891 | 892 | -------------------------------------------------------------------------------- /docs/out/GateMan.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | JSDoc: GateMan.js 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 42 |
43 |
44 |
45 |
46 | 53 |
54 |
55 |
56 |

Source

57 |

GateMan.js

58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 |
var role = require('./Models/Role');
 68 | var claim = require('./Models/Claim');
 69 | var roleClaim = require('./Models/RoleClaim');
 70 | var allowOps = require('./AllowOperations');
 71 | var disallowOps = require('./DisallowOperations');
 72 | var roleOps = require('./RoleOperations');
 73 | 
 74 | class GateMan {
 75 | 
 76 |     /**
 77 |      * Contains methods for managing application roles and claims
 78 |      * * Provide a valid mongoose connection object that will be used to store application credentials
 79 |      * @mongoose a mongoose connection object
 80 |      */
 81 |     constructor(mongoose){
 82 |         role = role(mongoose);
 83 |         claim = claim(mongoose);
 84 |         roleClaim = roleClaim(mongoose);
 85 |     }
 86 | 
 87 |      /**
 88 |      * creates a new gateman role and returns the role
 89 |      * @param roleName {String} A string that represents the name of the role to be created
 90 |      * #### Usage
 91 |      ```
 92 |      let role = await gateman.createRole("rolename");
 93 |     ```
 94 |      */
 95 |     async createRole(roleName) {
 96 |         try {
 97 |             if (roleName.trim() === "") throw new Error("role name cannot be empty");
 98 |             if (typeof(roleName) !== 'string') throw new Error("role name must be a string");
 99 |             let dbRole = await role.findOne({ name: roleName });
100 |             if (dbRole) return dbRole;
101 |             let newDbRole = await role.create({ name: roleName });
102 |             return newDbRole;
103 |         } catch (error) {
104 |             throw error;
105 |         }
106 |     }
107 | 
108 |     /**
109 |      * deletes an existing gateman role, does nothing if role does not exist
110 |      * @param roleName {String} A string that represents the name of the role to be removed
111 |      * #### Usage
112 |      ```
113 |      gateman.removeRole("rolename");
114 |      ``` 
115 |      */
116 |     async removeRole(roleName){
117 |         try {
118 |             if (typeof(roleName) !== 'string') throw new Error('role name must be a string');
119 |             return await role.findOneAndDelete({name: roleName});
120 |         } catch (error) {
121 |             throw error;
122 |         }        
123 |     }
124 | 
125 |     /**
126 |      * returns a gateman role specified by the name given
127 |      * @param roleName {String} A string that represents the name of the role to be returned
128 |      * #### Usage
129 |      ```
130 |      let role = await gateman.getRole("rolename");
131 |      ```
132 |      */
133 |     async getRole(roleName){
134 |         try {
135 |             if (roleName.trim() === '') return {};
136 |             if (typeof(roleName) !== 'string') throw new Error('role name must be a string');
137 |             let rol = await role.findOne({name:roleName});
138 |             return rol;
139 |         } catch (error) {
140 |             throw error;
141 |         }
142 |     }
143 |     
144 |     /**
145 |      * Allows members of a role to perform a claim
146 |      * @param rolename {String} the rolename
147 |      * #### Usage
148 |      ```
149 |     await gateman.allow("rolename").to("claim");
150 |      ```
151 |      */
152 |     allow(rolename){
153 |         let linker = new allowOps(role, claim, roleClaim);
154 |         if (rolename.trim() === '') throw new Error('role name must be provided');
155 |         if (typeof(rolename) !== 'string') throw new Error('role name must be a string');
156 |         linker.operation = 'allow';
157 |         linker.roler = rolename;
158 |         return linker;
159 |     }
160 | 
161 |     /**
162 |      * Dissallows a member of a role from performing a claim
163 |      * @param rolename {String} the rolename
164 |      * #### Usage
165 |      ```
166 |      await gateman.disallow('rolename').from('claim');
167 |     //Gateman does nothing if the role doesn't possess the claim
168 |      ```
169 |      */
170 |     disallow(rolename){
171 |         let linker = new disallowOps(role, claim, roleClaim);
172 |         if (rolename.trim() === '') throw new Error('role name must be provided');
173 |         if (typeof(rolename) !== 'string') throw new Error('role name must be a string');
174 |         linker.operation = 'dissallow';
175 |         linker.roler = rolename;
176 |         return linker;
177 |     }
178 | 
179 |     /**
180 |      * Returns existing roles in the system
181 |      * #### Usage
182 |      ```
183 |     let roles = await gateman.getRoles();
184 |     console.log(roles); //prints collection of all existing roles
185 |      ```
186 |      */
187 |     async getRoles(){
188 |         try {
189 |             return role.find({});
190 |         } catch (error) {
191 |             throw error;
192 |         }
193 |     }
194 | 
195 |     /**
196 |      * Creates a new claim
197 |      * @param claimName {String} A string that represents the name of the claim
198 |      * #### Usage
199 |      ```
200 |      await gateman.createClaim("delete");
201 |      ```
202 |      * @returns Promise 
203 |      */
204 |     async createClaim(claimName) {
205 |         try {
206 |             if (claimName === "") return "claim name cannot be empty";
207 |             let dbClaim = await claim.findOne({ name: claimName });
208 |             if (dbClaim) {
209 |                 return dbClaim;
210 |             } else {
211 |                 let newDbClaim = await claim.create({ name: claimName });
212 |                 return newDbClaim;
213 |             }
214 |         } catch (error) {
215 |             throw error;
216 |         }
217 |     }
218 | 
219 | 
220 |     /**
221 |      * Deletes an existing claim 
222 |      * @param claimName {String} A string that represents the name of the claim to be deleted 
223 |      * #### Usage
224 |      ```
225 |      await gateman.removeClaim("claimname");
226 |      ``` 
227 |      */
228 |     async removeClaim(claimName){
229 |         return claim.findOneAndDelete({name: claimName});
230 |     }
231 | 
232 |     /**
233 |      * Returns all claims existing in the system
234 |      * #### Usage
235 |      ```
236 |      let claims = await gateman.getClaims();
237 |      //claims is a collection of existing claims
238 |      ```
239 |      */
240 |     async getClaims(){
241 |         return claim.find({});
242 |     }
243 | 
244 |     /**
245 |      * Returns one claim that matches the claimName given
246 |      * @param claimName {String} - The name of the claim to find
247 |      * #### Usage
248 |      ```
249 |      let claim = await gateman.getClaim();
250 |      ```
251 |      */
252 |     async getClaim(claimName){
253 |         return claim.findOne({name:claimName});
254 |     }
255 | 
256 |     /**
257 |      * Returns an array of claims a role can perform
258 |      * @param roleName {String} represents the name of the role
259 |      * #### Usage
260 |      ```
261 |      let roleClaims = await gateman.getRoleClaims("rolename");
262 |      ```
263 |      */
264 |     async getRoleClaims(roleName){
265 |         try {
266 |             let result = [];
267 |             let dbRole = await role.findOne({ name: roleName });
268 |             if (dbRole) {
269 |                 let roleClaims = await roleClaim.find({ role: dbRole._id }).populate('role claim');
270 |                 if (roleClaims.length === 0) return result;
271 |                 for (let i=0; i<roleClaims.length; i++){
272 |                     result.push(roleClaims[i].claim && roleClaims[i].claim.name);
273 |                     if (i === roleClaims.length - 1) return result;
274 |                 }
275 |             } else {
276 |                 throw new Error('role does not exist');
277 |             }
278 |         } catch (error) {
279 |             throw error;
280 |         }
281 |     }
282 | 
283 |     /**
284 |      * Checks if a Role can perform a Claim, must be used with `can`
285 |      * @param roleName {String} A string that represents the name of the role 
286 |      * #### Usage
287 |      ```
288 |      let result = await gateman.role('rolename').can('claimname');
289 |      //should be true if role has the claim
290 |      ```
291 |      */
292 |     role(roleName){
293 |         let linker = new roleOps(role, claim, roleClaim);
294 |         if (roleName.trim() === '') throw new Error('role name must be provided');
295 |         if (typeof(roleName) !== 'string') throw new Error('role name must be a string');
296 |         linker.roleName = roleName;
297 |         return linker;
298 |     }
299 | 
300 | }
301 | 
302 | module.exports = GateMan;
303 |
304 |
305 | 306 | 307 | 308 | 309 |
310 |
311 |
312 |
313 | 314 | 315 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | -------------------------------------------------------------------------------- /docs/out/HasRolesAndClaims.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | JSDoc: HasRolesAndClaims 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 40 |
41 |
42 |
43 |
44 | 51 |
52 |
53 |
54 |

Class

55 |

HasRolesAndClaims

56 |
57 | 58 |
59 | 60 |
61 | 62 |

HasRolesAndClaims(mongoose)

63 | 64 |
65 | 66 |
67 |
68 | 69 | 70 |
71 |

Constructor

72 |
73 |
74 | 75 |

76 | # 77 | 78 | 79 | 80 | new HasRolesAndClaims(mongoose) 81 | 82 | 83 |

84 | 85 |
86 | Provide a valid mongoose connection object that will be used to store application credentials 87 |
88 | 89 |
Parameters:
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 | 115 |
NameTypeDescription
mongoose 108 | 109 | A mongoose connection object
116 | 117 |
118 |

119 | View Source 120 | 121 | HasRolesAndClaims.js, line 13 122 | 123 |

124 | 125 |
126 | 127 |
128 |
129 |
130 | 131 | 132 |
133 | 134 |
135 |

Methods

136 |
137 | 138 |
139 | 140 |

141 | # 142 | 143 | async 144 | 145 | 146 | 147 | allow(claimName) 148 | 149 | 150 |

151 | 152 |
153 | allows a user perform a claim, does nothing if user already has the claim 154 |
155 | 156 |
Parameters:
157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 181 | 182 | 183 | 184 | 185 | 186 |
NameTypeDescription
claimName 177 | 178 | String 179 | 180 | represents the claim you want to assign to a user
187 | 188 |
189 | 190 |

191 | View Source 192 | 193 | HasRolesAndClaims.js, line 31 194 | 195 |

196 |
Usage
197 |

let user = await UserModel.findOne({name: "chioma"});
198 |         
await UserModel.allow("claimname"});
199 | 200 |
201 | 202 |
203 |
204 | 205 |

206 | # 207 | 208 | async 209 | 210 | 211 | 212 | assign(roleName) 213 | 214 | 215 |

216 | 217 |
218 | assigns a role to a user directly 219 |
220 | 221 |
Parameters:
222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 246 | 247 | 248 | 249 | 250 | 251 |
NameTypeDescription
roleName 242 | 243 | string 244 | 245 | represents the role you want to assign to a user
252 | 253 |
254 | 255 |

256 | View Source 257 | 258 | HasRolesAndClaims.js, line 90 259 | 260 |

261 |
Usage
262 |

let user = await UserModel.findOne({name: "chioma"});
await user.assign("rolename");
263 | 264 |
265 | 266 |
267 | 268 |
269 | 270 |

271 | # 272 | 273 | 274 | async 275 | 276 | 277 | 278 | 279 | can(claimName) 280 | 281 | 282 |

283 | 284 |
285 | checks whether a user has the ability to perform a claim 286 |
287 | 288 |
Parameters:
289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 315 | 316 | 317 | 318 | 319 | 320 |
NameTypeDescription
claimName 311 | 312 | string 313 | 314 | represents the claim name
321 | 322 |
323 | 324 |

325 | View Source 326 | 327 | HasRolesAndClaims.js, line 153 328 | 329 |

330 |
Usage
331 |

let user = await UserModel.findOne({name: "chioma"});
332 |         
let userHasClaim = await user.can("claim"); 333 |
if (userHasClaim) { 334 | console.log("I have the claim");
}
335 |
336 | 337 |
338 | 339 |
340 |

341 | # 342 | async 343 | 344 | 345 | cannot(claimName) 346 | 347 | 348 |

349 |
350 | checks whether a user does not have the ability to perform a claim 351 |
352 |
Parameters:
353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 378 | 379 | 380 | 381 | 382 | 383 |
NameTypeDescription
claimName 374 | 375 | string 376 | 377 | represents the claim name
384 | 385 |
386 | 387 |

388 | View Source 389 | 390 | HasRolesAndClaims.js, line 192 391 | 392 |

393 |
Usage
394 |

let user = await UserModel.findOne({name: "chioma"});
395 |         
let noClaim = await user.cannot("claim"); 396 |
if (noClaim) { 397 | console.log("I do not have the claim");
}
398 | 399 | 400 |
401 | 402 |
403 | 404 |
405 | 406 | 407 | 408 |

409 | # 410 | 411 | 412 | async 413 | 414 | 415 | 416 | 417 | disallow(claimName) 418 | 419 | 420 |

421 | 422 |
423 | disallows a user from performing a particular claim 424 |
425 | 426 |
Parameters:
427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 453 | 454 | 460 | 461 | 462 | 463 |
NameTypeDescription
claimName 449 | 450 | string 451 | 452 | represents the claim you want to retract from a user 455 | #### Usage 456 | ``` 457 | let user = await UserModel.findOne({name: "chioma"}); 458 | await user.disallow("claim"); 459 | ```
464 | 465 |
466 | 467 |

468 | View Source 469 | 470 | HasRolesAndClaims.js, line 59 471 | 472 |

473 |
Usage
474 |

let user = await UserModel.findOne({name: "chioma"});
await user.dissallow("claim");
475 | 476 |
477 | 478 |
479 | 480 |
481 | 482 |

483 | # 484 | 485 | 486 | async 487 | 488 | 489 | 490 | 491 | getClaimsForUser() 492 | 493 | 494 |

495 | 496 | 497 |
498 | Returns a collection of Claims a User can perform 499 |
500 | 501 |
502 |

503 | View Source 504 | 505 | HasRolesAndClaims.js, line 347 506 | 507 |

508 |
Usage
509 |

let user = await UserModel.findOne({name: "chioma"});
let claims = await user.getClaimsForUser();
510 | 511 |
512 | 513 |
514 | 515 |
516 | 517 |

518 | # 519 | 520 | 521 | async 522 | 523 | 524 | 525 | 526 | getRolesForUser() 527 | 528 | 529 |

530 | 531 |
532 | Returns a collection of Roles assigned to a User 533 |
534 | 535 |
536 | 537 |

538 | View Source 539 | 540 | HasRolesAndClaims.js, line 312 541 | 542 |

543 |
Usage
544 |

let user = await UserModel.findOne({name: "chioma"});
let roles = await user.getRolesForUser();
545 | 546 |
547 | 548 |
549 | 550 |
551 | 552 | 553 | 554 |

555 | # 556 | 557 | 558 | async 559 | 560 | 561 | 562 | 563 | isA(roleName) 564 | 565 | 566 |

567 | 568 |
569 | checks if a user is a member of a role 570 |
571 | 572 |
Parameters:
573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 597 | 598 | 599 | 600 | 601 | 602 |
NameTypeDescription
roleName 593 | 594 | string 595 | 596 | represents the role name
603 | 604 |
605 | 606 |

607 | View Source 608 | 609 | HasRolesAndClaims.js, line 231 610 | 611 |

612 |
Usage
613 |

let user = await UserModel.findOne({name: "chioma"});
614 |         
let userHasRole = await user.isA("role"); 615 |
if (userHasRole) { 616 | console.log("User belongs to role");
}
617 | 618 |
619 | 620 |
621 | 622 |
623 | 624 |

625 | # 626 | 627 | 628 | async 629 | 630 | 631 | 632 | 633 | isAn(roleName) 634 | 635 | 636 |

637 | 638 | 639 |
640 | checks if a user is a member of a role 641 |
642 | 643 |
Parameters:
644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 669 | 670 | 671 | 672 | 673 | 674 |
NameTypeDescription
roleName 665 | 666 | string 667 | 668 | representing the role name
675 | 676 |
677 | 678 |

679 | View Source 680 | 681 | HasRolesAndClaims.js, line 257 682 | 683 |

684 |
Usage
685 |

let user = await UserModel.findOne({name: "chioma"});
686 |         
let userHasRole = await user.isAn("role"); 687 |
if (userHasRole) { 688 | console.log("User belongs to role");
}
689 | 690 |
691 | 692 |
693 | 694 |
695 | 696 |

697 | # 698 | 699 | 700 | async 701 | 702 | 703 | 704 | 705 | isNotA(roleName) 706 | 707 | 708 |

709 | 710 |
711 | checks if a user is not a member of a role 712 |
713 | 714 |
Parameters:
715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 741 | 742 | 743 | 744 | 745 | 746 |
NameTypeDescription
roleName 736 | 737 | 738 | string 739 | 740 | represents the role name
747 | 748 |
749 | 750 |

751 | View Source 752 | 753 | HasRolesAndClaims.js, line 273 754 | 755 |

756 |
Usage
757 |

let user = await UserModel.findOne({name: "chioma"});
758 |         
let result = await user.isNotA("role"); 759 |
if (result) { 760 | console.log("User does not belong to role");
}
761 | 762 |
763 | 764 |
765 | 766 |
767 | 768 |

769 | # 770 | 771 | async 772 | 773 | 774 | 775 | isNotAn(roleName) 776 | 777 | 778 |

779 | 780 |
781 | checks if a user is not a member of a role 782 |
783 | 784 |
Parameters:
785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 809 | 810 | 819 | 820 | 821 | 822 |
NameTypeDescription
roleName 805 | 806 | string 807 | 808 | represents the role name 811 | #### Usage 812 | ``` 813 | let user = await User.findOne({name: "chioma"}); 814 | let result = await user.isNotAn("role"); 815 | if (result){ 816 | //user does not belongs to role 817 | } 818 | ```
823 | 824 |
825 | 826 |

827 | View Source 828 | 829 | HasRolesAndClaims.js, line 299 830 | 831 |

832 |
Usage
833 |

let user = await UserModel.findOne({name: "chioma"});
834 |         
let result = await user.isNotAn("role"); 835 |
if (result) { 836 | console.log("User does not belong to role");
}
837 | 838 |
839 | 840 | 841 |
842 | 843 |
844 | 845 | 846 | 847 |

848 | # 849 | 850 | 851 | async 852 | 853 | 854 | 855 | 856 | retract(roleName) 857 | 858 | 859 |

860 | 861 | 862 |
863 | retracts a role from a user directly 864 |
865 | 866 |
Parameters:
867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 895 | 896 | 897 | 898 | 899 | 900 |
NameTypeDescription
roleName 890 | 891 | 892 | string 893 | 894 | represents the role you want to retract from the user
901 | 902 |
903 | 904 |

905 | View Source 906 | 907 | HasRolesAndClaims.js, line 120 908 | 909 |

910 |
Usage
911 |

let user = await UserModel.findOne({name: "chioma"});
await user.retract("role");
912 |
913 | 914 |
915 | 916 |
917 |
918 | 919 |
920 | 921 |
922 | 923 |
924 |
925 |
926 |
927 | 928 | 929 | 938 | 939 | 940 | 941 | 942 | 943 | -------------------------------------------------------------------------------- /docs/out/HasRolesAndClaims.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | JSDoc: HasRolesAndClaims.js 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 42 |
43 |
44 |
45 |
46 | 53 |
54 |
55 |
56 |

Source

57 |

HasRolesAndClaims.js

58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 |
var userClaim = require('./Models/UserClaim');
 68 | var userRole = require('./Models/UserRole');
 69 | var role = require('./Models/Role');
 70 | var roleClaim = require('./Models/RoleClaim');
 71 | var claim = require('./Models/Claim');
 72 | 
 73 | class HasRolesAndClaims {
 74 |     /**
 75 |      * Provide a valid mongoose connection object that will be used to store application credentials
 76 |      * @constructor
 77 |      * @param mongoose A mongoose connection object
 78 |      */
 79 |     constructor(mongoose) {
 80 |         userClaim = userClaim(mongoose);
 81 |         userRole = userRole(mongoose);
 82 |         role = role(mongoose);
 83 |         claim = claim(mongoose);
 84 |         roleClaim = roleClaim(mongoose);
 85 |     }
 86 | 
 87 |     /**
 88 |      * allows a user perform a claim, does nothing if user already has the claim
 89 |      * @param claimName {String} represents the claim  you want to assign to a user
 90 |      * #### Usage
 91 |      ```
 92 |      let user = await UserModel.findOne({name: "chioma"});
 93 |      await user.allow("claim");
 94 |      ```
 95 |      */
 96 | 
 97 |     async allow(claimName) {
 98 |         try {
 99 |             let dbClaim = await claim.findOne({ name: claimName });
100 |             if (dbClaim) {
101 |                 let uc = await userClaim.findOne({ user: this._id, claim: dbClaim._id });
102 |                 if (uc) {
103 |                     return "this claim was already assigned to the user";
104 |                 } else {
105 |                     let usrClaim = await userClaim.create({ user: this._id, claim: dbClaim._id });
106 |                     return usrClaim;
107 |                 }
108 |             } else {
109 |                 throw new Error("The claim does not exist. Consider creating it first");
110 |             }
111 |         } catch (error) {
112 |             throw error;
113 |         }
114 |     }
115 | 
116 |     /**
117 |      * disallows a user from performing a particular claim
118 |      * @param claimName {string} represents the claim you want to retract from a user
119 |      * #### Usage
120 |      ```
121 |      let user = await UserModel.findOne({name: "chioma"});
122 |      await user.disallow("claim");
123 |      ```
124 |      */
125 |     async disallow(claimName) {
126 |         try {
127 |             let dbClaim = await claim.findOne({ name: claimName });
128 |             if (dbClaim) {
129 |                 let uc = await userClaim.findOne({ user: this._id, claim: dbClaim._id });
130 |                 if (uc) {
131 |                     await userClaim.findOneAndDelete({ user: this._id, claim: dbClaim._id });
132 |                     return;
133 |                 } else {
134 |                     return "this claim was not assigned to the user";
135 |                 }
136 |             } else {
137 |                 throw new Error({
138 |                     message: "The claim does not exist. Consider creating it first"
139 |                 });
140 |             }
141 |         } catch (error) {
142 |             throw error;
143 |         }
144 |     }
145 | 
146 |     /**
147 |      * assigns a role to a user directly
148 |      * @param roleName {string} represents the role you want to assign to a user
149 |      * #### Usage
150 |      ```
151 |      let user = await UserModel.findOne({name: "chioma"});
152 |      await user.assign("role");
153 |      ```
154 |      */
155 | 
156 |     async assign(roleName) {
157 |         try {
158 |             let dbRole = await role.findOne({ name: roleName });
159 |             if (dbRole) {
160 |                 let rc = await userRole.findOne({ user: this._id, role: dbRole._id });
161 |                 if (rc) {
162 |                     return "this role was already assigned to the user";
163 |                 } else {
164 |                     let usrRole = await userRole.create({ user: this._id, role: dbRole._id });
165 |                     return usrRole;
166 |                 }
167 |             } else {
168 |                 throw new Error({
169 |                     message: "The role does not exist. Consider creating it first"
170 |                 });
171 |             }
172 |         } catch (error) {
173 |             throw error;
174 |         }
175 |     }
176 | 
177 |     /**
178 |      * retracts a role from a user directly
179 |      * @param roleName {string} represents the role you want to retract from the user 
180 |      * #### Usage
181 |      ```
182 |      let user = await UserModel.findOne({name: "chioma"});
183 |      await user.retract("role");
184 |      ```
185 |      */
186 |     async retract(roleName) {
187 |         try {
188 |             let dbRole = await role.findOne({ name: roleName });
189 |             if (dbRole) {
190 |                 let rc = await userRole.findOne({ user: this._id, role: dbRole._id });
191 |                 if (rc) {
192 |                     await userRole.findOneAndDelete({ user: this._id, role: dbRole._id });
193 |                     return;
194 |                 } else {
195 |                     return "this role was not assigned to the user";
196 |                 }
197 |             } else {
198 |                 throw new Error({
199 |                     message: "The role does not exist. Consider creating it first"
200 |                 });
201 |             }
202 |         } catch (error) {
203 |             throw error;
204 |         }
205 |     }
206 | 
207 |     /**
208 |      * checks whether a user has the ability to perform a claim
209 |      * @param claimName {string} represents the claim name 
210 |      * #### Usage
211 |      ```
212 |      let user = await User.findOne({name: "chioma"});
213 |      let userHasClaim = await user.can("claim");
214 |      if (userHasClaim) {
215 |         console.log('I have the claim');
216 |      }
217 |      ```
218 |      */
219 |     async can(claimName) {
220 |         try {
221 |             let c = await claim.findOne({ name: claimName });
222 |             if (c) {
223 |                 let ur = await userRole.find({ user: this._id });
224 |                 if (ur.length > 0) {
225 |                     for (let u of ur){
226 |                         let rc = await roleClaim.findOne({ role: u.role, claim: c._id });
227 |                         if (rc) {
228 |                             return true;
229 |                         } else {
230 |                             let uc = await userClaim.findOne({ user: u.user, claim: c._id });
231 |                             return uc ? true : false;
232 |                         }
233 |                     }
234 |                 } else {
235 |                     let uc = await userClaim.findOne({ user: this._id, claim: c._id });
236 |                     return uc ? true : false;
237 |                 }
238 |             } else {
239 |                 throw new Error("Error, claim does not exist");
240 |             }
241 |         } catch (error) {
242 |             throw error;
243 |         }
244 |     }
245 | 
246 |     /**
247 |      * checks whether a user does not have the ability to perform a claim
248 |      * @param claimName {string} represents the claim name
249 |      * #### Usage
250 |      ```
251 |       let user = await User.findOne({name: "chioma"});
252 |       let noClaim = await user.cannot("claim");
253 |       if (noClaim){
254 |           console.log('I do not have the claim');
255 |       }
256 |      ```
257 |      */
258 |     async cannot(claimName) {
259 |         try {
260 |             let c = await claim.findOne({ name: claimName });
261 |             if (c) {
262 |                 let urs = await userRole.find({ user: this._id });
263 |                 if (urs.length > 0) {
264 |                     urs.forEach(async (ur) => {
265 |                         let rc = await roleClaim.findOne({ role: ur.role, claim: c._id });
266 |                         if (rc) {
267 |                             return false;
268 |                         } else {
269 |                             let uc = await userClaim.findOne({ user: ur.user, claim: c._id });
270 |                             return uc ? false : true;
271 |                         }
272 |                     });
273 |                 } else {
274 |                     let uc = await userClaim.findOne({ user: this._id, claim: c._id });
275 |                     return uc ? false : true;
276 |                 }
277 |             } else {
278 |                 throw new Error("Error, user or claim does not exist");
279 |             }
280 |         } catch (error) {
281 |             throw error;
282 |         }
283 |     }
284 | 
285 |     /**
286 |      * checks if a user is a member of a role
287 |      * @param roleName {string} represents the role name
288 |      * #### Usage
289 |      ```
290 |      let user = await User.findOne({name: "chioma"});
291 |      let userHasRole = await user.isA("role");
292 |      if (userHasRole){
293 |         //user belongs to role
294 |       }
295 |      ```
296 |      */
297 |     async isA(roleName) {
298 |         try {
299 |             let r = await role.findOne({ name: roleName });
300 |             if (r) {
301 |                 let ur = await userRole.findOne({ user: this._id, role: r._id });
302 |                 return ur ? true : false;
303 |             } else {
304 |                 throw new Error("Error, role does not exist");
305 |             }
306 |         } catch (error) {
307 |             throw error;
308 |         }
309 |     }
310 | 
311 |     /**
312 |      * checks if a user is a member of a role
313 |      * @param roleName {string} representing the role name
314 |      * #### Usage
315 |      ```
316 |      let user = await User.findOne({name: "chioma"});
317 |      let userHasRole = await user.isAn("role");
318 |      if (userHasRole){
319 |         //user belongs to role
320 |      }
321 |      ```
322 |      */
323 |     async isAn(roleName) {
324 |         return await this.isA(roleName);
325 |     }
326 | 
327 |     /**
328 |      * checks if a user is not a member of a role
329 |      * @param roleName {string} represents the role name 
330 |      * #### Usage
331 |      ```
332 |      let user = await User.findOne({name: "chioma"});
333 |      let result = await user.isNotA("role");
334 |      if (result){
335 |         //user does not belongs to role
336 |      }
337 |      ```
338 |     */
339 |     async isNotA(roleName) {
340 |         try {
341 |             let r = await role.findOne({ name: roleName });
342 |             if (r) {
343 |                 let ur = await userRole.findOne({ user: this._id, role: r._id });
344 |                 return ur ? false : true;
345 |             } else {
346 |                 throw new Error("Error, user or role does not exist");
347 |             }
348 |         } catch (error) {
349 |             throw error;
350 |         }
351 |     }
352 | 
353 |     /**
354 |      * checks if a user is not a member of a role
355 |      * @param roleName {string} represents the role name
356 |      * #### Usage
357 |      ```
358 |      let user = await User.findOne({name: "chioma"});
359 |      let result = await user.isNotAn("role");
360 |      if (result){
361 |         //user does not belongs to role
362 |      }
363 |      ``` 
364 |     */
365 |     async isNotAn(roleName) {
366 |         return await this.isNotA(roleName);
367 |     }
368 | 
369 |     /**
370 |      * Returns a collection of Roles assigned to a User
371 |      * #### Usage
372 |      ```
373 |      let user = await User.findOne({name: "chioma"}, (err, user)=>{
374 |      let roles = await user.getRolesForUser();
375 |      console.log(roles);
376 |      ```
377 |      */
378 |     async getRolesForUser() {
379 |         try {
380 |             var result = [];
381 |             let roles = await userRole.find({ user: this._id });
382 |             if (roles.length < 1) {
383 |                 return result;
384 |             } else {
385 |                 for (var item of roles) {
386 |                     let roler = await role.find({_id: item.role});
387 |                     if (roler.length > 0){
388 |                         result.push(roler[0].name)
389 |                     } else {
390 |                         return result;
391 |                     }
392 |                     if (roles[roles.length - 1] == item) {
393 |                         //return only when you've added every role
394 |                         //Node is non-blocking, so the engine will return an empty array if resolve(code) is place outside the for-loop
395 |                         return result;
396 |                     }
397 |                 }
398 |             }
399 |         } catch (error) {
400 |             throw error;
401 |         }
402 |     }
403 | 
404 |     /**
405 |      * Returns a collection of Claims a User can perform
406 |      * #### Usage
407 |      ```
408 |      let user = await User.findOne({name: "chioma"});
409 |      let claims = await user.getClaimsForUser();
410 |      console.log(claims);
411 |      ```
412 |      */
413 |     async getClaimsForUser() {
414 |         try {
415 |             var result = [];
416 |             let userRoles = await userRole.find({ user: this._id });
417 |             if (userRoles.length >= 1) {
418 |                 for (let userRole of userRoles) {
419 |                     let roleClaims = await roleClaim.find({ role: userRole.role });
420 |                     if (roleClaims.length >= 1) {
421 |                         for (var item of roleClaims) {
422 |                             let roleClm = await claim.findOne({_id: item.claim});
423 |                             result.push(roleClm.name);
424 |                             if (roleClaims[roleClaims.length - 1] == item) {
425 |                                 let userClaims = await userClaim.find({ user: this._id });
426 |                                 if (userClaims.length >= 1) {
427 |                                     for (var item of userClaims) {
428 |                                         let roleClm = await claim.findOne({_id: item.claim});
429 |                                         result.push(roleClm.name);
430 |                                         if (userClaims[userClaims.length - 1] == item) {
431 |                                             return result.filter(this.onlyUnique);
432 |                                         }
433 |                                     }
434 |                                 } else {
435 |                                     return result.filter(this.onlyUnique);
436 |                                 }
437 |                             }
438 |                         }
439 |                     } else {
440 |                         let userClaims = await userClaim.find({ user: this._id });
441 |                         if (userClaims.length >= 1) {
442 |                             for (var item of userClaims) {
443 |                                 let roleClm = await claim.findOne({_id: item.claim});
444 |                                 result.push(roleClm.name);
445 |                                 if (userClaims[userClaims.length - 1] == item) {
446 |                                     return result.filter(this.onlyUnique);
447 |                                 }
448 |                             }
449 |                         }
450 |                     }
451 |                 }
452 |             } else {
453 |                 let userClaims = await userClaim.find({ user: this._id });
454 |                 if (userClaims.length >= 1) {
455 |                     for (var item of userClaims) {
456 |                         let roleClm = await claim.findOne({_id: item.claim});
457 |                         result.push(roleClm.name);
458 |                         if (userClaims[userClaims.length - 1] == item) {
459 |                             return result.filter(this.onlyUnique);
460 |                         }
461 |                     }
462 |                 } else {
463 |                     return result.filter(this.onlyUnique);
464 |                 }
465 |             }
466 |         } catch (error) {
467 |             throw error;
468 |         }
469 | 
470 |     }
471 | 
472 |     onlyUnique(value, index, self) {
473 |         return self.indexOf(value) === index;
474 |     }
475 | }
476 | 
477 | module.exports = HasRolesAndClaims;
478 |
479 |
480 | 481 | 482 | 483 | 484 |
485 |
486 |
487 |
488 | 489 | 490 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | -------------------------------------------------------------------------------- /docs/out/RoleOperations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JSDoc: RoleOperations 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 43 |
44 |
45 |
46 |
47 |
48 | 63 |
64 |
65 |
66 |
67 |

Class

68 |

RoleOperations

69 |
70 | 71 |
72 | 73 |
74 | 75 |

RoleOperations()

77 |
78 | 79 |
80 |
81 |
82 |

Constructor

83 |
84 |
85 | 86 |

87 | # 88 | 89 | 90 | 91 | new RoleOperations() 93 | 94 | 95 |

96 |
97 | Contains methods for managing application roles and claims 98 |
99 | 100 |
101 |

102 | View Source 103 | 104 | RoleOperations.js, line 10 106 | 107 |

108 | 109 |
110 | 111 |
112 |
113 |
114 | 115 |
116 |
117 |

Methods

118 |
119 |
120 |

121 | # 122 | 123 | async 124 | 125 | 126 | 127 | can(claimName) 129 | 130 | 131 |

132 |
133 | Checks if a Role can perform a Claim, must be used after `gateman.role()` 134 |
135 |
Parameters:
136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 151 | 153 | 154 | 155 |
NameTypeDescription
claimName 149 | String 150 | A string that represents the name of 152 | the Claim
156 |
157 |

158 | View Source 159 | 160 | RoleOperations.js, line 25 162 | 163 |

164 |
Usage
165 |

166 |
let result = await gateman.role("rolename").can("claim");
167 |
168 |
169 | 170 |
171 | 172 |

173 | # 174 | 175 | 176 | async 177 | 178 | 179 | 180 | 181 | cannot(claimName) 183 | 184 | 185 |

186 |
187 | Checks if a Role cannot perform a Claim, must be used after `gateman.role()` 188 |
189 |
Parameters:
190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 206 | 208 | 209 | 210 | 211 |
NameTypeDescription
claimName 204 | String 205 | A string that represents the name of 207 | the Claim
212 | 213 |
214 | 215 |

216 | View Source 217 | 218 | RoleOperations.js, line 54 220 | 221 |

222 |
Usage
223 |

224 |
let result = await gateman.role("rolename").cannot("claim");
225 | 226 |
227 | 228 |
229 | 230 |
231 |
232 | 233 |
234 | 235 |
236 |
237 |
238 |
239 |
240 | 241 | 242 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /docs/out/RoleOperations.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | JSDoc: RoleOperations.js 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 42 |
43 |
44 |
45 |
46 | 53 |
54 |
55 |
56 |

Source

57 |

RoleOperations.js

58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 |
var role, claim, roleClaim;
 68 | 
 69 | class RoleOperations {
 70 | 
 71 |     /**
 72 |      * Contains methods for managing application roles and claims
 73 |      * * Provide a valid mongoose connection object that will be used to store application credentials
 74 |      * @mongoose a mongoose connection object
 75 |      */
 76 |     constructor(rol, clm, roleClm){
 77 |         role = rol;
 78 |         claim = clm;
 79 |         roleClaim = roleClm;
 80 |     }
 81 | 
 82 |     /**
 83 |      * Checks if a Role can perform a Claim, must be used after `gateman.role()`
 84 |      * @param claimName {String} A string that represents the name of the Claim 
 85 |      * #### Usage
 86 |       ```
 87 |       let result = await gateman.role('rolename').can('claimname');
 88 |       //should be true if role has the claim
 89 |      ```
 90 |      */
 91 |     async can(claimName) {
 92 |         //find claim, role, then check if it has the claimName
 93 |         try {
 94 |             let dbClaim = await claim.findOne({ name: claimName });
 95 |             if (dbClaim) {
 96 |                 let dbRole = await role.findOne({ name: this.roleName });
 97 |                 if (dbRole) {
 98 |                     let roleClm = await roleClaim.findOne({ role: dbRole._id, claim: dbClaim._id });
 99 |                     return roleClm ? true : false;
100 |                 } else {
101 |                     return "role does not exist";
102 |                 }
103 |             } else {
104 |                 throw new Error("claim does not exist");
105 |             }
106 |         } catch (error) {
107 |             throw error;
108 |         }
109 |     }
110 | 
111 |     /**
112 |      * Checks if a Role cannot perform a Claim, must be used after `gateman.role()`
113 |      * @param claimName {String} A string that represents the name of the Claim 
114 |      * #### Usage
115 |       ```
116 |       let result = await gateman.role('rolename').cannnot('claimname');
117 |       //result is false if the role has the claim
118 |      ```
119 |      */
120 |     async cannot(claimName){
121 |         //find claim, role, then check if it has the claimName
122 |         try {
123 |             let dbClaim = await claim.findOne({ name: claimName });
124 |             if (dbClaim) {
125 |                 let dbRole = await role.findOne({ name: this.roleName });
126 |                 if (dbRole) {
127 |                     let roleClm = await roleClaim.findOne({ role: dbRole._id, claim: dbClaim._id });
128 |                     return roleClm ? false : true;
129 |                 } else {
130 |                     return "role does not exist";
131 |                 }
132 |             } else {
133 |                 throw new Error("claim does not exist");
134 |             }
135 |         } catch (error) {
136 |             throw error;
137 |         }
138 |     }
139 | 
140 | }
141 | module.exports = RoleOperations;
142 |
143 |
144 | 145 | 146 | 147 | 148 |
149 |
150 |
151 |
152 | 153 | 154 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /docs/out/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JSDoc: Home 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 43 |
44 |
45 |
46 |
47 |
48 | 63 |
64 |
65 |
66 |
67 |

Documentation

68 |

GateMan.js

69 |
70 | 71 |
72 | Gatemanjs is an authorization system designed to manage roles and claims in node applications that use mongodb for data storage. It works together with mongoose to provide a fluent approach to managing roles and claims. 73 |
74 | 75 |
76 |
77 |
78 |
79 | 80 | 81 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/out/scripts/app.min.js: -------------------------------------------------------------------------------- 1 | "use strict";$().ready(function(){});var sidebarIsVisible=!1,toggleSidebar=function(t){var i=!(0a&&window.pageYOffsete-o?t.find(".title").css({left:0,position:"absolute",bottom:"0",top:"auto"}):t.find(".title").css({left:i,bottom:"auto",position:"fixed",top:0}):t.find(".title").css({left:0,position:"absolute"})}var i=$(".vertical-section");if(0 a{ 6 | font-weight: 100; 7 | text-decoration: none; 8 | color: #BDC3CB; 9 | font-family: sans-serif; 10 | } 11 | .bd__button > a:hover { 12 | color: #798897; 13 | } -------------------------------------------------------------------------------- /docs/out/styles/prettify-jsdoc.css: -------------------------------------------------------------------------------- 1 | /* JSDoc prettify.js theme */ 2 | 3 | /* plain text */ 4 | .pln { 5 | color: #000000; 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | /* string content */ 11 | .str { 12 | color: #006400; 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | 17 | /* a keyword */ 18 | .kwd { 19 | color: #000000; 20 | font-weight: bold; 21 | font-style: normal; 22 | } 23 | 24 | /* a comment */ 25 | .com { 26 | font-weight: normal; 27 | font-style: italic; 28 | } 29 | 30 | /* a type name */ 31 | .typ { 32 | color: #000000; 33 | font-weight: normal; 34 | font-style: normal; 35 | } 36 | 37 | /* a literal value */ 38 | .lit { 39 | color: #006400; 40 | font-weight: normal; 41 | font-style: normal; 42 | } 43 | 44 | /* punctuation */ 45 | .pun { 46 | color: #000000; 47 | font-weight: bold; 48 | font-style: normal; 49 | } 50 | 51 | /* lisp open bracket */ 52 | .opn { 53 | color: #000000; 54 | font-weight: bold; 55 | font-style: normal; 56 | } 57 | 58 | /* lisp close bracket */ 59 | .clo { 60 | color: #000000; 61 | font-weight: bold; 62 | font-style: normal; 63 | } 64 | 65 | /* a markup tag name */ 66 | .tag { 67 | color: #006400; 68 | font-weight: normal; 69 | font-style: normal; 70 | } 71 | 72 | /* a markup attribute name */ 73 | .atn { 74 | color: #006400; 75 | font-weight: normal; 76 | font-style: normal; 77 | } 78 | 79 | /* a markup attribute value */ 80 | .atv { 81 | color: #006400; 82 | font-weight: normal; 83 | font-style: normal; 84 | } 85 | 86 | /* a declaration */ 87 | .dec { 88 | color: #000000; 89 | font-weight: bold; 90 | font-style: normal; 91 | } 92 | 93 | /* a variable name */ 94 | .var { 95 | color: #000000; 96 | font-weight: normal; 97 | font-style: normal; 98 | } 99 | 100 | /* a function name */ 101 | .fun { 102 | color: #000000; 103 | font-weight: bold; 104 | font-style: normal; 105 | } 106 | 107 | /* Specify class=linenums on a pre to get line numbering */ 108 | ol.linenums { 109 | margin-top: 0; 110 | margin-bottom: 0; 111 | } 112 | -------------------------------------------------------------------------------- /docs/out/styles/prettify-tomorrow.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #4d4d4c; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #718c00; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #8959a8; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #8e908c; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #4271ae; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #f5871f; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #4d4d4c; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #4d4d4c; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #4d4d4c; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #c82829; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #f5871f; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #3e999f; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #f5871f; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #c82829; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #4271ae; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | /* 99 | pre.prettyprint { 100 | background: white; 101 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 102 | font-size: 12px; 103 | line-height: 1.5; 104 | border: 1px solid #ccc; 105 | padding: 10px; } 106 | */ 107 | 108 | /* Specify class=linenums on a pre to get line numbering */ 109 | ol.linenums { 110 | margin-top: 0; 111 | margin-bottom: 0; } 112 | 113 | /* IE indents via margin-left */ 114 | li.L0, 115 | li.L1, 116 | li.L2, 117 | li.L3, 118 | li.L4, 119 | li.L5, 120 | li.L6, 121 | li.L7, 122 | li.L8, 123 | li.L9 { 124 | /* */ } 125 | 126 | /* Alternate shading for lines */ 127 | li.L1, 128 | li.L3, 129 | li.L5, 130 | li.L7, 131 | li.L9 { 132 | /* */ } 133 | -------------------------------------------------------------------------------- /docs/out/styles/reset.css: -------------------------------------------------------------------------------- 1 | /* reset css */ 2 | html, body, div, span, applet, object, iframe, 3 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 4 | a, abbr, acronym, address, big, cite, code, 5 | del, dfn, em, img, ins, kbd, q, s, samp, 6 | small, strike, strong, sub, sup, tt, var, 7 | b, u, i, center, 8 | dl, dt, dd, ol, ul, li, 9 | fieldset, form, label, legend, 10 | table, caption, tbody, tfoot, thead, tr, th, td, 11 | article, aside, canvas, details, embed, 12 | figure, figcaption, footer, header, hgroup, 13 | menu, nav, output, ruby, section, summary, 14 | time, mark, audio, video { 15 | margin: 0; 16 | padding: 0; 17 | border: 0; 18 | font-size: 100%; 19 | font: inherit; 20 | vertical-align: baseline; 21 | } 22 | /* HTML5 display-role reset for older browsers */ 23 | article, aside, details, figcaption, figure, 24 | footer, header, hgroup, menu, nav, section { 25 | display: block; 26 | } 27 | body { 28 | line-height: 1; 29 | } 30 | ol, ul { 31 | list-style: none; 32 | } 33 | blockquote, q { 34 | quotes: none; 35 | } 36 | blockquote:before, blockquote:after, 37 | q:before, q:after { 38 | content: ''; 39 | content: none; 40 | } 41 | table { 42 | border-collapse: collapse; 43 | border-spacing: 0; 44 | } 45 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var GateMan = require('./src/GateMan'); 2 | var rolesAndClaims = require('./src/HasRolesAndClaims'); 3 | 4 | /** 5 | * Creates a new Gateman instance for managing application roles and claims 6 | * * Provide a valid mongoose connection object that will be used to store application credentials 7 | * * `dbConnection` a mongoose object 8 | * #### Usage 9 | ``` 10 | var mongoose = require('mongoose'); 11 | var gateman = require("gatemanjs").GateMan(mongoose); 12 | ``` 13 | */ 14 | exports.GateMan = (dbConnection)=>{ 15 | return new GateMan(dbConnection); 16 | } 17 | 18 | /** 19 | * Initializes roles and abilities, to be extended by a valid *User* model 20 | * * Once extended by a *User* model, each User object has access to the methods 21 | * * `dbConnection` a mongoose object 22 | * 23 | * #### Usage 24 | ``` 25 | const mogoose = require('mongoose'); 26 | const RolesClaims = require('gatemanjs').hasRolesAndClaims(mogoose); 27 | 28 | var UserSchema = mongoose.Schema({ 29 | name: String, 30 | email: String 31 | }); 32 | 33 | UserSchema.loadClass(RolesClaims); 34 | module.exports = mongoose.model('User',UserSchema) 35 | ``` 36 | */ 37 | exports.hasRolesAndClaims = (dbConnection)=>{ 38 | new rolesAndClaims(dbConnection); 39 | return rolesAndClaims; 40 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatemanjs", 3 | "version": "1.1.0", 4 | "description": "Gateman is package for handling user authorization in node-mongo applications", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "find ./src/Tests -name '*.spec.js' | xargs mocha -R spec" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/NwangwuOsitadinma/gateman.git" 12 | }, 13 | "keywords": [ 14 | "authorization" 15 | ], 16 | "author": "Nwangwu Ositadinma", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/NwangwuOsitadinma/gateman/issues" 20 | }, 21 | "homepage": "https://github.com/NwangwuOsitadinma/gateman#readme", 22 | "Dependencies": { 23 | "mongoose": "^5.2.12" 24 | }, 25 | "devDependencies": { 26 | "better-docs": "^1.4.7", 27 | "chai": "^4.2.0", 28 | "chai-as-promised": "^7.1.1", 29 | "express": "^4.16.3", 30 | "mocha": "^6.1.4" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/AllowOperations.js: -------------------------------------------------------------------------------- 1 | var role, claim, roleClaim; 2 | 3 | class AllowOperations { 4 | 5 | /** 6 | * Contains methods for managing application roles and claims 7 | * * Provide a valid mongoose connection object that will be used to store application credentials 8 | * @mongoose a mongoose connection object 9 | */ 10 | constructor(rol, clm, roleClm){ 11 | role = rol; 12 | claim = clm; 13 | roleClaim = roleClm; 14 | } 15 | 16 | /** 17 | * pass in the claim to be assigned to a role 18 | * @param claimName {String} pass a claim as a string if you called allow 19 | * #### Usage 20 | ``` 21 | await gateman.allow("rolename").to("claim"); 22 | ``` 23 | */ 24 | async to(claimName) { 25 | try { 26 | if (this.operation === 'allow') { 27 | //find the role, allow was meant to do this 28 | let dbRole = await role.findOne({ name: this.roler }); 29 | if (dbRole) { 30 | //assign role here 31 | let c = await claim.where('name', claimName).limit(1).exec(); 32 | if (c.length > 0) { 33 | let rlclm = await roleClaim.findOne({ role: dbRole._id, claim: c[0]._id }); 34 | if (rlclm) { 35 | return "Claim has already been assigned to Role"; 36 | } else { 37 | await roleClaim.create({ role: dbRole._id, claim: c[0]._id }); 38 | return; 39 | } 40 | } else { 41 | claim.create({ name: claimName }, (err, claimE) => { 42 | if (err) throw new Error(err); 43 | roleClaim.create({ role: dbRole._id, claim: claimE._id }, function (err, roleClaim) { 44 | if (err) throw err; 45 | return; 46 | }); 47 | }); 48 | } 49 | } else { 50 | throw new Error("role not found"); 51 | } 52 | } 53 | } catch (error) { 54 | throw error; 55 | } 56 | } 57 | 58 | } 59 | module.exports = AllowOperations; -------------------------------------------------------------------------------- /src/DisallowOperations.js: -------------------------------------------------------------------------------- 1 | var role, claim, roleClaim; 2 | 3 | class DisallowOperations { 4 | 5 | /** 6 | * Contains methods for managing application roles and claims 7 | * * Provide a valid mongoose connection object that will be used to store application credentials 8 | * @mongoose a mongoose connection object 9 | */ 10 | constructor(rol, clm, roleClm){ 11 | role = rol; 12 | claim = clm; 13 | roleClaim = roleClm; 14 | } 15 | 16 | 17 | /** 18 | * pass in the claim to be retracted from a role 19 | * @param claimName {String} the claim to retract from a role 20 | * #### Usage 21 | ``` 22 | await gateman.disallow('rolename').from('claim') 23 | //Gateman does nothing if the role doesn't possess the claim 24 | ``` 25 | */ 26 | async from(claimName) { 27 | try { 28 | if (this.operation === 'dissallow') { 29 | let dbRole = await role.findOne({ name: this.roler }); 30 | if (dbRole) { 31 | let dbClaim = await claim.findOne({ name: claimName }); 32 | await roleClaim.findOneAndDelete({ role: dbRole, claim: dbClaim }); 33 | return; 34 | } 35 | } 36 | } catch (error) { 37 | throw error; 38 | } 39 | } 40 | 41 | } 42 | module.exports = DisallowOperations; -------------------------------------------------------------------------------- /src/GateMan.js: -------------------------------------------------------------------------------- 1 | var role = require('./Models/Role'); 2 | var claim = require('./Models/Claim'); 3 | var roleClaim = require('./Models/RoleClaim'); 4 | var allowOps = require('./AllowOperations'); 5 | var disallowOps = require('./DisallowOperations'); 6 | var roleOps = require('./RoleOperations'); 7 | 8 | class GateMan { 9 | 10 | /** 11 | * Contains methods for managing application roles and claims 12 | * * Provide a valid mongoose connection object that will be used to store application credentials 13 | * @mongoose a mongoose connection object 14 | */ 15 | constructor(mongoose){ 16 | role = role(mongoose); 17 | claim = claim(mongoose); 18 | roleClaim = roleClaim(mongoose); 19 | } 20 | 21 | /** 22 | * creates a new gateman role and returns the role 23 | * @param roleName {String} A string that represents the name of the role to be created 24 | * #### Usage 25 | ``` 26 | let role = await gateman.createRole("rolename"); 27 | ``` 28 | */ 29 | async createRole(roleName) { 30 | try { 31 | if (roleName.trim() === "") throw new Error("role name cannot be empty"); 32 | if (typeof(roleName) !== 'string') throw new Error("role name must be a string"); 33 | let dbRole = await role.findOne({ name: roleName }); 34 | if (dbRole) return dbRole; 35 | let newDbRole = await role.create({ name: roleName }); 36 | return newDbRole; 37 | } catch (error) { 38 | throw error; 39 | } 40 | } 41 | 42 | /** 43 | * deletes an existing gateman role, does nothing if role does not exist 44 | * @param roleName {String} A string that represents the name of the role to be removed 45 | * #### Usage 46 | ``` 47 | gateman.removeRole("rolename"); 48 | ``` 49 | */ 50 | async removeRole(roleName){ 51 | try { 52 | if (typeof(roleName) !== 'string') throw new Error('role name must be a string'); 53 | return await role.findOneAndDelete({name: roleName}); 54 | } catch (error) { 55 | throw error; 56 | } 57 | } 58 | 59 | /** 60 | * returns a gateman role specified by the name given 61 | * @param roleName {String} A string that represents the name of the role to be returned 62 | * #### Usage 63 | ``` 64 | let role = await gateman.getRole("rolename"); 65 | ``` 66 | */ 67 | async getRole(roleName){ 68 | try { 69 | if (roleName.trim() === '') return {}; 70 | if (typeof(roleName) !== 'string') throw new Error('role name must be a string'); 71 | let rol = await role.findOne({name:roleName}); 72 | return rol; 73 | } catch (error) { 74 | throw error; 75 | } 76 | } 77 | 78 | /** 79 | * Allows members of a role to perform a claim 80 | * @param rolename {String} the rolename 81 | * #### Usage 82 | ``` 83 | await gateman.allow("rolename").to("claim"); 84 | ``` 85 | */ 86 | allow(rolename){ 87 | let linker = new allowOps(role, claim, roleClaim); 88 | if (rolename.trim() === '') throw new Error('role name must be provided'); 89 | if (typeof(rolename) !== 'string') throw new Error('role name must be a string'); 90 | linker.operation = 'allow'; 91 | linker.roler = rolename; 92 | return linker; 93 | } 94 | 95 | /** 96 | * Dissallows a member of a role from performing a claim 97 | * @param rolename {String} the rolename 98 | * #### Usage 99 | ``` 100 | await gateman.disallow('rolename').from('claim'); 101 | //Gateman does nothing if the role doesn't possess the claim 102 | ``` 103 | */ 104 | disallow(rolename){ 105 | let linker = new disallowOps(role, claim, roleClaim); 106 | if (rolename.trim() === '') throw new Error('role name must be provided'); 107 | if (typeof(rolename) !== 'string') throw new Error('role name must be a string'); 108 | linker.operation = 'dissallow'; 109 | linker.roler = rolename; 110 | return linker; 111 | } 112 | 113 | /** 114 | * Returns existing roles in the system 115 | * #### Usage 116 | ``` 117 | let roles = await gateman.getRoles(); 118 | console.log(roles); //prints collection of all existing roles 119 | ``` 120 | */ 121 | async getRoles(){ 122 | try { 123 | return role.find({}); 124 | } catch (error) { 125 | throw error; 126 | } 127 | } 128 | 129 | /** 130 | * Creates a new claim 131 | * @param claimName {String} A string that represents the name of the claim 132 | * #### Usage 133 | ``` 134 | await gateman.createClaim("delete"); 135 | ``` 136 | * @returns Promise 137 | */ 138 | async createClaim(claimName) { 139 | try { 140 | if (claimName === "") return "claim name cannot be empty"; 141 | let dbClaim = await claim.findOne({ name: claimName }); 142 | if (dbClaim) { 143 | return dbClaim; 144 | } else { 145 | let newDbClaim = await claim.create({ name: claimName }); 146 | return newDbClaim; 147 | } 148 | } catch (error) { 149 | throw error; 150 | } 151 | } 152 | 153 | 154 | /** 155 | * Deletes an existing claim 156 | * @param claimName {String} A string that represents the name of the claim to be deleted 157 | * #### Usage 158 | ``` 159 | await gateman.removeClaim("claimname"); 160 | ``` 161 | */ 162 | async removeClaim(claimName){ 163 | return claim.findOneAndDelete({name: claimName}); 164 | } 165 | 166 | /** 167 | * Returns all claims existing in the system 168 | * #### Usage 169 | ``` 170 | let claims = await gateman.getClaims(); 171 | //claims is a collection of existing claims 172 | ``` 173 | */ 174 | async getClaims(){ 175 | return claim.find({}); 176 | } 177 | 178 | /** 179 | * Returns one claim that matches the claimName given 180 | * @param claimName {String} - The name of the claim to find 181 | * #### Usage 182 | ``` 183 | let claim = await gateman.getClaim(); 184 | ``` 185 | */ 186 | async getClaim(claimName){ 187 | return claim.findOne({name:claimName}); 188 | } 189 | 190 | /** 191 | * Returns an array of claims a role can perform 192 | * @param roleName {String} represents the name of the role 193 | * #### Usage 194 | ``` 195 | let roleClaims = await gateman.getRoleClaims("rolename"); 196 | ``` 197 | */ 198 | async getRoleClaims(roleName){ 199 | try { 200 | let result = []; 201 | let dbRole = await role.findOne({ name: roleName }); 202 | if (dbRole) { 203 | let roleClaims = await roleClaim.find({ role: dbRole._id }).populate('role claim'); 204 | if (roleClaims.length === 0) return result; 205 | for (let i=0; i 0) { 159 | for (let u of ur){ 160 | let rc = await roleClaim.findOne({ role: u.role, claim: c._id }); 161 | if (rc) { 162 | return true; 163 | } else { 164 | let uc = await userClaim.findOne({ user: u.user, claim: c._id }); 165 | return uc ? true : false; 166 | } 167 | } 168 | } else { 169 | let uc = await userClaim.findOne({ user: this._id, claim: c._id }); 170 | return uc ? true : false; 171 | } 172 | } else { 173 | throw new Error("Error, claim does not exist"); 174 | } 175 | } catch (error) { 176 | throw error; 177 | } 178 | } 179 | 180 | /** 181 | * checks whether a user does not have the ability to perform a claim 182 | * @param claimName {string} represents the claim name 183 | * #### Usage 184 | ``` 185 | let user = await User.findOne({name: "chioma"}); 186 | let noClaim = await user.cannot("claim"); 187 | if (noClaim){ 188 | console.log('I do not have the claim'); 189 | } 190 | ``` 191 | */ 192 | async cannot(claimName) { 193 | try { 194 | let c = await claim.findOne({ name: claimName }); 195 | if (c) { 196 | let urs = await userRole.find({ user: this._id }); 197 | if (urs.length > 0) { 198 | urs.forEach(async (ur) => { 199 | let rc = await roleClaim.findOne({ role: ur.role, claim: c._id }); 200 | if (rc) { 201 | return false; 202 | } else { 203 | let uc = await userClaim.findOne({ user: ur.user, claim: c._id }); 204 | return uc ? false : true; 205 | } 206 | }); 207 | } else { 208 | let uc = await userClaim.findOne({ user: this._id, claim: c._id }); 209 | return uc ? false : true; 210 | } 211 | } else { 212 | throw new Error("Error, user or claim does not exist"); 213 | } 214 | } catch (error) { 215 | throw error; 216 | } 217 | } 218 | 219 | /** 220 | * checks if a user is a member of a role 221 | * @param roleName {string} represents the role name 222 | * #### Usage 223 | ``` 224 | let user = await User.findOne({name: "chioma"}); 225 | let userHasRole = await user.isA("role"); 226 | if (userHasRole){ 227 | //user belongs to role 228 | } 229 | ``` 230 | */ 231 | async isA(roleName) { 232 | try { 233 | let r = await role.findOne({ name: roleName }); 234 | if (r) { 235 | let ur = await userRole.findOne({ user: this._id, role: r._id }); 236 | return ur ? true : false; 237 | } else { 238 | throw new Error("Error, role does not exist"); 239 | } 240 | } catch (error) { 241 | throw error; 242 | } 243 | } 244 | 245 | /** 246 | * checks if a user is a member of a role 247 | * @param roleName {string} representing the role name 248 | * #### Usage 249 | ``` 250 | let user = await User.findOne({name: "chioma"}); 251 | let userHasRole = await user.isAn("role"); 252 | if (userHasRole){ 253 | //user belongs to role 254 | } 255 | ``` 256 | */ 257 | async isAn(roleName) { 258 | return await this.isA(roleName); 259 | } 260 | 261 | /** 262 | * checks if a user is not a member of a role 263 | * @param roleName {string} represents the role name 264 | * #### Usage 265 | ``` 266 | let user = await User.findOne({name: "chioma"}); 267 | let result = await user.isNotA("role"); 268 | if (result){ 269 | //user does not belongs to role 270 | } 271 | ``` 272 | */ 273 | async isNotA(roleName) { 274 | try { 275 | let r = await role.findOne({ name: roleName }); 276 | if (r) { 277 | let ur = await userRole.findOne({ user: this._id, role: r._id }); 278 | return ur ? false : true; 279 | } else { 280 | throw new Error("Error, user or role does not exist"); 281 | } 282 | } catch (error) { 283 | throw error; 284 | } 285 | } 286 | 287 | /** 288 | * checks if a user is not a member of a role 289 | * @param roleName {string} represents the role name 290 | * #### Usage 291 | ``` 292 | let user = await User.findOne({name: "chioma"}); 293 | let result = await user.isNotAn("role"); 294 | if (result){ 295 | //user does not belongs to role 296 | } 297 | ``` 298 | */ 299 | async isNotAn(roleName) { 300 | return await this.isNotA(roleName); 301 | } 302 | 303 | /** 304 | * Returns a collection of Roles assigned to a User 305 | * #### Usage 306 | ``` 307 | let user = await User.findOne({name: "chioma"}, (err, user)=>{ 308 | let roles = await user.getRolesForUser(); 309 | console.log(roles); 310 | ``` 311 | */ 312 | async getRolesForUser() { 313 | try { 314 | var result = []; 315 | let roles = await userRole.find({ user: this._id }); 316 | if (roles.length < 1) { 317 | return result; 318 | } else { 319 | for (var item of roles) { 320 | let roler = await role.find({_id: item.role}); 321 | if (roler.length > 0){ 322 | result.push(roler[0].name) 323 | } else { 324 | return result; 325 | } 326 | if (roles[roles.length - 1] == item) { 327 | //return only when you've added every role 328 | //Node is non-blocking, so the engine will return an empty array if resolve(code) is place outside the for-loop 329 | return result; 330 | } 331 | } 332 | } 333 | } catch (error) { 334 | throw error; 335 | } 336 | } 337 | 338 | /** 339 | * Returns a collection of Claims a User can perform 340 | * #### Usage 341 | ``` 342 | let user = await User.findOne({name: "chioma"}); 343 | let claims = await user.getClaimsForUser(); 344 | console.log(claims); 345 | ``` 346 | */ 347 | async getClaimsForUser() { 348 | try { 349 | var result = []; 350 | let userRoles = await userRole.find({ user: this._id }); 351 | if (userRoles.length >= 1) { 352 | for (let userRole of userRoles) { 353 | let roleClaims = await roleClaim.find({ role: userRole.role }); 354 | if (roleClaims.length >= 1) { 355 | for (var item of roleClaims) { 356 | let roleClm = await claim.findOne({_id: item.claim}); 357 | result.push(roleClm.name); 358 | if (roleClaims[roleClaims.length - 1] == item) { 359 | let userClaims = await userClaim.find({ user: this._id }); 360 | if (userClaims.length >= 1) { 361 | for (var item of userClaims) { 362 | let roleClm = await claim.findOne({_id: item.claim}); 363 | result.push(roleClm.name); 364 | if (userClaims[userClaims.length - 1] == item) { 365 | return result.filter(this.onlyUnique); 366 | } 367 | } 368 | } else { 369 | return result.filter(this.onlyUnique); 370 | } 371 | } 372 | } 373 | } else { 374 | let userClaims = await userClaim.find({ user: this._id }); 375 | if (userClaims.length >= 1) { 376 | for (var item of userClaims) { 377 | let roleClm = await claim.findOne({_id: item.claim}); 378 | result.push(roleClm.name); 379 | if (userClaims[userClaims.length - 1] == item) { 380 | return result.filter(this.onlyUnique); 381 | } 382 | } 383 | } 384 | } 385 | } 386 | } else { 387 | let userClaims = await userClaim.find({ user: this._id }); 388 | if (userClaims.length >= 1) { 389 | for (var item of userClaims) { 390 | let roleClm = await claim.findOne({_id: item.claim}); 391 | result.push(roleClm.name); 392 | if (userClaims[userClaims.length - 1] == item) { 393 | return result.filter(this.onlyUnique); 394 | } 395 | } 396 | } else { 397 | return result.filter(this.onlyUnique); 398 | } 399 | } 400 | } catch (error) { 401 | throw error; 402 | } 403 | 404 | } 405 | 406 | onlyUnique(value, index, self) { 407 | return self.indexOf(value) === index; 408 | } 409 | } 410 | 411 | module.exports = HasRolesAndClaims; -------------------------------------------------------------------------------- /src/Models/Claim.js: -------------------------------------------------------------------------------- 1 | module.exports = (mongoose)=>{ 2 | var mn = mongoose.modelNames(); 3 | var ClaimSchema = mongoose.Schema({ 4 | name: { 5 | type: String, 6 | required: [true,'Sorry, the claim is required'], 7 | unique: true 8 | } 9 | }); 10 | if (mn.includes("GatemanClaim")){ 11 | return mongoose.model('GatemanClaim'); 12 | } else { 13 | return mongoose.model('GatemanClaim',ClaimSchema); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/Models/Role.js: -------------------------------------------------------------------------------- 1 | module.exports = (mongoose)=>{ 2 | var mn = mongoose.modelNames(); 3 | var RoleSchema = mongoose.Schema({ 4 | name: { 5 | type: String, 6 | required: [true,'Sorry, the role name is required'], 7 | unique: true 8 | } 9 | }); 10 | if (mn.includes("GatemanRole")){ 11 | return mongoose.model("GatemanRole"); 12 | } else { 13 | return mongoose.model("GatemanRole", RoleSchema); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Models/RoleClaim.js: -------------------------------------------------------------------------------- 1 | module.exports = (mongoose)=>{ 2 | var mn = mongoose.modelNames(); 3 | var RoleClaimSchema = mongoose.Schema({ 4 | role: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | required: [true,'Sorry, the role is required'], 7 | ref: 'GatemanRole' 8 | }, 9 | claim: { 10 | type: mongoose.Schema.Types.ObjectId, 11 | required: [true,'Sorry! the claim is required'], 12 | ref: 'GatemanClaim' 13 | } 14 | }); 15 | if (mn.includes("GatemanRoleClaim")){ 16 | return mongoose.model('GatemanRoleClaim'); 17 | } else { 18 | return mongoose.model('GatemanRoleClaim',RoleClaimSchema); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/Models/UserClaim.js: -------------------------------------------------------------------------------- 1 | module.exports = (mongoose)=>{ 2 | var mn = mongoose.modelNames(); 3 | var UserClaimSchema = mongoose.Schema({ 4 | user: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | required: [true,'Sorry, the user is required'] 7 | }, 8 | claim: { 9 | type: mongoose.Schema.Types.ObjectId, 10 | required: [true,'Sorry, the claim is required'], 11 | ref: 'GatemanClaim' 12 | } 13 | }); 14 | if (mn.includes("GatemanUserClaim")){ 15 | return mongoose.model('GatemanUserClaim'); 16 | } else { 17 | return mongoose.model('GatemanUserClaim',UserClaimSchema); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/Models/UserRole.js: -------------------------------------------------------------------------------- 1 | module.exports = (mongoose)=>{ 2 | var mn = mongoose.modelNames(); 3 | var UserRoleSchema = mongoose.Schema({ 4 | user: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | required: [true,'Sorry, the user is required'] 7 | }, 8 | role: { 9 | type: mongoose.Schema.Types.ObjectId, 10 | required: [true,'Sorry, the role is required'], 11 | ref: 'GatemanRole' 12 | } 13 | }); 14 | if (mn.includes("GatemanUserRole")){ 15 | return mongoose.model('GatemanUserRole'); 16 | } else { 17 | return mongoose.model('GatemanUserRole',UserRoleSchema); 18 | } 19 | } -------------------------------------------------------------------------------- /src/RoleOperations.js: -------------------------------------------------------------------------------- 1 | var role, claim, roleClaim; 2 | 3 | class RoleOperations { 4 | 5 | /** 6 | * Contains methods for managing application roles and claims 7 | * * Provide a valid mongoose connection object that will be used to store application credentials 8 | * @mongoose a mongoose connection object 9 | */ 10 | constructor(rol, clm, roleClm){ 11 | role = rol; 12 | claim = clm; 13 | roleClaim = roleClm; 14 | } 15 | 16 | /** 17 | * Checks if a Role can perform a Claim, must be used after `gateman.role()` 18 | * @param claimName {String} A string that represents the name of the Claim 19 | * #### Usage 20 | ``` 21 | let result = await gateman.role('rolename').can('claimname'); 22 | //should be true if role has the claim 23 | ``` 24 | */ 25 | async can(claimName) { 26 | //find claim, role, then check if it has the claimName 27 | try { 28 | let dbClaim = await claim.findOne({ name: claimName }); 29 | if (dbClaim) { 30 | let dbRole = await role.findOne({ name: this.roleName }); 31 | if (dbRole) { 32 | let roleClm = await roleClaim.findOne({ role: dbRole._id, claim: dbClaim._id }); 33 | return roleClm ? true : false; 34 | } else { 35 | return "role does not exist"; 36 | } 37 | } else { 38 | throw new Error("claim does not exist"); 39 | } 40 | } catch (error) { 41 | throw error; 42 | } 43 | } 44 | 45 | /** 46 | * Checks if a Role cannot perform a Claim, must be used after `gateman.role()` 47 | * @param claimName {String} A string that represents the name of the Claim 48 | * #### Usage 49 | ``` 50 | let result = await gateman.role('rolename').cannnot('claimname'); 51 | //result is false if the role has the claim 52 | ``` 53 | */ 54 | async cannot(claimName){ 55 | //find claim, role, then check if it has the claimName 56 | try { 57 | let dbClaim = await claim.findOne({ name: claimName }); 58 | if (dbClaim) { 59 | let dbRole = await role.findOne({ name: this.roleName }); 60 | if (dbRole) { 61 | let roleClm = await roleClaim.findOne({ role: dbRole._id, claim: dbClaim._id }); 62 | return roleClm ? false : true; 63 | } else { 64 | return "role does not exist"; 65 | } 66 | } else { 67 | throw new Error("claim does not exist"); 68 | } 69 | } catch (error) { 70 | throw error; 71 | } 72 | } 73 | 74 | } 75 | module.exports = RoleOperations; -------------------------------------------------------------------------------- /src/Tests/Gateman.spec.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var should = chai.should(); 3 | var expect = chai.expect; 4 | var mongoose = require('mongoose'); 5 | mongoose.set('useCreateIndex', true); 6 | mongoose.Promise = global.Promise; 7 | var gateman = require('../GateMan'); 8 | var GateMan = new gateman(mongoose); 9 | 10 | 11 | describe('Gateman Claims', function(){ 12 | before('ensuring the db is fresh',function(done){ 13 | mongoose.connect('mongodb://localhost:27017/GateManTest',{useNewUrlParser: true}); 14 | done(); 15 | }); 16 | after('ensuring everything is cleaned up',function(done){ 17 | mongoose.disconnect(); 18 | done(); 19 | }); 20 | 21 | describe('createClaim', function () { 22 | it('should return a claim object if created successfully', async() => { 23 | var c = 'turn-water-into-wine'; 24 | let claim = await GateMan.createClaim(c); 25 | should.equal(claim.name, c); 26 | }).timeout(10000); 27 | }); 28 | 29 | describe('removeClaim', function(){ 30 | it('should not return anything if it actually deleted', async()=>{ 31 | var c = 'turn-water-into-wine'; 32 | let claim = await GateMan.createClaim(c); 33 | await GateMan.removeClaim(claim.name); 34 | let clm = await GateMan.getClaim(claim.name); 35 | should.equal(clm,null); 36 | }).timeout(10000); 37 | }); 38 | 39 | describe('getClaim',function(){ 40 | it('should return one valid claim', async()=>{ 41 | var c = 'turn-water-into-wine'; 42 | let claim = await GateMan.createClaim(c); 43 | await GateMan.getClaim(c); 44 | should.equal(claim.name,c); 45 | }).timeout(10000); 46 | }); 47 | 48 | describe('getClaims',function(){ 49 | it('should return a collection of claims with at least one member', async()=>{ 50 | var c = 'turn-water-into-wine'; 51 | var c2 = 'claim2'; 52 | await GateMan.createClaim(c); 53 | await GateMan.createClaim(c2); 54 | let claims = await GateMan.getClaims(); 55 | claims.should.not.be.empty; 56 | }).timeout(10000); 57 | }); 58 | 59 | }); 60 | 61 | describe('Gateman Roles',function(){ 62 | before('ensuring db is fresh',(done)=>{ 63 | mongoose.connect('mongodb://localhost:27017/GateManTest',{useNewUrlParser: true}); 64 | done(); 65 | }); 66 | after('ensuring everything is cleaned up',function(done){ 67 | mongoose.disconnect(); 68 | done(); 69 | }); 70 | describe('createRole', function(){ 71 | it ('should return a role object if created successfully', async()=>{ 72 | var r = 'admin'; 73 | let role = await GateMan.createRole(r); 74 | should.equal(role.name,r); 75 | }).timeout(10000); 76 | }); 77 | describe('removeRole',function(){ 78 | it('should not return anything if it actually deleted',async ()=>{ 79 | var r = 'roler'; 80 | let role = await GateMan.createRole(r); 81 | await GateMan.removeRole(role.name); 82 | let rol = await GateMan.getRole(role.name); 83 | should.equal(rol, null); 84 | }).timeout(10000); 85 | }); 86 | 87 | describe('getRole',function(){ 88 | it('should return one valid role', async()=>{ 89 | var r = "admin"; 90 | await GateMan.createRole(r) 91 | let role = await GateMan.getRole(r); 92 | should.equal(role.name,r); 93 | }).timeout(10000); 94 | }); 95 | 96 | describe('getRoles',function(){ 97 | it('should return a collection of at least one valid role', async()=>{ 98 | var r = "admin"; 99 | await GateMan.createRole(r); 100 | let roles = await GateMan.getRoles(); 101 | roles.should.not.be.empty; 102 | }).timeout(10000) 103 | }); 104 | 105 | describe('Roles with claims', function(){ 106 | it('should return a role that has 2 claims', async()=>{ 107 | await GateMan.createRole('admin'); 108 | await GateMan.allow('admin').to('add'); 109 | await GateMan.allow('admin').to('delete'); 110 | let roleClaims = await GateMan.getRoleClaims('admin'); 111 | expect(roleClaims).to.be.an('array'); 112 | expect(roleClaims).to.have.members(['add','delete']); 113 | }); 114 | 115 | it('should return a role that has no claims', async()=>{ 116 | await GateMan.createRole('teacher'); 117 | await GateMan.allow('teacher').to('add'); 118 | await GateMan.disallow('teacher').from('add'); 119 | let roleClaims = await GateMan.getRoleClaims('teacher'); 120 | expect(roleClaims).to.be.an('array'); 121 | expect(roleClaims).to.have.members([]); 122 | }); 123 | 124 | it('should return true if role has claim', async ()=> { 125 | await GateMan.createRole('manager'); 126 | await GateMan.createClaim('edit'); 127 | await GateMan.allow('manager').to('edit'); 128 | let hasClaim = await GateMan.role('manager').can('edit'); 129 | expect(hasClaim).to.be.true; 130 | }); 131 | 132 | it('should return false if role does not have claim', async ()=> { 133 | await GateMan.createRole('manager'); 134 | let hasClaim = await GateMan.role('manager').can('add'); 135 | expect(hasClaim).to.be.false; 136 | }); 137 | 138 | it('should return false if role has claim', async ()=> { 139 | await GateMan.createRole('manager'); 140 | await GateMan.createClaim('edit'); 141 | await GateMan.allow('manager').to('edit'); 142 | let hasClaim = await GateMan.role('manager').cannot('edit'); 143 | expect(hasClaim).to.be.false; 144 | }); 145 | 146 | it('should return true if role does not have claim', async ()=> { 147 | await GateMan.createRole('manager'); 148 | let hasClaim = await GateMan.role('manager').cannot('delete'); 149 | expect(hasClaim).to.be.true; 150 | }); 151 | 152 | }); 153 | }); -------------------------------------------------------------------------------- /src/Tests/HasRolesAndAbilities.spec.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var should = chai.should(); 3 | var expect = chai.expect; 4 | var mongoose = require('mongoose'); 5 | mongoose.set('useCreateIndex', true); 6 | mongoose.Promise = global.Promise; 7 | // var gateman = require('../GateMan'); 8 | // var GateManClsss = require('../../index').GateMan(mongoose); 9 | const hasRolesAndClaims = require('../../index').hasRolesAndClaims(mongoose); 10 | 11 | var UserSchema = new mongoose.Schema({ 12 | name: String, 13 | email: String 14 | }); 15 | 16 | UserSchema.loadClass(hasRolesAndClaims); 17 | var userModel = mongoose.model('User',UserSchema); 18 | 19 | describe('Roles and Abilities with Mongoose Objects',function(){ 20 | before('ensuring db is fresh',async()=>{ 21 | await mongoose.connect('mongodb://localhost:27017/GateManTest',{useNewUrlParser: true}); 22 | await userModel.create({ 23 | name: 'chioma', 24 | email: 'random@server.ng' 25 | }); 26 | }); 27 | after('ensuring everything is cleaned up',function(done){ 28 | mongoose.disconnect(); 29 | userModel.findOneAndDelete({ 30 | name: 'chioma', 31 | email: 'random@server.ng' 32 | }); 33 | 34 | done(); 35 | }); 36 | 37 | it('should allow user perform a claim', async ()=> { 38 | let user = await userModel.findOne({name: "chioma"}); 39 | await user.allow('add'); 40 | let hasClaim = await user.can('add'); 41 | expect(hasClaim).to.be.true; 42 | }); 43 | 44 | it('should check if user belongs to a role', async ()=> { 45 | let user = await userModel.findOne({name: "chioma"}); 46 | let hasRole = await user.isAn('admin'); //role exists 47 | expect(hasRole).to.be.false; 48 | }); 49 | 50 | it('should assign role to user', async ()=> { 51 | let user = await userModel.findOne({name: "chioma"}); 52 | await user.assign('admin'); 53 | let hasRole = await user.isAn('admin'); //role exists 54 | expect(hasRole).to.be.true; 55 | }); 56 | 57 | it('should get user roles', async ()=> { 58 | let user = await userModel.findOne({name: "chioma"}); 59 | let roles = await user.getRolesForUser(); 60 | expect(roles).to.have.members(['admin']); 61 | }); 62 | 63 | it('should get user claims', async ()=> { 64 | let user = await userModel.findOne({name: "chioma"}); 65 | let claims = await user.getClaimsForUser(); 66 | expect(claims).to.have.members(['add','delete']); 67 | }); 68 | 69 | it('should retract role from user', async ()=> { 70 | let user = await userModel.findOne({name: "chioma"}); 71 | await user.retract('admin'); 72 | let hasRole = await user.isAn('admin'); //role exists 73 | expect(hasRole).to.be.false; 74 | }); 75 | 76 | }); --------------------------------------------------------------------------------