{"id":13483290,"url":"https://github.com/ilanusse/praetorian","last_synced_at":"2025-05-06T21:02:56.517Z","repository":{"id":33634293,"uuid":"159713213","full_name":"ilanusse/praetorian","owner":"ilanusse","description":"A minimalist Crystal authorization system inspired by https://github.com/varvet/pundit.","archived":false,"fork":false,"pushed_at":"2022-01-18T14:44:20.000Z","size":44,"stargazers_count":60,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T02:51:10.699Z","etag":null,"topics":["authorisation","authorization","crystal","crystal-lang","crystal-language","praetorian","shard"],"latest_commit_sha":null,"homepage":null,"language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ilanusse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-29T18:57:05.000Z","updated_at":"2025-01-17T21:16:42.000Z","dependencies_parsed_at":"2022-08-07T22:16:39.086Z","dependency_job_id":null,"html_url":"https://github.com/ilanusse/praetorian","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilanusse%2Fpraetorian","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilanusse%2Fpraetorian/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilanusse%2Fpraetorian/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilanusse%2Fpraetorian/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ilanusse","download_url":"https://codeload.github.com/ilanusse/praetorian/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252769396,"owners_count":21801375,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["authorisation","authorization","crystal","crystal-lang","crystal-language","praetorian","shard"],"created_at":"2024-07-31T17:01:09.745Z","updated_at":"2025-05-06T21:02:56.468Z","avatar_url":"https://github.com/ilanusse.png","language":"Crystal","funding_links":[],"categories":["Crystal","Framework Components"],"sub_categories":[],"readme":"# Praetorian\n[![Build Status](https://travis-ci.org/ilanusse/praetorian.svg?branch=master)](https://travis-ci.org/ilanusse/praetorian)\n[![Version](https://img.shields.io/github/tag/ilanusse/praetorian.svg?maxAge=360)](https://github.com/ilanusse/praetorian/releases/latest)\n[![License](https://img.shields.io/github/license/ilanusse/praetorian.svg)](https://github.com/ilanusse/praetorian/blob/master/LICENSE)\n\nPraetorian is a minimalist Crystal authorization system inspired by [Pundit](https://github.com/varvet/pundit). It aims to be both lightweight and dependency-less.\n\n## Installation\n\n```crystal\ndependencies:\n  praetorian:\n    github: ilanusse/praetorian\n```\n\n## How to use\n\nPraetorian, inspired by Pundit, works with policy classes. This shard is not designed to be extra compatible with any framework but rather with flexibility in mind.\nThis is a simple example that allows updating\na post if the user is an admin, or if the post is unpublished:\n\n```crystal\nclass Post\n  def policy_class\n    PostPolicy\n  end\nend\n\n\nclass PostPolicy\n  include Praetorian::Policy\n\n  property user, post\n\n  def initialize(user, post)\n    @user = user\n    @post = post\n  end\n\n  def update?\n    user.admin? || !post.published?\n  end\nend\n\n\n# Somewhere in your code\ndef update\n  @post = Post.find(params[:id])\n  Praetorian.authorize(current_user, @post, :update?) # You can also use .authorise if you're a Brit\n  # Rest of code flow\nend\n```\n\nThere are two things to notice here:\n- The Post is a class that should obey a certain Policy. We can either write a `policy_class` method to return the policy class name, or Praetorian will assume the policy classname to be `#{variable_name}Policy`.\n\n- The Policy class includes `Praetorian::Policy`. This adds default query methods to our policy as defaults that should be overwritten as necessary.\n\nThe default query methods defined in `Praetorian::Policy` are: `index?`, `show?`, `create?`, `new?`, `update?`, `edit?`, `destroy?`.\n\nA `Praetorian::NotAuthorizedException` will be raised if the user is not authorized to perform said query on the record.\n\nOk. So far, pretty simple.\n\nYou can set up a simple base class to inherit from:\n\n```crystal\nclass ApplicationPolicy\n  include Praetorian::Policy\n\n  property user, object\n\n  def initialize(user, object)\n    @user = user\n    @object = object\n  end\nend\n```\n\n### Including the shard as a module\n\nYou can include the shard as a module in your controller base class to avoid the prefix:\n\n```crystal\nclass ApplicationController\n  include Praetorian\nend\n\nclass PostController \u003c ApplicationController\n  @post = Post.find(params[:id])\n  authorize(current_user, @post, :update?) # yay no prefix\nend\n```\n\n### Using a specific policy class\nYou can pass an argument to override the policy class if necessary. For example:\n\n```crystal\ndef create\n  @publication = find_publication # assume this method returns any model that behaves like a publication\n  # @publication.class =\u003e Post\n  Praetorian.authorize(current_user, @publication, :create?, PublicationPolicy)\n  # Rest of code flow\nend\n```\n\n# License\n\nLicensed under the MIT license, see the separate LICENSE.txt file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filanusse%2Fpraetorian","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filanusse%2Fpraetorian","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filanusse%2Fpraetorian/lists"}