feat(rt): project grants (#10951)

This pull request introduces a new feature that allows adding, updating,
and querying project grants The changes are primarily in the backend and
include new database tables, repositories, and domain logic to support
project grants.

## Changes

* New `project_grants` table: A new table `zitadel.project_grants` is
introduced to store project grants It includes columns for
`instance_id`, `id`, `state`, `project_id`, `granted_org_id` and
`granting_org_id`.
* New `ProjectGrantRepository`: A new repository
`ProjectGrantRepository` is created to handle all database operations
for project grants. It provides methods to `Get`, `List`, `Create`,
`Update`, and `Delete`.
* New `project_grant_roles` table: A new table
`zitadel.project_grant_roles` is introduced to store project grant roles
It includes columns for `instance_id`, `grant_id`, `key`, `project_id`
and `project_org_id`.
* New `ProjectGrantRoleRepository`: A new repository
`ProjectGrantRoleRepository` is created to handle all database
operations for project grant roles. It provides methods to `Get`,
`List`, `Add`, and `Delete`.
* New `project_grant_relational_projection`: A new projection
`project_grant_relational_projection` is added to update the
`zitadel.project_grants` and `zitadel.project_grant_roles` tables based
on events. It handles all project grant events.
* Updated `ProjectRepository`: The `ProjectRepository` is updated to
list granted projects.

# Additional Context

Closes https://github.com/zitadel/zitadel/issues/10766

---------

Co-authored-by: Stefan Benz <[email protected]>
Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Silvan <[email protected]>
This commit is contained in:
Tim Möhlmann
2025-11-14 11:04:16 +00:00
committed by GitHub
co-authored by Stefan Benz Marco A. Silvan
parent 6051ce591d
commit 9274e008fe
15 changed files with 1782 additions and 30 deletions
@@ -0,0 +1,16 @@
package migration
import (
_ "embed"
)
var (
//go:embed 008_project_grants_table/up.sql
up008ProjectGrantsTable string
//go:embed 008_project_grants_table/down.sql
down008ProjectGrantsTable string
)
func init() {
registerSQLMigration(8, up008ProjectGrantsTable, down008ProjectGrantsTable)
}
@@ -0,0 +1,3 @@
DROP TYPE zitadel.project_grant_state;
DROP TABLE IF EXISTS zitadel.project_grant_roles;
DROP TABLE IF EXISTS zitadel.project_grants;
@@ -0,0 +1,45 @@
CREATE TYPE zitadel.project_grant_state AS ENUM (
'active',
'inactive'
);
CREATE TABLE zitadel.project_grants(
instance_id TEXT NOT NULL
, id TEXT NOT NULL CHECK (id <> '')
, granting_organization_id TEXT NOT NULL
, project_id TEXT NOT NULL
, granted_organization_id TEXT NOT NULL
, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
, state zitadel.project_grant_state NOT NULL
, PRIMARY KEY (instance_id, id)
, FOREIGN KEY (instance_id, granting_organization_id) REFERENCES zitadel.organizations(instance_id, id) ON DELETE CASCADE
, FOREIGN KEY (instance_id, granted_organization_id) REFERENCES zitadel.organizations(instance_id, id) ON DELETE CASCADE
, FOREIGN KEY (instance_id, project_id) REFERENCES zitadel.projects(instance_id, id) ON DELETE CASCADE
, UNIQUE (instance_id, project_id, granted_organization_id)
);
CREATE TRIGGER trg_set_updated_at_project_grants
BEFORE UPDATE ON zitadel.project_grants
FOR EACH ROW
WHEN (NEW.updated_at IS NULL)
EXECUTE FUNCTION zitadel.set_updated_at();
CREATE TABLE zitadel.project_grant_roles(
instance_id TEXT NOT NULL
, grant_id TEXT NOT NULL
, key TEXT NOT NULL CHECK (key <> '')
, project_id TEXT NOT NULL
, PRIMARY KEY (instance_id, grant_id, key)
, FOREIGN KEY (instance_id, grant_id) REFERENCES zitadel.project_grants(instance_id, id) ON DELETE CASCADE
, FOREIGN KEY (instance_id, project_id, key) REFERENCES zitadel.project_roles(instance_id, project_id, key) ON DELETE CASCADE
);