{"id":45277872,"url":"https://github.com/mikemclin/angular-acl","last_synced_at":"2026-02-21T02:01:31.056Z","repository":{"id":22512068,"uuid":"25852334","full_name":"mikemclin/angular-acl","owner":"mikemclin","description":"Role-based permissions for AngularJS","archived":false,"fork":false,"pushed_at":"2022-07-31T20:35:53.000Z","size":44,"stargazers_count":196,"open_issues_count":10,"forks_count":50,"subscribers_count":16,"default_branch":"master","last_synced_at":"2026-02-05T18:49:16.140Z","etag":null,"topics":["acl","angular-js"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mikemclin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-28T04:00:18.000Z","updated_at":"2026-01-25T18:58:22.000Z","dependencies_parsed_at":"2022-08-21T06:31:02.298Z","dependency_job_id":null,"html_url":"https://github.com/mikemclin/angular-acl","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/mikemclin/angular-acl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemclin%2Fangular-acl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemclin%2Fangular-acl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemclin%2Fangular-acl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemclin%2Fangular-acl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikemclin","download_url":"https://codeload.github.com/mikemclin/angular-acl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemclin%2Fangular-acl/sbom","scorecard":{"id":645760,"data":{"date":"2025-08-11","repo":{"name":"github.com/mikemclin/angular-acl","commit":"40f25d96908d15215f8bfca0771976e934dcb49d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":1,"reason":"Found 4/24 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T12:06:19.617Z","repository_id":22512068,"created_at":"2025-08-21T12:06:19.617Z","updated_at":"2025-08-21T12:06:19.617Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29671513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T00:11:43.526Z","status":"online","status_checked_at":"2026-02-21T02:00:07.432Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acl","angular-js"],"created_at":"2026-02-21T02:01:30.489Z","updated_at":"2026-02-21T02:01:31.044Z","avatar_url":"https://github.com/mikemclin.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Angular ACL\n\n[![Build Status](https://img.shields.io/travis/mikemclin/angular-acl/master.svg?style=flat-square)](https://travis-ci.org/mikemclin/angular-acl)\n[![Coverage Status](https://img.shields.io/coveralls/mikemclin/angular-acl/master.svg?style=flat-square)](https://coveralls.io/r/mikemclin/angular-acl?branch=master)\n\n---\n\n## About\n\nAngular ACL _(Access Control List)_ is a service that allows you to protect/show content based on the current user's assigned role(s), and those role(s) permissions (abilities).  So, if the current user has a \"moderator\" role, and a moderator can \"ban_users\", then the current user can \"ban_users\".\n\nCommon uses include:\n\n* Manipulate templates based on role/permissions\n* Prevent routes that should not be viewable to user\n\n### How secure is this?\n\nA great analogy to ACL's in JavaScript would be form validation in JavaScript.  Just like form validation, ACL's in the browser can be tampered with.  However, just like form validation, ACL's are really useful and provide a better experience for the user and the developer.  Just remember, **any sensitive data or actions should require a server (or similar) as the final authority**.\n\n##### Example Tampering Scenario\n\nThe current user has a role of \"guest\".  A guest is not able to \"create_users\".  However, this sneaky guest is clever enough to tamper with the system and give themselves that privilege. So, now that guest is at the \"Create Users\" page, and submits the form. The form data is sent to the server and the user is greeted with an \"Access Denied: Unauthorized\" message, because the server also checked to make sure that the user had the correct permissions.\n\nAny sensitive data or actions should integrate a server check like this example.\n\n---\n\n## Basic Example\n\n### Set Data\n\nSetup the `AclService` in your app module's `run()` block.\n\n```js\napp.run(['AclService', function (AclService) {\n  \n  // Set the ACL data. Normally, you'd fetch this from an API or something.\n  // The data should have the roles as the property names,\n  // with arrays listing their permissions as their value.\n  var aclData = {\n    guest: ['login'],\n    member: ['logout', 'view_content'],\n    admin: ['logout', 'view_content', 'manage_content']\n  }\n  AclService.setAbilities(aclData);\n\n  // Attach the member role to the current user\n  AclService.attachRole('member');\n\n}]);\n```\n\n### Protect a route\n\nIf the current user tries to go to the `/manage` route, they will be redirected because the current user is a `member`, and `manage_content` is not one of a member role's abilities.\n\nHowever, when the user goes to `/content`, route will work as normal, since the user has permission.  If the user was not a `member`, but a `guest`, then they would not be able to see the `content` route either, based on the data we set above.\n\n```js\napp.config(['$routeProvider', function ($routeProvider) {\n  $routeProvider\n    .when('/manage', {\n      resolve : {\n        'acl' : ['$q', 'AclService', function($q, AclService){\n          if(AclService.can('manage_content')){\n            // Has proper permissions\n            return true;\n          } else {\n            // Does not have permission\n            return $q.reject('Unauthorized');\n          }\n        }]\n      }\n    });\n    .when('/content', {\n      resolve : {\n        'acl' : ['$q', 'AclService', function($q, AclService){\n          if(AclService.can('view_content')){\n            // Has proper permissions\n            return true;\n          } else {\n            // Does not have permission\n            return $q.reject('Unauthorized');\n          }\n        }]\n      }\n    });\n}]);\n\napp.run(['$rootScope', '$location', function ($rootScope, $location) {\n  // If the route change failed due to our \"Unauthorized\" error, redirect them\n  $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){\n    if(rejection === 'Unauthorized'){\n      $location.path('/');\n    }\n  })\n}]);\n```\n\n### Manipulate a Template\n\nThe edit link in the template below will not show, because the current user is a `member`, and `manage_content` is not one of a member role's abilities.\n\n###### Controller\n\n```js\napp.controller('DemoCtrl', ['$scope', 'AclService', function ($scope, AclService) {\n  $scope.can = AclService.can;\n  $scope.id = 22;\n  $scope.title = 'My Demo Title';\n}]);\n```\n\n###### Template\n\n```html\n\u003ch1\u003e{{ title }}\u003c/h1\u003e\n\u003ca ng-href=\"edit/{{ id }}\" ng-show=\"can('manage_content')\"\u003eEdit\u003c/a\u003e\n```\n\n---\n\n## Install\n\nInstall with `bower`:\n\n```shell\nbower install angular-acl\n```\n\nAdd a `\u003cscript\u003e` to your `index.html`:\n\n```html\n\u003cscript src=\"/bower_components/angular-acl/angular-acl.js\"\u003e\u003c/script\u003e\n```\n\nAnd add `mm.acl` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['mm.acl']);\n```\n\n---\n\n## Documentation\n\n### Config\n\nYou can modify the configuration by extending the config object during the Angular configuration phase using the `config()` method on the `AclServiceProvider`.\n\n```js\napp.config(['AclServiceProvider', function (AclServiceProvider) {\n  var myConfig = {\n    storage: 'localStorage',\n    storageKey: 'AppAcl'\n  };\n  AclServiceProvider.config(myConfig);\n}]);\n```\n\n#### Config Options\n\n| Property | Default | Description |\n| -------- | ------- | ----------- |\n| `storage` | `\"sessionStorage\"` | `\"sessionStorage\"`, `\"localStorage\"`, `false`. Where you want to persist your ACL data. If you would prefer not to use web storage, then you can pass a value of `false`, and data will be reset on next page refresh _(next time the Angular app has to bootstrap)_ |\n| `storageKey` | `\"AclService\"` | The key that will be used when storing data in web storage |\n\n### Public Methods\n\n#### `AclService.resume()`\n\nRestore data from web storage.\n\n###### Returns\n\n**boolean** - true if web storage existed, false if it didn't\n\n###### Example Usage\n\n```js\napp.run(['AclService', function (AclService) {\n  // Attempt to load from web storage\n  if (!AclService.resume()) {\n    // Web storage record did not exist, we'll have to build it from scratch\n    \n    // Get the user role, and add it to AclService\n    var userRole = fetchUserRoleFromSomewhere();\n    AclService.addRole(userRole);\n    \n    // Get ACL data, and add it to AclService\n    var aclData = fetchAclFromSomewhere();\n    AclService.setAbilities(aclData);\n  }\n}]);\n```\n\nYou can also run `resume()` in the `config` phase, if you need the app to load the ACL data from web storage earlier in the app bootstrap process (e.g. before `$routeProvider` resolves the first route).\n\n```js\napp.config(['AclServiceProvider', function (AclServiceProvider) {\n  AclServiceProvider.resume();\n}]);\n```\n\n#### `AclService.flushStorage()`\n\nRemove all data from web storage.\n\n#### `AclService.attachRole(role)`\n\nAttach a role to the current user. A user can have multiple roles.\n\n###### Parameters\n\n| Param | Type | Example | Details |\n| ----- | ---- | ------- | ------- |\n| `role` | string | `\"admin\"` | The role label |\n\n#### `AclService.detachRole(role)`\n\nRemove a role from the current user\n\n###### Parameters\n\n| Param | Type | Example | Details |\n| ----- | ---- | ------- | ------- |\n| `role` | string | `\"admin\"` | The role label |\n\n#### `AclService.flushRoles()`\n\nRemove all roles from current user\n\n#### `AclService.getRoles()`\n\nGet all of the roles attached to the user\n\n###### Returns\n\n**array**\n\n#### `AclService.hasRole(role)`\n\nCheck if the current user has role(s) attached. If an array is given, all roles must be attached. To check if any roles in an array are attached see the `hasAnyRole()` method.\n\n###### Parameters\n\n| Param | Type | Example | Details |\n| ----- | ---- | ------- | ------- |\n| `role` | string/array | `\"admin\"` | The role label, or an array of role labels |\n\n###### Returns\n\n**boolean**\n\n#### `AclService.hasAnyRole(roles)`\n\nCheck if the current user has any of the given roles attached. To check if all roles in an array are attached see the `hasRole()` method.\n\n###### Parameters\n\n| Param | Type | Example | Details |\n| ----- | ---- | ------- | ------- |\n| `roles` | array | `[\"admin\",\"user\"]` | Array of role labels |\n\n###### Returns\n\n**boolean**\n\n#### `AclService.setAbilities(abilities)`\n\nSet the abilities object (overwriting previous abilities).\n\n###### Parameters\n\n| Param | Type | Details |\n| ----- | ---- | ------- |\n| `abilities` | object | Each property on the abilities object should be a role. Each role should have a value of an array. The array should contain a list of all of the role's abilities. |\n\n###### Example\n\n```js\nvar abilities = {\n  guest: ['login'],\n  user: ['logout', 'view_content'],\n  admin: ['logout', 'view_content', 'manage_content']\n}\nAclService.setAbilities(abilities);\n```\n\n#### `AclService.addAbility(role, ability)`\n\nAdd an ability to a role\n\n###### Parameters\n\n| Param | Type | Example | Details |\n| ----- | ---- | ------- | ------- |\n| `role` | string | `\"admin\"` | The role label |\n| `ability` | string | `\"create_users\"` | The ability/permission label |\n\n#### `AclService.can(ability)`\n\nDoes current user have permission to do the given ability?\n\n###### Returns\n\n**boolean**\n\n###### Example\n\n```js\n// Setup some abilities\nAclService.addAbility('moderator', 'ban_users');\nAclService.addAbility('admin', 'create_users');\n\n// Add moderator role to the current user\nAclService.attachRole('moderator');\n\n// Check if the current user has these permissions\nAclService.can('ban_users'); // returns true\nAclService.can('create_users'); // returns false\n```\n\n### Directives\n\n#### `aclShow`\n\nShow and element if truthy, otherwise hide it. \n\n###### Example Usage\n\nOnly user's that have the `edit_posts` permission would see the button.\n\n```html\n\u003cbutton acl-show=\"edit_posts\"\u003eEdit Post\u003c/button\u003e\n```\n\nThis is essentially a shortcut instead of having to type out an `ngShow` like this...\n\n```html\n\u003cbutton ng-show=\"$ctrl.AclService.can('edit_posts')\"\u003eEdit Post\u003c/button\u003e\n```\n\n---\n\n## License\n\nThe MIT License\n\nAngular ACL\nCopyright (c) 2016 Mike McLin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikemclin%2Fangular-acl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikemclin%2Fangular-acl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikemclin%2Fangular-acl/lists"}