Implement stepper for login

This commit is contained in:
Rene Vergara 2021-11-18 16:38:25 -06:00
parent e5ff05d814
commit 2f610c8f7f
6 changed files with 97 additions and 77 deletions

View file

@ -10,6 +10,7 @@ const itemmodel = require('./models/item');
const ordermodel = require('./models/order'); const ordermodel = require('./models/order');
const pricemodel = require('./models/price'); const pricemodel = require('./models/price');
const txmodel = require('./models/tx'); const txmodel = require('./models/tx');
const zecTxModel = require('./models/zectxs.js');
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const stdrpc = require('stdrpc'); const stdrpc = require('stdrpc');
const CoinGecko = require('coingecko-api'); const CoinGecko = require('coingecko-api');
@ -99,7 +100,7 @@ var blockInterval = setInterval( function() {
var re = /.*ZGO::(.*)\sReply-To:\s(z\w+)/; var re = /.*ZGO::(.*)\sReply-To:\s(z\w+)/;
async.each (txs, function(txData, callback) { async.each (txs, function(txData, callback) {
var memo = hexToString(txData.memo).replace(/\0/g, ''); var memo = hexToString(txData.memo).replace(/\0/g, '');
txmodel.updateOne({txid: txData.txid}, { confirmations: txData.confirmations, amount:txData.amount, memo: memo}, {new:true, upsert:true}, function(err,docs) { zecTxModel.updateOne({txid: txData.txid}, { txid: txData.txid, confirmations: txData.confirmations, amount:txData.amount, memo: memo}, {new:true, upsert:true}, function(err,docs) {
if (err) { if (err) {
console.log(err); console.log(err);
} }
@ -114,16 +115,14 @@ var blockInterval = setInterval( function() {
var amount = txData.amount; var amount = txData.amount;
var expiration = blocktime; var expiration = blocktime;
//console.log(' ', session, blocktime); //console.log(' ', session, blocktime);
txmodel.updateOne({txid: txData.txid}, { address: address, session: session, confirmations: txData.confirmations, amount:txData.amount, memo: memo}, {new:true, upsert:true}, function(err,docs) { txmodel.updateOne({txid: txData.txid}, { txid: txData.txid, address: address, session: session, confirmations: txData.confirmations, amount:txData.amount, memo: memo}, {new:true, upsert:true}, function(err,docs) {
if (err) { if (err) {
console.log(err); console.log(err);
} }
}); });
if (txData.confirmations >= 6 ) { if (txData.confirmations >= 6 ) {
usermodel.findOne({address: address, session: session, blocktime: blocktime}).then(function(doc){ usermodel.findOne({address: address, session: session, blocktime: blocktime}).then(function(doc){
if (doc != null) { if (doc == null){
console.log('Found user');
} else {
console.log('User not found', session, blocktime, amount); console.log('User not found', session, blocktime, amount);
if (amount >= 0.001 && amount < 0.005){ if (amount >= 0.001 && amount < 0.005){
expiration = blocktime + 3600; expiration = blocktime + 3600;
@ -152,9 +151,7 @@ var blockInterval = setInterval( function() {
} }
}); });
ownermodel.findOne({address: address}).then(function (oDoc) { ownermodel.findOne({address: address}).then(function (oDoc) {
if (oDoc != null) { if (oDoc == null) {
console.log('Found owner');
} else {
console.log('Owner not found', session); console.log('Owner not found', session);
var owner = new ownermodel({ var owner = new ownermodel({
address: address, address: address,

View file

@ -5,7 +5,7 @@ const txSchema = mongoose.Schema({
session: {type: String, required:true}, session: {type: String, required:true},
confirmations: {type: Number, required:true}, confirmations: {type: Number, required:true},
amount: {type: Number, required:true}, amount: {type: Number, required:true},
txid: {type:String, required:true}, txid: {type:String, required:true, unique: true},
memo: {type:String} memo: {type:String}
}); });

12
backend/models/zectxs.js Normal file
View file

@ -0,0 +1,12 @@
const mongoose = require('mongoose');
const ZecTxSchema = mongoose.Schema({
address: {type: String},
session: {type: String, required:true},
confirmations: {type: Number, required:true},
amount: {type: Number, required:true},
txid: {type:String, required:true, unique: true},
memo: {type:String}
});
module.exports = mongoose.model('ZecTx', ZecTxSchema);

View file

@ -12,6 +12,8 @@ import { MatIconModule } from '@angular/material/icon';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
import { MatListModule } from '@angular/material/list'; import { MatListModule } from '@angular/material/list';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatStepperModule } from '@angular/material/stepper';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
@ -63,6 +65,8 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
MatDividerModule, MatDividerModule,
MatListModule, MatListModule,
MatSelectModule, MatSelectModule,
MatProgressBarModule,
MatStepperModule,
BrowserAnimationsModule BrowserAnimationsModule
], ],
exports: [ exports: [

View file

@ -19,62 +19,51 @@
<div align="center"> <div align="center">
<mat-card> <mat-card>
<h3>The Zcash Register</h3> <h3>The Zcash Register</h3>
<div width="75%" align="left" *ngIf="!confirmedMemo"> <mat-vertical-stepper #stepper linear>
<ol> <mat-step label="Log in with a shielded memo">
<li> <mat-card [formGroup]="entryForm">
Select your session length. <div align="center" id="info">
</li> <p>Select your session length and confirm once you've sent your memo:</p>
<li> <mat-form-field appearance="outline">
Confirm you've sent your shielded memo. <mat-label>Session length</mat-label>
</li> <mat-select formControlName="selectedSession">
<li> <mat-option *ngFor="let ticket of tickets" [value]="ticket.value">
Wait for confirmation of your transaction on the Zcash blockchain (~10 minutes). {{ticket.viewValue}}
</li> </mat-option>
<li> </mat-select>
Enter the PIN provided by ZGo to your wallet to confirm ownership. </mat-form-field>
</li> <mat-card-actions>
</ol> <button mat-raised-button color="primary" [disabled]="!entryForm.valid" (click)="login(stepper)">
</div> <mat-icon class="icon">login</mat-icon><span class="bigbutton">Log in</span>
<div width="75%" *ngIf="confirmedMemo"> </button>
<p>Expecting confirmation around block {{targetBlock}}.</p> </mat-card-actions>
</div> </div>
</mat-card> </mat-card>
<mat-card [formGroup]="pinForm" *ngIf="prompt"> </mat-step>
<h4> <mat-step label="Step 2">
Check your wallet <p>{{barMessage}}</p>
</h4> <mat-progress-bar
<mat-form-field appearance="outline"> [mode]="barMode"
<mat-label>PIN</mat-label> [value]="barValue">
<input matInput formControlName="pinValue"> </mat-progress-bar>
</mat-form-field> </mat-step>
<mat-card-actions> <mat-step label="Step 3">
<button mat-raised-button color="primary" [disabled]="!pinForm.valid" (click)="confirmPin()"> <mat-card [formGroup]="pinForm">
Confirm <h4>
</button> Check your wallet
</mat-card-actions> </h4>
</mat-card> <mat-form-field appearance="outline">
<mat-card class="alert-success" *ngIf = "txs.length > 0"> <mat-label>PIN</mat-label>
<h4>Login received!</h4> <input matInput formControlName="pinValue">
<mat-list> </mat-form-field>
<mat-list-item *ngFor="let tx of txsUpdate | async">It needs {{6 - tx.confirmations}} more confirmations.</mat-list-item> <p *ngIf="pinError">Wrong pin!</p>
</mat-list> <mat-card-actions>
</mat-card> <button mat-raised-button color="primary" [disabled]="!pinForm.valid" (click)="confirmPin()">
<mat-card [formGroup]="entryForm" *ngIf="!prompt && txs.length <=0"> Confirm
<div align="center" id="info"> </button>
<mat-form-field appearance="outline"> </mat-card-actions>
<mat-label>Session length</mat-label> </mat-card>
<mat-select formControlName="selectedSession"> </mat-step>
<mat-option *ngFor="let ticket of tickets" [value]="ticket.value"> </mat-vertical-stepper>
{{ticket.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
<p *ngIf="pinError">Wrong pin!</p>
<mat-card-actions>
<button mat-raised-button color="primary" [disabled]="!entryForm.valid" (click)="login()">
<mat-icon class="icon">login</mat-icon><span class="bigbutton">Log in</span>
</button>
</mat-card-actions>
</div>
</mat-card> </mat-card>
</div> </div>

View file

@ -1,7 +1,9 @@
import { Component, OnInit, OnDestroy, Injectable, ChangeDetectorRef } from '@angular/core'; import { Component, OnInit, OnDestroy, Injectable, ChangeDetectorRef, ViewChild, AfterViewInit } from '@angular/core';
import { CanActivate, Router, RouterStateSnapshot, ActivatedRouteSnapshot, ActivatedRoute } from '@angular/router'; import { CanActivate, Router, RouterStateSnapshot, ActivatedRouteSnapshot, ActivatedRoute } from '@angular/router';
import { MatDialog, MatDialogConfig} from '@angular/material/dialog'; import { MatDialog, MatDialogConfig} from '@angular/material/dialog';
import { FormBuilder, Validators, FormGroup, FormControl } from '@angular/forms'; import { FormBuilder, Validators, FormGroup, FormControl } from '@angular/forms';
import { ProgressBarMode } from '@angular/material/progress-bar';
import { MatStepper } from '@angular/material/stepper';
import { UserService } from '../user.service'; import { UserService } from '../user.service';
import { FullnodeService } from '../fullnode.service'; import { FullnodeService } from '../fullnode.service';
import { ScanComponent} from '../scan/scan.component'; import { ScanComponent} from '../scan/scan.component';
@ -21,7 +23,7 @@ var Buffer = require('buffer/').Buffer;
styleUrls: ['./login.component.css'] styleUrls: ['./login.component.css']
}) })
export class LoginComponent implements OnInit { export class LoginComponent implements OnInit, AfterViewInit {
txs: Tx[] = []; txs: Tx[] = [];
intervalHolder: any; intervalHolder: any;
nodeAddress: string = ''; nodeAddress: string = '';
@ -57,10 +59,15 @@ export class LoginComponent implements OnInit {
prompt: boolean = false; prompt: boolean = false;
confirmedMemo: boolean = false; confirmedMemo: boolean = false;
targetBlock: number = 0; targetBlock: number = 0;
barMode: ProgressBarMode = 'indeterminate';
barValue = 0;
barMessage = 'Scanning blockchain for login memo, please wait.';
@ViewChild('stepper') private myStepper?: MatStepper;
entryForm: FormGroup; entryForm: FormGroup;
pinForm: FormGroup; pinForm: FormGroup;
constructor( constructor(
private fb: FormBuilder, private fb: FormBuilder,
private activatedRoute: ActivatedRoute, private activatedRoute: ActivatedRoute,
@ -89,7 +96,8 @@ export class LoginComponent implements OnInit {
}); });
} }
ngOnInit(){ ngAfterViewInit(){
//console.log('Step', this.myStepper);
this.pinError = false; this.pinError = false;
//console.log('Activated route data in Component:::', this.activatedRoute.data); //console.log('Activated route data in Component:::', this.activatedRoute.data);
this.activatedRoute.data.subscribe((addrData) => { this.activatedRoute.data.subscribe((addrData) => {
@ -105,12 +113,15 @@ export class LoginComponent implements OnInit {
} }
this.loginCheck(); this.loginCheck();
}); });
}
ngOnInit(){
this.intervalHolder = setInterval(() => { this.intervalHolder = setInterval(() => {
this.fullnodeService.getHeight(); this.fullnodeService.getHeight();
//this.userService.findUser(); //this.userService.findUser();
this.loginCheck(); this.loginCheck();
this._changeDetectorRef.markForCheck(); this._changeDetectorRef.markForCheck();
}, 1000 * 75); }, 1000 * 60);
} }
loginCheck(){ loginCheck(){
@ -122,16 +133,24 @@ export class LoginComponent implements OnInit {
}); });
this.userUpdate.subscribe((user) => { this.userUpdate.subscribe((user) => {
if (user.expiration > today) { if (user.expiration > today) {
this.prompt = true; if(this.myStepper!.selectedIndex === 1){
console.log('Log in found in blockchain!'); this.myStepper!.next();
}
//console.log('Log in found in blockchain!');
if (user.validated) { if (user.validated) {
this.router.navigate(['/shop']); this.router.navigate(['/shop']);
} }
} }
}); });
if (this.txs.length > 0) {
this.barMode = 'determinate';
this.barValue = (this.txs[0].confirmations / 6) * 100;
this.confirmedMemo = true;
this.barMessage = 'Login memo found, awaiting confirmations';
}
} }
login() { login(stepper: MatStepper) {
//console.log('Dropdown:', this.entryForm.value.selectedSession); //console.log('Dropdown:', this.entryForm.value.selectedSession);
const dialogConfig = new MatDialogConfig(); const dialogConfig = new MatDialogConfig();
@ -146,10 +165,9 @@ export class LoginComponent implements OnInit {
const dialogRef = this.dialog.open(ScanComponent, dialogConfig); const dialogRef = this.dialog.open(ScanComponent, dialogConfig);
dialogRef.afterClosed().subscribe((val) => { dialogRef.afterClosed().subscribe((val) => {
console.log('Awaiting confirmation'); console.log('Awaiting confirmation');
this.confirmedMemo = val; if(val){
this.heightUpdate.pipe(take(1)).subscribe(block => { stepper.next();
this.targetBlock = block + 10; }
});
}); });
} }