fix(console): display granted org name in authorizations and show user information (#7116)

* fix: add granted org info to user grants query response

* fix: show user info, tests and add columns to user grant

* fix: add check for org membership

* fix: typo in find logic

---------

Co-authored-by: Max Peintner <max@caos.ch>
This commit is contained in:
Miguel Cabrerizo 2024-01-24 11:36:04 +01:00 committed by GitHub
parent 94b3799690
commit d590da7c7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 208 additions and 19 deletions

View File

@ -109,7 +109,7 @@
<ng-container matColumnDef="org"> <ng-container matColumnDef="org">
<th mat-header-cell *matHeaderCellDef>{{ 'PROJECT.GRANT.ORG' | translate }}</th> <th mat-header-cell *matHeaderCellDef>{{ 'PROJECT.GRANT.ORG' | translate }}</th>
<td mat-cell *matCellDef="let grant"> <td mat-cell *matCellDef="let grant">
{{ grant.orgName }} {{ grant.grantedOrgName }}
</td> </td>
</ng-container> </ng-container>
@ -169,7 +169,7 @@
<i class="las la-trash"></i> <i class="las la-trash"></i>
</button> </button>
<button menuActions mat-menu-item [routerLink]="['/users', grant.userId]"> <button menuActions mat-menu-item (click)="showUser(grant)">
{{ 'ACTIONS.TABLE.SHOWUSER' | translate: { value: grant.displayName } }} {{ 'ACTIONS.TABLE.SHOWUSER' | translate: { value: grant.displayName } }}
</button> </button>
</cnsl-table-actions> </cnsl-table-actions>

View File

@ -8,7 +8,7 @@ import { tap } from 'rxjs/operators';
import { enterAnimations } from 'src/app/animations'; import { enterAnimations } from 'src/app/animations';
import { UserGrant as AuthUserGrant } from 'src/app/proto/generated/zitadel/auth_pb'; import { UserGrant as AuthUserGrant } from 'src/app/proto/generated/zitadel/auth_pb';
import { Role } from 'src/app/proto/generated/zitadel/project_pb'; import { Role } from 'src/app/proto/generated/zitadel/project_pb';
import { Type, UserGrant as MgmtUserGrant, UserGrantQuery } from 'src/app/proto/generated/zitadel/user_pb'; import { Type, UserGrant as MgmtUserGrant, UserGrantQuery, UserGrant } from 'src/app/proto/generated/zitadel/user_pb';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service'; import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { ManagementService } from 'src/app/services/mgmt.service'; import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
@ -18,6 +18,7 @@ import { PageEvent, PaginatorComponent } from '../paginator/paginator.component'
import { UserGrantRoleDialogComponent } from '../user-grant-role-dialog/user-grant-role-dialog.component'; import { UserGrantRoleDialogComponent } from '../user-grant-role-dialog/user-grant-role-dialog.component';
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component'; import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
import { UserGrantContext, UserGrantsDataSource } from './user-grants-datasource'; import { UserGrantContext, UserGrantsDataSource } from './user-grants-datasource';
import { Org, OrgState } from 'src/app/proto/generated/zitadel/org_pb';
export enum UserGrantListSearchKey { export enum UserGrantListSearchKey {
DISPLAY_NAME, DISPLAY_NAME,
@ -68,6 +69,7 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
@Input() public type: Type | undefined = undefined; @Input() public type: Type | undefined = undefined;
public filterOpen: boolean = false; public filterOpen: boolean = false;
public myOrgs: Array<Org.AsObject> = [];
constructor( constructor(
private authService: GrpcAuthService, private authService: GrpcAuthService,
private userService: ManagementService, private userService: ManagementService,
@ -115,6 +117,9 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
} }
this.loadGrantsPage(this.type); this.loadGrantsPage(this.type);
this.authService.listMyProjectOrgs(undefined, 0).then((orgs) => {
this.myOrgs = orgs.resultList;
});
} }
public ngAfterViewInit(): void { public ngAfterViewInit(): void {
@ -300,4 +305,21 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
this.loadGrantsPage(this.type); this.loadGrantsPage(this.type);
} }
} }
public showUser(grant: UserGrant.AsObject) {
const org: Org.AsObject = {
id: grant.grantedOrgId,
name: grant.grantedOrgName,
state: OrgState.ORG_STATE_ACTIVE,
primaryDomain: grant.grantedOrgDomain,
};
// Check if user has permissions for that org before changing active org
if (this.myOrgs.find((org) => org.id === grant.grantedOrgId)) {
this.authService.setActiveOrg(org);
this.router.navigate(['/users', grant.userId]);
} else {
this.toast.showInfo('GRANTS.TOAST.CANTSHOWINFO', true);
}
}
} }

View File

@ -2227,7 +2227,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Упълномощаването е актуализирано.", "UPDATED": "Упълномощаването е актуализирано.",
"REMOVED": "Упълномощаването е премахнато", "REMOVED": "Упълномощаването е премахнато",
"BULKREMOVED": "Разрешенията са премахнати." "BULKREMOVED": "Разрешенията са премахнати.",
"CANTSHOWINFO": "Не можете да посетите профила на този потребител, тъй като не сте член на организацията, към която принадлежи този потребител"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Изтриване на разрешението", "DELETE_TITLE": "Изтриване на разрешението",

View File

@ -2246,7 +2246,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Autorizace aktualizována.", "UPDATED": "Autorizace aktualizována.",
"REMOVED": "Autorizace odebrána", "REMOVED": "Autorizace odebrána",
"BULKREMOVED": "Autorizace odebrány." "BULKREMOVED": "Autorizace odebrány.",
"CANTSHOWINFO": "Nemůžete navštívit profil tohoto uživatele, protože nejste členem organizace, do které tento uživatel patří"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Smazat autorizaci", "DELETE_TITLE": "Smazat autorizaci",

View File

@ -2236,7 +2236,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Berechtigung geändert.", "UPDATED": "Berechtigung geändert.",
"REMOVED": "Berechtigung entfernt.", "REMOVED": "Berechtigung entfernt.",
"BULKREMOVED": "Berechtigungen entfernt." "BULKREMOVED": "Berechtigungen entfernt.",
"CANTSHOWINFO": "Sie können das Profil dieses Benutzers nicht besuchen, da Sie kein Mitglied der Organisation sind, zu der dieser Benutzer gehört"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Authorisierung löschen", "DELETE_TITLE": "Authorisierung löschen",

View File

@ -2255,7 +2255,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Authorization updated.", "UPDATED": "Authorization updated.",
"REMOVED": "Authorization removed", "REMOVED": "Authorization removed",
"BULKREMOVED": "Authorizations removed." "BULKREMOVED": "Authorizations removed.",
"CANTSHOWINFO": "You cannot visit this user's profile as you are not a member of the organization where this user belongs to"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Delete authorization", "DELETE_TITLE": "Delete authorization",

View File

@ -2234,7 +2234,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Autorización actualizada.", "UPDATED": "Autorización actualizada.",
"REMOVED": "Autorización eliminada", "REMOVED": "Autorización eliminada",
"BULKREMOVED": "Autorizaciones eliminadas." "BULKREMOVED": "Autorizaciones eliminadas.",
"CANTSHOWINFO": "No puedes visitar el perfil de este usuario porque no eres miembro de la organización a la que pertenece este usuario."
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Borrar autorización", "DELETE_TITLE": "Borrar autorización",

View File

@ -2237,7 +2237,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Autorisation mise à jour.", "UPDATED": "Autorisation mise à jour.",
"REMOVED": "Autorisation supprimée", "REMOVED": "Autorisation supprimée",
"BULKREMOVED": "Autorisations supprimées." "BULKREMOVED": "Autorisations supprimées.",
"CANTSHOWINFO": "Vous ne pouvez pas visiter le profil de cet utilisateur car vous n'êtes pas membre de l'organisation à laquelle appartient cet utilisateur."
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Supprimer une autorisation", "DELETE_TITLE": "Supprimer une autorisation",

View File

@ -2237,7 +2237,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Autorizzazione aggiornata.", "UPDATED": "Autorizzazione aggiornata.",
"REMOVED": "Autorizzazione rimossa con successo.", "REMOVED": "Autorizzazione rimossa con successo.",
"BULKREMOVED": "Autorizzazioni rimossi con successo." "BULKREMOVED": "Autorizzazioni rimossi con successo.",
"CANTSHOWINFO": "Non puoi visitare il profilo di questo utente poiché non sei un membro dell'organizzazione a cui appartiene questo utente"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Elima autorizzazione", "DELETE_TITLE": "Elima autorizzazione",

View File

@ -2228,7 +2228,8 @@
"TOAST": { "TOAST": {
"UPDATED": "認可が更新されました。", "UPDATED": "認可が更新されました。",
"REMOVED": "認可が削除されました", "REMOVED": "認可が削除されました",
"BULKREMOVED": "認可が削除されました。" "BULKREMOVED": "認可が削除されました。",
"CANTSHOWINFO": "このユーザーが所属する組織のメンバーではないため、このユーザーのプロフィールにアクセスできません"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "認可の削除", "DELETE_TITLE": "認可の削除",

View File

@ -2234,7 +2234,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Овластувањето е ажурирано.", "UPDATED": "Овластувањето е ажурирано.",
"REMOVED": "Овластувањето е отстрането", "REMOVED": "Овластувањето е отстрането",
"BULKREMOVED": "Овластувањата се отстранети." "BULKREMOVED": "Овластувањата се отстранети.",
"CANTSHOWINFO": "Не можете да го посетите профилот на овој корисник бидејќи не сте член на организацијата каде што припаѓа овој корисник"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Избриши овластување", "DELETE_TITLE": "Избриши овластување",

View File

@ -2255,7 +2255,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Autorisatie bijgewerkt.", "UPDATED": "Autorisatie bijgewerkt.",
"REMOVED": "Autorisatie verwijderd", "REMOVED": "Autorisatie verwijderd",
"BULKREMOVED": "Autorisaties verwijderd." "BULKREMOVED": "Autorisaties verwijderd.",
"CANTSHOWINFO": "U kunt het profiel van deze gebruiker niet bezoeken omdat u geen lid bent van de organisatie waartoe deze gebruiker behoort"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Verwijder autorisatie", "DELETE_TITLE": "Verwijder autorisatie",

View File

@ -2237,7 +2237,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Autoryzacja zaktualizowana.", "UPDATED": "Autoryzacja zaktualizowana.",
"REMOVED": "Autoryzacja usunięta", "REMOVED": "Autoryzacja usunięta",
"BULKREMOVED": "Autoryzacje usunięte." "BULKREMOVED": "Autoryzacje usunięte.",
"CANTSHOWINFO": "Nie możesz odwiedzić profilu tego użytkownika, ponieważ nie jesteś członkiem organizacji, do której należy ten użytkownik"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Usuń autoryzację", "DELETE_TITLE": "Usuń autoryzację",

View File

@ -2232,7 +2232,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Autorização atualizada.", "UPDATED": "Autorização atualizada.",
"REMOVED": "Autorização removida", "REMOVED": "Autorização removida",
"BULKREMOVED": "Autorizações removidas." "BULKREMOVED": "Autorizações removidas.",
"CANTSHOWINFO": "Você não pode visitar o perfil deste usuário porque não é membro da organização à qual esse usuário pertence"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Excluir autorização", "DELETE_TITLE": "Excluir autorização",

View File

@ -2226,7 +2226,8 @@
"TOAST": { "TOAST": {
"UPDATED": "Авторизация обновлена.", "UPDATED": "Авторизация обновлена.",
"REMOVED": "Авторизация удалена", "REMOVED": "Авторизация удалена",
"BULKREMOVED": "Авторизации удалены." "BULKREMOVED": "Авторизации удалены.",
"CANTSHOWINFO": "Вы не можете посетить профиль этого пользователя, поскольку вы не являетесь членом организации, к которой принадлежит этот пользователь."
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "Удалить авторизацию", "DELETE_TITLE": "Удалить авторизацию",

View File

@ -2236,7 +2236,8 @@
"TOAST": { "TOAST": {
"UPDATED": "授权已更新。", "UPDATED": "授权已更新。",
"REMOVED": "已移除授权。", "REMOVED": "已移除授权。",
"BULKREMOVED": "已移除授权。" "BULKREMOVED": "已移除授权。",
"CANTSHOWINFO": "您无法访问该用户的个人资料,因为您不是该用户所属组织的成员"
}, },
"DIALOG": { "DIALOG": {
"DELETE_TITLE": "删除授权", "DELETE_TITLE": "删除授权",

View File

@ -39,6 +39,9 @@ func UserGrantToPb(assetPrefix string, grant *query.UserGrant) *user_pb.UserGran
AvatarUrl: domain.AvatarURL(assetPrefix, grant.UserResourceOwner, grant.AvatarURL), AvatarUrl: domain.AvatarURL(assetPrefix, grant.UserResourceOwner, grant.AvatarURL),
PreferredLoginName: grant.PreferredLoginName, PreferredLoginName: grant.PreferredLoginName,
UserType: TypeToPb(grant.UserType), UserType: TypeToPb(grant.UserType),
GrantedOrgId: grant.GrantedOrgID,
GrantedOrgName: grant.GrantedOrgName,
GrantedOrgDomain: grant.GrantedOrgDomain,
Details: object.ToViewDetailsPb( Details: object.ToViewDetailsPb(
grant.Sequence, grant.Sequence,
grant.CreationDate, grant.CreationDate,

View File

@ -48,6 +48,10 @@ type UserGrant struct {
ProjectID string `json:"project_id,omitempty"` ProjectID string `json:"project_id,omitempty"`
ProjectName string `json:"project_name,omitempty"` ProjectName string `json:"project_name,omitempty"`
GrantedOrgID string `json:"granted_org_id,omitempty"`
GrantedOrgName string `json:"granted_org_name,omitempty"`
GrantedOrgDomain string `json:"granted_org_domain,omitempty"`
} }
type UserGrants struct { type UserGrants struct {
@ -209,6 +213,23 @@ var (
name: projection.UserGrantState, name: projection.UserGrantState,
table: userGrantTable, table: userGrantTable,
} }
GrantedOrgsTable = table{
name: projection.OrgProjectionTable,
alias: "granted_orgs",
instanceIDCol: projection.OrgColumnInstanceID,
}
GrantedOrgColumnId = Column{
name: projection.OrgColumnID,
table: GrantedOrgsTable,
}
GrantedOrgColumnName = Column{
name: projection.OrgColumnName,
table: GrantedOrgsTable,
}
GrantedOrgColumnDomain = Column{
name: projection.OrgColumnDomain,
table: GrantedOrgsTable,
}
) )
func (q *Queries) UserGrant(ctx context.Context, shouldTriggerBulk bool, queries ...SearchQuery) (grant *UserGrant, err error) { func (q *Queries) UserGrant(ctx context.Context, shouldTriggerBulk bool, queries ...SearchQuery) (grant *UserGrant, err error) {
@ -301,12 +322,17 @@ func prepareUserGrantQuery(ctx context.Context, db prepareDatabase) (sq.SelectBu
UserGrantProjectID.identifier(), UserGrantProjectID.identifier(),
ProjectColumnName.identifier(), ProjectColumnName.identifier(),
GrantedOrgColumnId.identifier(),
GrantedOrgColumnName.identifier(),
GrantedOrgColumnDomain.identifier(),
). ).
From(userGrantTable.identifier()). From(userGrantTable.identifier()).
LeftJoin(join(UserIDCol, UserGrantUserID)). LeftJoin(join(UserIDCol, UserGrantUserID)).
LeftJoin(join(HumanUserIDCol, UserGrantUserID)). LeftJoin(join(HumanUserIDCol, UserGrantUserID)).
LeftJoin(join(OrgColumnID, UserGrantResourceOwner)). LeftJoin(join(OrgColumnID, UserGrantResourceOwner)).
LeftJoin(join(ProjectColumnID, UserGrantProjectID)). LeftJoin(join(ProjectColumnID, UserGrantProjectID)).
LeftJoin(join(GrantedOrgColumnId, UserResourceOwnerCol)).
LeftJoin(join(LoginNameUserIDCol, UserGrantUserID) + db.Timetravel(call.Took(ctx))). LeftJoin(join(LoginNameUserIDCol, UserGrantUserID) + db.Timetravel(call.Took(ctx))).
Where( Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true}, sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
@ -329,6 +355,10 @@ func prepareUserGrantQuery(ctx context.Context, db prepareDatabase) (sq.SelectBu
orgDomain sql.NullString orgDomain sql.NullString
projectName sql.NullString projectName sql.NullString
grantedOrgID sql.NullString
grantedOrgName sql.NullString
grantedOrgDomain sql.NullString
) )
err := row.Scan( err := row.Scan(
@ -357,6 +387,10 @@ func prepareUserGrantQuery(ctx context.Context, db prepareDatabase) (sq.SelectBu
&g.ProjectID, &g.ProjectID,
&projectName, &projectName,
&grantedOrgID,
&grantedOrgName,
&grantedOrgDomain,
) )
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
@ -377,7 +411,9 @@ func prepareUserGrantQuery(ctx context.Context, db prepareDatabase) (sq.SelectBu
g.OrgName = orgName.String g.OrgName = orgName.String
g.OrgPrimaryDomain = orgDomain.String g.OrgPrimaryDomain = orgDomain.String
g.ProjectName = projectName.String g.ProjectName = projectName.String
g.GrantedOrgID = grantedOrgID.String
g.GrantedOrgName = grantedOrgName.String
g.GrantedOrgDomain = grantedOrgDomain.String
return g, nil return g, nil
} }
} }
@ -410,6 +446,10 @@ func prepareUserGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
UserGrantProjectID.identifier(), UserGrantProjectID.identifier(),
ProjectColumnName.identifier(), ProjectColumnName.identifier(),
GrantedOrgColumnId.identifier(),
GrantedOrgColumnName.identifier(),
GrantedOrgColumnDomain.identifier(),
countColumn.identifier(), countColumn.identifier(),
). ).
From(userGrantTable.identifier()). From(userGrantTable.identifier()).
@ -417,6 +457,7 @@ func prepareUserGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
LeftJoin(join(HumanUserIDCol, UserGrantUserID)). LeftJoin(join(HumanUserIDCol, UserGrantUserID)).
LeftJoin(join(OrgColumnID, UserGrantResourceOwner)). LeftJoin(join(OrgColumnID, UserGrantResourceOwner)).
LeftJoin(join(ProjectColumnID, UserGrantProjectID)). LeftJoin(join(ProjectColumnID, UserGrantProjectID)).
LeftJoin(join(GrantedOrgColumnId, UserResourceOwnerCol)).
LeftJoin(join(LoginNameUserIDCol, UserGrantUserID) + db.Timetravel(call.Took(ctx))). LeftJoin(join(LoginNameUserIDCol, UserGrantUserID) + db.Timetravel(call.Took(ctx))).
Where( Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true}, sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
@ -441,6 +482,10 @@ func prepareUserGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
orgName sql.NullString orgName sql.NullString
orgDomain sql.NullString orgDomain sql.NullString
grantedOrgID sql.NullString
grantedOrgName sql.NullString
grantedOrgDomain sql.NullString
projectName sql.NullString projectName sql.NullString
) )
@ -471,6 +516,10 @@ func prepareUserGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
&g.ProjectID, &g.ProjectID,
&projectName, &projectName,
&grantedOrgID,
&grantedOrgName,
&grantedOrgDomain,
&count, &count,
) )
if err != nil { if err != nil {
@ -489,6 +538,9 @@ func prepareUserGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
g.OrgName = orgName.String g.OrgName = orgName.String
g.OrgPrimaryDomain = orgDomain.String g.OrgPrimaryDomain = orgDomain.String
g.ProjectName = projectName.String g.ProjectName = projectName.String
g.GrantedOrgID = grantedOrgID.String
g.GrantedOrgName = grantedOrgName.String
g.GrantedOrgDomain = grantedOrgDomain.String
userGrants = append(userGrants, g) userGrants = append(userGrants, g)
} }

View File

@ -37,11 +37,15 @@ var (
", projections.orgs1.primary_domain" + ", projections.orgs1.primary_domain" +
", projections.user_grants4.project_id" + ", projections.user_grants4.project_id" +
", projections.projects4.name" + ", projections.projects4.name" +
", granted_orgs.id" +
", granted_orgs.name" +
", granted_orgs.primary_domain" +
" FROM projections.user_grants4" + " FROM projections.user_grants4" +
" LEFT JOIN projections.users10 ON projections.user_grants4.user_id = projections.users10.id AND projections.user_grants4.instance_id = projections.users10.instance_id" + " LEFT JOIN projections.users10 ON projections.user_grants4.user_id = projections.users10.id AND projections.user_grants4.instance_id = projections.users10.instance_id" +
" LEFT JOIN projections.users10_humans ON projections.user_grants4.user_id = projections.users10_humans.user_id AND projections.user_grants4.instance_id = projections.users10_humans.instance_id" + " LEFT JOIN projections.users10_humans ON projections.user_grants4.user_id = projections.users10_humans.user_id AND projections.user_grants4.instance_id = projections.users10_humans.instance_id" +
" LEFT JOIN projections.orgs1 ON projections.user_grants4.resource_owner = projections.orgs1.id AND projections.user_grants4.instance_id = projections.orgs1.instance_id" + " LEFT JOIN projections.orgs1 ON projections.user_grants4.resource_owner = projections.orgs1.id AND projections.user_grants4.instance_id = projections.orgs1.instance_id" +
" LEFT JOIN projections.projects4 ON projections.user_grants4.project_id = projections.projects4.id AND projections.user_grants4.instance_id = projections.projects4.instance_id" + " LEFT JOIN projections.projects4 ON projections.user_grants4.project_id = projections.projects4.id AND projections.user_grants4.instance_id = projections.projects4.instance_id" +
" LEFT JOIN projections.orgs1 AS granted_orgs ON projections.users10.resource_owner = granted_orgs.id AND projections.users10.instance_id = granted_orgs.instance_id" +
" LEFT JOIN projections.login_names3 ON projections.user_grants4.user_id = projections.login_names3.user_id AND projections.user_grants4.instance_id = projections.login_names3.instance_id" + " LEFT JOIN projections.login_names3 ON projections.user_grants4.user_id = projections.login_names3.user_id AND projections.user_grants4.instance_id = projections.login_names3.instance_id" +
` AS OF SYSTEM TIME '-1 ms' ` + ` AS OF SYSTEM TIME '-1 ms' ` +
" WHERE projections.login_names3.is_primary = $1") " WHERE projections.login_names3.is_primary = $1")
@ -67,7 +71,10 @@ var (
"name", //org name "name", //org name
"primary_domain", "primary_domain",
"project_id", "project_id",
"name", //project name "name", // project name
"id", // granted org id
"name", // granted org name
"primary_domain", // granted org domain
} }
userGrantsStmt = regexp.QuoteMeta( userGrantsStmt = regexp.QuoteMeta(
"SELECT projections.user_grants4.id" + "SELECT projections.user_grants4.id" +
@ -92,12 +99,16 @@ var (
", projections.orgs1.primary_domain" + ", projections.orgs1.primary_domain" +
", projections.user_grants4.project_id" + ", projections.user_grants4.project_id" +
", projections.projects4.name" + ", projections.projects4.name" +
", granted_orgs.id" +
", granted_orgs.name" +
", granted_orgs.primary_domain" +
", COUNT(*) OVER ()" + ", COUNT(*) OVER ()" +
" FROM projections.user_grants4" + " FROM projections.user_grants4" +
" LEFT JOIN projections.users10 ON projections.user_grants4.user_id = projections.users10.id AND projections.user_grants4.instance_id = projections.users10.instance_id" + " LEFT JOIN projections.users10 ON projections.user_grants4.user_id = projections.users10.id AND projections.user_grants4.instance_id = projections.users10.instance_id" +
" LEFT JOIN projections.users10_humans ON projections.user_grants4.user_id = projections.users10_humans.user_id AND projections.user_grants4.instance_id = projections.users10_humans.instance_id" + " LEFT JOIN projections.users10_humans ON projections.user_grants4.user_id = projections.users10_humans.user_id AND projections.user_grants4.instance_id = projections.users10_humans.instance_id" +
" LEFT JOIN projections.orgs1 ON projections.user_grants4.resource_owner = projections.orgs1.id AND projections.user_grants4.instance_id = projections.orgs1.instance_id" + " LEFT JOIN projections.orgs1 ON projections.user_grants4.resource_owner = projections.orgs1.id AND projections.user_grants4.instance_id = projections.orgs1.instance_id" +
" LEFT JOIN projections.projects4 ON projections.user_grants4.project_id = projections.projects4.id AND projections.user_grants4.instance_id = projections.projects4.instance_id" + " LEFT JOIN projections.projects4 ON projections.user_grants4.project_id = projections.projects4.id AND projections.user_grants4.instance_id = projections.projects4.instance_id" +
" LEFT JOIN projections.orgs1 AS granted_orgs ON projections.users10.resource_owner = granted_orgs.id AND projections.users10.instance_id = granted_orgs.instance_id" +
" LEFT JOIN projections.login_names3 ON projections.user_grants4.user_id = projections.login_names3.user_id AND projections.user_grants4.instance_id = projections.login_names3.instance_id" + " LEFT JOIN projections.login_names3 ON projections.user_grants4.user_id = projections.login_names3.user_id AND projections.user_grants4.instance_id = projections.login_names3.instance_id" +
` AS OF SYSTEM TIME '-1 ms' ` + ` AS OF SYSTEM TIME '-1 ms' ` +
" WHERE projections.login_names3.is_primary = $1") " WHERE projections.login_names3.is_primary = $1")
@ -166,6 +177,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
), ),
}, },
@ -192,6 +206,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
{ {
@ -224,6 +241,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
), ),
}, },
@ -250,6 +270,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
{ {
@ -282,6 +305,9 @@ func Test_UserGrantPrepares(t *testing.T) {
nil, nil,
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
), ),
}, },
@ -308,6 +334,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "", OrgPrimaryDomain: "",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
{ {
@ -340,6 +369,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
nil, nil,
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
), ),
}, },
@ -366,6 +398,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "", ProjectName: "",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
{ {
@ -398,6 +433,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
), ),
}, },
@ -424,6 +462,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
{ {
@ -486,6 +527,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
}, },
), ),
@ -518,6 +562,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
}, },
@ -553,6 +600,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
}, },
), ),
@ -585,6 +635,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
}, },
@ -620,6 +673,9 @@ func Test_UserGrantPrepares(t *testing.T) {
nil, nil,
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
}, },
), ),
@ -652,6 +708,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "", OrgPrimaryDomain: "",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
}, },
@ -687,6 +746,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
nil, nil,
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
}, },
), ),
@ -719,6 +781,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "", ProjectName: "",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
}, },
@ -754,6 +819,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
}, },
), ),
@ -786,6 +854,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
}, },
@ -821,6 +892,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
{ {
"id", "id",
@ -845,6 +919,9 @@ func Test_UserGrantPrepares(t *testing.T) {
"primary-domain", "primary-domain",
"project-id", "project-id",
"project-name", "project-name",
"granted-org-id",
"granted-org-name",
"granted-org-domain",
}, },
}, },
), ),
@ -877,6 +954,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
{ {
ID: "id", ID: "id",
@ -901,6 +981,9 @@ func Test_UserGrantPrepares(t *testing.T) {
OrgPrimaryDomain: "primary-domain", OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id", ProjectID: "project-id",
ProjectName: "project-name", ProjectName: "project-name",
GrantedOrgID: "granted-org-id",
GrantedOrgName: "granted-org-name",
GrantedOrgDomain: "granted-org-domain",
}, },
}, },
}, },

View File

@ -786,6 +786,21 @@ message UserGrant {
description: "type of the user (human / machine)" description: "type of the user (human / machine)"
} }
]; ];
string granted_org_id = 20 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\""
}
];
string granted_org_name = 21 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ZITADEL\"";
}
];
string granted_org_domain = 22 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"zitadel.cloud\"";
}
];
} }
enum UserGrantState { enum UserGrantState {