Sfoglia il codice sorgente

introduced session and websocket notification observables.

tags/2.037
Patrick Sun 4 anni fa
parent
commit
58164749ea
23 ha cambiato i file con 303 aggiunte e 199 eliminazioni
  1. +25
    -11
      src/app/app.component.ts
  2. +2
    -0
      src/app/app.config.model.ts
  3. +10
    -2
      src/app/app.config.ts
  4. +2
    -0
      src/app/app.module.ts
  5. +9
    -9
      src/app/auth/auth-http-interceptor.service.ts
  6. +4
    -2
      src/app/auth/auth.component.ts
  7. +5
    -6
      src/app/broker-loan-list/broker-loan-list.component.ts
  8. +5
    -3
      src/app/broker-reward/broker-reward.component.ts
  9. +3
    -2
      src/app/client-loan-list/client-loan-list.component.ts
  10. +4
    -3
      src/app/client-profile/client-profile.component.ts
  11. +1
    -1
      src/app/models/api-v1-login-response.ts
  12. +24
    -0
      src/app/models/user.model.ts
  13. +15
    -0
      src/app/models/websocket/ws.login.event.model.ts
  14. +3
    -2
      src/app/profile/broker-profile/broker-profile.component.ts
  15. +7
    -6
      src/app/profile/change-password/change-password.component.ts
  16. +10
    -8
      src/app/profile/people-profile/people-profile.component.ts
  17. +12
    -11
      src/app/profile/profile.component.ts
  18. +8
    -7
      src/app/profile/user-profile/user-profile.component.ts
  19. +24
    -80
      src/app/service/auth.service.ts
  20. +75
    -0
      src/app/service/session.service.ts
  21. +8
    -6
      src/app/top-bar/top-bar.component.ts
  22. +43
    -27
      src/app/websocket.ts
  23. +4
    -13
      src/index.html

+ 25
- 11
src/app/app.component.ts Vedi File

import { MenuService } from './service/menu.service'; import { MenuService } from './service/menu.service';


import {WebSocketService} from './websocket'; import {WebSocketService} from './websocket';
import {AppConfig} from './app.config';
import {Title} from '@angular/platform-browser';


@Component({ @Component({
selector: 'app-root', selector: 'app-root',
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class AppComponent implements OnInit , OnDestroy { export class AppComponent implements OnInit , OnDestroy {
title = 'SFM broker';
private menutItemSub: Subscription;
title = 'SFM Advanced Loan management';
private menuItemSub: Subscription;
@ViewChild('loanEditComponent', {static: true}) loanEdit: LoanEditComponent; @ViewChild('loanEditComponent', {static: true}) loanEdit: LoanEditComponent;


constructor(private menuService: MenuService, private authService: AuthService, private wsService: WebSocketService){
wsService.createObservableSocket(this.authService.apiWsUrl)
.subscribe(m => {
console.log('websocket server send this :', m);
});
webSocketSubscription: Subscription;
wsLoginSub: Subscription;

constructor(private menuService: MenuService,
private authService: AuthService,
private config: AppConfig,
private wsService: WebSocketService,
private titleService: Title){
this.webSocketSubscription = wsService.subscribe(m => {
console.log('websocket server send this :', m);
});

this.wsLoginSub = this.wsService.LoginEvent.subscribe( m => {
console.log('login event ', m);
});

this.titleService.setTitle(this.title);
} }


// tslint:disable-next-line:typedef // tslint:disable-next-line:typedef
} }


listenToMenuEvent(): void { listenToMenuEvent(): void {
this.menutItemSub = this.menuService.itemClicked.subscribe(
this.menuItemSub = this.menuService.itemClicked.subscribe(
(item:any) =>{ (item:any) =>{
// console.log("emit on select : " + item.text); // console.log("emit on select : " + item.text);
if ( item.popup === 'loanEdit'){ if ( item.popup === 'loanEdit'){


} }


// tslint:disable-next-line:typedef
ngOnDestroy() {
ngOnDestroy(): void {
this.webSocketSubscription.unsubscribe();
this.wsLoginSub.unsubscribe();
} }


} }

+ 2
- 0
src/app/app.config.model.ts Vedi File

export class AppConfigModel { export class AppConfigModel {
Server = 'https://c5016.biukop.com.au:8080/api/v1/'; Server = 'https://c5016.biukop.com.au:8080/api/v1/';
Socket = 'ws://c5016.biukop.com.au:8080/api/v1/'; Socket = 'ws://c5016.biukop.com.au:8080/api/v1/';
SessionStorageKey = 'sk';
Version = 2021;
} }

+ 10
- 2
src/app/app.config.ts Vedi File

static config: AppConfigModel; static config: AppConfigModel;
static debugConfig: AppConfigModel = { static debugConfig: AppConfigModel = {
Server: 'https://svr2021.lawipac.com:8080/api/v1/', Server: 'https://svr2021.lawipac.com:8080/api/v1/',
Socket: 'wss://svr2021.lawipac.com:8080/api/v1/ws'
Socket: 'wss://svr2021.lawipac.com:8080/api/v1/ws',
SessionStorageKey: 'sk',
Version: 2021
}; };


static productionConfig: AppConfigModel = { static productionConfig: AppConfigModel = {
Server: 'https://c5016.biukop.com.au:8080/api/v1/', Server: 'https://c5016.biukop.com.au:8080/api/v1/',
Socket: 'wss://c5016.biukop.com.au:8080/api/v1/ws'
Socket: 'wss://c5016.biukop.com.au:8080/api/v1/ws',
SessionStorageKey : 'sk',
Version: 2021
}; };


constructor(private http: HttpClient) {} constructor(private http: HttpClient) {}
return AppConfig.config.Socket; return AppConfig.config.Socket;
} }


public get storageKey(): string{
return AppConfig.config.SessionStorageKey;
}

public getUrl(key: string): string{ public getUrl(key: string): string{
const s = this.apiUrl + key; const s = this.apiUrl + key;
const kvPair: {key: string, value: string}[] = [ const kvPair: {key: string, value: string}[] = [

+ 2
- 0
src/app/app.module.ts Vedi File

import { RewardSelectComponent } from './reward-select/reward-select.component'; import { RewardSelectComponent } from './reward-select/reward-select.component';
import { RewardsAllComponent } from './rewards-all/rewards-all.component'; import { RewardsAllComponent } from './rewards-all/rewards-all.component';
import { SinglePayoutRewardsListComponent } from './single-payout-rewards-list/single-payout-rewards-list.component'; import { SinglePayoutRewardsListComponent } from './single-payout-rewards-list/single-payout-rewards-list.component';
import {SessionService} from './service/session.service';






MenuService, MenuService,
AuthGuard, AuthGuard,
AuthService, AuthService,
SessionService,
WebSocketService, WebSocketService,
LoanSummaryService, LoanSummaryService,
LoanSingleService, LoanSingleService,

+ 9
- 9
src/app/auth/auth-http-interceptor.service.ts Vedi File

import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {HttpEvent, HttpEventType, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http'; import {HttpEvent, HttpEventType, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {AuthService} from '../service/auth.service';
import {tap} from 'rxjs/operators'; import {tap} from 'rxjs/operators';
import {SessionService} from '../service/session.service';




@Injectable() @Injectable()
export class AuthHttpInterceptor implements HttpInterceptor { export class AuthHttpInterceptor implements HttpInterceptor {


constructor(private auth: AuthService) {
constructor(private ss: SessionService) {
} }


intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let h = req.headers; let h = req.headers;


if (this.auth.loggedIn.hasValidSession()) {
h = h.set('Biukop-Session', this.auth.loggedIn.session);
if (this.ss.loggedIn.hasValidSession()) {
h = h.set('Biukop-Session', this.ss.loggedIn.session);
} }


if (this.auth.loggedIn.hasValidMachineId()) {
h = h.set('Biukop-Mid', this.auth.loggedIn.machineId);
if (this.ss.loggedIn.hasValidMachineId()) {
h = h.set('Biukop-Mid', this.ss.loggedIn.machineId);
} }


const authReq = req.clone({ const authReq = req.clone({
if (event.type === HttpEventType.Response){ if (event.type === HttpEventType.Response){
const bs = event.headers.get('biukop-session'); const bs = event.headers.get('biukop-session');
if (bs !== undefined){ if (bs !== undefined){
if ( this.auth.loggedIn.session !== bs ){
this.auth.loggedIn.session = bs;
this.auth.saveSessionInfo();
if ( this.ss.loggedIn.session !== bs ){
this.ss.loggedIn.session = bs;
this.ss.saveSessionInfo();
console.log('switch session:' , bs); console.log('switch session:' , bs);
} }
} }

+ 4
- 2
src/app/auth/auth.component.ts Vedi File

import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { AuthService } from '../service/auth.service'; import { AuthService } from '../service/auth.service';
import {ApiV1LoginResponse} from '../models/api-v1-login-response'; import {ApiV1LoginResponse} from '../models/api-v1-login-response';
import {SessionService} from '../service/session.service';


@Component({ @Component({
selector: 'app-auth', selector: 'app-auth',
email: new FormControl('admin@supercredit.com.au', Validators.email) email: new FormControl('admin@supercredit.com.au', Validators.email)
}); });


constructor(private authService: AuthService, private router: Router, private notificationService: NotificationService) { }
constructor(private authService: AuthService, private ss: SessionService,
private router: Router, private notificationService: NotificationService) { }


ngOnInit(): void { ngOnInit(): void {
this.authService.logout(); this.authService.logout();
this.loginSub = this.authService.loginSuccess.subscribe(
this.loginSub = this.ss.loginSuccess.subscribe(
responseData => { responseData => {
// console.log(responseData); // console.log(responseData);
this.onLogin(responseData); this.onLogin(responseData);

+ 5
- 6
src/app/broker-loan-list/broker-loan-list.component.ts Vedi File

import {Component, Input, OnInit} from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {BrokerModel} from '../models/broker.model';
import {LoanModel} from '../models/loan.model';
import {LoanSummaryService} from '../service/loan_summary.service'; import {LoanSummaryService} from '../service/loan_summary.service';
import {CompositeFilterDescriptor, SortDescriptor} from '@progress/kendo-data-query'; import {CompositeFilterDescriptor, SortDescriptor} from '@progress/kendo-data-query';
import {AuthService} from '../service/auth.service';
import {PeopleModel} from '../models/people.model'; import {PeopleModel} from '../models/people.model';
import {AppConfig} from '../app.config';
import {SessionService} from '../service/session.service';


@Component({ @Component({
selector: 'app-broker-loan-list', selector: 'app-broker-loan-list',
@Input() public broker: PeopleModel = PeopleModel.EmptyNew(); @Input() public broker: PeopleModel = PeopleModel.EmptyNew();
public brokerLoans: LoanSummaryService; public brokerLoans: LoanSummaryService;


constructor( private lss: LoanSummaryService, private auth: AuthService) { }
constructor( private lss: LoanSummaryService, private ss: SessionService, private config: AppConfig) { }


ngOnInit(): void { ngOnInit(): void {
this.brokerLoans = this.lss; this.brokerLoans = this.lss;
this.broker = this.auth.loggedIn.User;
this.broker = this.ss.loggedIn.User;
this.loadData(); this.loadData();
} }


} }


private photoURL(peopleId: any): string { private photoURL(peopleId: any): string {
const url = this.auth.getUrl('avatar/') + peopleId;
const url = this.config.getUrl('avatar/') + peopleId;
return 'url("' + url + '")'; return 'url("' + url + '")';
} }
} }

+ 5
- 3
src/app/broker-reward/broker-reward.component.ts Vedi File

import {AuthService} from '../service/auth.service'; import {AuthService} from '../service/auth.service';
import {RewardByUserModel} from '../models/reward-by-user.model'; import {RewardByUserModel} from '../models/reward-by-user.model';
import {DataResult, GroupDescriptor, process} from '@progress/kendo-data-query'; import {DataResult, GroupDescriptor, process} from '@progress/kendo-data-query';
import {SessionService} from '../service/session.service';
import {AppConfig} from '../app.config';


@Component({ @Component({
selector: 'app-broker-reward', selector: 'app-broker-reward',
public groups: GroupDescriptor[] = [{ field: 'Description' }, { field: 'Item' } ]; public groups: GroupDescriptor[] = [{ field: 'Description' }, { field: 'Item' } ];
public gridView: DataResult; public gridView: DataResult;


constructor(private http: HttpClient, private auth: AuthService ) { }
constructor(private http: HttpClient, private ss: SessionService, private config: AppConfig ) { }


ngOnInit(): void { ngOnInit(): void {
this.loading = true; this.loading = true;
this.gridData = []; this.gridData = [];


// avoid loading everything when used with admin user // avoid loading everything when used with admin user
if ( this.auth.loggedIn.role === 'admin' && this.selectedBrokerId === '' ) {
if ( this.ss.loggedIn.role === 'admin' && this.selectedBrokerId === '' ) {
this.loading = false; this.loading = false;
return ; return ;
} }


// load a single user // load a single user
this.http.get<RewardByUserModel[]>(this.auth.getUrl('user-reward/' + this.selectedBrokerId )).subscribe(
this.http.get<RewardByUserModel[]>(this.config.getUrl('user-reward/' + this.selectedBrokerId )).subscribe(
rsp => { rsp => {
rsp.forEach(v => { rsp.forEach(v => {
this.gridData.push(new RewardByUserModel(v)); this.gridData.push(new RewardByUserModel(v));

+ 3
- 2
src/app/client-loan-list/client-loan-list.component.ts Vedi File

import {LoanModel} from '../models/loan.model'; import {LoanModel} from '../models/loan.model';
import {LoanSingleService} from '../service/loan.single.service'; import {LoanSingleService} from '../service/loan.single.service';
import {AuthService} from '../service/auth.service'; import {AuthService} from '../service/auth.service';
import {SessionService} from '../service/session.service';


@Component({ @Component({
selector: 'app-client-loan-list', selector: 'app-client-loan-list',


public Loans: LoanModel[] =[]; public Loans: LoanModel[] =[];


constructor(private ls: LoanSingleService, private auth: AuthService) { }
constructor(private ls: LoanSingleService, private ss: SessionService) { }


ngOnInit(): void { ngOnInit(): void {
this.ls.getLoanByClient(this.auth.loggedIn.User.Id).subscribe(
this.ls.getLoanByClient(this.ss.loggedIn.User.Id).subscribe(
resp => { resp => {
this.Loans = []; this.Loans = [];
resp.forEach( v => { resp.forEach( v => {

+ 4
- 3
src/app/client-profile/client-profile.component.ts Vedi File

import {FileInfo, FileRestrictions, FileSelectComponent, SelectEvent} from '@progress/kendo-angular-upload'; import {FileInfo, FileRestrictions, FileSelectComponent, SelectEvent} from '@progress/kendo-angular-upload';
import {BrokerModel} from '../models/broker.model'; import {BrokerModel} from '../models/broker.model';
import {AppConfig} from '../app.config'; import {AppConfig} from '../app.config';
import {SessionService} from '../service/session.service';


@Component({ @Component({
selector: 'app-client-profile', selector: 'app-client-profile',
public opened = false; // dialog box public opened = false; // dialog box
public Message = ''; // dialog message public Message = ''; // dialog message


constructor(private auth: AuthService, private ps: PeopleService) {
constructor(private ss: SessionService, private config: AppConfig, private ps: PeopleService) {
this.avatarUrl = 'url("' + location.origin + './assets/img/avatar.png' + '")'; this.avatarUrl = 'url("' + location.origin + './assets/img/avatar.png' + '")';
} }




ngOnInit(): void { ngOnInit(): void {
this.User = this.auth.loggedIn.User;
this.avatarUrl = 'url(' + this.auth.getUrl('avatar/' + this.User.Id) + ')';
this.User = this.ss.loggedIn.User;
this.avatarUrl = 'url(' + this.config.getUrl('avatar/' + this.User.Id) + ')';
} }





+ 1
- 1
src/app/models/api-v1-login-response.ts Vedi File

public sessionExpire: number, // unix timestamp public sessionExpire: number, // unix timestamp
public role: string, public role: string,
public User: PeopleModel, public User: PeopleModel,
public UserExtra?: UserExtraModel // extra user informaiton
public UserExtra?: UserExtraModel // extra user information
) { ) {
this.login = login; this.login = login;
this.machineId = machineId; this.machineId = machineId;

+ 24
- 0
src/app/models/user.model.ts Vedi File

import {PeopleModel} from './people.model';
import {BrokerModel} from './broker.model';

export enum UserRoles {
Unknown = 'Unknown',
People = 'People',
Broker = 'Broker',
Beneficiary = 'Beneficiary',
Admin = 'admin',
Accountant = 'accountant',
Super = 'super',
}

export class UserModel extends PeopleModel{
Role: UserRoles;
Broker?: BrokerModel;
Login: string;
constructor(payload: Partial<UserModel>) {
super(payload);
this.Role = payload.Role || 'People' as UserRoles;
this.Login = payload.Login || '';
this.Broker = new BrokerModel(payload);
}
}

+ 15
- 0
src/app/models/websocket/ws.login.event.model.ts Vedi File


export class WsLoginEventModel{
T: string;
Mid: string;
Sid: string;
Uid: string;
Role: string;
constructor( payload: Partial<WsLoginEventModel>) {
this.T = payload.T || '';
this.Mid = payload.Mid || '';
this.Sid = payload.Sid || '';
this.Uid = payload.Uid || '';
this.Role = payload.Uid || '';
}
}

+ 3
- 2
src/app/profile/broker-profile/broker-profile.component.ts Vedi File

import {MessageBoxComponent} from '../../message-box/message-box.component'; import {MessageBoxComponent} from '../../message-box/message-box.component';
import {UserExtraModel} from '../../models/user-extra.model'; import {UserExtraModel} from '../../models/user-extra.model';
import {PeopleModel} from '../../models/people.model'; import {PeopleModel} from '../../models/people.model';
import {SessionService} from '../../service/session.service';






@ViewChild('messageBox', {static: true})msgBox: MessageBoxComponent; @ViewChild('messageBox', {static: true})msgBox: MessageBoxComponent;
public isAdmin = false; public isAdmin = false;


constructor( private auth: AuthService, private ps: PeopleService) { }
constructor( private ss: SessionService, private ps: PeopleService) { }


ngOnInit(): void { ngOnInit(): void {
this.isAdmin = this.auth.isAdmin();
this.isAdmin = this.ss.isAdmin();
} }


public save(brokerForm: NgForm): void{ public save(brokerForm: NgForm): void{

+ 7
- 6
src/app/profile/change-password/change-password.component.ts Vedi File

import {AuthService} from '../../service/auth.service'; import {AuthService} from '../../service/auth.service';
import {PeopleService} from '../../service/people.service'; import {PeopleService} from '../../service/people.service';
import {MessageBoxComponent} from '../../message-box/message-box.component'; import {MessageBoxComponent} from '../../message-box/message-box.component';
import {SessionService} from '../../service/session.service';


@Component({ @Component({
selector: 'app-change-password', selector: 'app-change-password',
NewPass: new FormControl(), NewPass: new FormControl(),
NewPass1: new FormControl(), NewPass1: new FormControl(),
}); });
constructor(private auth: AuthService, private ps: PeopleService) { }
constructor(private ss: SessionService, private ps: PeopleService) { }


ngOnInit(): void { ngOnInit(): void {
if (this.auth.isAdmin() && this.PeopleId !== '' && !this.auth.isCurrentUser(this.PeopleId)) {
this.isAdmin = this.auth.isAdmin();
if (this.ss.isAdmin() && this.PeopleId !== '' && !this.ss.isCurrentUser(this.PeopleId)) {
this.isAdmin = this.ss.isAdmin();
} }
} }
public hidePass(): void{ public hidePass(): void{
} }


public canChangePassword(): boolean { public canChangePassword(): boolean {
if ( this.auth.isCurrentUser(this.PeopleId) ) {
return this.auth.isUser() || this.auth.isBroker() || this.auth.isAdmin();
if ( this.ss.isCurrentUser(this.PeopleId) ) {
return this.ss.isUser() || this.ss.isBroker() || this.ss.isAdmin();
}else{ }else{
return this.auth.isAdmin() ;
return this.ss.isAdmin() ;
} }
} }
} }

+ 10
- 8
src/app/profile/people-profile/people-profile.component.ts Vedi File

import {PeopleService} from '../../service/people.service'; import {PeopleService} from '../../service/people.service';
import {NgForm} from '@angular/forms'; import {NgForm} from '@angular/forms';
import {PeopleModel} from '../../models/people.model'; import {PeopleModel} from '../../models/people.model';
import {SessionService} from '../../service/session.service';
import {AppConfig} from '../../app.config';


@Component({ @Component({
selector: 'app-people-profile', selector: 'app-people-profile',
@ViewChild('messagebox', {static: true}) msgBox: MessageBoxComponent; @ViewChild('messagebox', {static: true}) msgBox: MessageBoxComponent;
@ViewChild('fileSelect', {static: true}) fs: FileSelectComponent; @ViewChild('fileSelect', {static: true}) fs: FileSelectComponent;


constructor(private auth: AuthService, private ps: PeopleService) { }
constructor(private ss: SessionService, private config: AppConfig, private ps: PeopleService) { }


ngOnInit(): void { ngOnInit(): void {
if (this.auth.isAdmin() && !this.auth.isCurrentUser(this.People.Id)) {
if (this.ss.isAdmin() && !this.ss.isCurrentUser(this.People.Id)) {
// //
}else{ }else{
this.People = this.auth.loggedIn.User;
this.People = this.ss.loggedIn.User;
} }
this.avatarUrl = 'url(' + this.auth.getUrl('avatar/' + this.People.Id) + ')';
this.avatarUrl = 'url(' + this.config.getUrl('avatar/' + this.People.Id) + ')';
} }


onDialogClose(status: string): void { onDialogClose(status: string): void {
} }
this.ps.savePeople(this.People).subscribe( () => { this.ps.savePeople(this.People).subscribe( () => {
this.msgBox.Show('Updated successfully '); this.msgBox.Show('Updated successfully ');
if ( this.auth.loggedIn.User.Id === this.People.Id ) {
this.auth.UpdatePeopleInfo(this.People);
if ( this.ss.loggedIn.User.Id === this.People.Id ) {
this.ss.UpdatePeopleInfo(this.People);
} }
peopleForm.form.markAsPristine(); peopleForm.form.markAsPristine();
}, err => { }, err => {
ppl => { ppl => {
this.People.Copy(ppl); this.People.Copy(ppl);
this.newPeople.emit(this.People); this.newPeople.emit(this.People);
this.avatarUrl = 'url(' + this.auth.getUrl('avatar/' + this.People.Id) + ')';
this.avatarUrl = 'url(' + this.config.getUrl('avatar/' + this.People.Id) + ')';
} }
); );
} }


public PeopleChanged(ppl: PeopleModel): void { public PeopleChanged(ppl: PeopleModel): void {
console.log(this); console.log(this);
this.avatarUrl = 'url(' + this.auth.getUrl('avatar/' + this.People.Id) + ')';
this.avatarUrl = 'url(' + this.config.getUrl('avatar/' + this.People.Id) + ')';
} }


public startSelectAvatar(): void { public startSelectAvatar(): void {

+ 12
- 11
src/app/profile/profile.component.ts Vedi File

import {UserExtraModel} from '../models/user-extra.model'; import {UserExtraModel} from '../models/user-extra.model';
import {MessageBoxComponent} from '../message-box/message-box.component'; import {MessageBoxComponent} from '../message-box/message-box.component';
import {setTime} from '@progress/kendo-angular-dateinputs/dist/es2015/util'; import {setTime} from '@progress/kendo-angular-dateinputs/dist/es2015/util';
import {SessionService} from '../service/session.service';


@Component({ @Component({
selector: 'app-profile', selector: 'app-profile',
public isValidPeople = true; public isValidPeople = true;
public isValidBroker = true; public isValidBroker = true;


constructor(private auth: AuthService, private ps: PeopleService, private actRoute: ActivatedRoute) { }
constructor(private auth: AuthService, private ss: SessionService, private ps: PeopleService, private actRoute: ActivatedRoute) { }


ngOnInit(): void { ngOnInit(): void {
const id = this.actRoute.snapshot.params.id; const id = this.actRoute.snapshot.params.id;
this.PeopleId = id; this.PeopleId = id;
} }


if (this.auth.isAdmin() && this.PeopleId !== '' ){
if (this.ss.isAdmin() && this.PeopleId !== '' ){
if (this.PeopleId === 'start-new-people' ){ if (this.PeopleId === 'start-new-people' ){
return; return;
}else if (this.PeopleId !== '' && !this.auth.isCurrentUser(this.PeopleId)) { // admin editing someone else
}else if (this.PeopleId !== '' && !this.ss.isCurrentUser(this.PeopleId)) { // admin editing someone else
this.loadOtherPeople(); this.loadOtherPeople();
} }
}else { // edit himself }else { // edit himself
this.role = this.auth.loggedIn.role;
this.PeopleId = this.auth.loggedIn.User.Id;
this.People = this.auth.loggedIn.User;
this.UserExtra = this.auth.loggedIn.UserExtra;
this.role = this.ss.loggedIn.role;
this.PeopleId = this.ss.loggedIn.User.Id;
this.People = this.ss.loggedIn.User;
this.UserExtra = this.ss.loggedIn.UserExtra;
} }
this.updateShowHide(); this.updateShowHide();
} }
private updateShowHide(): void { private updateShowHide(): void {
this.resetShowHide(); this.resetShowHide();


this.editOtherPeople = ! this.auth.isCurrentUser(this.PeopleId);
this.editOtherPeople = ! this.ss.isCurrentUser(this.PeopleId);
if ( this.editOtherPeople ) { if ( this.editOtherPeople ) {
this.showAdminTool = this.isAdmin() && this.People.Id !== '' ; this.showAdminTool = this.isAdmin() && this.People.Id !== '' ;
if ( this.showAdminTool ){ if ( this.showAdminTool ){


// the user who performs this edit action // the user who performs this edit action
public isAdmin(): boolean { public isAdmin(): boolean {
return this.auth.isAdmin();
return this.ss.isAdmin();
} }


// the user who performs this edit action // the user who performs this edit action
public isBroker(): boolean { public isBroker(): boolean {
return this.auth.isBroker();
return this.ss.isBroker();
} }


// the user who performs this edit action // the user who performs this edit action
public isUser(): boolean { public isUser(): boolean {
return this.auth.isUser();
return this.ss.isUser();
} }


public deletePeople(): void { public deletePeople(): void {

+ 8
- 7
src/app/profile/user-profile/user-profile.component.ts Vedi File

import {PeopleService} from '../../service/people.service'; import {PeopleService} from '../../service/people.service';
import {asyncValidatorLoginAvailable} from '../../validator/unique.login.validator'; import {asyncValidatorLoginAvailable} from '../../validator/unique.login.validator';
import {PeopleModel} from '../../models/people.model'; import {PeopleModel} from '../../models/people.model';
import {SessionService} from '../../service/session.service';


@Component({ @Component({
selector: 'app-user-profile', selector: 'app-user-profile',


public UserForm: FormGroup; public UserForm: FormGroup;


constructor(private auth: AuthService, private http: HttpClient, private ps: PeopleService) { }
constructor(private auth: AuthService, private ss: SessionService, private http: HttpClient) { }


ngOnInit(): void { ngOnInit(): void {


this.showAdmin = this.auth.isAdmin();
this.isCurrentUser = this.auth.isCurrentUser(this.People.Id);
this.showAdmin = this.ss.isAdmin();
this.isCurrentUser = this.ss.isCurrentUser(this.People.Id);


if (this.auth.isAdmin() && !this.auth.isCurrentUser(this.People.Id)) {
if (this.ss.isAdmin() && !this.ss.isCurrentUser(this.People.Id)) {
// edit other people, // edit other people,
}else{ }else{
this.People.Id = this.auth.loggedIn.User.Id;
this.UserExtra = this.auth.loggedIn.UserExtra;
this.People.Id = this.ss.loggedIn.User.Id;
this.UserExtra = this.ss.loggedIn.UserExtra;
} }
this.UserForm = new FormGroup({ this.UserForm = new FormGroup({
Login: new FormControl({value: this.UserExtra.Login, disabled: ! this.showAdmin }, Login: new FormControl({value: this.UserExtra.Login, disabled: ! this.showAdmin },
} }


public currentUserIsAdmin(): boolean { public currentUserIsAdmin(): boolean {
return this.auth.loggedIn.role === 'admin';
return this.ss.loggedIn.role === 'admin';
} }


public canEditUser(): boolean { public canEditUser(): boolean {

+ 24
- 80
src/app/service/auth.service.ts Vedi File

import {UserExtraModel} from '../models/user-extra.model'; import {UserExtraModel} from '../models/user-extra.model';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {AppConfig} from '../app.config'; import {AppConfig} from '../app.config';
import {SessionService} from './session.service';


@Injectable() @Injectable()
export class AuthService { export class AuthService {
public apiUrl = '';
public apiWsUrl = '';

public loggedIn = ApiV1LoginResponse.EmptyNew();
loginSuccess = new EventEmitter <ApiV1LoginResponse>();


constructor( private http: HttpClient , constructor( private http: HttpClient ,
private router: Router, private router: Router,
private config: AppConfig) {
this.apiUrl = config.apiUrl;
this.apiWsUrl = config.apiWsUrl;
}
private ss: SessionService,
private config: AppConfig) { }


public AutoLogin(): void { public AutoLogin(): void {
const sfm: ApiV1LoginResponse = JSON.parse(localStorage.getItem('sfm'));
const sfm: ApiV1LoginResponse = JSON.parse(localStorage.getItem(this.config.storageKey));
if (!sfm) { if (!sfm) {
console.log('no auto login'); console.log('no auto login');
return; return;
} }
this.loggedIn = new ApiV1LoginResponse(
this.ss.loggedIn = new ApiV1LoginResponse(
sfm.login, sfm.login,
sfm.machineId, sfm.machineId,
sfm.session, sfm.session,
); );


if ( sfm.UserExtra !== undefined ) { if ( sfm.UserExtra !== undefined ) {
this.loggedIn.UserExtra = new UserExtraModel(sfm.UserExtra);
this.ss.loggedIn.UserExtra = new UserExtraModel(sfm.UserExtra);
} }

this.loginSuccess.emit(this.loggedIn);
// console.log ( 'auto login emit events', this.loggedIn);
this.ss.loginSuccess.emit(this.ss.loggedIn);
} }




isAuthenticated(): boolean { isAuthenticated(): boolean {
return this.loggedIn.login;
return this.ss.loggedIn.login;
} }


allowEditLoan(): boolean{ allowEditLoan(): boolean{
} }


saveSessionInfo(): void { saveSessionInfo(): void {
localStorage.setItem('sfm', JSON.stringify(this.loggedIn));
localStorage.setItem('mid', this.loggedIn.machineId);
localStorage.setItem(this.config.storageKey, JSON.stringify(this.ss.loggedIn));
localStorage.setItem('mid', this.ss.loggedIn.machineId);
} }


login(email: string, password: string): void { login(email: string, password: string): void {


this.http.post<ApiV1LoginResponse>(this.apiUrl + 'login', {u: email, p: password}).subscribe(
this.http.post<ApiV1LoginResponse>(this.config.apiUrl + 'login', {u: email, p: password}).subscribe(
responseData => { responseData => {
this.loggedIn.session = responseData['Biukop-Session'];
this.loggedIn.login = responseData.login;
this.loggedIn.machineId = responseData['Biukop-Mid'];
this.loggedIn.sessionExpire = responseData.sessionExpire;
this.loggedIn.role = responseData.role;
this.ss.loggedIn.session = responseData['Biukop-Session'];
this.ss.loggedIn.login = responseData.login;
this.ss.loggedIn.machineId = responseData['Biukop-Mid'];
this.ss.loggedIn.sessionExpire = responseData.sessionExpire;
this.ss.loggedIn.role = responseData.role;
if ( responseData.User !== undefined) { if ( responseData.User !== undefined) {
this.loggedIn.User = new PeopleModel(responseData.User);
this.ss.loggedIn.User = new PeopleModel(responseData.User);


if (responseData.UserExtra !== undefined ) { if (responseData.UserExtra !== undefined ) {
this.loggedIn.UserExtra = new UserExtraModel(responseData.UserExtra);
this.ss.loggedIn.UserExtra = new UserExtraModel(responseData.UserExtra);
}else{ }else{
this.loggedIn.UserExtra = UserExtraModel.EmptyNew();
this.ss.loggedIn.UserExtra = UserExtraModel.EmptyNew();
} }
}else{ }else{
this.loggedIn.User = PeopleModel.EmptyNew();
this.ss.loggedIn.User = PeopleModel.EmptyNew();
} }


this.saveSessionInfo(); this.saveSessionInfo();
this.loginSuccess.emit(responseData);
this.ss.loginSuccess.emit(responseData);
}, },
error => { error => {
this.loggedIn = ApiV1LoginResponse.EmptyNew();
this.ss.loggedIn = ApiV1LoginResponse.EmptyNew();
console.log('login error', error); console.log('login error', error);
this.loginSuccess.emit(this.loggedIn);
this.ss.loginSuccess.emit(this.ss.loggedIn);
} }


); );
} }


logout(): void { logout(): void {
this.loggedIn = ApiV1LoginResponse.EmptyNew();
localStorage.removeItem('sfm');
this.loginSuccess.emit(this.loggedIn);
this.router.navigate(['/login']).then(r => {
console.log('prepare to log back in');
} );
this.http.post(`${this.apiUrl}logout`, '').subscribe(
resp => {
console.log('successfully logout from server');
},
event => {
console.log('error logout from server', event);
}
);
this.ss.logout();
} }




public getUrl(key: string): string{ public getUrl(key: string): string{
return this.config.getUrl(key); return this.config.getUrl(key);
// const s = this.apiUrl + key;
// const kvPair: {key: string, value: string}[] = [
// {key: 'login', value: this.apiUrl + 'login'},
// {key: 'logout', value: this.apiUrl + 'logout'}
// ];
//
// kvPair.forEach( item => {
// if ( item.key === key) {
// return item.value;
// }
// });
//
// // not found if arrive here
// return s;
} }


public UpdatePeopleInfo(people: PeopleModel): void{
this.loggedIn.User.Display = people.Display;
this.loggedIn.User.First = people.First;
this.loggedIn.User.Last = people.Last;
this.saveSessionInfo();
}


public LoginAvailable(v: string): Observable<boolean> { public LoginAvailable(v: string): Observable<boolean> {
return this.http.get<boolean>(this.getUrl('login-available/' + v)); return this.http.get<boolean>(this.getUrl('login-available/' + v));
} }


public isAdmin(): boolean {
return this.loggedIn.role === 'admin';
}

public isBroker(): boolean {
return this.loggedIn.role === 'broker';
}

public isUser(): boolean {
return this.loggedIn.login === true;
}

public isCurrentUser(id: string): boolean {
return this.loggedIn.login === true && this.loggedIn.User !== undefined && this.loggedIn.User.Id === id;
}
} }

+ 75
- 0
src/app/service/session.service.ts Vedi File

import {EventEmitter, Injectable} from '@angular/core';
import {AppConfig} from '../app.config';
import {ApiV1LoginResponse} from '../models/api-v1-login-response';
import {PeopleModel} from '../models/people.model';
import {HttpClient} from '@angular/common/http';
import {Router} from '@angular/router';
import {NotificationService} from '@progress/kendo-angular-notification';

@Injectable()
export class SessionService {
public loggedIn = ApiV1LoginResponse.EmptyNew();
loginSuccess = new EventEmitter <ApiV1LoginResponse>();


constructor(private config: AppConfig, private http: HttpClient, private router: Router, private ns: NotificationService){ }

public saveSessionInfo(): void {
localStorage.setItem(this.config.storageKey, JSON.stringify(this.loggedIn));
localStorage.setItem('mid', this.loggedIn.machineId);
}

public isAdmin(): boolean {
return this.loggedIn.role === 'admin';
}

public isBroker(): boolean {
return this.loggedIn.role === 'broker';
}

public isUser(): boolean {
return this.loggedIn.login === true;
}

public isCurrentUser(id: string): boolean {
return this.loggedIn.login === true && this.loggedIn.User !== undefined && this.loggedIn.User.Id === id;
}

public UpdatePeopleInfo(people: PeopleModel): void{
this.loggedIn.User.Display = people.Display;
this.loggedIn.User.First = people.First;
this.loggedIn.User.Last = people.Last;
this.saveSessionInfo();
}

logout(): void {
if ( !this.loggedIn.login ){
return;
}
this.loggedIn = ApiV1LoginResponse.EmptyNew();
localStorage.removeItem(this.config.storageKey);
this.loginSuccess.emit(this.loggedIn);
this.router.navigate(['/login']).then(r => {
this.show();
} );
this.http.post(`${this.config.apiUrl}logout`, '').subscribe(
resp => {
console.log('successfully logout from server');
},
event => {
console.log('error logout from server', event);
}
);
}

public show(): void {
this.ns.show({
content: 'Successfully logged out',
cssClass: 'button-notification',
animation: { type: 'slide', duration: 400 },
position: { horizontal: 'center', vertical: 'top' },
type: { style: 'info', icon: true },
hideAfter : 2000
});
}
}

+ 8
- 6
src/app/top-bar/top-bar.component.ts Vedi File

import {ApiV1LoginResponse} from '../models/api-v1-login-response'; import {ApiV1LoginResponse} from '../models/api-v1-login-response';
import {Subscription} from 'rxjs'; import {Subscription} from 'rxjs';
import {PeopleModel} from '../models/people.model'; import {PeopleModel} from '../models/people.model';
import {SessionService} from '../service/session.service';




@Component({ @Component({
public opened = false; public opened = false;


constructor(private menuService: MenuService, constructor(private menuService: MenuService,
private ss: SessionService,
private authService: AuthService) { private authService: AuthService) {
} }


} }


public initAndSubLogin(): void{ public initAndSubLogin(): void{
this.login = this.authService.loggedIn.login;
this.LoggedInUser = this.authService.loggedIn.User;
this.login = this.ss.loggedIn.login;
this.LoggedInUser = this.ss.loggedIn.User;


this.selectMenuShow(this.authService.loggedIn.role);
this.selectMenuShow(this.ss.loggedIn.role);


this.loginSub = this.authService.loginSuccess.subscribe(
this.loginSub = this.ss.loginSuccess.subscribe(
(rsp: ApiV1LoginResponse) => { (rsp: ApiV1LoginResponse) => {
this.login = rsp.login; this.login = rsp.login;
this.LoggedInUser = this.authService.loggedIn.User;
this.LoggedInUser = this.ss.loggedIn.User;
this.selectMenuShow(rsp.role); this.selectMenuShow(rsp.role);
} }
); );
} }


public loggedInUserAvatar(): string { public loggedInUserAvatar(): string {
return this.authService.getUrl('avatar/') + this.authService.loggedIn.User.Id;
return this.authService.getUrl('avatar/') + this.ss.loggedIn.User.Id;
} }


public profile(): void { public profile(): void {

+ 43
- 27
src/app/websocket.ts Vedi File

import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import {Observable, Subscriber} from 'rxjs';
import {Observable, Subject, Subscriber} from 'rxjs';
import {AppConfig} from './app.config';
import {WsLoginEventModel} from './models/websocket/ws.login.event.model';






@Injectable() @Injectable()
export class WebSocketService {
export class WebSocketService extends Subject<string>{


public ws: WebSocket; public ws: WebSocket;
private url: string;
private observer: Subscriber<string>;

public createObservableSocket(url: string): Observable<string> {
this.url = url;
const ret = new Observable<string> ( observer => {
this.observer = observer;
});
private readonly url: string;
public LoginEvent: Subject<WsLoginEventModel>;

constructor(private config: AppConfig) {
super();
this.url = config.apiWsUrl;
this.startWebsocket(); this.startWebsocket();
return ret;
this.LoginEvent = new Subject<WsLoginEventModel>();
} }


// tslint:disable-next-line:typedef
public onMessage(event){
this.observer.next(event.data);
private startWebsocket(): void {
console.log('starting websocket now..', this.url);
this.ws = new WebSocket(this.url);
this.ws.onmessage = this.onMessage.bind(this);
this.ws.onerror = this.onError.bind(this);
this.ws.onclose = this.onClose.bind(this);
} }


// tslint:disable-next-line:typedef
public onError(event){
// public createObservableSocket(url: string): Observable<string> {
// this.url = url;
// const ret = new Observable<string> ( observer => {
// this.observer = observer;
// });
// this.startWebsocket();
// return ret;
// }


public onMessage(event): void{
super.next(event.data);
try {
const e = JSON.parse(event.data);
if ( e.T === 'login' || e.T === 'logout' ){
this.LoginEvent.next(new WsLoginEventModel(e));
}
}catch (e) {
console.log(e);
}
}

public onError(event): void{
console.log('on error ', event); console.log('on error ', event);
} }


// tslint:disable-next-line:typedef
public onClose(event){
console.log('websocket closed.. reconnect in 1s ..');
public onClose(event): void{
console.log('websocket closed.. reconnect in 1s ..', event);
setTimeout(() => { this.startWebsocket(); } , 1000); setTimeout(() => { this.startWebsocket(); } , 1000);
} }


// tslint:disable-next-line:typedef
public startWebsocket() {
console.log('starting websocket now..', this.url);
this.ws = new WebSocket(this.url);
this.ws.onmessage = this.onMessage.bind(this);
this.ws.onerror = this.onError.bind(this);
this.ws.onclose = this.onClose.bind(this);
}



public sendMessage(message: any): void { public sendMessage(message: any): void {
this.ws.send(message); this.ws.send(message);

+ 4
- 13
src/index.html Vedi File

server="https://sc5016.biukop.com.au:8080/" server="https://sc5016.biukop.com.au:8080/"
version="0.9.1" version="0.9.1"
> >
eyJTZXJ2ZXIiOiJodHRwczpcL1wvYzUwMTYuYml1a29wLmNvbS5h
dTo4MDgwXC9hcGlcL3YxXC8iLCJTb2NrZXQiOiJ3c3M6XC9cL2M1
MDE2LmJpdWtvcC5jb20uYXU6ODA4MFwvYXBpXC92MVwvd3MifQ==
eyJTZXJ2ZXIiOiJodHRwczpcL1wvYzUwMTYuYml1a29wLmNvbS5hd
To4MDgwXC9hcGlcL3YxXC8iLCJTb2NrZXQiOiJ3c3M6XC9cL2M1MD
E2LmJpdWtvcC5jb20uYXU6ODA4MFwvYXBpXC92MVwvd3MiLCJTZXN
zaW9uS2V5Ijoic2siLCJWZXJzaW9uIjoyMDIxfQ==
</script> </script>
<app-root></app-root> <app-root></app-root>

<script id="config-svr2021" type="text/biukop-config"
server="https://svr2021.lawipac.com:8080/"
version="0.9.1"
>
eyJTZXJ2ZXIiOiAiaHR0cHM6Ly9zdnIyMDIxLmxhd2lwYWMuY29tO
jgwODAvYXBpL3YxLyIsICJTb2NrZXQiOiAid3NzOi8vc3ZyMjAyMS
5sYXdpcGFjLmNvbTo4MDgwL2FwaS92MS93cyJ9
</script>

</body> </body>


</html> </html>

Loading…
Annulla
Salva