From 465081ee6de0160dda65f988f87bce1781c7eec7 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 14 Jun 2021 13:53:40 +0200 Subject: [PATCH] fix(console): remove cropper, set avatar url if available (#1865) * set avatarurl if available * lint * force sidemargin * dont load image via asset * rm log * stylelint * add ZITADEL domain to csp img src * sanitize url * fix undefined link projects * use name as fallback * operator: rename uploadServiceURL to assetServiceURL in environment json for console * remove data * rm logs * center crop image * add avatar to changes Co-authored-by: Livio Amstutz --- console/src/app/app.component.html | 2 +- .../accounts-card.component.html | 4 +- .../accounts-card/accounts-card.component.ts | 1 - .../app/modules/avatar/avatar.component.html | 3 +- .../app/modules/avatar/avatar.component.scss | 8 ++ .../app/modules/avatar/avatar.component.ts | 6 ++ .../modules/changes/changes.component.html | 5 +- .../app/modules/changes/changes.component.ts | 4 + .../contributors/contributors.component.html | 2 +- .../members-table.component.html | 2 +- .../private-labeling-policy.component.ts | 1 + .../search-user-autocomplete.component.html | 2 +- .../user-grants/user-grants.component.html | 2 +- .../src/app/pages/home/home.component.html | 1 + .../granted-project-list.component.html | 2 +- .../owned-project-list.component.html | 6 +- .../detail-form/detail-form.component.html | 5 +- .../detail-form/detail-form.component.scss | 7 -- .../detail-form/detail-form.component.ts | 20 +---- .../profile-picture.component.html | 37 ++-------- .../profile-picture.component.scss | 3 +- .../profile-picture.component.ts | 73 +++++-------------- .../user-table/user-table.component.html | 2 +- console/src/styles.scss | 4 + docs/docs/apis/proto/change.md | 1 + internal/api/grpc/change/changes.go | 4 + .../eventsourcing/eventstore/user.go | 11 ++- .../eventsourcing/eventstore/org.go | 1 + .../eventsourcing/eventstore/project.go | 2 + .../eventsourcing/eventstore/user.go | 1 + internal/org/model/org.go | 1 + internal/project/model/application.go | 1 + internal/project/model/project.go | 1 + internal/ui/console/console.go | 2 +- internal/user/model/user_changes.go | 1 + .../kinds/iam/zitadel/configuration/adapt.go | 16 ++-- .../iam/zitadel/configuration/literals.go | 2 +- .../zitadel/configuration/literals_test.go | 12 +-- proto/zitadel/change.proto | 6 ++ 39 files changed, 111 insertions(+), 153 deletions(-) diff --git a/console/src/app/app.component.html b/console/src/app/app.component.html index eecac29a83..9e8929e6a9 100644 --- a/console/src/app/app.component.html +++ b/console/src/app/app.component.html @@ -60,7 +60,7 @@
diff --git a/console/src/app/modules/accounts-card/accounts-card.component.html b/console/src/app/modules/accounts-card/accounts-card.component.html index 02bc67cdc7..f48d99343a 100644 --- a/console/src/app/modules/accounts-card/accounts-card.component.html +++ b/console/src/app/modules/accounts-card/accounts-card.component.html @@ -2,7 +2,7 @@ @@ -15,7 +15,7 @@
- +
diff --git a/console/src/app/modules/accounts-card/accounts-card.component.ts b/console/src/app/modules/accounts-card/accounts-card.component.ts index cc961e438a..52e338b279 100644 --- a/console/src/app/modules/accounts-card/accounts-card.component.ts +++ b/console/src/app/modules/accounts-card/accounts-card.component.ts @@ -20,7 +20,6 @@ export class AccountsCardComponent implements OnInit { constructor(public authService: AuthenticationService, private router: Router, private userService: GrpcAuthService) { this.userService.listMyUserSessions().then(sessions => { this.sessions = sessions.resultList; - console.log(sessions.resultList); const index = this.sessions.findIndex(user => user.loginName === this.user.preferredLoginName); if (index > -1) { this.sessions.splice(index, 1); diff --git a/console/src/app/modules/avatar/avatar.component.html b/console/src/app/modules/avatar/avatar.component.html index b38b6a7c67..f2b7cd1feb 100644 --- a/console/src/app/modules/avatar/avatar.component.html +++ b/console/src/app/modules/avatar/avatar.component.html @@ -2,5 +2,6 @@ matRippleCentered="true" [ngStyle]="{'height': size+'px', 'width': size+'px', 'fontSize': (fontSize-1)+'px', 'background': color}" [ngClass]="{'active': active}"> - {{credentials}} + + {{credentials}}
\ No newline at end of file diff --git a/console/src/app/modules/avatar/avatar.component.scss b/console/src/app/modules/avatar/avatar.component.scss index 04d92187b2..4e77af14b7 100644 --- a/console/src/app/modules/avatar/avatar.component.scss +++ b/console/src/app/modules/avatar/avatar.component.scss @@ -17,5 +17,13 @@ outline: none; color: white; font-weight: bold; + + img { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; + object-position: center; + } } } diff --git a/console/src/app/modules/avatar/avatar.component.ts b/console/src/app/modules/avatar/avatar.component.ts index 0932a9de2e..d258f24ed0 100644 --- a/console/src/app/modules/avatar/avatar.component.ts +++ b/console/src/app/modules/avatar/avatar.component.ts @@ -13,6 +13,7 @@ export class AvatarComponent implements OnInit { @Input() active: boolean = false; @Input() color: string = ''; @Input() forColor: string = ''; + @Input() avatarUrl: string = ''; constructor() { } ngOnInit(): void { @@ -21,6 +22,11 @@ export class AvatarComponent implements OnInit { if (!this.color) { this.color = this.getColor(this.forColor || ''); } + } else if (!this.credentials && this.name) { + this.credentials = this.getInitials(this.name); + if (!this.color) { + this.color = this.getColor(this.name || ''); + } } if (this.size > 50) { diff --git a/console/src/app/modules/changes/changes.component.html b/console/src/app/modules/changes/changes.component.html index 356d254230..1583dca63d 100644 --- a/console/src/app/modules/changes/changes.component.html +++ b/console/src/app/modules/changes/changes.component.html @@ -13,7 +13,8 @@
+ [name]="dayelement.editorDisplayName" [size]="32" [forColor]="dayelement?.editorPreferredLoginName" + [avatarUrl]="dayelement.editorAvatarUrl || ''">
@@ -40,4 +41,4 @@
{{'CHANGES.BOTTOM' | translate}} -
\ No newline at end of file +
diff --git a/console/src/app/modules/changes/changes.component.ts b/console/src/app/modules/changes/changes.component.ts index 1c6c86a60a..b77dcd4670 100644 --- a/console/src/app/modules/changes/changes.component.ts +++ b/console/src/app/modules/changes/changes.component.ts @@ -190,6 +190,8 @@ export class ChangesComponent implements OnInit, OnDestroy { editor: change.editorDisplayName, editorId: change.editorId, editorDisplayName: change.editorDisplayName, + editorPreferredLoginName: change.editorPreferredLoginName, + editorAvatarUrl: change.editorAvatarUrl, dates: [change.changeDate], // data: [change.data], @@ -211,6 +213,8 @@ export class ChangesComponent implements OnInit, OnDestroy { editor: change.editorDisplayName, editorId: change.editorId, editorDisplayName: change.editorDisplayName, + editorPreferredLoginName: change.editorPreferredLoginName, + editorAvatarUrl: change.editorAvatarUrl, dates: [change.changeDate], // data: [change.data], diff --git a/console/src/app/modules/contributors/contributors.component.html b/console/src/app/modules/contributors/contributors.component.html index 2b35131363..30c9302a6c 100644 --- a/console/src/app/modules/contributors/contributors.component.html +++ b/console/src/app/modules/contributors/contributors.component.html @@ -14,7 +14,7 @@ [ngStyle]="{'z-index': 100 - i}"> diff --git a/console/src/app/modules/members-table/members-table.component.html b/console/src/app/modules/members-table/members-table.component.html index 41fd9436a2..1a6371697d 100644 --- a/console/src/app/modules/members-table/members-table.component.html +++ b/console/src/app/modules/members-table/members-table.component.html @@ -22,7 +22,7 @@ + [name]="row.displayName" [avatarUrl]="row.avatarUrl || ''" [avatarUrl]="row.avatarUrl|| ''" [forColor]="row?.preferredLoginName" [size]="32">
diff --git a/console/src/app/modules/policies/private-labeling-policy/private-labeling-policy.component.ts b/console/src/app/modules/policies/private-labeling-policy/private-labeling-policy.component.ts index 0b19051b18..19d6bbe852 100644 --- a/console/src/app/modules/policies/private-labeling-policy/private-labeling-policy.component.ts +++ b/console/src/app/modules/policies/private-labeling-policy/private-labeling-policy.component.ts @@ -482,6 +482,7 @@ export class PrivateLabelingPolicyComponent implements OnDestroy { private loadAsset(imagekey: string, url: string): Promise { return this.assetService.load(`${url}`, this.org.id).then(data => { + console.log(data); const objectURL = URL.createObjectURL(data); this.images[imagekey] = this.sanitizer.bypassSecurityTrustUrl(objectURL); this.refreshPreview.emit(); diff --git a/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.html b/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.html index 7d853a3658..d9a0d2ab92 100644 --- a/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.html +++ b/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.html @@ -57,7 +57,7 @@
+ class="avatar" [name]="user.human.displayName" [avatarUrl]="user.human?.profile?.avatarUrl || ''" [forColor]="user?.preferredLoginName" [size]="32">
diff --git a/console/src/app/modules/user-grants/user-grants.component.html b/console/src/app/modules/user-grants/user-grants.component.html index 8813f1f700..71a5cade46 100644 --- a/console/src/app/modules/user-grants/user-grants.component.html +++ b/console/src/app/modules/user-grants/user-grants.component.html @@ -31,7 +31,7 @@ (change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)"> + class="avatar" [name]="row.displayName" [avatarUrl]="row.avatarUrl || ''" [forColor]="row?.preferredLoginName" [size]="32"> diff --git a/console/src/app/pages/home/home.component.html b/console/src/app/pages/home/home.component.html index 850c1568d4..4671bca621 100644 --- a/console/src/app/pages/home/home.component.html +++ b/console/src/app/pages/home/home.component.html @@ -3,6 +3,7 @@ diff --git a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-list.component.html b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-list.component.html index a732b01084..0ba80e16cd 100644 --- a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-list.component.html +++ b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-list.component.html @@ -67,7 +67,7 @@ + [routerLink]="['/granted-projects', row.projectId, 'grant', row.grantId]">
diff --git a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.html b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.html index 10eb720899..02dae47c72 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.html +++ b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.html @@ -66,9 +66,9 @@ - @@ -76,7 +76,7 @@ + [routerLink]="['/projects', row.id]">
diff --git a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.html b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.html index d00217ada6..abfd1e7fd9 100644 --- a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.html +++ b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.html @@ -5,10 +5,9 @@
- + *ngIf="user && user.profile?.displayName && user.profile?.firstName && user?.profile.lastName" + class="avatar" [name]="user.profile?.displayName" [avatarUrl]="user?.profile?.avatarUrl || ''" [forColor]="preferredLoginName" [size]="80"> diff --git a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.scss b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.scss index 3a4e4f8019..330dfbaf19 100644 --- a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.scss +++ b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.scss @@ -46,13 +46,6 @@ background-color: #00000080; } } - - .pic { - height: 80px; - width: 80px; - object-fit: contain; - border-radius: 50%; - } } .formfield { diff --git a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.ts b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.ts index ee9d2d86e5..69ca9d8e32 100644 --- a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.ts +++ b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.ts @@ -1,11 +1,8 @@ import { Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core'; import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; -import { DomSanitizer } from '@angular/platform-browser'; import { Subscription } from 'rxjs'; import { Gender, Human, User } from 'src/app/proto/generated/zitadel/user_pb'; -import { AssetService } from 'src/app/services/asset.service'; -import { ToastService } from 'src/app/services/toast.service'; import { ProfilePictureComponent } from './profile-picture/profile-picture.component'; @@ -25,7 +22,6 @@ export class DetailFormComponent implements OnDestroy, OnChanges { @Output() public submitData: EventEmitter = new EventEmitter(); @Output() public changedLanguage: EventEmitter = new EventEmitter(); - public profilePic: any = null; public profileForm!: FormGroup; private sub: Subscription = new Subscription(); @@ -33,9 +29,6 @@ export class DetailFormComponent implements OnDestroy, OnChanges { constructor( private fb: FormBuilder, private dialog: MatDialog, - private assetService: AssetService, - private toast: ToastService, - private sanitizer: DomSanitizer, ) { this.profileForm = this.fb.group({ userName: [{ value: '', disabled: true }, [ @@ -48,8 +41,6 @@ export class DetailFormComponent implements OnDestroy, OnChanges { gender: [{ value: 0, disabled: this.disabled }], preferredLanguage: [{ value: '', disabled: this.disabled }], }); - - this.loadAvatar(); } public ngOnChanges(): void { @@ -85,7 +76,7 @@ export class DetailFormComponent implements OnDestroy, OnChanges { public openUploadDialog(): void { const dialogRef = this.dialog.open(ProfilePictureComponent, { data: { - profilePic: this.profilePic, + profilePic: this.user.profile?.avatarUrl, }, width: '400px', }); @@ -96,15 +87,6 @@ export class DetailFormComponent implements OnDestroy, OnChanges { }); } - public loadAvatar(): Promise { - return this.assetService.load(`users/me/avatar`).then(data => { - const objectURL = URL.createObjectURL(data); - this.profilePic = this.sanitizer.bypassSecurityTrustUrl(objectURL); - }).catch(error => { - this.toast.showError(error); - }); - } - public get userName(): AbstractControl | null { return this.profileForm.get('userName'); } diff --git a/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.html b/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.html index 275885b459..69600dcf72 100644 --- a/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.html +++ b/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.html @@ -2,38 +2,15 @@

{{'USER.PROFILE.AVATAR.CURRENT' | translate}}

- - - - - -
- - -

{{'USER.PROFILE.AVATAR.PREVIEW' | translate}}

- -
- - -
- -

{{'USER.PROFILE.AVATAR.CROPPERERROR' | translate}}

- - -
- + + + + + +
-
\ No newline at end of file diff --git a/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.scss b/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.scss index 2f7ab14863..9b7d154ee8 100644 --- a/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.scss +++ b/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.scss @@ -22,7 +22,8 @@ .pic { height: 80px; width: 80px; - object-fit: contain; + object-fit: cover; + object-position: center; border-radius: 50%; background-color: #00000030; } diff --git a/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.ts b/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.ts index fa53b2c50e..ca4bca8f95 100644 --- a/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.ts +++ b/console/src/app/pages/users/user-detail/detail-form/profile-picture/profile-picture.component.ts @@ -1,6 +1,6 @@ -import { Component, Inject, OnInit } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { ImageCroppedEvent } from 'ngx-image-cropper'; +import { DomSanitizer } from '@angular/platform-browser'; import { AssetService } from 'src/app/services/asset.service'; import { GrpcAuthService } from 'src/app/services/grpc-auth.service'; import { ToastService } from 'src/app/services/toast.service'; @@ -10,40 +10,29 @@ import { ToastService } from 'src/app/services/toast.service'; templateUrl: './profile-picture.component.html', styleUrls: ['./profile-picture.component.scss'], }) -export class ProfilePictureComponent implements OnInit { - public isHovering: boolean = false; - - public imageChangedEvent: any = ''; - public imageChangedFormat: string = ''; - public croppedImage: any = ''; - public showCropperError: boolean = false; - +export class ProfilePictureComponent { constructor( private authService: GrpcAuthService, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, private toast: ToastService, - private assetService: AssetService) { } - - public ngOnInit(): void { - } - - public toggleHover(isHovering: boolean): void { - this.isHovering = isHovering; + private assetService: AssetService, + private sanitizer: DomSanitizer, + ) { } public onDrop(event: any): Promise | void { const filelist: FileList = event.target.files; - console.log(event.target.files); - this.imageChangedEvent = event; const file = filelist.item(0); + if (file) { - this.imageChangedFormat = file.type; + const formData = new FormData(); + formData.append('file', file); + return this.handleUploadPromise(this.assetService.upload('users/me/avatar', formData)); } } public deletePic(): void { - console.log('delete'); this.authService.removeMyAvatar().then(() => { this.toast.showInfo('USER.PROFILE.AVATAR.DELETESUCCESS', true); this.data.profilePic = null; @@ -55,45 +44,17 @@ export class ProfilePictureComponent implements OnInit { private handleUploadPromise(task: Promise): Promise { return task.then(() => { this.toast.showInfo('POLICY.TOAST.UPLOADSUCCESS', true); - this.data.profilePic = this.croppedImage; + this.assetService.load('users/me/avatar').then(data => { + const objectURL = URL.createObjectURL(data); + const pic = this.sanitizer.bypassSecurityTrustUrl(objectURL); + this.data.profilePic = pic; + }).catch(error => { + this.toast.showError(error); + }); }).catch(error => this.toast.showError(error)); } - public fileChangeEvent(event: any): void { - this.imageChangedEvent = event; - } - - public imageCropped(event: ImageCroppedEvent): void { - this.showCropperError = false; - this.croppedImage = event.base64; - } - - public upload(): Promise | void { - const formData = new FormData(); - const splitted = this.croppedImage.split(';base64,'); - if (splitted[1]) { - const blob = this.base64toBlob(splitted[1]); - formData.append('file', blob); - return this.handleUploadPromise(this.assetService.upload('users/me/avatar', formData)); - } - } - - public loadImageFailed(): void { - this.showCropperError = true; - } - public closeDialog(): void { this.dialogRef.close(false); } - - public base64toBlob(b64: string): Blob { - const byteCharacters = atob(b64); - const byteNumbers = new Array(byteCharacters.length); - for (let i = 0; i < byteCharacters.length; i++) { - byteNumbers[i] = byteCharacters.charCodeAt(i); - } - const byteArray = new Uint8Array(byteNumbers); - const blob = new Blob([byteArray], { type: this.imageChangedFormat }); - return blob; - } } diff --git a/console/src/app/pages/users/user-list/user-table/user-table.component.html b/console/src/app/pages/users/user-list/user-table/user-table.component.html index f33ee4311f..29cb8a91b7 100644 --- a/console/src/app/pages/users/user-list/user-table/user-table.component.html +++ b/console/src/app/pages/users/user-list/user-table/user-table.component.html @@ -35,7 +35,7 @@ + class="avatar" [name]="user.human.profile.displayName" [avatarUrl]="user.human?.profile?.avatarUrl || ''" [forColor]="user?.preferredLoginName" [size]="32">
diff --git a/console/src/styles.scss b/console/src/styles.scss index a6392b8a6c..fd50d8fd8d 100644 --- a/console/src/styles.scss +++ b/console/src/styles.scss @@ -312,3 +312,7 @@ h2 { i { font-size: 1.5rem; } + +.mat-checkbox-inner-container.mat-checkbox-inner-container-no-side-margin { + margin-right: .5rem !important; +} diff --git a/docs/docs/apis/proto/change.md b/docs/docs/apis/proto/change.md index ccebf012df..f7d02a269d 100644 --- a/docs/docs/apis/proto/change.md +++ b/docs/docs/apis/proto/change.md @@ -22,6 +22,7 @@ title: zitadel/change.proto | editor_display_name | string | - | | | resource_owner_id | string | - | | | editor_preferred_login_name | string | - | | +| editor_avatar_url | string | - | | diff --git a/internal/api/grpc/change/changes.go b/internal/api/grpc/change/changes.go index 8e5b64a7a4..3b380c8538 100644 --- a/internal/api/grpc/change/changes.go +++ b/internal/api/grpc/change/changes.go @@ -31,6 +31,7 @@ func UserChangeToPb(change *user_model.UserChange) *change_pb.Change { EditorId: change.ModifierID, EditorDisplayName: change.ModifierName, EditorPreferredLoginName: change.ModifierLoginName, + EditorAvatarUrl: change.ModifierAvatarURL, // ResourceOwnerId: change.,TODO: resource owner not returned } } @@ -51,6 +52,7 @@ func OrgChangeToPb(change *org_model.OrgChange) *change_pb.Change { EditorId: change.ModifierId, EditorDisplayName: change.ModifierName, EditorPreferredLoginName: change.ModifierLoginName, + EditorAvatarUrl: change.ModifierAvatarURL, // ResourceOwnerId: change.,TODO: resource owner not returned } } @@ -71,6 +73,7 @@ func ProjectChangeToPb(change *proj_model.ProjectChange) *change_pb.Change { EditorId: change.ModifierId, EditorDisplayName: change.ModifierName, EditorPreferredLoginName: change.ModifierLoginName, + EditorAvatarUrl: change.ModifierAvatarURL, // ResourceOwnerId: change.,TODO: resource owner not returned } } @@ -91,6 +94,7 @@ func AppChangeToPb(change *proj_model.ApplicationChange) *change_pb.Change { EditorId: change.ModifierId, EditorDisplayName: change.ModifierName, EditorPreferredLoginName: change.ModifierLoginName, + EditorAvatarUrl: change.ModifierAvatarURL, // ResourceOwnerId: change.,TODO: resource owner not returned } } diff --git a/internal/auth/repository/eventsourcing/eventstore/user.go b/internal/auth/repository/eventsourcing/eventstore/user.go index 191a7bbbfc..3e30117f35 100644 --- a/internal/auth/repository/eventsourcing/eventstore/user.go +++ b/internal/auth/repository/eventsourcing/eventstore/user.go @@ -4,18 +4,16 @@ import ( "context" "time" - "github.com/caos/zitadel/internal/eventstore/v1" - "github.com/golang/protobuf/ptypes" - - "github.com/caos/zitadel/internal/config/systemdefaults" - key_model "github.com/caos/zitadel/internal/key/model" - "github.com/caos/logging" + "github.com/golang/protobuf/ptypes" "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view" + "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/v1" "github.com/caos/zitadel/internal/eventstore/v1/models" + key_model "github.com/caos/zitadel/internal/key/model" key_view_model "github.com/caos/zitadel/internal/key/repository/view/model" "github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/zitadel/internal/user/model" @@ -206,6 +204,7 @@ func (repo *UserRepo) MyUserChanges(ctx context.Context, lastSequence uint64, li change.ModifierLoginName = user.PreferredLoginName if user.HumanView != nil { change.ModifierName = user.HumanView.DisplayName + change.ModifierAvatarURL = user.HumanView.AvatarURL } if user.MachineView != nil { change.ModifierName = user.MachineView.Name diff --git a/internal/management/repository/eventsourcing/eventstore/org.go b/internal/management/repository/eventsourcing/eventstore/org.go index acac0382e2..fa65372211 100644 --- a/internal/management/repository/eventsourcing/eventstore/org.go +++ b/internal/management/repository/eventsourcing/eventstore/org.go @@ -108,6 +108,7 @@ func (repo *OrgRepository) OrgChanges(ctx context.Context, id string, lastSequen change.ModifierLoginName = user.PreferredLoginName if user.HumanView != nil { change.ModifierName = user.HumanView.DisplayName + change.ModifierAvatarURL = user.HumanView.AvatarURL } if user.MachineView != nil { change.ModifierName = user.MachineView.Name diff --git a/internal/management/repository/eventsourcing/eventstore/project.go b/internal/management/repository/eventsourcing/eventstore/project.go index 785bf46ad1..439e8f2943 100644 --- a/internal/management/repository/eventsourcing/eventstore/project.go +++ b/internal/management/repository/eventsourcing/eventstore/project.go @@ -203,6 +203,7 @@ func (repo *ProjectRepo) ProjectChanges(ctx context.Context, id string, lastSequ change.ModifierLoginName = user.PreferredLoginName if user.HumanView != nil { change.ModifierName = user.HumanView.DisplayName + change.ModifierAvatarURL = user.HumanView.AvatarURL } if user.MachineView != nil { change.ModifierName = user.MachineView.Name @@ -282,6 +283,7 @@ func (repo *ProjectRepo) ApplicationChanges(ctx context.Context, projectID strin change.ModifierLoginName = user.PreferredLoginName if user.HumanView != nil { change.ModifierName = user.HumanView.DisplayName + change.ModifierAvatarURL = user.HumanView.AvatarURL } if user.MachineView != nil { change.ModifierName = user.MachineView.Name diff --git a/internal/management/repository/eventsourcing/eventstore/user.go b/internal/management/repository/eventsourcing/eventstore/user.go index dcfe9adaff..3126b9c82c 100644 --- a/internal/management/repository/eventsourcing/eventstore/user.go +++ b/internal/management/repository/eventsourcing/eventstore/user.go @@ -105,6 +105,7 @@ func (repo *UserRepo) UserChanges(ctx context.Context, id string, lastSequence u change.ModifierLoginName = user.PreferredLoginName if user.HumanView != nil { change.ModifierName = user.HumanView.DisplayName + change.ModifierAvatarURL = user.HumanView.AvatarURL } if user.MachineView != nil { change.ModifierName = user.MachineView.Name diff --git a/internal/org/model/org.go b/internal/org/model/org.go index 3b7b2db054..f304d3fdba 100644 --- a/internal/org/model/org.go +++ b/internal/org/model/org.go @@ -40,6 +40,7 @@ type OrgChange struct { ModifierId string `json:"modifierUser,omitempty"` ModifierName string `json:"-"` ModifierLoginName string `json:"-"` + ModifierAvatarURL string `json:"-"` Data interface{} `json:"data,omitempty"` } diff --git a/internal/project/model/application.go b/internal/project/model/application.go index 2dbc220c8a..1eead637e3 100644 --- a/internal/project/model/application.go +++ b/internal/project/model/application.go @@ -28,6 +28,7 @@ type ApplicationChange struct { ModifierId string `json:"modifierUser,omitempty"` ModifierName string `json:"-"` ModifierLoginName string `json:"-"` + ModifierAvatarURL string `json:"-"` Data interface{} `json:"data,omitempty"` } diff --git a/internal/project/model/project.go b/internal/project/model/project.go index e8e3eed851..8dd899300f 100644 --- a/internal/project/model/project.go +++ b/internal/project/model/project.go @@ -30,6 +30,7 @@ type ProjectChange struct { ModifierId string `json:"modifierUser,omitempty"` ModifierName string `json:"-"` ModifierLoginName string `json:"-"` + ModifierAvatarURL string `json:"-"` Data interface{} `json:"data,omitempty"` } diff --git a/internal/ui/console/console.go b/internal/ui/console/console.go index ee3c6f61c0..43756c6c31 100644 --- a/internal/ui/console/console.go +++ b/internal/ui/console/console.go @@ -86,7 +86,7 @@ func csp(zitadelDomain string) *middleware.CSP { AddHost("fonts.googleapis.com"). AddHost("fonts.gstatic.com"). AddHost("maxst.icons8.com") //TODO: host it - csp.ImgSrc = csp.ImgSrc.AddScheme("blob") + csp.ImgSrc = csp.ImgSrc.AddHost(zitadelDomain).AddScheme("blob") return &csp } diff --git a/internal/user/model/user_changes.go b/internal/user/model/user_changes.go index 98da031b3c..6c13653ba2 100644 --- a/internal/user/model/user_changes.go +++ b/internal/user/model/user_changes.go @@ -16,5 +16,6 @@ type UserChange struct { ModifierID string `json:"modifierUser,omitempty"` ModifierName string `json:"-"` ModifierLoginName string `json:"-"` + ModifierAvatarURL string `json:"-"` Data interface{} `json:"data,omitempty"` } diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/adapt.go b/operator/zitadel/kinds/iam/zitadel/configuration/adapt.go index 1cd773c14e..c995e66593 100644 --- a/operator/zitadel/kinds/iam/zitadel/configuration/adapt.go +++ b/operator/zitadel/kinds/iam/zitadel/configuration/adapt.go @@ -1,24 +1,26 @@ package configuration import ( + "time" + "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/kubernetes/resources/configmap" "github.com/caos/orbos/pkg/kubernetes/resources/secret" "github.com/caos/orbos/pkg/labels" + "github.com/caos/zitadel/operator" "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration/users" "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" - "time" ) type ConsoleEnv struct { - AuthServiceURL string `json:"authServiceUrl"` - MgmtServiceURL string `json:"mgmtServiceUrl"` - Issuer string `json:"issuer"` - ClientID string `json:"clientid"` - SubServiceURL string `json:"subscriptionServiceUrl"` - UploadServiceURL string `json:"uploadServiceUrl"` + AuthServiceURL string `json:"authServiceUrl"` + MgmtServiceURL string `json:"mgmtServiceUrl"` + Issuer string `json:"issuer"` + ClientID string `json:"clientid"` + SubServiceURL string `json:"subscriptionServiceUrl"` + AssetServiceURL string `json:"assetServiceUrl"` } const ( diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/literals.go b/operator/zitadel/kinds/iam/zitadel/configuration/literals.go index ba45f39d7b..e8d9b655bd 100644 --- a/operator/zitadel/kinds/iam/zitadel/configuration/literals.go +++ b/operator/zitadel/kinds/iam/zitadel/configuration/literals.go @@ -228,7 +228,7 @@ func literalsConsoleCM( consoleEnv.AuthServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain consoleEnv.MgmtServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain consoleEnv.SubServiceURL = "https://" + dns.Subdomains.Subscription + "." + dns.Domain - consoleEnv.UploadServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain + consoleEnv.AssetServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain data, err := json.Marshal(consoleEnv) if err != nil { diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/literals_test.go b/operator/zitadel/kinds/iam/zitadel/configuration/literals_test.go index 51d3cec9cf..3eb6c7e4b1 100644 --- a/operator/zitadel/kinds/iam/zitadel/configuration/literals_test.go +++ b/operator/zitadel/kinds/iam/zitadel/configuration/literals_test.go @@ -553,7 +553,7 @@ func TestConfiguration_LiteralsConsoleCM(t *testing.T) { Data: map[string]string{"environment.json": "{\"authServiceUrl\":\"https://.\",\"mgmtServiceUrl\":\"https://.\",\"issuer\":\"https://.\",\"clientid\":\"\",\"subscriptionServiceUrl\":\"https://.\"}"}, } - equals := map[string]string{"environment.json": "{\"authServiceUrl\":\"https://.\",\"mgmtServiceUrl\":\"https://.\",\"issuer\":\"https://.\",\"clientid\":\"\",\"subscriptionServiceUrl\":\"https://.\",\"uploadServiceUrl\":\"https://.\"}"} + equals := map[string]string{"environment.json": "{\"authServiceUrl\":\"https://.\",\"mgmtServiceUrl\":\"https://.\",\"issuer\":\"https://.\",\"clientid\":\"\",\"subscriptionServiceUrl\":\"https://.\",\"assetServiceUrl\":\"https://.\"}"} k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil) literals := literalsConsoleCM(clientID, desiredEmpty.DNS, k8sClient, namespace, cmName) @@ -575,7 +575,7 @@ func TestConfiguration_LiteralsConsoleCMFull(t *testing.T) { } equals := map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"uploadServiceUrl\":\"https://api.domain\"}", + "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", } k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil) @@ -595,12 +595,12 @@ func TestConfiguration_LiteralsConsoleCMWithCM(t *testing.T) { Name: cmName, }, Data: map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"uploadServiceUrl\":\"https://api.domain\"}", + "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", }, } equals := map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"uploadServiceUrl\":\"https://api.domain\"}", + "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", } k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil) @@ -620,12 +620,12 @@ func TestConfiguration_LiteralsConsoleCMWithCMFull(t *testing.T) { Name: cmName, }, Data: map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"uploadServiceUrl\":\"https://api.domain\"}", + "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", }, } equals := map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"uploadServiceUrl\":\"https://api.domain\"}", + "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", } k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil) diff --git a/proto/zitadel/change.proto b/proto/zitadel/change.proto index 67733924d3..dd79501ed9 100644 --- a/proto/zitadel/change.proto +++ b/proto/zitadel/change.proto @@ -45,6 +45,12 @@ message Change { example: "\"gigi@acme.zitadel.ch\""; } ]; + string editor_avatar_url = 8 [ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "avatar url of the editor"; + example: "\"https://api.zitadel.ch/assets/v1/avatar-32432jkh4kj32\""; + } + ]; } message ChangeQuery {