Hi all, need help on content-digital commerce use ...
# help
p
Hi all, need help on content-digital commerce use case. So in this case a User can only view video after she purchased it. Let’s say there is a user
user-1
that purchased order
order-1
that contains 2 videos
video-1
and
video-2
. when
user-1
want to
view
a video
video-1
, the system will do check. How to best achieve this? Should the system created a new principal policy on every successful purchase?
c
Well, you could generalize it by creating a resource policy for
video
that has a condition for the
view
action that checks whether the resource (say,
video-1
) is in the list of purchased videos of the principal (
user-1
). You have to send the list of purchased videos as a principal attribute. That will work if a typical user only purchases a small number of videos. If they can purchase hundreds or thousands, then it won't be practical to list all. In that case, I don't think using Cerbos for that would be very helpful because you can just do a much more efficient database check to see if the video is in the purchased list of the user.
What you could do is to use Cerbos to enforce other restrictions on the video once you have ascertained yourself that the user has purchased it. Something like enforcing licence restrictions on a purchased video would be an ideal use case for Cerbos in that context.
p
Let’s say on average I have hundreds of thousands users, and each users on average purchase hundreds videos. If on every purchase, the system publish new principal role such as
Copy code
principalPolicy:
    principal: user-1
    rules:
        - resource: videos:video-1
          actions:
            - action: ['view', 'download_offline']
              effect: allow
would that be efficient?
c
Hmm... You could do that I suppose. But, it would be quite hard to maintain and reason about. The way I would model something similar would be to create licence levels. When a user buys a video, they get assigned a licence level. When they try to access the video, you retrieve the licence level assigned to that video for that user and send it to Cerbos along with the action they are trying to perform. There would be a Cerbos resource policy that compares the licence level (and other relevant information) to give you an yes/no answer. That is much more efficient to implement and much easier to reason about.
p
I dont quite understand. Can you elaborate and give example?
c
So, as a very simple example, let's say there's a
standard
level where users can play a video online only, a
gold
level where they can play online or download the video, a
preview
level where users can play a video only once. Here's a Playground link with a sample resource policy that enforces those rules: https://play.cerbos.dev/p/T632814caYDGEAPiZnzeEEyYPZcgkz31. When a user tries to do something with a video, you need to lookup the licence level assigned to that video for that user and send it to Cerbos. If there's no licence level stored in the database, that means that user has not bought it. You can either deny the request right away or assign them a default licence level like
preview
and perform the check using Cerbos anyway.
p
yes, that works in Netflix model where people purchase subscriptions then they can watch all the available videos, and extended subscriptions where they can watch videos in say 4K videos. But I see what you are saying. What if I create a simple policy like below
Copy code
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  version: default
  resource: "videos"
  rules:
    - actions:
        - "view"
      effect: EFFECT_ALLOW
      roles:
        - customer
      condition:
        match:
          expr: request.principal.attr.is_enrolled == true
The attr
is_enrolled
will be queried between tables to determine whether the user is enrolled to certain videos. Then I will send this
Copy code
{
  "id": "123456-7890123",
  "roles": [
    "customer"
  ],
  "attr": {
    "is_enrolled": true
  }
}
The downside is, that the backend will need to query everytime they need to check.
I am just curious, if I principal policy like this, how’s the database performance?
Copy code
apiVersion: api.cerbos.dev/v1
principalPolicy:
  version: default
  principal: "user.123456"
  rules:
    - resource: "videos"
      actions:
        - action: "watch"
          effect: EFFECT_ALLOW
          condition:
            match:
              expr: R.id == "video.123456"
        - action: "watch"
          effect: EFFECT_ALLOW
          condition:
            match:
              expr: R.id == "video.1234567"
c
I am just curious, if I principal policy like this, how’s the database performance?
Well, it's hard to give you a definitive answer there because it depends on a lot of factors. This is not the most efficient way to do it though and, frankly, I don't see the point of doing that. If all you're interested in are the videos that a user has access to, it would be much simpler to store them in a database table. That data won't be opaque, you can add indexes and partitions to look them up very efficiently, and you don' t have to constantly keep updating the policies (which is more complicated than adding a row to a table) as people buy more videos.