-1

I have a complete Login and Registration system in my Django app, that lets me register users, log in users, logout users, change passwords, reset passwords, invite users. I have all the basic functionality.

I want now to have Workspaces for users, as per following points:

  • There will be a workspace admin of each workspace.
  • Workspace admins can only add/remove (register/delete) users to his own workspaces.
  • Users can react to (log in to) only those workspaces to which they have been added.
  • A superuser (main admin) can manage all workspaces, all workspaces-admins and all users.

How do I accomplish this? You can say this is similar to a Slack thing. I just need a guidelines/roadmap and I will implement it myself.

I have already created a Workspace Model, which looks like below:

class Workspace(models.Model):
    name = models.CharField(max_length=254)
    created_at = models.DateTimeField(auto_now_add=True)

    def make_admin(self, user):
        user.is_workspace_admin = True
        user.save()

    def remove_admin(self, user):
        user.is_workspace_admin = False
        user.save()

and my User model has following two attributes beside other default Django fields:

class User(AbstractBaseUser, PermissionsMixin):
    is_workspace_admin = models.BooleanField(default=True)
    workspaces = models.ManyToManyField(Workspace)

Is this approach correct? If not please guide me to the proper way. BTW, using this approach, I can add/assign workspaces to any user, but how will I be able to manage the users logging in their own workspaces and reacting with only their workspaces to which they have been assigned. And also workspaces admins controlling their workspaces’ users etc?

I know about using Groups. So let's say I create all relevant permissions (Can you also tell me how to create permissions?) to add workspace user, remove workspace user, make workspace user a workspace admin, remove workspace admin from workspace adminship etc. and create different Groups and add relevant permissions in each group. Suppose my groups looks like manage_workspace_a to manage (add/remove) the workspace users groups, manage_workspace_admins to manage (add/remove) workspace admins, and default permissions that Django provides for each Model.

So, how will i be able to have the functionality that when a "User A" that has is_superuser=True, makes the is_workspace_admin=True of "User B", then "User B" should automatically gets all the Workspace Admin Permissions. Something like this:

workspace_user = User.objects.get(email="some-email-address")

if request.user.is_superuser:
    wordspace_user.permissions.add([Workspace Admin Permissions])

Can somebody explain the whole process with a small code example?

1 Answers1

0

This is a very long, multi-part question but hopefully I can point you in the right direction

  1. I would suggest adding another Many-to-Many field on your User model that handles administrator status. At the moment, you have it set to Boolean flag - so an administrator can either manage all workspaces or none.

  2. Personally, I would reverse the M2M status and put users and administrators on the workspace, rather than on the user model. It's not problematic to have on the user model but I feel it makes more sense to check that the user is in the workspace's permitted users/admins rather than the workspace is in the user's list of workspaces and admin workspaces.

  3. You will need to change your code that adds an administrator to a workspace as you won't want to use a boolean flag:

    def make_admin(self, user):
         self.administrators.add(user)
    
  4. As to how you manage the workspace itself, you can just put ORM filters at the very start of your relevant views:

    def workspace_view(request, workspace_id):
       workspace = get_object_or_404(Workspace, workspace_id)
       if request.user not in workspace.users:
           return redirect(...)
    
       ...the rest of your view
    

    Bear in mind that this doesn't allow administrators in unless they are in the users group - you will either need to add them to users or add another condition to check if they are in administrators.

  5. If you want an overview of all the workspaces in some sort of index/home page, you would just use the m2m reverse accessor which depends on your reverse name (or /relation/_set by default):

    def workspaces(request):
        workspaces = request.user.workspaces.all()
    

You can definitely leverage Django's in-built permissions system, I would point you to the documentation because that is a long subject:

https://docs.djangoproject.com/en/4.0/topics/auth/default/#permissions-and-authorization

0sVoid
  • 2,547
  • 1
  • 10
  • 25
  • I don't want a lot of admins for a single Worlspace. So M2M relation will allow one Workspace instance to have a lot of admins. I want each Workspace instance to have only one admin. Secondly, `of request.user not in workspace.users` will make every workspace user go to a same view. What I want is to show the name of workspace the user is assigned to, in the template. So can you tll me how do I get this functionality done? – Khubaib Khawar Jul 19 '22 at 16:40
  • You can do `admin = models.ForeignKey(` instead of m2m then. And how else would you go to a workspace without a view for one? If you just want to show the user which workspace they're in then do `request.user.workspaces.all` in the template – 0sVoid Jul 19 '22 at 16:44
  • To do this, would I need to have `ForiegnKey()` in `Workspace` model like: `class Workspace:` `admins = ForiegnKey(User)` and M2M relation in `User` model, like: `class User:` `workspaces = ManyToManyField(User)` If yes, would not it create a inherit cycle which Django does not allow? and if not, then how do I use `request.user.workspaces.all` as you told in above comment? – Khubaib Khawar Jul 19 '22 at 17:16
  • You could do either, but if you have `admin` on workspace and `workspaces` on User then you need to use string reference with your app name like `workspaces = models.ManyToMany('myapp.Workspace', ...` – 0sVoid Jul 19 '22 at 17:26