modernice/goes

contrib/auth: make `Granter` usable from non-auth services

Closed this issue · 0 comments

Problem

Currently, the Granter has dependencies on ActorRepositories and RoleRepository, which, in a well designed system, are not accessible from other services than an application's auth service. This means the permission granter in its current design could/should only be used within the auth service. Implementing permissions for each service of an app within the auth service makes the auth service dependent on all services that require permissions (because the auth service must handle the permission events of the other services).

Each service should be able to implement its own permission granter that grants and revokes permissions via a command bus.

Proposal

Proposal is to remove the repository dependencies from the granter and replace them with a single CommandClient dependency. The CommandClient exposes the different grant and revoke commands as an interface so that it can be implemented using an underlying command bus but also using actor and role repositories.

package auth

type CommandClient interface {
  GrantToActor(...) error
  GrantToRole(...) error
  RevokeFromActor(...) error
  RevokeFromRole(...) error
}

Using a Command Bus

package example

func example(events []string, bus command.Bus) {
  granter := auth.NewGranter([]string{"foo", "bar", "baz"}, auth.CommandBusClient(bus))
}

Using Repositories

It is still possible to implement the granter as described above (with dependencies to other services) using repositories.

package example

func example(events []string, actors ActorRepositories, roles RoleRepository) {
  client := auth.RepositoryCommandClient(actors, roles)
  g := auth.NewGranter(events, client)
}