fix: management api remove otp (#1010)

* fix: management api remove otp

* add postinstall

* remove mgmt otp

Co-authored-by: Max Peintner <max@caos.ch>
This commit is contained in:
Fabi 2020-11-24 12:06:46 +01:00 committed by GitHub
parent 855725c3c0
commit 75bf0409c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 2 deletions

View File

@ -17,6 +17,16 @@
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MFA.TABLEACTIONS' | translate }} </th>
<td mat-cell *matCellDef="let mfa">
<button matTooltip="{{'ACTIONS.REMOVE' | translate}}" color="warn" mat-icon-button
(click)="deleteMFA(mfa.type)">
<i class="las la-trash"></i>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;">
</tr>

View File

@ -1,9 +1,12 @@
import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSort } from '@angular/material/sort';
import { MatTable, MatTableDataSource } from '@angular/material/table';
import { BehaviorSubject, Observable } from 'rxjs';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
import { MFAState, MfaType, UserMultiFactor, UserView } from 'src/app/proto/generated/management_pb';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
export interface MFAItem {
@ -17,7 +20,7 @@ export interface MFAItem {
styleUrls: ['./user-mfa.component.scss'],
})
export class UserMfaComponent implements OnInit, OnDestroy {
public displayedColumns: string[] = ['type', 'state'];
public displayedColumns: string[] = ['type', 'state', 'actions'];
@Input() private user!: UserView.AsObject;
public mfaSubject: BehaviorSubject<UserMultiFactor.AsObject[]> = new BehaviorSubject<UserMultiFactor.AsObject[]>([]);
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
@ -31,7 +34,7 @@ export class UserMfaComponent implements OnInit, OnDestroy {
public MFAState: any = MFAState;
public error: string = '';
constructor(private mgmtUserService: ManagementService) { }
constructor(private mgmtUserService: ManagementService, private dialog: MatDialog, private toast: ToastService) { }
public ngOnInit(): void {
this.getOTP();
@ -50,4 +53,34 @@ export class UserMfaComponent implements OnInit, OnDestroy {
this.error = error.message;
});
}
public deleteMFA(type: MfaType): void {
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {
confirmKey: 'ACTIONS.DELETE',
cancelKey: 'ACTIONS.CANCEL',
titleKey: 'USER.MFA.DIALOG.OTP_DELETE_TITLE',
descriptionKey: 'USER.MFA.DIALOG.OTP_DELETE_DESCRIPTION',
},
width: '400px',
});
dialogRef.afterClosed().subscribe(resp => {
if (resp) {
if (type === MfaType.MFATYPE_OTP) {
this.mgmtUserService.removeMfaOTP(this.user.id).then(() => {
this.toast.showInfo('USER.TOAST.OTPREMOVED', true);
const index = this.dataSource.data.findIndex(mfa => mfa.type === type);
if (index > -1) {
this.dataSource.data.splice(index, 1);
}
this.getOTP();
}).catch(error => {
this.toast.showError(error);
});
}
}
});
}
}

View File

@ -677,6 +677,12 @@ export class ManagementService {
return this.grpcService.mgmt.getUserMfas(req);
}
public removeMfaOTP(id: string): Promise<Empty> {
const req = new UserID();
req.setId(id);
return this.grpcService.mgmt.removeMfaOTP(req);
}
public SaveUserProfile(
id: string,
firstName?: string,

View File

@ -221,6 +221,11 @@ func (s *Server) GetUserMfas(ctx context.Context, userID *management.UserID) (*m
return &management.UserMultiFactors{Mfas: mfasFromModel(mfas)}, nil
}
func (s *Server) RemoveMfaOTP(ctx context.Context, userID *management.UserID) (*empty.Empty, error) {
err := s.user.RemoveOTP(ctx, userID.Id)
return &empty.Empty{}, err
}
func (s *Server) SearchUserMemberships(ctx context.Context, in *management.UserMembershipSearchRequest) (*management.UserMembershipSearchResponse, error) {
request := userMembershipSearchRequestsToModel(in)
request.AppendUserIDQuery(in.UserId)

View File

@ -223,6 +223,10 @@ func (repo *UserRepo) UserMfas(ctx context.Context, userID string) ([]*usr_model
return []*usr_model.MultiFactor{{Type: usr_model.MfaTypeOTP, State: user.OTPState}}, nil
}
func (repo *UserRepo) RemoveOTP(ctx context.Context, userID string) error {
return repo.UserEvents.RemoveOTP(ctx, userID)
}
func (repo *UserRepo) SetOneTimePassword(ctx context.Context, password *usr_model.Password) (*usr_model.Password, error) {
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if err != nil && caos_errs.IsNotFound(err) {

View File

@ -31,6 +31,7 @@ type UserRepository interface {
ChangeProfile(ctx context.Context, profile *model.Profile) (*model.Profile, error)
UserMfas(ctx context.Context, userID string) ([]*model.MultiFactor, error)
RemoveOTP(ctx context.Context, userID string) error
SearchExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error)
RemoveExternalIDP(ctx context.Context, externalIDP *model.ExternalIDP) error

View File

@ -388,6 +388,16 @@ rpc GetUserByID(UserID) returns (UserView) {
};
}
rpc RemoveMfaOTP(UserID) returns (google.protobuf.Empty) {
option (google.api.http) = {
delete: "/users/{id}/mfas/otp"
};
option (caos.zitadel.utils.v1.auth_option) = {
permission: "user.write"
};
}
// Sends an Notification (Email/SMS) with a password reset Link
rpc SendSetPasswordNotification(SetPasswordNotificationRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {