profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/Anniepoo/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Anne Ogborn Anniepoo Hasura.io Bangalore, India http://theelginworks.com/ contributor to @SWI-Prolog, Prolog nut, social roboticist, Haskell noob, automated manufacturing fan.

Anniepoo/amziexpertsystemsinprolog 7

This is a fork of the amzi expert systems in prolog ported to swi-prolog and put in git instead of awkward file by file dl on amzi site

Anniepoo/declswiplweb 3

End to end declarative web programming with no JS using htmx and SWI-Prolog

Anniepoo/foxesandrabbits 3

Example for logtalk of predator prey simulation

Anniepoo/fflpractice 2

Simple example of calling SWI-Prolog from within a C wrapper

Anniepoo/gcode 2

G Code library. G Code (RS-274) is a representation for commands for numerically contreolled machine tools

Anniepoo/enron 1

tools to work with the enron email corpus

Anniepoo/games4diversity 1

Games for diversity Game Jam

AnnieAtDataChemist/ffipractice 0

me fiddling about with calling back and forth among Prolog, C, C++, and Rust

AnnieAtDataChemist/terminus-client 0

Javascript client for TerminusDB - reference implementation of API

AnnieAtDataChemist/website-copy 0

A repository for exercism's website's copy

push eventAnniepoo/transhavengame

Anne Ogborn

commit sha a2bc883e2bcd590b052871c83412b9bb6ba9ad52

player_amy done, including hands, and rigged

view details

Anne Ogborn

commit sha 17b1f0a2a1e693bab148436f015161db75bf35f3

player_amy rigging done

view details

push time in 5 days

issue commentImageMagick/ImageMagick

Support for Telegram / TGS animated vector stickers

landed here while searching for the same. Here's what I've got so far.

https://core.telegram.org/animated_stickers

https://telegram.org/blog/animated-stickers

jtagcat

comment created time in 9 days

push eventAnniepoo/transhavengame

Anne Ogborn

commit sha bfa934c270ebfb09e8bc8f83f7a5ce84d9532cbb

smaller board, fixed the missing js problem

view details

push time in 13 days

create barnchAnniepoo/transhavengame

branch : unity

created branch time in 13 days

create barnchAnniepoo/transhavengame

branch : nochr

created branch time in 19 days

create barnchAnniepoo/transhavengame

branch : chr

created branch time in a month

push eventAnniepoo/transhavengame

Anne Ogborn

commit sha ce803b6d637c92ef4e43b543febe6c4dd9026040

check in prolog files

view details

Anne Ogborn

commit sha eb2b92a98e2274111fce4699f554554227dcf312

remove old unused prolog

view details

push time in a month

create barnchAnniepoo/transhavengame

branch : main

created branch time in a month

created repositoryAnniepoo/transhavengame

A game about making a trans haven

created time in a month

create barnchAnniepoo/threejspractice

branch : main

created branch time in a month

created repositoryAnniepoo/threejspractice

learning threejs and some blender, this is my practice project. Probably of no interest to others.

created time in a month

push eventAnniepoo/vinkings

Anne Ogborn

commit sha f746ebec6e06cd71229c94430d8f44562f350b82

improved ship

view details

push time in a month

MemberEvent

push eventAnniepoo/vinkings

Anne Ogborn

commit sha 5d3e8b7e3402b2766c37100cd46d3643ce4f523b

add a physics document

view details

push time in a month

push eventAnniepoo/vinkings

Anne Ogborn

commit sha ad72b6932e47e1bef18165865a713bf666f0c2ad

added ship

view details

push time in a month

push eventAnniepoo/vinkings

Anne Ogborn

commit sha 9793b70af4c5caaac7b6e5ad1a06d3f044a18833

clean up checked in files, darn unity

view details

Anne Ogborn

commit sha 25b79983049361cd02bd8008e9a450cb1b529926

yet more cleanup

view details

push time in a month

push eventAnniepoo/vinkings

Anne Ogborn

commit sha cf7dfe1cbe13bbe9d18807659ec90237d1c86b59

initial checkin

view details

push time in a month

MemberEvent

create barnchAnniepoo/vinkings

branch : main

created branch time in a month

created repositoryAnniepoo/vinkings

Entry for the historically accurate game jam

created time in a month

push eventlitonico/oso

Anne Ogborn

commit sha 49fcb28af0f348ff674fa92caa8c5e7a5153a5d5

closed some of Daves comments on the PR

view details

push time in a month

pull request commentosohq/oso

Roles quickstart

transcluding Gabe's note about late changes from Quill here

https://app.quill.chat/channel/5472268830447067652/?team=3322017235002072273&st=WyIvYWN0aXZpdHkvZGV0YWlsLzUwNjM4NTU5MDI2MTExMDEzNjYvIl0%3D

Annie / Lito if you're tracking the Polar roles code on main, you'll need to add an allow/3 rule once you update to this change that went in yesterday: https://github.com/osohq/oso/commit/9d5554714f570f1a23f06345facc52876d9cdedc

the simplest rule would look like: allow(actor, action, resource) if role_allow(actor, action, resource); we changed the entrypoint for the Polar roles policy from allow/3 -> role_allow/3 to make it so the Polar roles predicate can be composed with additional clauses in an allow/3, such as the following: allow(actor, action, post: Post) if post.is_public and role_allow(actor, action, post);

litonico

comment created time in a month

Pull request review commentosohq/oso

Roles quickstart

 --- title: Quickstart (5 min) description: |-  Ready to get started? See Oso in action, and walk through our quick-  tutorial for adding authorization to a simple web server.+  Ready to get started? See Oso in action, and walk through adding roles to an app. weight: 1 --- -# Oso in 5 minutes+# Oso Quickstart -Oso helps developers build authorization into their applications. If you’ve-never used Oso before and want to see it in action, this guide is for you.-We’re going to walk through how to use Oso to add authorization to a simple web-server.+Oso is an open-source, batteries-included library for authorizing actions in your app.+Out of the box, Oso lets you give your users roles and lets you specify permissions for those roles.+Roles can be as simple as User and Admin, or as complex as a management hierarchy. -{{% callout "Try it!" "green" %}}-  To follow along, clone the {{% exampleGet "githubApp" %}}:+[DIAGRAM] -  ```console-  git clone {{% exampleGet "githubURL" %}}-  ```-{{% /callout %}}--## Run the server+Oso isn’t restricted to roles, though — you can replace any authorization code in your app with an Oso policy. -Our sample application serves data about expenses submitted by users. The-sample application has three important files.+Why use Oso?+- Authorization always starts out simple, but can be increasingly difficult to manage as your app grows.+- Authorization is security and should be as reliable as possible.+- If you’re not an authorization expert, Oso’s design will guide you to best practices. -One file defines a simple `Expense` class and some sample data stored in a map.+Oso is a library — it runs alongside your app code and doesn’t make any calls over the network.+Your data doesn’t leave your server. Oso also doesn’t persist user data inside the library, so you stay in control of your data. -A second file has our HTTP server code, where we have defined a route handler-for `GET` requests to the path `/expenses/:id`. We’ve already added an-authorization check using the [Oso library](reference) to control access to-expense resources. <!-- TODO(gj): You can learn more about how to add Oso to-your application [here](Add To Your Application). -->+Here’s how data flows between your app and the Oso library: -The third file is the Oso policy file, `expenses.polar`, and is currently-empty.+[DIAGRAM] -{{% callout "Try it!" "green" %}}-{{% exampleGet "installation" %}}+## Install the Oso library -With the server running, open a second terminal and make a request using-cURL:--```console-$ curl localhost:5050/expenses/1-Not Authorized!+```bash+pip install --upgrade oso+# Or find the Oso package on <http://pypi.python.org/pypi/oso/>+```+## Add Oso to your app+To start, `import` Oso, create an Oso instance, and enable roles.+(Roles are a new thing in Oso, and they’re hidden behind a feature flag.)++```python+from oso import Oso+oso = Oso()+oso.enable_roles() ``` -You’ll get a “Not Authorized!” response because we haven’t added any rules to-our Oso policy (in `expenses.polar`), and Oso is deny-by-default.-{{% /callout %}}--Let’s start implementing our access control scheme by adding some rules to the-Oso policy.--## Adding our first rule--Oso rules are written in a declarative policy language called Polar. You can-include any kind of rule in a policy, but the Oso library is designed to-evaluate [allow rules](glossary#allow-rules), which specify the conditions that-allow an **actor** to perform an **action** on a **resource**.--{{% callout "Edit it!" "blue" %}}-In our policy file (`expenses.polar`), let's add a rule that allows anyone-with an email ending in `"@example.com"` to view all expenses:--{{< literalInclude dynPath="expensesPath1"-                   fallback="expenses1" >}}--Note that the call to `{{< exampleGet "endswith" >}}` is actually calling-out to {{< exampleGet "endswithURL" >}}. The actor value passed to Oso is a-string, and Oso allows us to call methods on it.-{{% /callout %}}--The `Expense` and `String` terms following the colons in the head of the rule-are [specializers](polar-syntax#specialization), patterns that control rule-execution based on whether they match the supplied argument. This syntax-ensures that the rule will only be evaluated when the actor is a string and the-resource is an instance of the `Expense` class.+## Accept or deny requests -{{% callout "Try it!" "green" %}}-  Once we've added our new rule and restarted the web server, every user with-  an `@example.com` email should be allowed to view any expense:+When a request arrives, your application will ask Oso if it should accept the request. Oso needs three pieces of information to make that decision:+- Who is making the request? (the "actor")+- What are they trying to do? (the "action")+- What are they doing it to? (the "resource") -  ```console-  $ curl -H "user: alice@example.com" localhost:5050/expenses/1-  Expense(...)-  ```-{{% /callout %}}+In Oso, these pieces of information are passed to the `is_allowed` call: `is_allowed(actor, action, resource)`.+`is_allowed` will return `True` or `False`, and your application can choose how to enforce that decision. -Okay, so what just happened?+That enforcement can happen in the request handler, at the database layer, or in middleware — here, we’ve chosen to enforce in the request handler.+Here’s a Flask route that displays a page if this user is allowed to read the associated page. -When we ask Oso for a policy decision via `Oso.{{% exampleGet "isAllowed" %}}()`, the Oso engine-searches through its knowledge base to determine whether the provided-**actor**, **action**, and **resource** satisfy any **allow** rules. In the-above case, we passed in `"alice@example.com"` as the **actor**, `"GET"` as the-**action**, and the `Expense` object with `id=1` as the **resource**. Since-`"alice@example.com"` ends with `@example.com`, our rule is satisfied, and-Alice is allowed to view the requested expense.+```python+from flask import Flask -{{% callout "Try it!" "green" %}}-  If a user's email doesn't end in `"@example.com"`, the rule fails, and they-  are denied access:+app = Flask(__name__)+@app.route("/some/page/<pagenum>")+def page_show(pagenum):+   page = Page.pages[int(pagenum)]+   if oso.is_allowed(+       get_user(), # the user doing the request+       "read", # the action we want to do+       page): # the resource we want to do it to -```console-$ curl -H "user: alice@foo.com" localhost:5050/expenses/1-Not Authorized!+       return f'<h1>A Page</h1><p>this is page {pagenum}</p>'+   else:+       return f'<h1>Sorry</h1><p>You are not allowed to see this page</p>' ``` -  If you aren’t seeing the same thing, make sure you created your policy-  correctly in `expenses.polar`.-{{% /callout %}}--## Using application data--We now have some basic access control in place, but we can do better.-Currently, anyone with an email ending in `@example.com` can see all expenses —-including expenses submitted by others.--{{% callout "Edit it!" "blue" %}}-  Let's modify our existing rule such that users can only see their own-  expenses:--  {{< literalInclude dynPath="expensesPath2"-                     fallback="expenses2" >}}-{{% /callout %}}+Oso denies requests unless you explicitly tell it to accept that sort of request.+You can tell Oso what requests to accept by providing it with a file full of rules, which we call a ‘policy’. -Behind the scenes, Oso looks up the `submitted_by` field on the provided-`Expense` instance and compares that value against the provided **actor**. And-just like that, an actor can only see an expense if they submitted it!+## Write an authorization policy+Here is a typical policy, written in our declarative language, **Polar**.+It lets any actor with the role `user` read a page, but only lets actors with the role `admin` write to a page. -{{% callout "Try it!" "green" %}}-  Alice can see her own expenses but not Bhavik's:+We can load our example policy from a file with the extension `.polar`. -```console-$ curl -H "user: alice@example.com" localhost:5050/expenses/1-Expense(...)+```python+oso.load_file("example.polar") ``` -```console-$ curl -H "user: alice@example.com" localhost:5050/expenses/3-Not Authorized!+Here’s the example.polar file:++```polar+actor_role(actor, role) if+   resources = Page.pages and+   r in resources and+   actions = r.has_roles(actor) and+   action in actions and+   role = { name: action, resource: r };++resource(_type: Page, "page", actions, roles) if+   actions = ["read", "write"] and+   roles = {+       admin: {+           permissions: ["write"],+           implies: ["user"]+       },+       user: {+           permissions: ["read"]+       }+   };+ ```++An _actor_role_ rule expresses the relationship between an actor and a role object of the form `{name: “the-role-name”, resource: TheResourceObject}`.+The `is_allowed` call in your Python code will look up this rule, so this is required.++A _resource_ rule governs access to a specific resource in your app — for instance, a page, an object, a route, or a database entry.+Here, there are two possible actions that can be done to a Page: “read” and “write.”+Users can read, but not write, to a page.+Admins are allowed to write to a Page.+The line `implies: [“user”]` says that admins can also do anything Users are allowed to do; that is, read a Page.++There’s much more you can do with Polar, including defining parent-child relationships — we’re just scratching the surface here.++## Calling back into your Python code++You can call properties and methods on your Python objects from Polar.+These will defer control back to your app.+Oso leaves the decision of how to store role assignments up to you — you might choose to store those role assignments in a database, in memory, or create them dynamically.+Our `actor_role` rule calls your Python method `has_roles` to get all the roles for our actor.++```polar+actor_role(actor, role) if+     resources = Page.pages and+     r in resources and+     actions = r.has_roles(actor) and+     action in actions and+     role = { name: action, resource: r };+ ```++To access properties on your Python objects, you must `register` their classes with Oso.++```python+from oso import Oso+oso = Oso()++oso.register_class(Page)+oso.register_class(User) ``` -  ```console-  $ curl -H "user: alice@example.com" localhost:5050/expenses/3-  Not Authorized!-  ```-{{% /callout %}}--Feel free to play around with the current policy and experiment with adding-your own rules!--For example, if you have `Expense` and `User` classes defined in your-application, you could write a policy rule in Oso that says a `User` may-`"approve"` an `Expense` if they manage the `User` who submitted the expense-and the expense’s amount is less than $100.00:--{{< code file="expenses.polar" >}}-allow(approver: User, "approve", expense: Expense) if-    approver = expense.{{% exampleGet "submitted_by" %}}.{{% exampleGet "manager" %}}-    and expense.{{% exampleGet "amount" %}} < 10000;-{{< /code >}}--In the process of evaluating that rule, the Oso engine would call back into the-application in order to make determinations that rely on application data, such-as:--- Which user submitted the expense in question?-- Who is their manager?-- Is their manager the user who’s attempting to approve the expense?-- Does the expense’s `amount` field contain a value less than $100.00?--For more on leveraging application data in an Oso policy, check out-[Application Types](policies#application-types).- ## Want to talk it through?  If you have any questions, are getting stuck, or just want to talk something through, jump into [Slack](https://join-slack.osohq.com/) and an engineer from the core team (or one of the hundreds of developers in the growing community) will help you out. +## Complete Running Example++```python+# install Oso+# put this code in a file named example.py+# run:+# python example.py+# browse http://127.0.0.1:5000/some/page/2++class Page:+   pages = []++   def __init__(self, pagenum):+       self.pagenum = pagenum++   # in a real application the returned list would+   # include all the roles available for this actor+   # for now every actor has the role "user"+   def has_roles(self, actor):+       return ["user"]++   def get_pages():+       return Page.pages++Page.pages = [Page(0), Page(1), Page(2)]++class User:+   def __init__(self, name):+       self.name = name++# Get the user -+def get_user():+   return User("someuser")++def get_page(pagenum):+   return Page.pages[pagenum]++from oso import Oso+oso = Oso()+oso.enable_roles()+oso.register_class(Page)+oso.register_class(User)++from flask import Flask++app = Flask(__name__)+@app.route("/some/page/<pagenum>")+def page_show(pagenum):+   page = Page.pages[int(pagenum)]+   if oso.is_allowed(+       get_user(), # the user doing the request+       "read", # the action we want to do+       page): # the resource we want to do it to++       return f'<h1>A Page</h1><p>this is page {pagenum}</p>'+   else:+       return f'<h1>Sorry</h1><p>You are not allowed to see this page</p>'++# we can load our policy from a file, or from a string, as here+oso.load_str("""

Already addressed - this is the best compromise for making a one file example while explaining what a .polar file is. There's no perfect solution here. See comment in complete example.

litonico

comment created time in a month

PullRequestReviewEvent

Pull request review commentosohq/oso

Roles quickstart

 --- title: Quickstart (5 min) description: |-  Ready to get started? See Oso in action, and walk through our quick-  tutorial for adding authorization to a simple web server.+  Ready to get started? See Oso in action, and walk through adding roles to an app. weight: 1 --- -# Oso in 5 minutes+# Oso Quickstart -Oso helps developers build authorization into their applications. If you’ve-never used Oso before and want to see it in action, this guide is for you.-We’re going to walk through how to use Oso to add authorization to a simple web-server.+Oso is an open-source, batteries-included library for authorizing actions in your app.+Out of the box, Oso lets you give your users roles and lets you specify permissions for those roles.+Roles can be as simple as User and Admin, or as complex as a management hierarchy. -{{% callout "Try it!" "green" %}}-  To follow along, clone the {{% exampleGet "githubApp" %}}:+[DIAGRAM] -  ```console-  git clone {{% exampleGet "githubURL" %}}-  ```-{{% /callout %}}--## Run the server+Oso isn’t restricted to roles, though — you can replace any authorization code in your app with an Oso policy. -Our sample application serves data about expenses submitted by users. The-sample application has three important files.+Why use Oso?+- Authorization always starts out simple, but can be increasingly difficult to manage as your app grows.+- Authorization is security and should be as reliable as possible.+- If you’re not an authorization expert, Oso’s design will guide you to best practices. -One file defines a simple `Expense` class and some sample data stored in a map.+Oso is a library — it runs alongside your app code and doesn’t make any calls over the network.+Your data doesn’t leave your server. Oso also doesn’t persist user data inside the library, so you stay in control of your data. -A second file has our HTTP server code, where we have defined a route handler-for `GET` requests to the path `/expenses/:id`. We’ve already added an-authorization check using the [Oso library](reference) to control access to-expense resources. <!-- TODO(gj): You can learn more about how to add Oso to-your application [here](Add To Your Application). -->+Here’s how data flows between your app and the Oso library: -The third file is the Oso policy file, `expenses.polar`, and is currently-empty.+[DIAGRAM] -{{% callout "Try it!" "green" %}}-{{% exampleGet "installation" %}}+## Install the Oso library -With the server running, open a second terminal and make a request using-cURL:--```console-$ curl localhost:5050/expenses/1-Not Authorized!+```bash+pip install --upgrade oso+# Or find the Oso package on <http://pypi.python.org/pypi/oso/>+```+## Add Oso to your app+To start, `import` Oso, create an Oso instance, and enable roles.+(Roles are a new thing in Oso, and they’re hidden behind a feature flag.)++```python+from oso import Oso+oso = Oso()+oso.enable_roles() ``` -You’ll get a “Not Authorized!” response because we haven’t added any rules to-our Oso policy (in `expenses.polar`), and Oso is deny-by-default.-{{% /callout %}}--Let’s start implementing our access control scheme by adding some rules to the-Oso policy.--## Adding our first rule--Oso rules are written in a declarative policy language called Polar. You can-include any kind of rule in a policy, but the Oso library is designed to-evaluate [allow rules](glossary#allow-rules), which specify the conditions that-allow an **actor** to perform an **action** on a **resource**.--{{% callout "Edit it!" "blue" %}}-In our policy file (`expenses.polar`), let's add a rule that allows anyone-with an email ending in `"@example.com"` to view all expenses:--{{< literalInclude dynPath="expensesPath1"-                   fallback="expenses1" >}}--Note that the call to `{{< exampleGet "endswith" >}}` is actually calling-out to {{< exampleGet "endswithURL" >}}. The actor value passed to Oso is a-string, and Oso allows us to call methods on it.-{{% /callout %}}--The `Expense` and `String` terms following the colons in the head of the rule-are [specializers](polar-syntax#specialization), patterns that control rule-execution based on whether they match the supplied argument. This syntax-ensures that the rule will only be evaluated when the actor is a string and the-resource is an instance of the `Expense` class.+## Accept or deny requests -{{% callout "Try it!" "green" %}}-  Once we've added our new rule and restarted the web server, every user with-  an `@example.com` email should be allowed to view any expense:+When a request arrives, your application will ask Oso if it should accept the request. Oso needs three pieces of information to make that decision:+- Who is making the request? (the "actor")+- What are they trying to do? (the "action")+- What are they doing it to? (the "resource") -  ```console-  $ curl -H "user: alice@example.com" localhost:5050/expenses/1-  Expense(...)-  ```-{{% /callout %}}+In Oso, these pieces of information are passed to the `is_allowed` call: `is_allowed(actor, action, resource)`.+`is_allowed` will return `True` or `False`, and your application can choose how to enforce that decision. -Okay, so what just happened?+That enforcement can happen in the request handler, at the database layer, or in middleware — here, we’ve chosen to enforce in the request handler.+Here’s a Flask route that displays a page if this user is allowed to read the associated page. -When we ask Oso for a policy decision via `Oso.{{% exampleGet "isAllowed" %}}()`, the Oso engine-searches through its knowledge base to determine whether the provided-**actor**, **action**, and **resource** satisfy any **allow** rules. In the-above case, we passed in `"alice@example.com"` as the **actor**, `"GET"` as the-**action**, and the `Expense` object with `id=1` as the **resource**. Since-`"alice@example.com"` ends with `@example.com`, our rule is satisfied, and-Alice is allowed to view the requested expense.+```python+from flask import Flask -{{% callout "Try it!" "green" %}}-  If a user's email doesn't end in `"@example.com"`, the rule fails, and they-  are denied access:+app = Flask(__name__)+@app.route("/some/page/<pagenum>")+def page_show(pagenum):+   page = Page.pages[int(pagenum)]+   if oso.is_allowed(+       get_user(), # the user doing the request+       "read", # the action we want to do+       page): # the resource we want to do it to -```console-$ curl -H "user: alice@foo.com" localhost:5050/expenses/1-Not Authorized!+       return f'<h1>A Page</h1><p>this is page {pagenum}</p>'+   else:+       return f'<h1>Sorry</h1><p>You are not allowed to see this page</p>' ``` -  If you aren’t seeing the same thing, make sure you created your policy-  correctly in `expenses.polar`.-{{% /callout %}}--## Using application data--We now have some basic access control in place, but we can do better.-Currently, anyone with an email ending in `@example.com` can see all expenses —-including expenses submitted by others.--{{% callout "Edit it!" "blue" %}}-  Let's modify our existing rule such that users can only see their own-  expenses:--  {{< literalInclude dynPath="expensesPath2"-                     fallback="expenses2" >}}-{{% /callout %}}+Oso denies requests unless you explicitly tell it to accept that sort of request.+You can tell Oso what requests to accept by providing it with a file full of rules, which we call a ‘policy’. -Behind the scenes, Oso looks up the `submitted_by` field on the provided-`Expense` instance and compares that value against the provided **actor**. And-just like that, an actor can only see an expense if they submitted it!+## Write an authorization policy+Here is a typical policy, written in our declarative language, **Polar**.+It lets any actor with the role `user` read a page, but only lets actors with the role `admin` write to a page. -{{% callout "Try it!" "green" %}}-  Alice can see her own expenses but not Bhavik's:+We can load our example policy from a file with the extension `.polar`. -```console-$ curl -H "user: alice@example.com" localhost:5050/expenses/1-Expense(...)+```python+oso.load_file("example.polar") ``` -```console-$ curl -H "user: alice@example.com" localhost:5050/expenses/3-Not Authorized!+Here’s the example.polar file:++```polar+actor_role(actor, role) if+   resources = Page.pages and+   r in resources and+   actions = r.has_roles(actor) and+   action in actions and+   role = { name: action, resource: r };++resource(_type: Page, "page", actions, roles) if+   actions = ["read", "write"] and+   roles = {+       admin: {+           permissions: ["write"],+           implies: ["user"]+       },+       user: {+           permissions: ["read"]+       }+   };+ ```++An _actor_role_ rule expresses the relationship between an actor and a role object of the form `{name: “the-role-name”, resource: TheResourceObject}`.+The `is_allowed` call in your Python code will look up this rule, so this is required.++A _resource_ rule governs access to a specific resource in your app — for instance, a page, an object, a route, or a database entry.+Here, there are two possible actions that can be done to a Page: “read” and “write.”+Users can read, but not write, to a page.+Admins are allowed to write to a Page.+The line `implies: [“user”]` says that admins can also do anything Users are allowed to do; that is, read a Page.++There’s much more you can do with Polar, including defining parent-child relationships — we’re just scratching the surface here.++## Calling back into your Python code++You can call properties and methods on your Python objects from Polar.+These will defer control back to your app.+Oso leaves the decision of how to store role assignments up to you — you might choose to store those role assignments in a database, in memory, or create them dynamically.+Our `actor_role` rule calls your Python method `has_roles` to get all the roles for our actor.++```polar+actor_role(actor, role) if+     resources = Page.pages and+     r in resources and+     actions = r.has_roles(actor) and+     action in actions and+     role = { name: action, resource: r };+ ```++To access properties on your Python objects, you must `register` their classes with Oso.

fixed

litonico

comment created time in a month

PullRequestReviewEvent

Pull request review commentosohq/oso

Roles quickstart

 --- title: Quickstart (5 min) description: |-  Ready to get started? See Oso in action, and walk through our quick-  tutorial for adding authorization to a simple web server.+  Ready to get started? See Oso in action, and walk through adding roles to an app. weight: 1 --- -# Oso in 5 minutes+# Oso Quickstart -Oso helps developers build authorization into their applications. If you’ve-never used Oso before and want to see it in action, this guide is for you.-We’re going to walk through how to use Oso to add authorization to a simple web-server.+Oso is an open-source, batteries-included library for authorizing actions in your app.+Out of the box, Oso lets you give your users roles and lets you specify permissions for those roles.+Roles can be as simple as User and Admin, or as complex as a management hierarchy. -{{% callout "Try it!" "green" %}}-  To follow along, clone the {{% exampleGet "githubApp" %}}:+[DIAGRAM] -  ```console-  git clone {{% exampleGet "githubURL" %}}-  ```-{{% /callout %}}--## Run the server+Oso isn’t restricted to roles, though — you can replace any authorization code in your app with an Oso policy. -Our sample application serves data about expenses submitted by users. The-sample application has three important files.+Why use Oso?+- Authorization always starts out simple, but can be increasingly difficult to manage as your app grows.+- Authorization is security and should be as reliable as possible.+- If you’re not an authorization expert, Oso’s design will guide you to best practices. -One file defines a simple `Expense` class and some sample data stored in a map.+Oso is a library — it runs alongside your app code and doesn’t make any calls over the network.+Your data doesn’t leave your server. Oso also doesn’t persist user data inside the library, so you stay in control of your data. -A second file has our HTTP server code, where we have defined a route handler-for `GET` requests to the path `/expenses/:id`. We’ve already added an-authorization check using the [Oso library](reference) to control access to-expense resources. <!-- TODO(gj): You can learn more about how to add Oso to-your application [here](Add To Your Application). -->+Here’s how data flows between your app and the Oso library: -The third file is the Oso policy file, `expenses.polar`, and is currently-empty.+[DIAGRAM] -{{% callout "Try it!" "green" %}}-{{% exampleGet "installation" %}}+## Install the Oso library -With the server running, open a second terminal and make a request using-cURL:--```console-$ curl localhost:5050/expenses/1-Not Authorized!+```bash+pip install --upgrade oso+# Or find the Oso package on <http://pypi.python.org/pypi/oso/>+```+## Add Oso to your app+To start, `import` Oso, create an Oso instance, and enable roles.+(Roles are a new thing in Oso, and they’re hidden behind a feature flag.)++```python+from oso import Oso+oso = Oso()+oso.enable_roles() ``` -You’ll get a “Not Authorized!” response because we haven’t added any rules to-our Oso policy (in `expenses.polar`), and Oso is deny-by-default.-{{% /callout %}}--Let’s start implementing our access control scheme by adding some rules to the-Oso policy.--## Adding our first rule--Oso rules are written in a declarative policy language called Polar. You can-include any kind of rule in a policy, but the Oso library is designed to-evaluate [allow rules](glossary#allow-rules), which specify the conditions that-allow an **actor** to perform an **action** on a **resource**.--{{% callout "Edit it!" "blue" %}}-In our policy file (`expenses.polar`), let's add a rule that allows anyone-with an email ending in `"@example.com"` to view all expenses:--{{< literalInclude dynPath="expensesPath1"-                   fallback="expenses1" >}}--Note that the call to `{{< exampleGet "endswith" >}}` is actually calling-out to {{< exampleGet "endswithURL" >}}. The actor value passed to Oso is a-string, and Oso allows us to call methods on it.-{{% /callout %}}--The `Expense` and `String` terms following the colons in the head of the rule-are [specializers](polar-syntax#specialization), patterns that control rule-execution based on whether they match the supplied argument. This syntax-ensures that the rule will only be evaluated when the actor is a string and the-resource is an instance of the `Expense` class.+## Accept or deny requests -{{% callout "Try it!" "green" %}}-  Once we've added our new rule and restarted the web server, every user with-  an `@example.com` email should be allowed to view any expense:+When a request arrives, your application will ask Oso if it should accept the request. Oso needs three pieces of information to make that decision:+- Who is making the request? (the "actor")+- What are they trying to do? (the "action")+- What are they doing it to? (the "resource") -  ```console-  $ curl -H "user: alice@example.com" localhost:5050/expenses/1-  Expense(...)-  ```-{{% /callout %}}+In Oso, these pieces of information are passed to the `is_allowed` call: `is_allowed(actor, action, resource)`.+`is_allowed` will return `True` or `False`, and your application can choose how to enforce that decision. -Okay, so what just happened?+That enforcement can happen in the request handler, at the database layer, or in middleware — here, we’ve chosen to enforce in the request handler.+Here’s a Flask route that displays a page if this user is allowed to read the associated page. -When we ask Oso for a policy decision via `Oso.{{% exampleGet "isAllowed" %}}()`, the Oso engine-searches through its knowledge base to determine whether the provided-**actor**, **action**, and **resource** satisfy any **allow** rules. In the-above case, we passed in `"alice@example.com"` as the **actor**, `"GET"` as the-**action**, and the `Expense` object with `id=1` as the **resource**. Since-`"alice@example.com"` ends with `@example.com`, our rule is satisfied, and-Alice is allowed to view the requested expense.+```python+from flask import Flask -{{% callout "Try it!" "green" %}}-  If a user's email doesn't end in `"@example.com"`, the rule fails, and they-  are denied access:+app = Flask(__name__)+@app.route("/some/page/<pagenum>")+def page_show(pagenum):+   page = Page.pages[int(pagenum)]+   if oso.is_allowed(+       get_user(), # the user doing the request+       "read", # the action we want to do+       page): # the resource we want to do it to -```console-$ curl -H "user: alice@foo.com" localhost:5050/expenses/1-Not Authorized!+       return f'<h1>A Page</h1><p>this is page {pagenum}</p>'+   else:+       return f'<h1>Sorry</h1><p>You are not allowed to see this page</p>' ``` -  If you aren’t seeing the same thing, make sure you created your policy-  correctly in `expenses.polar`.-{{% /callout %}}--## Using application data--We now have some basic access control in place, but we can do better.-Currently, anyone with an email ending in `@example.com` can see all expenses —-including expenses submitted by others.--{{% callout "Edit it!" "blue" %}}-  Let's modify our existing rule such that users can only see their own-  expenses:--  {{< literalInclude dynPath="expensesPath2"-                     fallback="expenses2" >}}-{{% /callout %}}+Oso denies requests unless you explicitly tell it to accept that sort of request.+You can tell Oso what requests to accept by providing it with a file full of rules, which we call a ‘policy’. -Behind the scenes, Oso looks up the `submitted_by` field on the provided-`Expense` instance and compares that value against the provided **actor**. And-just like that, an actor can only see an expense if they submitted it!+## Write an authorization policy+Here is a typical policy, written in our declarative language, **Polar**.+It lets any actor with the role `user` read a page, but only lets actors with the role `admin` write to a page. -{{% callout "Try it!" "green" %}}-  Alice can see her own expenses but not Bhavik's:+We can load our example policy from a file with the extension `.polar`. -```console-$ curl -H "user: alice@example.com" localhost:5050/expenses/1-Expense(...)+```python+oso.load_file("example.polar") ``` -```console-$ curl -H "user: alice@example.com" localhost:5050/expenses/3-Not Authorized!+Here’s the example.polar file:++```polar+actor_role(actor, role) if+   resources = Page.pages and+   r in resources and+   actions = r.has_roles(actor) and+   action in actions and+   role = { name: action, resource: r };++resource(_type: Page, "page", actions, roles) if+   actions = ["read", "write"] and+   roles = {+       admin: {+           permissions: ["write"],+           implies: ["user"]+       },+       user: {+           permissions: ["read"]+       }+   };+ ```++An _actor_role_ rule expresses the relationship between an actor and a role object of the form `{name: “the-role-name”, resource: TheResourceObject}`.+The `is_allowed` call in your Python code will look up this rule, so this is required.++A _resource_ rule governs access to a specific resource in your app — for instance, a page, an object, a route, or a database entry.+Here, there are two possible actions that can be done to a Page: “read” and “write.”+Users can read, but not write, to a page.+Admins are allowed to write to a Page.+The line `implies: [“user”]` says that admins can also do anything Users are allowed to do; that is, read a Page.

Fixed, pushing update to PR soon.

litonico

comment created time in a month

PullRequestReviewEvent

Pull request review commentosohq/oso

Roles quickstart

 --- title: Quickstart (5 min) description: |-  Ready to get started? See Oso in action, and walk through our quick-  tutorial for adding authorization to a simple web server.+  Ready to get started? See Oso in action, and walk through adding roles to an app. weight: 1 --- -# Oso in 5 minutes+# Oso Quickstart -Oso helps developers build authorization into their applications. If you’ve-never used Oso before and want to see it in action, this guide is for you.-We’re going to walk through how to use Oso to add authorization to a simple web-server.+Oso is an open-source, batteries-included library for authorizing actions in your app.+Out of the box, Oso lets you give your users roles and lets you specify permissions for those roles.+Roles can be as simple as User and Admin, or as complex as a management hierarchy. -{{% callout "Try it!" "green" %}}-  To follow along, clone the {{% exampleGet "githubApp" %}}:+[DIAGRAM] -  ```console-  git clone {{% exampleGet "githubURL" %}}-  ```-{{% /callout %}}--## Run the server+Oso isn’t restricted to roles, though — you can replace any authorization code in your app with an Oso policy. -Our sample application serves data about expenses submitted by users. The-sample application has three important files.+Why use Oso?+- Authorization always starts out simple, but can be increasingly difficult to manage as your app grows.+- Authorization is security and should be as reliable as possible.+- If you’re not an authorization expert, Oso’s design will guide you to best practices. -One file defines a simple `Expense` class and some sample data stored in a map.+Oso is a library — it runs alongside your app code and doesn’t make any calls over the network.+Your data doesn’t leave your server. Oso also doesn’t persist user data inside the library, so you stay in control of your data. -A second file has our HTTP server code, where we have defined a route handler-for `GET` requests to the path `/expenses/:id`. We’ve already added an-authorization check using the [Oso library](reference) to control access to-expense resources. <!-- TODO(gj): You can learn more about how to add Oso to-your application [here](Add To Your Application). -->+Here’s how data flows between your app and the Oso library: -The third file is the Oso policy file, `expenses.polar`, and is currently-empty.+[DIAGRAM] -{{% callout "Try it!" "green" %}}-{{% exampleGet "installation" %}}+## Install the Oso library -With the server running, open a second terminal and make a request using-cURL:--```console-$ curl localhost:5050/expenses/1-Not Authorized!+```bash+pip install --upgrade oso+# Or find the Oso package on <http://pypi.python.org/pypi/oso/>+```+## Add Oso to your app+To start, `import` Oso, create an Oso instance, and enable roles.+(Roles are a new thing in Oso, and they’re hidden behind a feature flag.)++```python+from oso import Oso+oso = Oso()+oso.enable_roles() ``` -You’ll get a “Not Authorized!” response because we haven’t added any rules to-our Oso policy (in `expenses.polar`), and Oso is deny-by-default.-{{% /callout %}}--Let’s start implementing our access control scheme by adding some rules to the-Oso policy.--## Adding our first rule--Oso rules are written in a declarative policy language called Polar. You can-include any kind of rule in a policy, but the Oso library is designed to-evaluate [allow rules](glossary#allow-rules), which specify the conditions that-allow an **actor** to perform an **action** on a **resource**.--{{% callout "Edit it!" "blue" %}}-In our policy file (`expenses.polar`), let's add a rule that allows anyone-with an email ending in `"@example.com"` to view all expenses:--{{< literalInclude dynPath="expensesPath1"-                   fallback="expenses1" >}}--Note that the call to `{{< exampleGet "endswith" >}}` is actually calling-out to {{< exampleGet "endswithURL" >}}. The actor value passed to Oso is a-string, and Oso allows us to call methods on it.-{{% /callout %}}--The `Expense` and `String` terms following the colons in the head of the rule-are [specializers](polar-syntax#specialization), patterns that control rule-execution based on whether they match the supplied argument. This syntax-ensures that the rule will only be evaluated when the actor is a string and the-resource is an instance of the `Expense` class.+## Accept or deny requests -{{% callout "Try it!" "green" %}}-  Once we've added our new rule and restarted the web server, every user with-  an `@example.com` email should be allowed to view any expense:+When a request arrives, your application will ask Oso if it should accept the request. Oso needs three pieces of information to make that decision:+- Who is making the request? (the "actor")+- What are they trying to do? (the "action")+- What are they doing it to? (the "resource") -  ```console-  $ curl -H "user: alice@example.com" localhost:5050/expenses/1-  Expense(...)-  ```-{{% /callout %}}+In Oso, these pieces of information are passed to the `is_allowed` call: `is_allowed(actor, action, resource)`.+`is_allowed` will return `True` or `False`, and your application can choose how to enforce that decision. -Okay, so what just happened?+That enforcement can happen in the request handler, at the database layer, or in middleware — here, we’ve chosen to enforce in the request handler.+Here’s a Flask route that displays a page if this user is allowed to read the associated page. -When we ask Oso for a policy decision via `Oso.{{% exampleGet "isAllowed" %}}()`, the Oso engine-searches through its knowledge base to determine whether the provided-**actor**, **action**, and **resource** satisfy any **allow** rules. In the-above case, we passed in `"alice@example.com"` as the **actor**, `"GET"` as the-**action**, and the `Expense` object with `id=1` as the **resource**. Since-`"alice@example.com"` ends with `@example.com`, our rule is satisfied, and-Alice is allowed to view the requested expense.+```python+from flask import Flask -{{% callout "Try it!" "green" %}}-  If a user's email doesn't end in `"@example.com"`, the rule fails, and they-  are denied access:+app = Flask(__name__)+@app.route("/some/page/<pagenum>")+def page_show(pagenum):+   page = Page.pages[int(pagenum)]+   if oso.is_allowed(+       get_user(), # the user doing the request+       "read", # the action we want to do+       page): # the resource we want to do it to -```console-$ curl -H "user: alice@foo.com" localhost:5050/expenses/1-Not Authorized!+       return f'<h1>A Page</h1><p>this is page {pagenum}</p>'+   else:+       return f'<h1>Sorry</h1><p>You are not allowed to see this page</p>' ``` -  If you aren’t seeing the same thing, make sure you created your policy-  correctly in `expenses.polar`.-{{% /callout %}}--## Using application data--We now have some basic access control in place, but we can do better.-Currently, anyone with an email ending in `@example.com` can see all expenses —-including expenses submitted by others.--{{% callout "Edit it!" "blue" %}}-  Let's modify our existing rule such that users can only see their own-  expenses:--  {{< literalInclude dynPath="expensesPath2"-                     fallback="expenses2" >}}-{{% /callout %}}+Oso denies requests unless you explicitly tell it to accept that sort of request.+You can tell Oso what requests to accept by providing it with a file full of rules, which we call a ‘policy’. -Behind the scenes, Oso looks up the `submitted_by` field on the provided-`Expense` instance and compares that value against the provided **actor**. And-just like that, an actor can only see an expense if they submitted it!+## Write an authorization policy+Here is a typical policy, written in our declarative language, **Polar**.+It lets any actor with the role `user` read a page, but only lets actors with the role `admin` write to a page. -{{% callout "Try it!" "green" %}}-  Alice can see her own expenses but not Bhavik's:+We can load our example policy from a file with the extension `.polar`. -```console-$ curl -H "user: alice@example.com" localhost:5050/expenses/1-Expense(...)+```python+oso.load_file("example.polar") ``` -```console-$ curl -H "user: alice@example.com" localhost:5050/expenses/3-Not Authorized!+Here’s the example.polar file:++```polar+actor_role(actor, role) if+   resources = Page.pages and+   r in resources and+   actions = r.has_roles(actor) and+   action in actions and+   role = { name: action, resource: r };++resource(_type: Page, "page", actions, roles) if+   actions = ["read", "write"] and+   roles = {+       admin: {+           permissions: ["write"],+           implies: ["user"]+       },+       user: {+           permissions: ["read"]+       }+   };+ ```++An _actor_role_ rule expresses the relationship between an actor and a role object of the form `{name: “the-role-name”, resource: TheResourceObject}`.+The `is_allowed` call in your Python code will look up this rule, so this is required.++A _resource_ rule governs access to a specific resource in your app — for instance, a page, an object, a route, or a database entry.+Here, there are two possible actions that can be done to a Page: “read” and “write.”+Users can read, but not write, to a page.+Admins are allowed to write to a Page.+The line `implies: [“user”]` says that admins can also do anything Users are allowed to do; that is, read a Page.

Messed up in the markdown conversion process, I'm pushing an update to fix. Marking resolved.

litonico

comment created time in a month

PullRequestReviewEvent