I have 2 user and I want implement three actions:
Update user A resource.
Update user B resource.
Get userA and userB resources, modify both user A also user B resources.
How could I design actors for concurrency action handling?
In thread base model, I had use RepeatRead isolation transaction and wrap in a while loop until it succeed.
In actor model, if I only create one resource actor to handle all modify request, I wonder it could make a botteneck :v
Related
I have an AWS Amplify application that has a structure with multi-organizations:
Organization A -> Content of Organization A
Organization B -> Content of Organization B
Let's say we have the user Alice, Alice belongs to both organizations, however, she has different roles in each one, on organization A Alice is an administrator and has more privileges (i.e: can delete content or modify other's content), while on Organization B she is a regular user.
For this reason I cannot simply set regular groups on Amplify (Cognito), because some users, like Alice, can belong to different groups on different organizations.
One solution that I thought was having a group for each combination of organization and role.
i.e: OrganizationA__ADMIN, OrganizationB__USER, etc
So I could restrict the access on the schema using a group auth directive on the Content model:
{allow: group, groupsField: "group", operations: [update]},
The content would have a group field with a value: OrganizationA__ADMIN
Then I could add the user to the group using the Admin Queries API
However, it doesn't seem to be possible to add a user to a group dynamically, I'd have to manually create each group every time a new organization is created, which pretty much kills my idea.
Any other idea on how I can achieve the result I'm aiming for?
I know that I can add the restriction on code, but this is less safe, and I'd rather to have this constraint on the database layer.
Look into generating additional claims in you pre-token-generation handler
Basically you can create an attribute that includes organization role mapping
e.g.
{
// ...
"custom:orgmapping": "OrgA:User,OrgB:Admin"
}
then transform them in your pre-token-generation handler into "pseudo" groups that don't actually exist in the pool.
I'm developing a huge application in django and I need a permission system and I assume that the native user/group permission within django is not sufficient. Here my needs:
The application will be available through multiple departments. In each department there will be nearly the same actions. But maybe an user will be allowed to add a new team member in department A and in department B he is only allowed to view the team list and in the other departments he has no access at all.
I though using a RBAC system would be most appropriate. Roles must also be inheritable, stored in a model an managable through an interface. Any good ideas or suggestions? Regards
What you are looking for is called abac aka Attribute-Based Access Control. It's an evolution of RBAC as an access control model. In RBAC, you define access control in terms of roles, groups, and potentially permissions. You then have to write code within your application to make sense of the roles and groups. This is called identity-centric access control.
In ABAC, there are 2 new elements:
attributes which are a generalization of groups and roles. Attributes are a key-value pair that can describe anyone and anything. For instance, department, member, and action are all attributes.
policies tie attributes together to determine whether access should be granted or denied. Policies are a human-friendly way of expressing authorization. Rather than write custom code in your app, you write a policy that can be centrally managed and reused across apps, databases and APIs.
There are a couple of ABAC languages such as xacml and alfa. Using ALFA, I could write the following policy:
A user will be allowed to add a new team member in department A
In department B he is only allowed to view the team list
In the other departments he has no access at all.
Roles must also be inheritable, stored in a model an managable through an interface.
policyset appAccess{
apply firstApplicable
policy members{
target clause object = "member"
apply firstApplicable
/**
* A user can add a member to a department if they are a manager and if they are assigned to that department.
*/
rule addMember{
target clause role == "manager" and action == "add"
permit
condition user.department == target.department
}
}
}
One of the key benefits of ABAC is that you can develop as many policies as you like, audit them, share them, and not have to touch your application code at all because you end up externalizing authorization.
There are several engines / projects that implement ABAC such as:
AuthZForce (a Java library for XACML authorization)
Axiomatics Policy Server (commercial product - disclaimer: I work there)
AT&T XACML
There are two components to this question:
First, role management. Roles can be achieved through group membership, i.e. departmentA_addMember & departmentB_listMembers. These Groups would have corresponding permissions attached, e.g. "Member | Add" and "Member | View". A department in this context may have more resources included, that require separate permissions. Django allows to extend Objects with custom Permissions.
Second, inheritance. Do I understand you want to have individual Groups being member of other groups? Then this is something Django would require you to implement yourself.
However, should you be looking for a really more complex authentication solution, it may be worthwhile to integrate with 3rd party services through, e.g. django-allauth. There are sure more/other solutions, just to throw in one name.
Let's say I have a super simple user registration check that a user's email must be unique across all users.
I've expressed this requirement in such functions.
(defn validate-user [user]
(and (:email user) (is-unique? (:email user))))
(defn is-unique? [email]
(not (db-api/user-exists {:email email})))
But I want to decouple my validation from the database, I want to make it purely functional. I could probably also inject the database API as a parameter to validate-user, like
(defn validate-user [db-api user]
(and (:email user) (is-unique? db-api (:email user))))
(defn is-unique? [db-api email]
(not ((:user-exists db-api) {:email email})))
but I don't know if this is idiomatic.
Also, it feels like the consumer of validate-user should not care about the database api. It feels like having this dependency undermines the entire concept of separating the business logic layer from the persistence layer. So I'm looking for a mindset that explains how to do this properly, or why it could not be done.
In order to avoid race conditions, the database should handle this constraint. You are probably looking for the equivalent of INSERT IF NOT EXISTSin the SQL world.
In practise, you could have a function create-user and a function update-user. The create-user function could use the IF NOT EXISTS check.
You cannot decouple it from the database : it is the database responsibility to maintain the constraints of the data (relations, in the relational world). Nobody else than the database can do it due to race conditions.
Let me expand on that with an example :
Suppose that two users (userA and userB) wish at the very same time to create an account with a new email not already chosen : "user#example.com". Your system then queries the database :
checking that "user#example.com" doesn't exists on behalf of userA, it returns true
checking that "user#example.com" doesn't exists on behalf of userB, it returns true
You then proceed to :
create an account for userA with a mail "user#example.com"
create an account for userB with a mail "user#example.com"
Depending of the semantics of the database and your requests, you may end up with :
two accounts with the mail "user#example.com" (ex. no constraint on the database, no unique index)
an account for "userB" is created, no account for userA (ex. the request to create the account for userA failed because there was already a mal present)
an account for "userB" is created, then the data for "userA" overrides the data from "userB" (ex. the semantics of an update statement are user in the database - probably a bug at this point)
Because of that, you should try to create an account, and let the database tell you if it failed. You just cannot check that yourself, without recreating the properties of a database yourself (I personally wouldn't dare trying).
I would like to automatically create some objects instance when a new user is created. I think using signals would be the best strategy but it seems there is no signal attached to user creation.
I am also using django-registration, but I would prefer using signals on user creation rather than on user registration.
What is the best approach for such purpose?
Using tastypie, how do I only authorize authors of objects the ability to edit/delete objects they have created? For example, if user 1 created an object A, how can I make it so user 2 cannot edit or delete object A but user 1 can edit or delete object A?
Check this cook-book entry:
http://django-tastypie.readthedocs.org/en/latest/cookbook.html#creating-per-user-resources
If that doesn't fit you well, there is an WIP on per-object permissions in the perms branch of tastypie repo. You might want to check that out but beware that it's not ready yet.