Преглед на файлове

начало личного кабинета

kpmy преди 5 години
родител
ревизия
76bc37e3a1

+ 1 - 1
src/app/package.json

@@ -3,7 +3,7 @@
   "version": "0.0.1",
   "scripts": {
     "start": "npx ng serve --aot --source-map --proxy-config proxyconf.json --base-href / --serve-path /",
-    "build": "npx ng build --base-href /"
+    "build": "npx ng build --prod --base-href /"
   },
   "private": true,
   "dependencies": {

+ 25 - 0
src/app/src/app/account/account.service.ts

@@ -0,0 +1,25 @@
+import {Injectable} from "@angular/core";
+import {HttpClient} from "@angular/common/http";
+import {Observable} from "rxjs";
+import {map} from "rxjs/operators";
+
+@Injectable({providedIn: "root"})
+export class AccountService {
+
+  constructor(private httpClient: HttpClient) {
+
+  }
+
+  getAccountsInfo(personId: string): Observable<AccountInfo[]> {
+    return this.httpClient.get(`/api/old/person/${personId}/accounts`).pipe(map((res: any) => <AccountInfo[]>res.accounts))
+  }
+
+  addAccount(personId: string): Observable<string> {
+    return this.httpClient.post(`/api/old/person/${personId}/accounts/add`, {}).pipe(map((res: any) => <string>res.id))
+  }
+}
+
+export class AccountInfo {
+  id: string
+  overall: number
+}

+ 3 - 0
src/app/src/app/app-routing.module.ts

@@ -2,11 +2,14 @@ import {NgModule} from '@angular/core';
 import {RouterModule, Routes} from '@angular/router';
 import {AppLoginComponent} from "./app.login.component";
 import {AppIndexComponent} from "./app.index.component";
+import {PersonPageComponent} from "./person/person.page.component";
+import {PersonService} from "./person/person.service";
 
 
 const routes: Routes = [
   {path: 'frei', component: AppIndexComponent},
   {path: 'login', component: AppLoginComponent},
+  {path: 'personal', component: PersonPageComponent, canActivate: [PersonService], canActivateChild: [PersonService]},
   {path: '', redirectTo: 'frei', pathMatch: 'full'},
 ];
 

+ 10 - 4
src/app/src/app/app.component.html

@@ -1,9 +1,15 @@
-<mat-toolbar class="mat-elevation-z6">
+<mat-toolbar class="mat-elevation-z6" color="primary">
   <mat-toolbar-row fxLayout="row" fxLayoutAlign="space-between center">
     <span><span [routerLink]="['/']" class="href"><img alt="logo" src="../assets/favicon-16x16.png">&nbsp;СВОБОДНЫЕ ДЕНЬГИ</span></span>
-    <div [ngSwitch]="hasAuth() | async">
-      <button (click)="logout()" *ngSwitchCase="true" mat-button>ВЫЙТИ</button>
-      <button *ngSwitchDefault [routerLink]="['/login']" mat-button>ВОЙТИ</button>
+
+    <div fxLayout="row">
+      <button *ngIf="hasAuth() | async" [routerLink]="['/personal']" mat-button>
+        <mat-icon>account_circle</mat-icon>&nbsp;КАБИНЕТ
+      </button>
+      <div [ngSwitch]="hasAuth() | async">
+        <button (click)="logout()" *ngSwitchCase="true" mat-button>ВЫЙТИ</button>
+        <button *ngSwitchDefault [routerLink]="['/login']" mat-button>ВОЙТИ</button>
+      </div>
     </div>
   </mat-toolbar-row>
 </mat-toolbar>

+ 3 - 1
src/app/src/app/app.component.ts

@@ -3,6 +3,7 @@ import {Observable} from "rxjs";
 import {PersonService} from "./person/person.service";
 import {map} from "rxjs/operators";
 import * as _ from 'underscore'
+import {Router} from "@angular/router";
 
 @Component({
   selector: 'app-root',
@@ -11,7 +12,7 @@ import * as _ from 'underscore'
 })
 export class AppComponent {
 
-  constructor(private personService: PersonService) {
+  constructor(private personService: PersonService, private router: Router) {
 
   }
 
@@ -21,5 +22,6 @@ export class AppComponent {
 
   logout() {
     this.personService.resetCurrentPerson()
+    this.router.navigateByUrl("/")
   }
 }

+ 6 - 2
src/app/src/app/app.login.component.ts

@@ -3,6 +3,7 @@ import {HttpClient} from "@angular/common/http";
 import {ReplaySubject} from "rxjs";
 import {MatSnackBar} from "@angular/material/snack-bar";
 import {PersonService} from "./person/person.service";
+import {Router} from "@angular/router";
 
 @Component({
   selector: 'app-login',
@@ -14,7 +15,7 @@ export class AppLoginComponent implements OnInit {
   public code: string
   public valid: number = null;
 
-  constructor(private personService: PersonService, private httpClient: HttpClient, private snackBar: MatSnackBar) {
+  constructor(private personService: PersonService, private router: Router, private httpClient: HttpClient, private snackBar: MatSnackBar) {
     this.qr = new ReplaySubject<QrResponse>();
   }
 
@@ -28,7 +29,10 @@ export class AppLoginComponent implements OnInit {
         this.personService.getCurrentPerson().subscribe(person => {
           this.httpClient.post("/api/new/person/check6", {siteId: person.siteId, code: c, key: qrRes.key}).subscribe((res: QrSixResponse) => {
             this.valid = res.ok ? 1 : 0;
-            if (res.ok) this.personService.setCurrentPerson(res.token)
+            if (res.ok) {
+              this.personService.setCurrentPerson(res.token)
+              this.router.navigateByUrl("/personal")
+            }
           })
         })
       })

+ 6 - 1
src/app/src/app/app.module.ts

@@ -21,6 +21,9 @@ import {MatIconModule} from "@angular/material/icon";
 import {PersonService} from "./person/person.service";
 import {JwtModule} from "@auth0/angular-jwt";
 import {NgxInitModule} from "ngx-init";
+import {PersonPageComponent} from "./person/person.page.component";
+import {MatListModule} from "@angular/material/list";
+import {AccountService} from "./account/account.service";
 
 registerLocaleData(localeRu);
 
@@ -30,7 +33,7 @@ export function jwtTokenGetter() {
 
 @NgModule({
   declarations: [
-    AppComponent, AppLoginComponent, AppIndexComponent
+    AppComponent, AppLoginComponent, AppIndexComponent, PersonPageComponent
   ],
   imports: [
     BrowserModule,
@@ -54,9 +57,11 @@ export function jwtTokenGetter() {
         blacklistedRoutes: [],
       },
     }),
+    MatListModule,
   ],
   providers: [
     PersonService,
+    AccountService,
     {provide: LOCALE_ID, useValue: "ru-RU"},
     {provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: {duration: 2500}}
   ],

+ 22 - 0
src/app/src/app/person/person.page.component.html

@@ -0,0 +1,22 @@
+<div fxFlex="100" fxLayout="row" fxLayoutAlign="stretch start" fxLayoutGap="1em">
+  <div fxFlex="25" fxLayout="column">
+    <mat-card>
+      блабла о вас
+      <mat-card-actions>
+        <button (click)="addAccount()" mat-button>ОТКРЫТЬ СЧЁТ</button>
+      </mat-card-actions>
+    </mat-card>
+    <mat-list>
+      <mat-list-item *ngFor="let account of accounts">
+        <span>Баланс: {{account.overall}}</span>
+      </mat-list-item>
+    </mat-list>
+  </div>
+  <mat-list fxFlex="50">
+    <mat-list-item>туда</mat-list-item>
+    <mat-list-item>сюда</mat-list-item>
+  </mat-list>
+  <mat-card fxFlex="25">
+    всё обо всём
+  </mat-card>
+</div>

+ 29 - 0
src/app/src/app/person/person.page.component.ts

@@ -0,0 +1,29 @@
+import {Component, OnInit} from "@angular/core";
+import {AccountInfo, AccountService} from "../account/account.service";
+import {PersonService} from "./person.service";
+
+@Component({
+  selector: 'person-page',
+  templateUrl: 'person.page.component.html'
+})
+export class PersonPageComponent implements OnInit {
+
+  accounts: AccountInfo[] = []
+
+  constructor(private personService: PersonService, private accountService: AccountService) {
+  }
+
+  ngOnInit(): void {
+    this.personService.getCurrentPerson().subscribe(person => {
+      this.accountService.getAccountsInfo(person.auth.id).subscribe(accounts => {
+        this.accounts = accounts
+      })
+    })
+
+  }
+
+
+  addAccount() {
+    this.personService.getCurrentPerson().subscribe(person => this.accountService.addAccount(person.auth.id).subscribe(res => this.ngOnInit()))
+  }
+}

+ 17 - 3
src/app/src/app/person/person.service.ts

@@ -3,9 +3,11 @@ import {Observable, ReplaySubject} from "rxjs";
 import {v4 as uuidv4} from 'uuid';
 import {JwtHelperService} from "@auth0/angular-jwt";
 import * as _ from 'underscore';
+import {ActivatedRouteSnapshot, CanActivate, CanActivateChild, RouterStateSnapshot, UrlTree} from "@angular/router";
+import {map} from "rxjs/operators";
 
 @Injectable({providedIn: "root"})
-export class PersonService {
+export class PersonService implements CanActivate, CanActivateChild {
 
   private siteId: string
   private helper = new JwtHelperService();
@@ -17,6 +19,14 @@ export class PersonService {
     }
   }
 
+  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
+    return this.getCurrentPerson().pipe(map(person => _.isObject(person.auth)))
+  }
+
+  canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
+    return this.canActivate(childRoute, state)
+  }
+
   resetCurrentPerson() {
     localStorage.removeItem("token");
     this.currentPerson = null;
@@ -38,7 +48,7 @@ export class PersonService {
           let decodedToken = this.helper.decodeToken(tkr);
           //const expirationDate = this.helper.getTokenExpirationDate(tkr);
           if (!this.helper.isTokenExpired(tkr)) {
-            p.auth = {};
+            p.auth = <PersonInfo>{id: decodedToken.sub};
           }
         }
         ret.next(p)
@@ -51,5 +61,9 @@ export class PersonService {
 
 export class Person {
   public siteId: string
-  public auth: any
+  public auth: PersonInfo
+}
+
+export class PersonInfo {
+  id: string
 }

+ 1 - 1
src/main/kotlin/inn/ocsf/bee/freigeld/serve/Security.kt

@@ -168,7 +168,7 @@ class JwtRequestFilter : OncePerRequestFilter() {
             } catch (e: ExpiredJwtException) {
                 System.out.println("JWT Token has expired")
             }
-        } else {
+        } else if (requestTokenHeader != null) {
             logger.warn("JWT Token does not begin with Bearer String")
         }
         if (username != null && SecurityContextHolder.getContext().authentication == null) {

+ 26 - 1
src/main/kotlin/inn/ocsf/bee/freigeld/serve/rest/PersonController.kt

@@ -12,6 +12,7 @@ import dev.samstevens.totp.secret.DefaultSecretGenerator
 import dev.samstevens.totp.time.SystemTimeProvider
 import dev.samstevens.totp.time.TimeProvider
 import dev.samstevens.totp.util.Utils.getDataUriForImage
+import inn.ocsf.bee.freigeld.core.model.CentralBank
 import inn.ocsf.bee.freigeld.core.model.GlobalWorld
 import inn.ocsf.bee.freigeld.core.model.PersonIdentityFullName
 import inn.ocsf.bee.freigeld.core.model.PersonIdentitySecret
@@ -27,9 +28,33 @@ import org.springframework.web.bind.annotation.*
 import java.util.*
 import javax.inject.Inject
 
+@RestController
+class PersonController {
+
+    @Inject
+    private lateinit var world: GlobalWorld
+
+    @Inject
+    private lateinit var bank: CentralBank
+
+    @RequestMapping("api/old/person/{personId}/accounts", method = [RequestMethod.GET])
+    fun getAccountsInfo(@PathVariable("personId") personId: UUID): ResponseEntity<Map<String, Any?>> {
+        val accounts = bank.getAccounts(personId).map { AccountInfo(it.id, it.overall) }
+        return ResponseEntity.ok(mapOf("accounts" to accounts))
+    }
+
+    @RequestMapping("api/old/person/{personId}/accounts/add", method = [RequestMethod.POST])
+    fun addAccount(@PathVariable("personId") personId: UUID): ResponseEntity<Map<String, Any?>> {
+        val account = bank.addAccount(personId)
+        return ResponseEntity.ok(mapOf("id" to account.id))
+    }
+}
+
+data class AccountInfo(val id: UUID, val overall: Long)
+
 @RestController
 @CrossOrigin
-class PersonController : JwtAuthenticationController() {
+class PersonAuthController : JwtAuthenticationController() {
 
     @Inject
     private lateinit var storage: KeyValueStorage