What is the correct way to model authorization in KeyCloak?
We would like to model:
Who is allowed
On what peace of data
What kind of action to do
For example, does the user Bob [who] can edit [action] a note title [peace of data]?
Related
I have sample project for identity customization using
Install-Package Microsoft.AspNet.Identity.Samples -pre
command. But, for this project I have a general ApplicationUser class representing all the users of my application. What if I have different categories of users. For example, I may have Teacher and Student entities and data representing both the entities will be different. How can I customize my application to store data for both the entities having all the features of ApplicationUser?
One way that I think is inheriting both the classes from ApplicationUser and then doing appropriate changes in IdentityConfig.csand defining Controllers for each of them. Is there any other efficient way of doing this?
What if I want to use the built-in authentication and authorization features but using database first workflow?
First, you want to know how to create "types" of users. The way you would do that is exactly how you expected: inherit from ApplicationUser. By default, this will result in a single "users" table with an additional Discriminator column. This column will store the class type that was persisted, i.e. "Teacher", "Student", or "ApplicationUser", and EF will utilize this information to new up the right class for each particular record.
One thing to note with this, though, is that you need to be aware of how UserManager works, namely that it's a generic class (UserManager<TUser>). The default AccountController implementation you have from the sample defines a UserManager property on the controller which is an instance of UserManager<ApplicationUser>. If you use this instance with something like Teacher, it will be upcast to ApplicationUser. In particular if you were to do something like UserManager.Create(teacher), it will actually save an ApplicationUser, instead (the Discriminator column's value will be "ApplicationUser", rather than "Teacher"). If you need to work with the derived user types, you'll need to create separate instances of UserManager<Teacher> and UserManager<Student> for that purpose.
Next, you want to know if you can use a "database first workflow". To answer that, we need to define exactly what that means. EF has what it calls "Database First" which employs EDMX to represent your database entities. This in particular is incompatible with Identity. However, despite the name, what EF calls "Code First", can work with an existing database just as well as create a new one. In other words, yes, you can use an existing database, if you prefer, but no you cannot use "Database First", in the EF-sense. For more information about using an existing database with Code First, see my post.
I've been using Loopback to create an API. The documentation is generally really good but doesn't really answer my question about the following: how do I extend (not replace) a built in model?
The most promising piece of information came from this page - it specifies the way of basing a class from another class, via inheritance. This is useful but not ideal - I'd like to create relationships to custom models from the stock models, for example - "Role" should have many "Permission".
The page I mention also shows a Javascript file, located at common/models/<modelName>.js, where it states you can "extend" a model based on the properties and options you give it. The server never seems to hit the file... For example - I put a file in common/models/role.js with the following content:
var properties = {
exampleProperty: {type: String, required: true}
};
var user = loopback.Model.extend('Role', properties);
console.log('test');
First off, it doesn't seem to hit the file at all (no console.log output given). Second, obviously because of the first point, it doesn't extend the model with the properties I created.
Am I missing something obvious or is the documentation just plain wrong?
You should generate a new model via slc loopback:model named user. By default, the built in user is named User, which is why you can use lowercase user or even UserModel if you prefer. Then when you are prompted by the model generator for a base model, choose User. See https://github.com/strongloop/loopback-faq-user-management/blob/master/common/models/user.json#L3
While using sails validation I need some fields only to get validated while updating and not during creation. The scenario is that when the user is getting creating the i am just taking username and password and later I ask for all the remaining data for the user and I need to apply some validation rules only during updation and not creation.
I know I can do some manual validation using lifecycle callback beforeUpdate but then I wont be using sails validation which I think is not the proper way.
How can tell the model that these rules need to be applied only during updation?
what rules specifically? One thing you can do is give the rules a true/false check to see if the record has as an Id. If it does, then its an update, if it does not, then its a create.
favorite_color : {
required : function(){
return 'id' in this // ID should be your primary key field.
}
}
I will say it would be nice if you could specify when validations occur, but currently you can not.
You may split DB entity into two separate entities and use two models. First model will require username and password and second model will require other fields.
I have noticed in Geddy that when I create a model and a subsequent record for that model, I get a very ugly model ID associated with the record. Something like:
http://localhost:4000/posts/3FEEDE8D-2669-445B-AEA1-A31092A7FEDA
Is there a way to change this?
Ideally, I would always want this to be some sort of string. Where it be for a post or user:
http://localhost:4000/posts/this-is-a-post-title
http://localhost:4000/profile/meebix
If this is possible, how should I:
Configure routes
Change primary key for model
Other implementation steps I may need
Thanks!
Yes, you can change the id if you really want to, but you'll be going off the beaten path there, so it's quite a bad idea. Let Geddy handle IDs for you.
The way I would do this (and certainly how many others have too) is to have a "slugging" function create a slug from the post title, and save that in your database. Then, query on that instead in your show action. You won't have to change your routes.
This is what your query will look like in the show action:
Post.first({slug: params.id}, function (err, post) {
params.id is whatever string you use in the route /posts/<this string>
So once you change your show links to use the slug instead of the ID you will be all set!
I want to add a form into my application for generating rules considering the attributes of Liferay Users.
Do you know a function for getting a list of this attributes? (List of parameter names)
Example:
1. Address,
2. FullName,
3. AccountId,
4. Create Date,
5. Employee Numbre,
6. And so on.....
Do you know a function for getting the type of each parameter? (Due to check type errors)
Example:
1. Address -> String
2. FullName -> String
Thank you,
Oriol
AFAIK, there is not such a method. But even if it existed, it would not provide all the info you're going for, because some of it, is not an attribute of the User Class, or the corresponding 'user_' table in the LF database.
If you understand how ServiceBuilder Model works, you'll see that there's a complex Model running under the hood, and it's not working like attributes.
For example, there is no 'user.getAddress()'., Because, Address is a Complex Class, subclassing Contact, and keeps a FK to the User. If you want one of his addresses, You can only get all his addresses (User.getAddresses()), and iterate through them, check by ContantactType and e.g. get his "business address". Respectfully, you can't call 'user.setAddress(String)', not even a "user.addAddress(Address)". A working code would look much more like :
//update an existing Address
existingAddr.setStreet1(street);
existingAddr.setZip(zip);
existingAddr.setCity(city);
AddressLocalServiceUtil.updateAddress(existingAddr);
//then update the user, to store the changes.
UserLocalServiceUtil.updateUser(user);
The same goes for the birthday, the Phones, websites and facebook urls etc
For the rest of the 'Attributes' (names and Types), you should look here
You can get a User object by calling:
User u = userService.getUserById(0);
or check liferay docs for UserService
then you can use getters like:
u.getAddresses();
u.getBirthday();
u.getFullName();
you can get it from:
User user = UserLocalServiceUtil.getUser(userId);
user.getFullName();
user.getEmailAddress();