Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Looking for explanation on how Group, User, Project, and Account objects are meant to interact #396

Open
Freddo3000 opened this issue Mar 15, 2025 · 5 comments

Comments

@Freddo3000
Copy link

I'm looking into having a go at implementing #156 but I'm a bit confused about the setup user/account schema.

classDiagram
direction BT
class accounts {
   bigint group_id
   timestamp(0) inserted_at
   timestamp(0) updated_at
   bigint parent_id
   bigint id
}
class groups {
   bigint parent_id
   varchar(255) name
   timestamp(0) inserted_at
   timestamp(0) updated_at
   bigint id
}
class permissions {
   varchar(255) name
   timestamp(0) inserted_at
   timestamp(0) updated_at
   bigint id
}
class projects {
   bigint group_id
   varchar(255) name
   timestamp(0) inserted_at
   timestamp(0) updated_at
   bigint id
}
class role_permissions {
   bigint role_id
   bigint permission_id
   boolean is_inherited
   timestamp(0) inserted_at
   timestamp(0) updated_at
   bigint id
}
class roles {
   bigint parent_id
   varchar(255) name
   timestamp(0) inserted_at
   timestamp(0) updated_at
   bigint id
}
class user_group_roles {
   bigint user_group_id
   bigint role_id
   timestamp(0) inserted_at
   timestamp(0) updated_at
   bigint id
}
class user_groups {
   bigint user_id
   bigint group_id
   timestamp(0) inserted_at
   timestamp(0) updated_at
   bigint id
}
class users {
   citext email
   varchar(255) password_hash
   timestamp(0) activated_at
   timestamp(0) inserted_at
   timestamp(0) updated_at
   varchar(6) locale
   bigint id
}

accounts  -->  accounts : parent_id
accounts  -->  groups : group_id
groups  -->  groups : parent_id
projects  -->  groups : group_id
role_permissions  -->  permissions : permission_id
role_permissions  -->  roles : role_id
roles  -->  roles : parent_id
user_group_roles  -->  roles : role_id
user_group_roles  -->  user_groups : user_group_id
user_groups  -->  groups : group_id
user_groups  -->  users : user_id
Loading

So, a user is tied to accounts via groups, which seems to grant it access to not only accounts, but also projects and permissions such as admin access to Keila. This stands in contrast to what @wmnnd says in #156 as projects are not tied to accounts but instead groups, or at least that's the case in schema. Accounts may also have parent accounts, which I'm not sure how it is supposed to work. And on top of this there's role permissions which largely does not seem to be in use yet tied to to the user groups?

It feels like there are some foreign keys that should either point to other places, be one-to-one relationships, or merged, though I could just be misunderstanding the schema.

@wmnnd
Copy link
Contributor

wmnnd commented Mar 15, 2025

Hey there, I’m happy to explain how these things work!

Accounts are essentially billing entities (think of them as billing accounts), that's why they can have a parent account.
Users represent an individual with login credentials.
Projects are how all domain-relevant information is grouped; i.e. every contact, campaign, signup form, etc. belongs to a project.

Now here is what currently happens when a new user is created:

  1. A new Group is created
  2. A new Account is created and associated with that Group
  3. The new User is associated with the same Group

When that user creates a project, this is what happens:

  1. The current user’s account Group is retrieved
  2. A new Group is created for the project with the account Group as its parent
  3. The new Project is associated with the new Group

The association between a User and a Group is done through the user_group_roles table which also allows specifying a Role (which in turn can have Permissions) for that association. Currently, the role and permissions system is not really used (because the UI doesn't allow adding multiple people to a project/account) - except for determining who is a "system admin", i.e. who has the "administer_keila" permission on the root group.

@wmnnd
Copy link
Contributor

wmnnd commented Mar 15, 2025

I hope that clears it up a bit. If you do want to take on #156, I would kindly ask you to write out the specs of what exactly you want to implement and which additional UIs you want to build and share them with me beforehand so we can make sure it aligns with the overall roadmap I have in mind 😊

@Freddo3000
Copy link
Author

It clears it up a bit. When it comes to parent accounts, should a user that has access to a group of a parent account have access to all child accounts, and likewise for parent groups? How does sending out a campaign through a project determine which account to bill? It seems to me that group-account should be a one-to-one relationship as you describe it, and looking at stuff like

def get_project_account(project_id) when is_id(project_id) do
project = Keila.Projects.get_project(project_id)
from(a in Account)
|> join(:inner, [a], g in Auth.Group, on: g.id == a.group_id)
|> join(:inner, [a, g], pg in Auth.Group, on: pg.parent_id == g.id)
|> join(:inner, [a, g, pg], p in Keila.Projects.Project, on: p.group_id == pg.id)
|> where([a, g, pg, p], p.id == ^project.id)
|> Repo.one()
end

@wmnnd
Copy link
Contributor

wmnnd commented Mar 15, 2025

Every account is directly associated with only one group. Every project is associated with only one group. Though neither is enforced at the DB-level iirc.

The code example above can be read from bottom to top like this:

  1. Find the project with the given ID
  2. Get the project's group
  3. Get the parent group of that group
  4. Get the account that is associated with the parent group

@Freddo3000
Copy link
Author

Freddo3000 commented Mar 17, 2025

Alright, got it.

The way I'd envision changing it then is to split Account and User settings, moving the current settings to User settings, and adding an option to add/remove users to accounts. I'd also add an Account select at the top of the sidebar similar to how Stripe handles accounts v users. Depending on the currently selected account different projects would be visible. I might also look into disabling the default account creation whenever you create a user, instead requiring the user to create an account afterwards and set whatever account settings.

Is that in line with what you have in mind?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants