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 { MemberPageComponent } from './member-page.component';
|
||||
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({
|
||||
imports: [
|
||||
CommonModule,
|
||||
MaterialModule,
|
||||
MemberPageRoutingModule,
|
||||
MemberModule,
|
||||
MemberTotpModule,
|
||||
],
|
||||
declarations: [
|
||||
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>
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
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({
|
||||
selector: 'of-totp',
|
||||
|
@ -7,7 +11,11 @@ import { Component, OnInit } from '@angular/core';
|
|||
})
|
||||
export class TotpComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
constructor(private activatedRoute: ActivatedRoute,
|
||||
private router: Router,
|
||||
private store: Store<TotpStore.State>,
|
||||
private formBuilder: FormBuilder,
|
||||
) { }
|
||||
|
||||
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 { 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 { QRCodeModule } from 'angularx-qrcode';
|
||||
|
||||
import { COMPONENTS } from './component';
|
||||
import {SERVICES} from "../../probe/service";
|
||||
import { SERVICES } from '../../settings/member/service'
|
||||
import { MemberTotpStoreModule } from './member-totp-store.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
MaterialModule,
|
||||
QRCodeModule
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
QRCodeModule,
|
||||
MemberTotpStoreModule
|
||||
],
|
||||
exports: [
|
||||
COMPONENTS,
|
||||
|
@ -24,4 +29,4 @@ import {SERVICES} from "../../probe/service";
|
|||
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 = [
|
||||
MemberTotpService,
|
||||
|
|
|
@ -13,15 +13,15 @@ export class MemberTotpService {
|
|||
|
||||
}
|
||||
|
||||
public createTotp(): Observable<MemberTotp[]> {
|
||||
public createTotp(member: Member): Observable<MemberTotp[]> {
|
||||
// Todo Store get member object
|
||||
|
||||
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 = {
|
||||
Member: {id: 1,},
|
||||
Member: {id: 1, },
|
||||
MemberTotp: {id: 1, secretCode: 'dkdkdkdk'},
|
||||
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.effect';
|
||||
// export * from './totp.reducer';
|
||||
// export * from './totp.state';
|
||||
export * from './totp.effect';
|
||||
export * from './totp.reducer';
|
||||
export * from './totp.state';
|
||||
|
|
|
@ -2,8 +2,7 @@ import { Action } from '@ngrx/store';
|
|||
|
||||
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 {
|
||||
CreateTotp = '[member.totp] CreateTotp',
|
||||
|
@ -18,7 +17,7 @@ export enum ActionType {
|
|||
export class CreateTotp implements Action {
|
||||
readonly type = ActionType.CreateTotp;
|
||||
|
||||
constructor(public payload: {key: string, uri: string}) {}
|
||||
constructor(public payload: {member: Member}) {}
|
||||
}
|
||||
|
||||
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