Merge pull request #5244 from mempool/nymkappa/refresh-checkout-state-logout
[accelerator] refresh checkout state logout
This commit is contained in:
commit
011a854a84
@ -7,7 +7,7 @@ import { AudioService } from '../../services/audio.service';
|
|||||||
import { ETA, EtaService } from '../../services/eta.service';
|
import { ETA, EtaService } from '../../services/eta.service';
|
||||||
import { Transaction } from '../../interfaces/electrs.interface';
|
import { Transaction } from '../../interfaces/electrs.interface';
|
||||||
import { MiningStats } from '../../services/mining.service';
|
import { MiningStats } from '../../services/mining.service';
|
||||||
import { StorageService } from '../../services/storage.service';
|
import { IAuth, AuthServiceMempool } from '../../services/auth.service';
|
||||||
|
|
||||||
export type PaymentMethod = 'balance' | 'bitcoin' | 'cashapp';
|
export type PaymentMethod = 'balance' | 'bitcoin' | 'cashapp';
|
||||||
|
|
||||||
@ -71,7 +71,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
simpleMode: boolean = true;
|
simpleMode: boolean = true;
|
||||||
paymentMethod: 'cashapp' | 'btcpay';
|
paymentMethod: 'cashapp' | 'btcpay';
|
||||||
|
|
||||||
user: any = undefined;
|
authSubscription$: Subscription;
|
||||||
|
auth: IAuth | null = null;
|
||||||
|
|
||||||
// accelerator stuff
|
// accelerator stuff
|
||||||
square: { appId: string, locationId: string};
|
square: { appId: string, locationId: string};
|
||||||
@ -109,16 +110,22 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
public stateService: StateService,
|
public stateService: StateService,
|
||||||
private servicesApiService: ServicesApiServices,
|
private servicesApiService: ServicesApiServices,
|
||||||
private storageService: StorageService,
|
|
||||||
private etaService: EtaService,
|
private etaService: EtaService,
|
||||||
private audioService: AudioService,
|
private audioService: AudioService,
|
||||||
private cd: ChangeDetectorRef
|
private cd: ChangeDetectorRef,
|
||||||
|
private authService: AuthServiceMempool
|
||||||
) {
|
) {
|
||||||
this.accelerationUUID = window.crypto.randomUUID();
|
this.accelerationUUID = window.crypto.randomUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.user = this.storageService.getAuth()?.user ?? null;
|
this.authSubscription$ = this.authService.getAuth$().subscribe((auth) => {
|
||||||
|
this.auth = auth;
|
||||||
|
this.estimate = null;
|
||||||
|
this.moveToStep('summary');
|
||||||
|
});
|
||||||
|
this.authService.refreshAuth$().subscribe();
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
if (urlParams.get('cash_request_id')) { // Redirected from cashapp
|
if (urlParams.get('cash_request_id')) { // Redirected from cashapp
|
||||||
this.moveToStep('processing');
|
this.moveToStep('processing');
|
||||||
@ -146,6 +153,9 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
if (this.estimateSubscription) {
|
if (this.estimateSubscription) {
|
||||||
this.estimateSubscription.unsubscribe();
|
this.estimateSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
if (this.authSubscription$) {
|
||||||
|
this.authSubscription$.unsubscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
@ -456,8 +466,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isLoggedIn(): boolean {
|
isLoggedIn(): boolean {
|
||||||
const auth = this.storageService.getAuth();
|
return this.auth !== null;
|
||||||
return auth !== null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,7 +129,7 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div class="flex-grow-1"></div>
|
<div class="flex-grow-1"></div>
|
||||||
<app-global-footer *ngIf="footerVisible"></app-global-footer>
|
<app-global-footer *ngIf="footerVisible" [user]="user"></app-global-footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { StorageService } from '../../services/storage.service';
|
|||||||
import { Router, NavigationStart } from '@angular/router';
|
import { Router, NavigationStart } from '@angular/router';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
import { IUser, ServicesApiServices } from '../../services/services-api.service';
|
import { IUser, ServicesApiServices } from '../../services/services-api.service';
|
||||||
|
import { AuthServiceMempool } from '../../services/auth.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-menu',
|
selector: 'app-menu',
|
||||||
@ -26,7 +27,8 @@ export class MenuComponent implements OnInit, OnDestroy {
|
|||||||
private servicesApiServices: ServicesApiServices,
|
private servicesApiServices: ServicesApiServices,
|
||||||
private storageService: StorageService,
|
private storageService: StorageService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private stateService: StateService
|
private stateService: StateService,
|
||||||
|
private authService: AuthServiceMempool
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -61,12 +63,19 @@ export class MenuComponent implements OnInit, OnDestroy {
|
|||||||
this.loggedOut.emit(true);
|
this.loggedOut.emit(true);
|
||||||
if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) {
|
if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) {
|
||||||
this.userMenuGroups$ = this.servicesApiServices.getUserMenuGroups$();
|
this.userMenuGroups$ = this.servicesApiServices.getUserMenuGroups$();
|
||||||
this.router.navigateByUrl('/');
|
this.authService.logout();
|
||||||
|
if (window.location.toString().includes('services')) {
|
||||||
|
this.router.navigateByUrl('/login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onLinkClick(link) {
|
onLinkClick(link) {
|
||||||
|
if (link === 'logout') {
|
||||||
|
this.toggleMenu(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!this.isServicesPage || this.isSmallScreen()) {
|
if (!this.isServicesPage || this.isSmallScreen()) {
|
||||||
this.toggleMenu(false);
|
this.toggleMenu(false);
|
||||||
}
|
}
|
||||||
|
71
frontend/src/app/services/auth.service.ts
Normal file
71
frontend/src/app/services/auth.service.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { map, Observable, ReplaySubject, switchMap, tap } from 'rxjs';
|
||||||
|
import { ServicesApiServices } from './services-api.service';
|
||||||
|
|
||||||
|
export interface IAuth {
|
||||||
|
token: string;
|
||||||
|
user: {
|
||||||
|
userId: number;
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AuthServiceMempool {
|
||||||
|
private auth$: ReplaySubject<IAuth | null> = new ReplaySubject(1);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private servicesApiService: ServicesApiServices,
|
||||||
|
private router: Router,
|
||||||
|
) {
|
||||||
|
const localStorageAuth = localStorage.getItem('auth');
|
||||||
|
if (!localStorageAuth || localStorageAuth.length === 0) {
|
||||||
|
this.setAuth(null);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
this.setAuth(JSON.parse(localStorageAuth));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Unable to parse 'auth' from localStorage`, e);
|
||||||
|
localStorage.removeItem('auth');
|
||||||
|
this.setAuth(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshAuth$(): Observable<IAuth | null> {
|
||||||
|
return this.servicesApiService.getJWT$()
|
||||||
|
.pipe(
|
||||||
|
tap((user) => {
|
||||||
|
this.setAuth(user);
|
||||||
|
}),
|
||||||
|
map((user) => {
|
||||||
|
return user;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
this.setAuth(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAuth(auth: any) {
|
||||||
|
if (!auth) {
|
||||||
|
localStorage.removeItem('auth');
|
||||||
|
} else {
|
||||||
|
localStorage.setItem('auth', JSON.stringify(auth));
|
||||||
|
}
|
||||||
|
this.auth$.next(auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAuth$(): Observable<IAuth | null> {
|
||||||
|
if (!localStorage.getItem('auth')) {
|
||||||
|
return this.refreshAuth$().pipe(
|
||||||
|
switchMap(() => this.auth$.asObservable())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.auth$.asObservable();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import { Router, NavigationStart } from '@angular/router';
|
import { Router, NavigationStart } from '@angular/router';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { StateService } from './state.service';
|
import { StateService } from './state.service';
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
import { MenuGroup } from '../interfaces/services.interface';
|
import { MenuGroup } from '../interfaces/services.interface';
|
||||||
@ -120,6 +120,10 @@ export class ServicesApiServices {
|
|||||||
return this.httpClient.post(`${SERVICES_API_PREFIX}/auth/logout`, {});
|
return this.httpClient.post(`${SERVICES_API_PREFIX}/auth/logout`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getJWT$() {
|
||||||
|
return this.httpClient.get<any>(`${SERVICES_API_PREFIX}/auth/getJWT`);
|
||||||
|
}
|
||||||
|
|
||||||
getServicesBackendInfo$(): Observable<IBackendInfo> {
|
getServicesBackendInfo$(): Observable<IBackendInfo> {
|
||||||
return this.httpClient.get<IBackendInfo>(`${SERVICES_API_PREFIX}/version`);
|
return this.httpClient.get<IBackendInfo>(`${SERVICES_API_PREFIX}/version`);
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<a *ngIf="stateService.isMempoolSpaceBuild" class="btn btn-purple sponsor d-none d-sm-flex justify-content-center" [routerLink]="['/login']">
|
<a *ngIf="stateService.isMempoolSpaceBuild" class="btn btn-purple sponsor d-none d-sm-flex justify-content-center" [routerLink]="['/login']">
|
||||||
<span *ngIf="loggedIn" i18n="shared.my-account" class="nowrap">My Account</span>
|
<span *ngIf="user" i18n="shared.my-account" class="nowrap">My Account</span>
|
||||||
<span *ngIf="!loggedIn" i18n="shared.sign-in" class="nowrap">Sign In</span>
|
<span *ngIf="!user" i18n="shared.sign-in" class="nowrap">Sign In</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@if (!env.customize?.theme) {
|
@if (!env.customize?.theme) {
|
||||||
@ -44,8 +44,8 @@
|
|||||||
}
|
}
|
||||||
@if (!enterpriseInfo?.footer_img) {
|
@if (!enterpriseInfo?.footer_img) {
|
||||||
<a *ngIf="stateService.isMempoolSpaceBuild" class="btn btn-purple sponsor d-flex d-sm-none justify-content-center ml-auto mr-auto mt-0 mb-2" [routerLink]="['/login']">
|
<a *ngIf="stateService.isMempoolSpaceBuild" class="btn btn-purple sponsor d-flex d-sm-none justify-content-center ml-auto mr-auto mt-0 mb-2" [routerLink]="['/login']">
|
||||||
<span *ngIf="loggedIn" i18n="shared.my-account" class="nowrap">My Account</span>
|
<span *ngIf="user" i18n="shared.my-account" class="nowrap">My Account</span>
|
||||||
<span *ngIf="!loggedIn" i18n="shared.sign-in" class="nowrap">Sign In</span>
|
<span *ngIf="!user" i18n="shared.sign-in" class="nowrap">Sign In</span>
|
||||||
</a>
|
</a>
|
||||||
<p class="explore-tagline-desktop">
|
<p class="explore-tagline-desktop">
|
||||||
<ng-container i18n="@@7deec1c1520f06170e1f8e8ddfbe4532312f638f">Explore the full Bitcoin ecosystem</ng-container>
|
<ng-container i18n="@@7deec1c1520f06170e1f8e8ddfbe4532312f638f">Explore the full Bitcoin ecosystem</ng-container>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, Inject, LOCALE_ID, HostListener, OnDestroy } from '@angular/core';
|
import { Input, ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, OnChanges, SimpleChanges, Inject, LOCALE_ID, OnDestroy } from '@angular/core';
|
||||||
import { Router, ActivatedRoute } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
import { Observable, merge, of, Subject, Subscription } from 'rxjs';
|
import { Observable, merge, of, Subject, Subscription } from 'rxjs';
|
||||||
import { tap, takeUntil } from 'rxjs/operators';
|
import { tap, takeUntil } from 'rxjs/operators';
|
||||||
@ -16,7 +16,9 @@ import { EnterpriseService } from '../../../services/enterprise.service';
|
|||||||
styleUrls: ['./global-footer.component.scss'],
|
styleUrls: ['./global-footer.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class GlobalFooterComponent implements OnInit, OnDestroy {
|
export class GlobalFooterComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
|
@Input() user: any = undefined;
|
||||||
|
|
||||||
private destroy$: Subject<any> = new Subject<any>();
|
private destroy$: Subject<any> = new Subject<any>();
|
||||||
env: Env;
|
env: Env;
|
||||||
officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
|
officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
|
||||||
@ -29,7 +31,6 @@ export class GlobalFooterComponent implements OnInit, OnDestroy {
|
|||||||
network$: Observable<string>;
|
network$: Observable<string>;
|
||||||
networkPaths: { [network: string]: string };
|
networkPaths: { [network: string]: string };
|
||||||
currentNetwork = '';
|
currentNetwork = '';
|
||||||
loggedIn = false;
|
|
||||||
urlSubscription: Subscription;
|
urlSubscription: Subscription;
|
||||||
isServicesPage = false;
|
isServicesPage = false;
|
||||||
|
|
||||||
@ -72,11 +73,17 @@ export class GlobalFooterComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.urlSubscription = this.route.url.subscribe((url) => {
|
this.urlSubscription = this.route.url.subscribe((url) => {
|
||||||
this.loggedIn = this.storageService.getAuth() !== null;
|
this.user = this.storageService.getAuth();
|
||||||
this.cd.markForCheck();
|
this.cd.markForCheck();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
if (changes.user) {
|
||||||
|
this.user = this.storageService.getAuth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.destroy$.next(true);
|
this.destroy$.next(true);
|
||||||
this.destroy$.complete();
|
this.destroy$.complete();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user