mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-07 21:47:42 +00:00
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 <livio.a@gmail.com>
This commit is contained in:
parent
ab78b34c6c
commit
465081ee6d
@ -60,7 +60,7 @@
|
|||||||
<div (clickOutside)="closeAccountCard()" class="icon-container">
|
<div (clickOutside)="closeAccountCard()" class="icon-container">
|
||||||
<app-avatar
|
<app-avatar
|
||||||
*ngIf="user && (user.human?.profile?.displayName || (user.human?.profile?.firstName && user.human?.profile?.lastName))"
|
*ngIf="user && (user.human?.profile?.displayName || (user.human?.profile?.firstName && user.human?.profile?.lastName))"
|
||||||
class="avatar dontcloseonclick" (click)="showAccount = !showAccount" [active]="showAccount" [forColor]="user?.preferredLoginName"
|
class="avatar dontcloseonclick" (click)="showAccount = !showAccount" [active]="showAccount" [avatarUrl]="user.human?.profile?.avatarUrl || ''" [forColor]="user?.preferredLoginName"
|
||||||
[name]="user.human.profile.displayName ? user.human.profile.displayName : (user.human.profile.firstName + ' '+ user.human.profile.lastName)"
|
[name]="user.human.profile.displayName ? user.human.profile.displayName : (user.human.profile.firstName + ' '+ user.human.profile.lastName)"
|
||||||
[size]="38">
|
[size]="38">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<app-avatar
|
<app-avatar
|
||||||
*ngIf="user.human?.profile && (user.human?.profile?.displayName || (user.human?.profile?.firstName && user.human?.profile?.lastName))"
|
*ngIf="user.human?.profile && (user.human?.profile?.displayName || (user.human?.profile?.firstName && user.human?.profile?.lastName))"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
[forColor]="user.preferredLoginName"
|
[forColor]="user.preferredLoginName" [avatarUrl]="user.human?.profile?.avatarUrl || ''"
|
||||||
[name]="user.human?.profile?.displayName ? user.human?.profile?.displayName : (user.human?.profile?.firstName + ' '+ user.human?.profile?.lastName)"
|
[name]="user.human?.profile?.displayName ? user.human?.profile?.displayName : (user.human?.profile?.firstName + ' '+ user.human?.profile?.lastName)"
|
||||||
[size]="80">
|
[size]="80">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
@ -15,7 +15,7 @@
|
|||||||
<div class="l-accounts">
|
<div class="l-accounts">
|
||||||
<mat-progress-bar *ngIf="loadingUsers" color="primary" mode="indeterminate"></mat-progress-bar>
|
<mat-progress-bar *ngIf="loadingUsers" color="primary" mode="indeterminate"></mat-progress-bar>
|
||||||
<a class="row" *ngFor="let session of sessions" (click)="selectAccount(session.loginName)">
|
<a class="row" *ngFor="let session of sessions" (click)="selectAccount(session.loginName)">
|
||||||
<app-avatar *ngIf="session && session.displayName" class="small-avatar" [forColor]="session.loginName" [size]="32">
|
<app-avatar *ngIf="session && session.displayName" class="small-avatar" [avatarUrl]="session.avatarUrl || ''" [forColor]="session.loginName" [size]="32">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
@ -20,7 +20,6 @@ export class AccountsCardComponent implements OnInit {
|
|||||||
constructor(public authService: AuthenticationService, private router: Router, private userService: GrpcAuthService) {
|
constructor(public authService: AuthenticationService, private router: Router, private userService: GrpcAuthService) {
|
||||||
this.userService.listMyUserSessions().then(sessions => {
|
this.userService.listMyUserSessions().then(sessions => {
|
||||||
this.sessions = sessions.resultList;
|
this.sessions = sessions.resultList;
|
||||||
console.log(sessions.resultList);
|
|
||||||
const index = this.sessions.findIndex(user => user.loginName === this.user.preferredLoginName);
|
const index = this.sessions.findIndex(user => user.loginName === this.user.preferredLoginName);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
this.sessions.splice(index, 1);
|
this.sessions.splice(index, 1);
|
||||||
|
@ -2,5 +2,6 @@
|
|||||||
matRippleCentered="true"
|
matRippleCentered="true"
|
||||||
[ngStyle]="{'height': size+'px', 'width': size+'px', 'fontSize': (fontSize-1)+'px', 'background': color}"
|
[ngStyle]="{'height': size+'px', 'width': size+'px', 'fontSize': (fontSize-1)+'px', 'background': color}"
|
||||||
[ngClass]="{'active': active}">
|
[ngClass]="{'active': active}">
|
||||||
{{credentials}}
|
<img class="dontcloseonclick" *ngIf="avatarUrl; else creds" [src]="avatarUrl"/>
|
||||||
|
<ng-template #creds>{{credentials}}</ng-template>
|
||||||
</div>
|
</div>
|
@ -17,5 +17,13 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ export class AvatarComponent implements OnInit {
|
|||||||
@Input() active: boolean = false;
|
@Input() active: boolean = false;
|
||||||
@Input() color: string = '';
|
@Input() color: string = '';
|
||||||
@Input() forColor: string = '';
|
@Input() forColor: string = '';
|
||||||
|
@Input() avatarUrl: string = '';
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -21,6 +22,11 @@ export class AvatarComponent implements OnInit {
|
|||||||
if (!this.color) {
|
if (!this.color) {
|
||||||
this.color = this.getColor(this.forColor || '');
|
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) {
|
if (this.size > 50) {
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<app-avatar matTooltip="{{ dayelement.editorDisplayName }}"
|
<app-avatar matTooltip="{{ dayelement.editorDisplayName }}"
|
||||||
*ngIf="dayelement.editorDisplayName; else spacer" class="avatar"
|
*ngIf="dayelement.editorDisplayName; else spacer" class="avatar"
|
||||||
[name]="dayelement.editorDisplayName" [size]="32" [forColor]="dayelement?.preferredLoginName">
|
[name]="dayelement.editorDisplayName" [size]="32" [forColor]="dayelement?.editorPreferredLoginName"
|
||||||
|
[avatarUrl]="dayelement.editorAvatarUrl || ''">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
<ng-template #spacer>
|
<ng-template #spacer>
|
||||||
<div class="spacer"></div>
|
<div class="spacer"></div>
|
||||||
@ -40,4 +41,4 @@
|
|||||||
<mat-spinner *ngIf="loading | async" diameter="25"></mat-spinner>
|
<mat-spinner *ngIf="loading | async" diameter="25"></mat-spinner>
|
||||||
</div>
|
</div>
|
||||||
<span class="end-container" *ngIf="bottom">{{'CHANGES.BOTTOM' | translate}}</span>
|
<span class="end-container" *ngIf="bottom">{{'CHANGES.BOTTOM' | translate}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -190,6 +190,8 @@ export class ChangesComponent implements OnInit, OnDestroy {
|
|||||||
editor: change.editorDisplayName,
|
editor: change.editorDisplayName,
|
||||||
editorId: change.editorId,
|
editorId: change.editorId,
|
||||||
editorDisplayName: change.editorDisplayName,
|
editorDisplayName: change.editorDisplayName,
|
||||||
|
editorPreferredLoginName: change.editorPreferredLoginName,
|
||||||
|
editorAvatarUrl: change.editorAvatarUrl,
|
||||||
|
|
||||||
dates: [change.changeDate],
|
dates: [change.changeDate],
|
||||||
// data: [change.data],
|
// data: [change.data],
|
||||||
@ -211,6 +213,8 @@ export class ChangesComponent implements OnInit, OnDestroy {
|
|||||||
editor: change.editorDisplayName,
|
editor: change.editorDisplayName,
|
||||||
editorId: change.editorId,
|
editorId: change.editorId,
|
||||||
editorDisplayName: change.editorDisplayName,
|
editorDisplayName: change.editorDisplayName,
|
||||||
|
editorPreferredLoginName: change.editorPreferredLoginName,
|
||||||
|
editorAvatarUrl: change.editorAvatarUrl,
|
||||||
|
|
||||||
dates: [change.changeDate],
|
dates: [change.changeDate],
|
||||||
// data: [change.data],
|
// data: [change.data],
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
[ngStyle]="{'z-index': 100 - i}">
|
[ngStyle]="{'z-index': 100 - i}">
|
||||||
<app-avatar
|
<app-avatar
|
||||||
*ngIf="member && member.displayName && member.firstName && member.lastName; else cog"
|
*ngIf="member && member.displayName && member.firstName && member.lastName; else cog"
|
||||||
class="avatar dontcloseonclick" [forColor]="member?.userName"[forColor]="member?.preferredLoginName"
|
class="avatar dontcloseonclick" [avatarUrl]="member.avatarUrl|| ''" [forColor]="member?.userName"[forColor]="member?.preferredLoginName"
|
||||||
[name]="member.displayName ? member.displayName : (member.firstName + ' '+ member.lastName)"
|
[name]="member.displayName ? member.displayName : (member.firstName + ' '+ member.lastName)"
|
||||||
[size]="32">
|
[size]="32">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<mat-checkbox [disabled]="!canWrite" color="primary" (click)="$event.stopPropagation()"
|
<mat-checkbox [disabled]="!canWrite" color="primary" (click)="$event.stopPropagation()"
|
||||||
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
|
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
|
||||||
<app-avatar *ngIf="row?.displayName && row.firstName && row.lastName; else cog" class="avatar"
|
<app-avatar *ngIf="row?.displayName && row.firstName && row.lastName; else cog" class="avatar"
|
||||||
[name]="row.displayName" [forColor]="row?.preferredLoginName" [size]="32">
|
[name]="row.displayName" [avatarUrl]="row.avatarUrl || ''" [avatarUrl]="row.avatarUrl|| ''" [forColor]="row?.preferredLoginName" [size]="32">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
<ng-template #cog>
|
<ng-template #cog>
|
||||||
<div class="sa-icon">
|
<div class="sa-icon">
|
||||||
|
@ -482,6 +482,7 @@ export class PrivateLabelingPolicyComponent implements OnDestroy {
|
|||||||
|
|
||||||
private loadAsset(imagekey: string, url: string): Promise<any> {
|
private loadAsset(imagekey: string, url: string): Promise<any> {
|
||||||
return this.assetService.load(`${url}`, this.org.id).then(data => {
|
return this.assetService.load(`${url}`, this.org.id).then(data => {
|
||||||
|
console.log(data);
|
||||||
const objectURL = URL.createObjectURL(data);
|
const objectURL = URL.createObjectURL(data);
|
||||||
this.images[imagekey] = this.sanitizer.bypassSecurityTrustUrl(objectURL);
|
this.images[imagekey] = this.sanitizer.bypassSecurityTrustUrl(objectURL);
|
||||||
this.refreshPreview.emit();
|
this.refreshPreview.emit();
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
<div class="circle">
|
<div class="circle">
|
||||||
<app-avatar
|
<app-avatar
|
||||||
*ngIf="user.human && user.human.displayName && user.human?.firstName && user.human?.lastName; else cog"
|
*ngIf="user.human && user.human.displayName && user.human?.firstName && user.human?.lastName; else cog"
|
||||||
class="avatar" [name]="user.human.displayName" [forColor]="user?.preferredLoginName" [size]="32">
|
class="avatar" [name]="user.human.displayName" [avatarUrl]="user.human?.profile?.avatarUrl || ''" [forColor]="user?.preferredLoginName" [size]="32">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
<ng-template #cog>
|
<ng-template #cog>
|
||||||
<div class="sa-icon">
|
<div class="sa-icon">
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
|
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
|
||||||
<app-avatar
|
<app-avatar
|
||||||
*ngIf="context !== UserGrantContext.USER && row && row?.displayName && row.firstName && row.lastName"
|
*ngIf="context !== UserGrantContext.USER && row && row?.displayName && row.firstName && row.lastName"
|
||||||
class="avatar" [name]="row.displayName" [forColor]="row?.preferredLoginName" [size]="32">
|
class="avatar" [name]="row.displayName" [avatarUrl]="row.avatarUrl || ''" [forColor]="row?.preferredLoginName" [size]="32">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</td>
|
</td>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<app-avatar [routerLink]="['/users/me']"
|
<app-avatar [routerLink]="['/users/me']"
|
||||||
*ngIf="user && (user.human?.profile?.displayName || (user.human?.profile?.firstName && user.human?.profile?.lastName))"
|
*ngIf="user && (user.human?.profile?.displayName || (user.human?.profile?.firstName && user.human?.profile?.lastName))"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
|
[avatarUrl]="user.human?.profile?.avatarUrl || ''"
|
||||||
[forColor]="user?.preferredLoginName"
|
[forColor]="user?.preferredLoginName"
|
||||||
[name]="user.human?.profile?.displayName ? user.human?.profile?.displayName : (user.human?.profile?.firstName + ' '+ user.human?.profile?.lastName)"
|
[name]="user.human?.profile?.displayName ? user.human?.profile?.displayName : (user.human?.profile?.firstName + ' '+ user.human?.profile?.lastName)"
|
||||||
[size]="100">
|
[size]="100">
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"
|
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"
|
||||||
[routerLink]="['/granted-projects', row.projectId, 'grant', row.id]"></tr>
|
[routerLink]="['/granted-projects', row.projectId, 'grant', row.grantId]"></tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
<div *ngIf="(loading$ | async) == false && !dataSource?.data?.length" class="no-content-row">
|
<div *ngIf="(loading$ | async) == false && !dataSource?.data?.length" class="no-content-row">
|
||||||
|
@ -66,9 +66,9 @@
|
|||||||
<ng-container matColumnDef="actions" stickyEnd>
|
<ng-container matColumnDef="actions" stickyEnd>
|
||||||
<th mat-header-cell *matHeaderCellDef></th>
|
<th mat-header-cell *matHeaderCellDef></th>
|
||||||
<td mat-cell *matCellDef="let project">
|
<td mat-cell *matCellDef="let project">
|
||||||
<button class="dlt-button" *ngIf="project.projectId !== zitadelProjectId" color="warn"
|
<button class="dlt-button" *ngIf="project.id !== zitadelProjectId" color="warn"
|
||||||
mat-icon-button matTooltip="{{'ACTIONS.DELETE' | translate}}"
|
mat-icon-button matTooltip="{{'ACTIONS.DELETE' | translate}}"
|
||||||
(click)="deleteProject(project.projectId)">
|
(click)="deleteProject(project.id)">
|
||||||
<i class="las la-trash"></i>
|
<i class="las la-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"
|
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"
|
||||||
[routerLink]="['/projects', row.projectId]"></tr>
|
[routerLink]="['/projects', row.id]"></tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
<div *ngIf="(loading$ | async) == false && !dataSource?.data?.length" class="no-content-row">
|
<div *ngIf="(loading$ | async) == false && !dataSource?.data?.length" class="no-content-row">
|
||||||
|
@ -5,10 +5,9 @@
|
|||||||
<div class="i-wrapper" *ngIf="showEditImage">
|
<div class="i-wrapper" *ngIf="showEditImage">
|
||||||
<i class="las la-camera"></i>
|
<i class="las la-camera"></i>
|
||||||
</div>
|
</div>
|
||||||
<img class="pic" [src]="profilePic" *ngIf="profilePic"/>
|
|
||||||
<app-avatar
|
<app-avatar
|
||||||
*ngIf="!profilePic && user && user.profile?.displayName && user.profile?.firstName && user?.profile.lastName"
|
*ngIf="user && user.profile?.displayName && user.profile?.firstName && user?.profile.lastName"
|
||||||
class="avatar" [name]="user.profile?.displayName" [forColor]="preferredLoginName" [size]="80">
|
class="avatar" [name]="user.profile?.displayName" [avatarUrl]="user?.profile?.avatarUrl || ''" [forColor]="preferredLoginName" [size]="80">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -46,13 +46,6 @@
|
|||||||
background-color: #00000080;
|
background-color: #00000080;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.pic {
|
|
||||||
height: 80px;
|
|
||||||
width: 80px;
|
|
||||||
object-fit: contain;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.formfield {
|
.formfield {
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core';
|
||||||
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { Gender, Human, User } from 'src/app/proto/generated/zitadel/user_pb';
|
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';
|
import { ProfilePictureComponent } from './profile-picture/profile-picture.component';
|
||||||
|
|
||||||
@ -25,7 +22,6 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
@Output() public submitData: EventEmitter<User> = new EventEmitter<User>();
|
@Output() public submitData: EventEmitter<User> = new EventEmitter<User>();
|
||||||
@Output() public changedLanguage: EventEmitter<string> = new EventEmitter<string>();
|
@Output() public changedLanguage: EventEmitter<string> = new EventEmitter<string>();
|
||||||
|
|
||||||
public profilePic: any = null;
|
|
||||||
public profileForm!: FormGroup;
|
public profileForm!: FormGroup;
|
||||||
|
|
||||||
private sub: Subscription = new Subscription();
|
private sub: Subscription = new Subscription();
|
||||||
@ -33,9 +29,6 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
constructor(
|
constructor(
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private assetService: AssetService,
|
|
||||||
private toast: ToastService,
|
|
||||||
private sanitizer: DomSanitizer,
|
|
||||||
) {
|
) {
|
||||||
this.profileForm = this.fb.group({
|
this.profileForm = this.fb.group({
|
||||||
userName: [{ value: '', disabled: true }, [
|
userName: [{ value: '', disabled: true }, [
|
||||||
@ -48,8 +41,6 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
gender: [{ value: 0, disabled: this.disabled }],
|
gender: [{ value: 0, disabled: this.disabled }],
|
||||||
preferredLanguage: [{ value: '', disabled: this.disabled }],
|
preferredLanguage: [{ value: '', disabled: this.disabled }],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.loadAvatar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnChanges(): void {
|
public ngOnChanges(): void {
|
||||||
@ -85,7 +76,7 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
public openUploadDialog(): void {
|
public openUploadDialog(): void {
|
||||||
const dialogRef = this.dialog.open(ProfilePictureComponent, {
|
const dialogRef = this.dialog.open(ProfilePictureComponent, {
|
||||||
data: {
|
data: {
|
||||||
profilePic: this.profilePic,
|
profilePic: this.user.profile?.avatarUrl,
|
||||||
},
|
},
|
||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
@ -96,15 +87,6 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadAvatar(): Promise<any> {
|
|
||||||
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 {
|
public get userName(): AbstractControl | null {
|
||||||
return this.profileForm.get('userName');
|
return this.profileForm.get('userName');
|
||||||
}
|
}
|
||||||
|
@ -2,38 +2,15 @@
|
|||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<p class="desc">{{'USER.PROFILE.AVATAR.CURRENT' | translate}}</p>
|
<p class="desc">{{'USER.PROFILE.AVATAR.CURRENT' | translate}}</p>
|
||||||
<div class="current-pic-wrapper">
|
<div class="current-pic-wrapper">
|
||||||
<img class="pic" [src]="data.profilePic" *ngIf="data.profilePic"/>
|
<img class="pic" [src]="data.profilePic" *ngIf="data.profilePic"/>
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
<input #selectedFile style="display: none;" class="file-input" type="file" (change)="onDrop($event)">
|
<input #selectedFile style="display: none;" class="file-input" type="file" (change)="onDrop($event)">
|
||||||
<button class="btn" mat-stroked-button type="button" (click)="selectedFile.click();">{{'USER.PROFILE.AVATAR.UPLOADBTN' | translate}}</button>
|
<button class="btn" mat-raised-button color="primary" type="button" (click)="selectedFile.click();">{{'USER.PROFILE.AVATAR.UPLOADBTN' | translate}}</button>
|
||||||
<button *ngIf="data.profilePic" matTooltip="{{'ACTIONS.DELETE' | translate}}" color="warn" (click)="deletePic()" mat-icon-button><mat-icon>remove_circle</mat-icon></button>
|
<button *ngIf="data.profilePic" matTooltip="{{'ACTIONS.DELETE' | translate}}" color="warn" (click)="deletePic()" mat-icon-button><mat-icon>remove_circle</mat-icon></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="imageChangedEvent">
|
|
||||||
<p class="desc">{{'USER.PROFILE.AVATAR.PREVIEW' | translate}}</p>
|
|
||||||
|
|
||||||
<div class="cropped-preview" *ngIf="croppedImage">
|
|
||||||
<img class="pic" [src]="croppedImage"/>
|
|
||||||
<button color="primary" mat-raised-button (click)="upload()">{{'USER.PROFILE.AVATAR.UPLOAD' | translate}}</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="error" *ngIf="showCropperError">{{'USER.PROFILE.AVATAR.CROPPERERROR' | translate}}</p>
|
|
||||||
|
|
||||||
<image-cropper
|
|
||||||
class="cropper"
|
|
||||||
[imageChangedEvent]="imageChangedEvent"
|
|
||||||
[maintainAspectRatio]="true"
|
|
||||||
[aspectRatio]="4 / 4"
|
|
||||||
[roundCropper]="true"
|
|
||||||
[autoCrop]="true"
|
|
||||||
(imageCropped)="imageCropped($event)"
|
|
||||||
(loadImageFailed)="loadImageFailed()"
|
|
||||||
></image-cropper>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
<button color="primary" mat-raised-button class="ok-button" (click)="closeDialog()">
|
<button color="primary" mat-stroked-button class="ok-button" (click)="closeDialog()">
|
||||||
{{'ACTIONS.CLOSE' | translate}}
|
{{'ACTIONS.CLOSE' | translate}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
@ -22,7 +22,8 @@
|
|||||||
.pic {
|
.pic {
|
||||||
height: 80px;
|
height: 80px;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
object-fit: contain;
|
object-fit: cover;
|
||||||
|
object-position: center;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #00000030;
|
background-color: #00000030;
|
||||||
}
|
}
|
||||||
|
@ -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 { 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 { AssetService } from 'src/app/services/asset.service';
|
||||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||||
import { ToastService } from 'src/app/services/toast.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',
|
templateUrl: './profile-picture.component.html',
|
||||||
styleUrls: ['./profile-picture.component.scss'],
|
styleUrls: ['./profile-picture.component.scss'],
|
||||||
})
|
})
|
||||||
export class ProfilePictureComponent implements OnInit {
|
export class ProfilePictureComponent {
|
||||||
public isHovering: boolean = false;
|
|
||||||
|
|
||||||
public imageChangedEvent: any = '';
|
|
||||||
public imageChangedFormat: string = '';
|
|
||||||
public croppedImage: any = '';
|
|
||||||
public showCropperError: boolean = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private authService: GrpcAuthService,
|
private authService: GrpcAuthService,
|
||||||
public dialogRef: MatDialogRef<ProfilePictureComponent>,
|
public dialogRef: MatDialogRef<ProfilePictureComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||||
private toast: ToastService,
|
private toast: ToastService,
|
||||||
private assetService: AssetService) { }
|
private assetService: AssetService,
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
public ngOnInit(): void {
|
) {
|
||||||
}
|
|
||||||
|
|
||||||
public toggleHover(isHovering: boolean): void {
|
|
||||||
this.isHovering = isHovering;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onDrop(event: any): Promise<any> | void {
|
public onDrop(event: any): Promise<any> | void {
|
||||||
const filelist: FileList = event.target.files;
|
const filelist: FileList = event.target.files;
|
||||||
console.log(event.target.files);
|
|
||||||
this.imageChangedEvent = event;
|
|
||||||
const file = filelist.item(0);
|
const file = filelist.item(0);
|
||||||
|
|
||||||
if (file) {
|
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 {
|
public deletePic(): void {
|
||||||
console.log('delete');
|
|
||||||
this.authService.removeMyAvatar().then(() => {
|
this.authService.removeMyAvatar().then(() => {
|
||||||
this.toast.showInfo('USER.PROFILE.AVATAR.DELETESUCCESS', true);
|
this.toast.showInfo('USER.PROFILE.AVATAR.DELETESUCCESS', true);
|
||||||
this.data.profilePic = null;
|
this.data.profilePic = null;
|
||||||
@ -55,45 +44,17 @@ export class ProfilePictureComponent implements OnInit {
|
|||||||
private handleUploadPromise(task: Promise<any>): Promise<any> {
|
private handleUploadPromise(task: Promise<any>): Promise<any> {
|
||||||
return task.then(() => {
|
return task.then(() => {
|
||||||
this.toast.showInfo('POLICY.TOAST.UPLOADSUCCESS', true);
|
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));
|
}).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<any> | 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 {
|
public closeDialog(): void {
|
||||||
this.dialogRef.close(false);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
<app-avatar
|
<app-avatar
|
||||||
*ngIf="user.human && user.human.profile.displayName && user.human?.profile.firstName && user.human?.profile.lastName; else cog"
|
*ngIf="user.human && user.human.profile.displayName && user.human?.profile.firstName && user.human?.profile.lastName; else cog"
|
||||||
class="avatar" [name]="user.human.profile.displayName" [forColor]="user?.preferredLoginName" [size]="32">
|
class="avatar" [name]="user.human.profile.displayName" [avatarUrl]="user.human?.profile?.avatarUrl || ''" [forColor]="user?.preferredLoginName" [size]="32">
|
||||||
</app-avatar>
|
</app-avatar>
|
||||||
<ng-template #cog>
|
<ng-template #cog>
|
||||||
<div class="sa-icon" *ngIf="user.machine">
|
<div class="sa-icon" *ngIf="user.machine">
|
||||||
|
@ -312,3 +312,7 @@ h2 {
|
|||||||
i {
|
i {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mat-checkbox-inner-container.mat-checkbox-inner-container-no-side-margin {
|
||||||
|
margin-right: .5rem !important;
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ title: zitadel/change.proto
|
|||||||
| editor_display_name | string | - | |
|
| editor_display_name | string | - | |
|
||||||
| resource_owner_id | string | - | |
|
| resource_owner_id | string | - | |
|
||||||
| editor_preferred_login_name | string | - | |
|
| editor_preferred_login_name | string | - | |
|
||||||
|
| editor_avatar_url | string | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ func UserChangeToPb(change *user_model.UserChange) *change_pb.Change {
|
|||||||
EditorId: change.ModifierID,
|
EditorId: change.ModifierID,
|
||||||
EditorDisplayName: change.ModifierName,
|
EditorDisplayName: change.ModifierName,
|
||||||
EditorPreferredLoginName: change.ModifierLoginName,
|
EditorPreferredLoginName: change.ModifierLoginName,
|
||||||
|
EditorAvatarUrl: change.ModifierAvatarURL,
|
||||||
// ResourceOwnerId: change.,TODO: resource owner not returned
|
// ResourceOwnerId: change.,TODO: resource owner not returned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,6 +52,7 @@ func OrgChangeToPb(change *org_model.OrgChange) *change_pb.Change {
|
|||||||
EditorId: change.ModifierId,
|
EditorId: change.ModifierId,
|
||||||
EditorDisplayName: change.ModifierName,
|
EditorDisplayName: change.ModifierName,
|
||||||
EditorPreferredLoginName: change.ModifierLoginName,
|
EditorPreferredLoginName: change.ModifierLoginName,
|
||||||
|
EditorAvatarUrl: change.ModifierAvatarURL,
|
||||||
// ResourceOwnerId: change.,TODO: resource owner not returned
|
// ResourceOwnerId: change.,TODO: resource owner not returned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,6 +73,7 @@ func ProjectChangeToPb(change *proj_model.ProjectChange) *change_pb.Change {
|
|||||||
EditorId: change.ModifierId,
|
EditorId: change.ModifierId,
|
||||||
EditorDisplayName: change.ModifierName,
|
EditorDisplayName: change.ModifierName,
|
||||||
EditorPreferredLoginName: change.ModifierLoginName,
|
EditorPreferredLoginName: change.ModifierLoginName,
|
||||||
|
EditorAvatarUrl: change.ModifierAvatarURL,
|
||||||
// ResourceOwnerId: change.,TODO: resource owner not returned
|
// ResourceOwnerId: change.,TODO: resource owner not returned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,6 +94,7 @@ func AppChangeToPb(change *proj_model.ApplicationChange) *change_pb.Change {
|
|||||||
EditorId: change.ModifierId,
|
EditorId: change.ModifierId,
|
||||||
EditorDisplayName: change.ModifierName,
|
EditorDisplayName: change.ModifierName,
|
||||||
EditorPreferredLoginName: change.ModifierLoginName,
|
EditorPreferredLoginName: change.ModifierLoginName,
|
||||||
|
EditorAvatarUrl: change.ModifierAvatarURL,
|
||||||
// ResourceOwnerId: change.,TODO: resource owner not returned
|
// ResourceOwnerId: change.,TODO: resource owner not returned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,16 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"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/caos/logging"
|
||||||
|
"github.com/golang/protobuf/ptypes"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/authz"
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
"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/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
"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"
|
key_view_model "github.com/caos/zitadel/internal/key/repository/view/model"
|
||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
"github.com/caos/zitadel/internal/user/model"
|
"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
|
change.ModifierLoginName = user.PreferredLoginName
|
||||||
if user.HumanView != nil {
|
if user.HumanView != nil {
|
||||||
change.ModifierName = user.HumanView.DisplayName
|
change.ModifierName = user.HumanView.DisplayName
|
||||||
|
change.ModifierAvatarURL = user.HumanView.AvatarURL
|
||||||
}
|
}
|
||||||
if user.MachineView != nil {
|
if user.MachineView != nil {
|
||||||
change.ModifierName = user.MachineView.Name
|
change.ModifierName = user.MachineView.Name
|
||||||
|
@ -108,6 +108,7 @@ func (repo *OrgRepository) OrgChanges(ctx context.Context, id string, lastSequen
|
|||||||
change.ModifierLoginName = user.PreferredLoginName
|
change.ModifierLoginName = user.PreferredLoginName
|
||||||
if user.HumanView != nil {
|
if user.HumanView != nil {
|
||||||
change.ModifierName = user.HumanView.DisplayName
|
change.ModifierName = user.HumanView.DisplayName
|
||||||
|
change.ModifierAvatarURL = user.HumanView.AvatarURL
|
||||||
}
|
}
|
||||||
if user.MachineView != nil {
|
if user.MachineView != nil {
|
||||||
change.ModifierName = user.MachineView.Name
|
change.ModifierName = user.MachineView.Name
|
||||||
|
@ -203,6 +203,7 @@ func (repo *ProjectRepo) ProjectChanges(ctx context.Context, id string, lastSequ
|
|||||||
change.ModifierLoginName = user.PreferredLoginName
|
change.ModifierLoginName = user.PreferredLoginName
|
||||||
if user.HumanView != nil {
|
if user.HumanView != nil {
|
||||||
change.ModifierName = user.HumanView.DisplayName
|
change.ModifierName = user.HumanView.DisplayName
|
||||||
|
change.ModifierAvatarURL = user.HumanView.AvatarURL
|
||||||
}
|
}
|
||||||
if user.MachineView != nil {
|
if user.MachineView != nil {
|
||||||
change.ModifierName = user.MachineView.Name
|
change.ModifierName = user.MachineView.Name
|
||||||
@ -282,6 +283,7 @@ func (repo *ProjectRepo) ApplicationChanges(ctx context.Context, projectID strin
|
|||||||
change.ModifierLoginName = user.PreferredLoginName
|
change.ModifierLoginName = user.PreferredLoginName
|
||||||
if user.HumanView != nil {
|
if user.HumanView != nil {
|
||||||
change.ModifierName = user.HumanView.DisplayName
|
change.ModifierName = user.HumanView.DisplayName
|
||||||
|
change.ModifierAvatarURL = user.HumanView.AvatarURL
|
||||||
}
|
}
|
||||||
if user.MachineView != nil {
|
if user.MachineView != nil {
|
||||||
change.ModifierName = user.MachineView.Name
|
change.ModifierName = user.MachineView.Name
|
||||||
|
@ -105,6 +105,7 @@ func (repo *UserRepo) UserChanges(ctx context.Context, id string, lastSequence u
|
|||||||
change.ModifierLoginName = user.PreferredLoginName
|
change.ModifierLoginName = user.PreferredLoginName
|
||||||
if user.HumanView != nil {
|
if user.HumanView != nil {
|
||||||
change.ModifierName = user.HumanView.DisplayName
|
change.ModifierName = user.HumanView.DisplayName
|
||||||
|
change.ModifierAvatarURL = user.HumanView.AvatarURL
|
||||||
}
|
}
|
||||||
if user.MachineView != nil {
|
if user.MachineView != nil {
|
||||||
change.ModifierName = user.MachineView.Name
|
change.ModifierName = user.MachineView.Name
|
||||||
|
@ -40,6 +40,7 @@ type OrgChange struct {
|
|||||||
ModifierId string `json:"modifierUser,omitempty"`
|
ModifierId string `json:"modifierUser,omitempty"`
|
||||||
ModifierName string `json:"-"`
|
ModifierName string `json:"-"`
|
||||||
ModifierLoginName string `json:"-"`
|
ModifierLoginName string `json:"-"`
|
||||||
|
ModifierAvatarURL string `json:"-"`
|
||||||
Data interface{} `json:"data,omitempty"`
|
Data interface{} `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ type ApplicationChange struct {
|
|||||||
ModifierId string `json:"modifierUser,omitempty"`
|
ModifierId string `json:"modifierUser,omitempty"`
|
||||||
ModifierName string `json:"-"`
|
ModifierName string `json:"-"`
|
||||||
ModifierLoginName string `json:"-"`
|
ModifierLoginName string `json:"-"`
|
||||||
|
ModifierAvatarURL string `json:"-"`
|
||||||
Data interface{} `json:"data,omitempty"`
|
Data interface{} `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ type ProjectChange struct {
|
|||||||
ModifierId string `json:"modifierUser,omitempty"`
|
ModifierId string `json:"modifierUser,omitempty"`
|
||||||
ModifierName string `json:"-"`
|
ModifierName string `json:"-"`
|
||||||
ModifierLoginName string `json:"-"`
|
ModifierLoginName string `json:"-"`
|
||||||
|
ModifierAvatarURL string `json:"-"`
|
||||||
Data interface{} `json:"data,omitempty"`
|
Data interface{} `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ func csp(zitadelDomain string) *middleware.CSP {
|
|||||||
AddHost("fonts.googleapis.com").
|
AddHost("fonts.googleapis.com").
|
||||||
AddHost("fonts.gstatic.com").
|
AddHost("fonts.gstatic.com").
|
||||||
AddHost("maxst.icons8.com") //TODO: host it
|
AddHost("maxst.icons8.com") //TODO: host it
|
||||||
csp.ImgSrc = csp.ImgSrc.AddScheme("blob")
|
csp.ImgSrc = csp.ImgSrc.AddHost(zitadelDomain).AddScheme("blob")
|
||||||
return &csp
|
return &csp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,5 +16,6 @@ type UserChange struct {
|
|||||||
ModifierID string `json:"modifierUser,omitempty"`
|
ModifierID string `json:"modifierUser,omitempty"`
|
||||||
ModifierName string `json:"-"`
|
ModifierName string `json:"-"`
|
||||||
ModifierLoginName string `json:"-"`
|
ModifierLoginName string `json:"-"`
|
||||||
|
ModifierAvatarURL string `json:"-"`
|
||||||
Data interface{} `json:"data,omitempty"`
|
Data interface{} `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
package configuration
|
package configuration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/caos/orbos/mntr"
|
"github.com/caos/orbos/mntr"
|
||||||
"github.com/caos/orbos/pkg/kubernetes"
|
"github.com/caos/orbos/pkg/kubernetes"
|
||||||
"github.com/caos/orbos/pkg/kubernetes/resources/configmap"
|
"github.com/caos/orbos/pkg/kubernetes/resources/configmap"
|
||||||
"github.com/caos/orbos/pkg/kubernetes/resources/secret"
|
"github.com/caos/orbos/pkg/kubernetes/resources/secret"
|
||||||
"github.com/caos/orbos/pkg/labels"
|
"github.com/caos/orbos/pkg/labels"
|
||||||
|
|
||||||
"github.com/caos/zitadel/operator"
|
"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/configuration/users"
|
||||||
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database"
|
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConsoleEnv struct {
|
type ConsoleEnv struct {
|
||||||
AuthServiceURL string `json:"authServiceUrl"`
|
AuthServiceURL string `json:"authServiceUrl"`
|
||||||
MgmtServiceURL string `json:"mgmtServiceUrl"`
|
MgmtServiceURL string `json:"mgmtServiceUrl"`
|
||||||
Issuer string `json:"issuer"`
|
Issuer string `json:"issuer"`
|
||||||
ClientID string `json:"clientid"`
|
ClientID string `json:"clientid"`
|
||||||
SubServiceURL string `json:"subscriptionServiceUrl"`
|
SubServiceURL string `json:"subscriptionServiceUrl"`
|
||||||
UploadServiceURL string `json:"uploadServiceUrl"`
|
AssetServiceURL string `json:"assetServiceUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -228,7 +228,7 @@ func literalsConsoleCM(
|
|||||||
consoleEnv.AuthServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain
|
consoleEnv.AuthServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain
|
||||||
consoleEnv.MgmtServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain
|
consoleEnv.MgmtServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain
|
||||||
consoleEnv.SubServiceURL = "https://" + dns.Subdomains.Subscription + "." + 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)
|
data, err := json.Marshal(consoleEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -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://.\"}"},
|
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)
|
k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil)
|
||||||
|
|
||||||
literals := literalsConsoleCM(clientID, desiredEmpty.DNS, k8sClient, namespace, cmName)
|
literals := literalsConsoleCM(clientID, desiredEmpty.DNS, k8sClient, namespace, cmName)
|
||||||
@ -575,7 +575,7 @@ func TestConfiguration_LiteralsConsoleCMFull(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
equals := map[string]string{
|
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)
|
k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil)
|
||||||
|
|
||||||
@ -595,12 +595,12 @@ func TestConfiguration_LiteralsConsoleCMWithCM(t *testing.T) {
|
|||||||
Name: cmName,
|
Name: cmName,
|
||||||
},
|
},
|
||||||
Data: map[string]string{
|
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{
|
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)
|
k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil)
|
||||||
|
|
||||||
@ -620,12 +620,12 @@ func TestConfiguration_LiteralsConsoleCMWithCMFull(t *testing.T) {
|
|||||||
Name: cmName,
|
Name: cmName,
|
||||||
},
|
},
|
||||||
Data: map[string]string{
|
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{
|
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)
|
k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil)
|
||||||
|
|
||||||
|
@ -45,6 +45,12 @@ message Change {
|
|||||||
example: "\"gigi@acme.zitadel.ch\"";
|
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 {
|
message ChangeQuery {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user