I'm trying to extend User models with my custom model by inheriting from it like this:
class Profile(User):
...
I would like to add my custom fields to the User model but django nonrel fails with an error:
DatabaseError: Multi-table inheritance is not supported by non-relational DBs.
So how I can solve this problem? I definitely need my custom fields in User model.
Instead of overriding the User model you should create another class that holds the additional fields and bind it to User model by a 1-to-1 relationship.
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
nickname = models.CharField(max_length=50)
...
...
You Cannot do something like that in google-app-engine. If you want to have relationship in your model. You should denormailse your model in such a way that the same can be achieved in appengine's way.To know more about modeling in appengine . You can have go through the following links.
modeling in appengine
Daily profeth modeling in appengine
I wanted the request.user object to be the normal User object, but with added fields. The accepted answer doesn't allow that, as UserProfile has a member "user" instead of being a user.
This article explains how to instead inherit from User.
The steps in brief:
Make CustomUser inherit from User
Set up a custom authentication backend to return CustomUser
Have not tried it yet.
Related
We are in the process of making a UberEat like app and will be using Django for the backend. I discovered wagtail not so long ago and was wondering if it would be possible to use it for our vendors, with each vendor having the possibility to log into Wagtail admin and having access to his/her own products, category, prices, etc. Rephrased, is there a possibility to have different admins in Wagtail that would have access to their own model instances ?
Thanks to you all
With Wagtail’s page permissions you could solve that via a "parent" page in combination with a custom "group" for each vendor. A clumsy workaround to be honest, it would require 3 steps, which could be automated. But this way you could use the full-featured Wagtail CMS in a way, in which each vendor could only see their "own" pages.
You could manage images and documents in the same way by assigning collections to vendors as well. But let’s start with the pages here.
The slug would look something like ubereatlike.app/vendorxyz/... with vendorxyz/ representing this "parent" page.
Groups can be added via the SETTINGS in the sidebar. Groups are a native part of the Django framework, see documentation. To add a new vendor, you would have to do three steps. (1) Create a parent page for this vendor. (2) Create a group for this vendor via SETTINGS --> GROUPS. Here you should check "Can access admin" and create a "native" new page permisson for the vendor’s page with all necessary permissions, like "Add", "Edit" and "Publish", for example. (3) Lastly you would have to add a new User for the vendor and choose its group as role.
To automate this I would create a custom user model, see documentation. With a post_signal for this custom user model, I would create both the parent page and the group and its permissions. This way you would add the User only and the page and the group would be generated programmatically.
# startapp vendors with models.py
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import Group, Permission
from django.dispatch import receiver
from wagtail.models import Page
from home.models import HomePage
class VendorPage(Page):
parent_page_types = ['home.HomePage']
...
class Vendor(AbstractUser):
company_name = models.CharField(max_length=255)
# ...other fields
#receiver(models.signals.post_save, sender=Vendor)
def vendor_created(sender, instance, created, **kwargs):
if created:
# create vendor page as child of home page
home_page = HomePage.objects.first()
vendor_page = VendorPage(title=instance.company_name)
home_page.add_child(instance=vendor_page)
vendor_page.save_revision().publish() # recommended
# create group with permissions
vendor_group = Group.objects.create(...)
permission = Permisson.objects.get(...) # please look into Wagtail’s page permissons, this is just a rough draft
vendor_group.permissions.add(permission)
I want to get rid of the existing fields in the Django's in-built user model like, is_staff, last_login etc, and keep only the username and password. How can I do this in a clean way?
I was using djoser, but ran into snags customizing emails and was referred to allauth + rest-auth.
I'm trying to convert my endpoints and running into problems with models.
Firstly, my user model with djoser dropped the username in favor of email, and I moved first & last name to a one-to-one profile table and added zipcode to the user model -- effectively my users are emails with passwords and zipcodes.
allauth threw an error that username didn't exist, after searching around I found a hacky 'solution' in adding an empty username filed back into my user model (and just ignoring it). When I changed my login endpoint from /auth/token/login/ to /rest-auth/login/ I got another error django.core.exceptions.ImproperlyConfigured: Field name 'first_name' is not valid for model 'User'. I'd really like to avoid adding all of the profile fields into my user model and making them nullable -- and I don't really want to write my own authentication backend.
Does anyone have experience with this type of model overriding?
Cheers,
-E
Unless you are planning on completely avoiding Django's user infrastructure, I would not bother trying to remove the default fields.
Whenever you're customizing the django user you'll want to extend AbstractBaseUser which includes first_name, last_name, username, email, date_joined, is_staff, and is_active. You don't have to use them but they will be there. You can specify which field will be used for the username
Once you're using AbstractBaseUser as the base for your user class, your problems here will go away and you can specify what you need from allauth from their configuration docs.
Also see the allauth doc on custom user models
I'm implementing the ACL component for my CakePHP app (1.3.14). I have everything setup correctly, but there are a few areas where I'm still fuzzy.
Mainly, do I need to explicitly set rights (ACOs) for a special base user group (AROs)?
For simplicity, let's say I have Administrators and then everyone else (general users). So do I need to create a group for these general users and map all their allow rights? Seems like management of these rights would be never ending as the app grew.
Also, what about assigning users to multiple groups?
Ideally if a person had a user account the Auth component would grant access to the system as a whole. Then ACL would simply deny them from the sections that were protected by an existing group.
It seems like the coupling of ACL and Auth is too high. But it may be my new (limited) understanding. Any clarification would be greatly appreciated.
UPDATE
I've started a bounty. In summary, I want to implement CakePHP ACL (preferably, but a matching third-party component is acceptable) that meets/addresses the following:
Assign users to multiple groups
Easily maintain a "public" user group - don't have to constantly add the controllers/actions a general user can access
Code example of managing access to a controller/access
Code example of properly testing a user belongs to a group.
I think the best you can hope for using Cake's native ACL implementation is something like the following:
cake acl create aro root public
cake acl create aro root registered
cake acl create aro registered administrators
(create acos using AclExtras)
cake acl grant registered controllers
cake acl grant public controllers
cake acl deny public controllers/MySecureController
cake acl deny public controllers/Widgets update
cake acl deny public controllers/Widgets delete
(the above is all done through the cake shell, but is easily translated to the PHP variant)
Basically, you can either use a "default-deny" paradigm (as demonstrated in Cake's own ACL tutorial), or a "default-allow" paradigm as above. Whichever method you choose will depend on how you expect the application to grow: will most of your controllers be public with only a select few restricted to Administrators, or will most of your application be restricted with Public given specific access where needed? Either way, you still need to either grant or deny access.
Notice the two AROs created under root: public and registered. With this model, treat registered as if it were root when creating your ARO tree -- put all of your "real user" groups underneath it. That way, you can use ACL as normal on the objects under registered, and the public users will exist outside of that.
All that said, there's nothing stopping you from using Cake's authentication mechanism and rolling your own access control method. Here's an example: Simple Authentication and Authorization Application. (NOTE: This is written for CakePHP 2.0, but the concepts apply to 1.3 as well).
EDIT -
After re-reading the question and the other responses, I realized you're aiming more for a role-based access control model rather than the traditional one-aro-per-user model of the builtin ACL component. Here are a couple of examples of extending the built-in auth component for RBAC:
Role-based ACL in CakePHP
CakePHP Auth component: Users, Groups, Permissions
Also, this two-part article describes an approach to database-backed role-based authorization that can be applied to your Cake application.
You can have both ACOs tree and AROs tree. In the AROs tree you will have adminsGroup<-usersGroup. You will need to setup rights for these groups. In the ACOs tree you will have baseACO<-subACO<-treeOfACOsForUsers. You will not need to maintain any new ACOs if: 1) userGroups are allowed to use subACO, 2) any new ACO is a child of subACO. The idea is to organize a tree of ACOs, so that if you allow access to a parent all children are accessable automatically. You can have a branch with denied access also. So you will need to maintain (assigning permissions) only several branches close to the root.
You may be interested to look at my PoundCake Control Panel - a plugin implementing ACL with user friendly web interface (CakePHP v1.3 is supported).
UPDATE:
Here is what you need.
i use auth componnet in my cakephp project
I add type field into users Mysql table
that enum type: admin, client
i need auth component to redirect admin's to CP page, and client to their profile page and only can access one conttroller..
ofcourse without using ACL or any others related
I'd recommend taking advantage of the isAuthorized() function that you can add in the controller, or the model. Set the AuthComponent::authorize = {'controller'|'model'} to choose which you want to use.
Then you write an isAuthorized() function in the model|controller that returns t/f on auth/not auth for each action. You can do some row-level checking as well, if you'd like.
Now, if instead you just wanted to redirect an admin to their correct pages on login/etc, you can add code to the beforeFilter() method (either in a specific controller, or in app_controller.php). In that, just check to see if the admin value set by the app is the same as the user's admin value (which will be stored by AuthComponent in the Session data, accessible by $this->Auth->User()). Then route appropriately to the admin/non admin areas.
isAuthorized() is the best choice.
i would recommend to separate the users from their groups in the database, so User habtm Group... but It is not a problem if user belongs to one and only one group
I do not recommend ACL for non record-level-based permissions system
Just something to pay attention to, but unless something has changed recently CakePHP does not support ENUM column types.
Your best bet is a Group model ( groups mysql table ) and a group_id field on the users table.
Then you can $hasOne = array( 'Group' ); in your User model.
From there you can follow any one of a HUGE number of group access control tutorials for the Auth Component via an easy google search for "CakePHP Auth User Group"