member totp component modify & store added
This commit is contained in:
parent
2024d2a7dd
commit
951f7f5207
|
@ -3,14 +3,14 @@ import { CommonModule } from '@angular/common';
|
||||||
import { MaterialModule } from 'app/commons/ui/material/material.module';
|
import { MaterialModule } from 'app/commons/ui/material/material.module';
|
||||||
import { MemberPageComponent } from './member-page.component';
|
import { MemberPageComponent } from './member-page.component';
|
||||||
import { MemberPageRoutingModule } from './member-page-routing.module';
|
import { MemberPageRoutingModule } from './member-page-routing.module';
|
||||||
import { MemberModule } from 'packages/settings/member/member.module';
|
import { MemberTotpModule } from 'packages/settings/member/member-totp.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
MemberPageRoutingModule,
|
MemberPageRoutingModule,
|
||||||
MemberModule,
|
MemberTotpModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
MemberPageComponent
|
MemberPageComponent
|
||||||
|
|
|
@ -1,3 +1,39 @@
|
||||||
<div fxLayout="row" fxLayoutWrap fxLayoutAlign="left">
|
|
||||||
<qrcode [qrdata]="'otpauth://totp/overFlow:geekdev@naver.com?secret=X6AWAK573M5372NM'" [size]="256" [level]="'M'"></qrcode>
|
<div fxLayout="row" fxLayoutWrap fxLayoutAlign="center">
|
||||||
|
<div fxLayout="row" fxLayoutWrap fxLayoutAlign="center">
|
||||||
|
|
||||||
|
<mat-card class="example-card">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>QR Code</mat-card-title>
|
||||||
|
<!--<mat-card-subtitle>Select Target</mat-card-subtitle>-->
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<div fxLayout="row" fxLayoutWrap fxLayoutAlign="left">
|
||||||
|
<qrcode [qrdata]="'otpauth://totp/overFlow:geekdev@naver.com?secret=X6AWAK573M5372NM'" [size]="128" [level]="'M'"></qrcode>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" fxLayoutWrap fxLayoutAlign="center">
|
||||||
|
|
||||||
|
<mat-card class="example-card">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Secret Code</mat-card-title>
|
||||||
|
<mat-card-subtitle>X6AWAK573M5372NM</mat-card-subtitle>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<form fxLayout="column" fxLayoutAlign="start stretch" [formGroup]="totpForm" (ngSubmit)="regist()">
|
||||||
|
<mat-form-field class="full-width">
|
||||||
|
<input type="number" id="code" class="input" placeholder="Please enter your code"
|
||||||
|
formControlName="code" required matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
<!--<div *ngIf="formErrors.email" class="help is-danger">-->
|
||||||
|
<!--{{ formErrors.email }}-->
|
||||||
|
<!--</div>-->
|
||||||
|
</form>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import * as TotpStore from '../../store/totp';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import {FormBuilder} from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'of-totp',
|
selector: 'of-totp',
|
||||||
|
@ -7,7 +11,11 @@ import { Component, OnInit } from '@angular/core';
|
||||||
})
|
})
|
||||||
export class TotpComponent implements OnInit {
|
export class TotpComponent implements OnInit {
|
||||||
|
|
||||||
constructor() { }
|
constructor(private activatedRoute: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private store: Store<TotpStore.State>,
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
}
|
}
|
||||||
|
|
24
src/packages/settings/member/member-totp-store.module.ts
Normal file
24
src/packages/settings/member/member-totp-store.module.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { StoreModule } from '@ngrx/store';
|
||||||
|
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||||
|
import {
|
||||||
|
StoreRouterConnectingModule,
|
||||||
|
RouterStateSerializer,
|
||||||
|
} from '@ngrx/router-store';
|
||||||
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
|
import { combineReducers, ActionReducer, ActionReducerMap, MetaReducer } from '@ngrx/store';
|
||||||
|
|
||||||
|
import {
|
||||||
|
REDUCERS,
|
||||||
|
EFFECTS,
|
||||||
|
} from './store';
|
||||||
|
|
||||||
|
import { MODULE } from './member-totp.constant';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
StoreModule.forFeature(MODULE.name, REDUCERS),
|
||||||
|
EffectsModule.forFeature(EFFECTS),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class MemberTotpStoreModule { }
|
3
src/packages/settings/member/member-totp.constant.ts
Normal file
3
src/packages/settings/member/member-totp.constant.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const MODULE = {
|
||||||
|
name: 'member-totp'
|
||||||
|
};
|
|
@ -1,18 +1,23 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import {FormsModule} from '@angular/forms';
|
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||||
|
|
||||||
import { MaterialModule } from 'app/commons/ui/material/material.module';
|
import { MaterialModule } from 'app/commons/ui/material/material.module';
|
||||||
import { QRCodeModule } from 'angularx-qrcode';
|
import { QRCodeModule } from 'angularx-qrcode';
|
||||||
|
|
||||||
import { COMPONENTS } from './component';
|
import { COMPONENTS } from './component';
|
||||||
import {SERVICES} from "../../probe/service";
|
import { SERVICES } from '../../settings/member/service'
|
||||||
|
import { MemberTotpStoreModule } from './member-totp-store.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
QRCodeModule
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
QRCodeModule,
|
||||||
|
MemberTotpStoreModule
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
COMPONENTS,
|
COMPONENTS,
|
||||||
|
@ -24,4 +29,4 @@ import {SERVICES} from "../../probe/service";
|
||||||
SERVICES,
|
SERVICES,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class MemberModule { }
|
export class MemberTotpModule{ }
|
|
@ -1,4 +1,4 @@
|
||||||
import {MemberTotpService} from './member-totp.service';
|
import { MemberTotpService } from './member-totp.service';
|
||||||
|
|
||||||
export const SERVICES = [
|
export const SERVICES = [
|
||||||
MemberTotpService,
|
MemberTotpService,
|
||||||
|
|
|
@ -13,15 +13,15 @@ export class MemberTotpService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public createTotp(): Observable<MemberTotp[]> {
|
public createTotp(member: Member): Observable<MemberTotp[]> {
|
||||||
// Todo Store get member object
|
// Todo Store get member object
|
||||||
|
|
||||||
return this.rpcClient.call<MemberTotp[]>('MemberTotpService.createTotp', {id: '1'});
|
return this.rpcClient.call<MemberTotp[]>('MemberTotpService.createTotp', {id: '1'});
|
||||||
}
|
}
|
||||||
|
|
||||||
public regist(): Observable<boolean> {
|
public regist(member: Member, secretCode: string, code: string): Observable<boolean> {
|
||||||
const param = {
|
const param = {
|
||||||
Member: {id: 1,},
|
Member: {id: 1, },
|
||||||
MemberTotp: {id: 1, secretCode: 'dkdkdkdk'},
|
MemberTotp: {id: 1, secretCode: 'dkdkdkdk'},
|
||||||
code: '123123'
|
code: '123123'
|
||||||
};
|
};
|
||||||
|
|
31
src/packages/settings/member/store/index.ts
Normal file
31
src/packages/settings/member/store/index.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import {
|
||||||
|
createSelector,
|
||||||
|
createFeatureSelector,
|
||||||
|
ActionReducerMap,
|
||||||
|
} from '@ngrx/store';
|
||||||
|
|
||||||
|
import { StateSelector } from 'packages/core/ngrx/store';
|
||||||
|
|
||||||
|
import { MODULE } from '../member-totp.constant';
|
||||||
|
|
||||||
|
import * as TotpStore from './totp';
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
totp: TotpStore.State;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const REDUCERS = {
|
||||||
|
totp: TotpStore.reducer,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EFFECTS = [
|
||||||
|
TotpStore.Effects,
|
||||||
|
];
|
||||||
|
|
||||||
|
export const selectMemberTotpState = createFeatureSelector<State>(MODULE.name);
|
||||||
|
|
||||||
|
export const AuthSelector = new StateSelector<TotpStore.State>(createSelector(
|
||||||
|
selectMemberTotpState,
|
||||||
|
(state: State) => state.totp
|
||||||
|
));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export * from './totp.action';
|
export * from './totp.action';
|
||||||
// export * from './totp.effect';
|
export * from './totp.effect';
|
||||||
// export * from './totp.reducer';
|
export * from './totp.reducer';
|
||||||
// export * from './totp.state';
|
export * from './totp.state';
|
||||||
|
|
|
@ -2,8 +2,7 @@ import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { RESTError } from 'packages/core/rest/error';
|
import { RESTError } from 'packages/core/rest/error';
|
||||||
|
|
||||||
import { DomainMember } from 'packages/domain/model';
|
import { Member } from '../../../../member/model';
|
||||||
import {Member} from "../../../../member/model";
|
|
||||||
|
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
CreateTotp = '[member.totp] CreateTotp',
|
CreateTotp = '[member.totp] CreateTotp',
|
||||||
|
@ -18,7 +17,7 @@ export enum ActionType {
|
||||||
export class CreateTotp implements Action {
|
export class CreateTotp implements Action {
|
||||||
readonly type = ActionType.CreateTotp;
|
readonly type = ActionType.CreateTotp;
|
||||||
|
|
||||||
constructor(public payload: {key: string, uri: string}) {}
|
constructor(public payload: {member: Member}) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CreateTotpSuccess implements Action {
|
export class CreateTotpSuccess implements Action {
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { Effects } from './totp.effect';
|
||||||
|
|
||||||
|
describe('ProbeList.Effects', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [Effects]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([Effects], (effects: Effects) => {
|
||||||
|
expect(effects).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
|
@ -0,0 +1,81 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { Effect, Actions, ofType } from '@ngrx/effects';
|
||||||
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { of } from 'rxjs/observable/of';
|
||||||
|
|
||||||
|
import 'rxjs/add/operator/catch';
|
||||||
|
import 'rxjs/add/operator/do';
|
||||||
|
import 'rxjs/add/operator/exhaustMap';
|
||||||
|
import 'rxjs/add/operator/switchMap';
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import 'rxjs/add/operator/take';
|
||||||
|
|
||||||
|
import { RESTError } from 'packages/core/rest/error';
|
||||||
|
import { MemberTotpService } from '../../service/member-totp.service';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CreateTotp,
|
||||||
|
CreateTotpSuccess,
|
||||||
|
CreateTotpFailure,
|
||||||
|
|
||||||
|
Regist,
|
||||||
|
RegistSuccess,
|
||||||
|
RegistFailure,
|
||||||
|
|
||||||
|
ActionType,
|
||||||
|
} from './totp.action';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class Effects {
|
||||||
|
private _returnURL: any;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private actions$: Actions,
|
||||||
|
private memberTotpService: MemberTotpService,
|
||||||
|
private router: Router
|
||||||
|
) { }
|
||||||
|
|
||||||
|
@Effect()
|
||||||
|
createTotp$: Observable<Action> = this.actions$
|
||||||
|
.ofType(ActionType.CreateTotp)
|
||||||
|
.map((action: CreateTotp) => action.payload)
|
||||||
|
.switchMap(payload => {
|
||||||
|
// this._returnURL = payload.returnURL;
|
||||||
|
return this.memberTotpService.createTotp(payload.member);
|
||||||
|
})
|
||||||
|
.map((result: any) => {
|
||||||
|
const key = result['key'];
|
||||||
|
const uri = result['uri'];
|
||||||
|
return new CreateTotpSuccess({key: key, uri: uri});
|
||||||
|
})
|
||||||
|
.catch((error: RESTError) => {
|
||||||
|
return of(new CreateTotpFailure(error));
|
||||||
|
});
|
||||||
|
|
||||||
|
@Effect({ dispatch: false })
|
||||||
|
createTotpSuccess$ = this.actions$
|
||||||
|
.ofType(ActionType.CreateTotpSuccess)
|
||||||
|
.do(() => {
|
||||||
|
// Todo TOTP View Print
|
||||||
|
this.router.navigateByUrl(this._returnURL);
|
||||||
|
});
|
||||||
|
|
||||||
|
@Effect()
|
||||||
|
regist: Observable<Action> = this.actions$
|
||||||
|
.ofType(ActionType.Regist)
|
||||||
|
.map((action: Regist) => action.payload)
|
||||||
|
.switchMap((payload) => {
|
||||||
|
// this._returnURL = payload.returnURL;
|
||||||
|
return this.memberTotpService.regist(payload.member, payload.secretCode, payload.code);
|
||||||
|
})
|
||||||
|
.map((result: any) => {
|
||||||
|
return new RegistSuccess(result);
|
||||||
|
})
|
||||||
|
.catch((error: RESTError) => {
|
||||||
|
return of(new RegistFailure(error));
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
import {
|
||||||
|
Actions,
|
||||||
|
ActionType,
|
||||||
|
} from './totp.action';
|
||||||
|
|
||||||
|
import {
|
||||||
|
State,
|
||||||
|
initialState,
|
||||||
|
} from './totp.state';
|
||||||
|
|
||||||
|
export function reducer(state = initialState, action: Actions): State {
|
||||||
|
switch (action.type) {
|
||||||
|
case ActionType.CreateTotp: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
error: null,
|
||||||
|
pending: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case ActionType.CreateTotpSuccess: {
|
||||||
|
const secretKey = action.payload.key;
|
||||||
|
const keyURI = action.payload.uri;
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
error: null,
|
||||||
|
pending: false,
|
||||||
|
secretKey: secretKey,
|
||||||
|
keyURI: keyURI,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case ActionType.CreateTotpFailure: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
error: action.payload,
|
||||||
|
pending: false,
|
||||||
|
secretKey: null,
|
||||||
|
keyURI: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case ActionType.Regist: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
error: null,
|
||||||
|
pending: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case ActionType.RegistSuccess: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
error: null,
|
||||||
|
pending: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case ActionType.RegistFailure: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
error: action.payload,
|
||||||
|
pending: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { RESTError } from 'packages/core/rest/error';
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
secretKey: string;
|
||||||
|
keyURI: string;
|
||||||
|
error: RESTError | null;
|
||||||
|
pending: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: State = {
|
||||||
|
secretKey: null,
|
||||||
|
keyURI: null,
|
||||||
|
error: null,
|
||||||
|
pending: false,
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user