ソースを参照

introduced session and websocket notification observables.

tags/2.037
Patrick Sun 4年前
コミット
58164749ea
23個のファイルの変更303行の追加199行の削除
  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 ファイルの表示

@@ -6,6 +6,8 @@ import { AuthService } from './service/auth.service';
import { MenuService } from './service/menu.service';

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

@Component({
selector: 'app-root',
@@ -14,15 +16,27 @@ import {WebSocketService} from './websocket';
encapsulation: ViewEncapsulation.None
})
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;

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
@@ -33,7 +47,7 @@ export class AppComponent implements OnInit , OnDestroy {
}

listenToMenuEvent(): void {
this.menutItemSub = this.menuService.itemClicked.subscribe(
this.menuItemSub = this.menuService.itemClicked.subscribe(
(item:any) =>{
// console.log("emit on select : " + item.text);
if ( item.popup === 'loanEdit'){
@@ -45,9 +59,9 @@ export class AppComponent implements OnInit , OnDestroy {

}

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

}

+ 2
- 0
src/app/app.config.model.ts ファイルの表示

@@ -2,4 +2,6 @@
export class AppConfigModel {
Server = 'https://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 ファイルの表示

@@ -9,12 +9,16 @@ export class AppConfig {
static config: AppConfigModel;
static debugConfig: AppConfigModel = {
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 = {
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) {}
@@ -55,6 +59,10 @@ export class AppConfig {
return AppConfig.config.Socket;
}

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

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

+ 2
- 0
src/app/app.module.ts ファイルの表示

@@ -111,6 +111,7 @@ import { PDFExportModule } from '@progress/kendo-angular-pdf-export';
import { RewardSelectComponent } from './reward-select/reward-select.component';
import { RewardsAllComponent } from './rewards-all/rewards-all.component';
import { SinglePayoutRewardsListComponent } from './single-payout-rewards-list/single-payout-rewards-list.component';
import {SessionService} from './service/session.service';



@@ -233,6 +234,7 @@ export function initializeApp(appConfig: AppConfig): () => Promise<void> {
MenuService,
AuthGuard,
AuthService,
SessionService,
WebSocketService,
LoanSummaryService,
LoanSingleService,

+ 9
- 9
src/app/auth/auth-http-interceptor.service.ts ファイルの表示

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


@Injectable()
export class AuthHttpInterceptor implements HttpInterceptor {

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

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
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({
@@ -32,9 +32,9 @@ export class AuthHttpInterceptor implements HttpInterceptor {
if (event.type === HttpEventType.Response){
const bs = event.headers.get('biukop-session');
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);
}
}

+ 4
- 2
src/app/auth/auth.component.ts ファイルの表示

@@ -5,6 +5,7 @@ import { NotificationService } from '@progress/kendo-angular-notification';
import { Subscription } from 'rxjs';
import { AuthService } from '../service/auth.service';
import {ApiV1LoginResponse} from '../models/api-v1-login-response';
import {SessionService} from '../service/session.service';

@Component({
selector: 'app-auth',
@@ -20,11 +21,12 @@ export class AuthComponent implements OnInit, OnDestroy{
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 {
this.authService.logout();
this.loginSub = this.authService.loginSuccess.subscribe(
this.loginSub = this.ss.loginSuccess.subscribe(
responseData => {
// console.log(responseData);
this.onLogin(responseData);

+ 5
- 6
src/app/broker-loan-list/broker-loan-list.component.ts ファイルの表示

@@ -1,10 +1,9 @@
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 {CompositeFilterDescriptor, SortDescriptor} from '@progress/kendo-data-query';
import {AuthService} from '../service/auth.service';
import {PeopleModel} from '../models/people.model';
import {AppConfig} from '../app.config';
import {SessionService} from '../service/session.service';

@Component({
selector: 'app-broker-loan-list',
@@ -16,11 +15,11 @@ export class BrokerLoanListComponent implements OnInit {
@Input() public broker: PeopleModel = PeopleModel.EmptyNew();
public brokerLoans: LoanSummaryService;

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

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

@@ -31,7 +30,7 @@ export class BrokerLoanListComponent implements OnInit {
}

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

+ 5
- 3
src/app/broker-reward/broker-reward.component.ts ファイルの表示

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

@Component({
selector: 'app-broker-reward',
@@ -18,7 +20,7 @@ export class BrokerRewardComponent implements OnInit {
public groups: GroupDescriptor[] = [{ field: 'Description' }, { field: 'Item' } ];
public gridView: DataResult;

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

ngOnInit(): void {
this.loading = true;
@@ -29,13 +31,13 @@ export class BrokerRewardComponent implements OnInit {
this.gridData = [];

// 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;
return ;
}

// 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.forEach(v => {
this.gridData.push(new RewardByUserModel(v));

+ 3
- 2
src/app/client-loan-list/client-loan-list.component.ts ファイルの表示

@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
import {LoanModel} from '../models/loan.model';
import {LoanSingleService} from '../service/loan.single.service';
import {AuthService} from '../service/auth.service';
import {SessionService} from '../service/session.service';

@Component({
selector: 'app-client-loan-list',
@@ -12,10 +13,10 @@ export class ClientLoanListComponent implements OnInit {

public Loans: LoanModel[] =[];

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

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

+ 4
- 3
src/app/client-profile/client-profile.component.ts ファイルの表示

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

@Component({
selector: 'app-client-profile',
@@ -24,14 +25,14 @@ export class ClientProfileComponent implements OnInit {
public opened = false; // dialog box
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' + '")';
}


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 ファイルの表示

@@ -13,7 +13,7 @@ export class ApiV1LoginResponse {
public sessionExpire: number, // unix timestamp
public role: string,
public User: PeopleModel,
public UserExtra?: UserExtraModel // extra user informaiton
public UserExtra?: UserExtraModel // extra user information
) {
this.login = login;
this.machineId = machineId;

+ 24
- 0
src/app/models/user.model.ts ファイルの表示

@@ -0,0 +1,24 @@
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 ファイルの表示

@@ -0,0 +1,15 @@

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 ファイルの表示

@@ -6,6 +6,7 @@ import {BrokerModel} from '../../models/broker.model';
import {MessageBoxComponent} from '../../message-box/message-box.component';
import {UserExtraModel} from '../../models/user-extra.model';
import {PeopleModel} from '../../models/people.model';
import {SessionService} from '../../service/session.service';



@@ -20,10 +21,10 @@ export class BrokerProfileComponent implements OnInit {
@ViewChild('messageBox', {static: true})msgBox: MessageBoxComponent;
public isAdmin = false;

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

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

public save(brokerForm: NgForm): void{

+ 7
- 6
src/app/profile/change-password/change-password.component.ts ファイルの表示

@@ -3,6 +3,7 @@ import {FormControl, FormGroup} from '@angular/forms';
import {AuthService} from '../../service/auth.service';
import {PeopleService} from '../../service/people.service';
import {MessageBoxComponent} from '../../message-box/message-box.component';
import {SessionService} from '../../service/session.service';

@Component({
selector: 'app-change-password',
@@ -21,11 +22,11 @@ export class ChangePasswordComponent implements OnInit {
NewPass: new FormControl(),
NewPass1: new FormControl(),
});
constructor(private auth: AuthService, private ps: PeopleService) { }
constructor(private ss: SessionService, private ps: PeopleService) { }

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{
@@ -56,10 +57,10 @@ export class ChangePasswordComponent implements OnInit {
}

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{
return this.auth.isAdmin() ;
return this.ss.isAdmin() ;
}
}
}

+ 10
- 8
src/app/profile/people-profile/people-profile.component.ts ファイルの表示

@@ -5,6 +5,8 @@ import {AuthService} from '../../service/auth.service';
import {PeopleService} from '../../service/people.service';
import {NgForm} from '@angular/forms';
import {PeopleModel} from '../../models/people.model';
import {SessionService} from '../../service/session.service';
import {AppConfig} from '../../app.config';

@Component({
selector: 'app-people-profile',
@@ -23,15 +25,15 @@ export class PeopleProfileComponent implements OnInit {
@ViewChild('messagebox', {static: true}) msgBox: MessageBoxComponent;
@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 {
if (this.auth.isAdmin() && !this.auth.isCurrentUser(this.People.Id)) {
if (this.ss.isAdmin() && !this.ss.isCurrentUser(this.People.Id)) {
//
}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 {
@@ -72,8 +74,8 @@ export class PeopleProfileComponent implements OnInit {
}
this.ps.savePeople(this.People).subscribe( () => {
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();
}, err => {
@@ -86,14 +88,14 @@ export class PeopleProfileComponent implements OnInit {
ppl => {
this.People.Copy(ppl);
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 {
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 {

+ 12
- 11
src/app/profile/profile.component.ts ファイルの表示

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

@Component({
selector: 'app-profile',
@@ -56,7 +57,7 @@ export class ProfileComponent implements OnInit {
public isValidPeople = 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 {
const id = this.actRoute.snapshot.params.id;
@@ -64,17 +65,17 @@ export class ProfileComponent implements OnInit {
this.PeopleId = id;
}

if (this.auth.isAdmin() && this.PeopleId !== '' ){
if (this.ss.isAdmin() && this.PeopleId !== '' ){
if (this.PeopleId === 'start-new-people' ){
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();
}
}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();
}
@@ -117,7 +118,7 @@ export class ProfileComponent implements OnInit {
private updateShowHide(): void {
this.resetShowHide();

this.editOtherPeople = ! this.auth.isCurrentUser(this.PeopleId);
this.editOtherPeople = ! this.ss.isCurrentUser(this.PeopleId);
if ( this.editOtherPeople ) {
this.showAdminTool = this.isAdmin() && this.People.Id !== '' ;
if ( this.showAdminTool ){
@@ -163,17 +164,17 @@ export class ProfileComponent implements OnInit {

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

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

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

public deletePeople(): void {

+ 8
- 7
src/app/profile/user-profile/user-profile.component.ts ファイルの表示

@@ -7,6 +7,7 @@ import {MessageBoxComponent} from '../../message-box/message-box.component';
import {PeopleService} from '../../service/people.service';
import {asyncValidatorLoginAvailable} from '../../validator/unique.login.validator';
import {PeopleModel} from '../../models/people.model';
import {SessionService} from '../../service/session.service';

@Component({
selector: 'app-user-profile',
@@ -23,18 +24,18 @@ export class UserProfileComponent implements OnInit {

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 {

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,
}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({
Login: new FormControl({value: this.UserExtra.Login, disabled: ! this.showAdmin },
@@ -62,7 +63,7 @@ export class UserProfileComponent implements OnInit {
}

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

public canEditUser(): boolean {

+ 24
- 80
src/app/service/auth.service.ts ファイルの表示

@@ -6,29 +6,23 @@ import {PeopleModel} from '../models/people.model';
import {UserExtraModel} from '../models/user-extra.model';
import {Observable} from 'rxjs';
import {AppConfig} from '../app.config';
import {SessionService} from './session.service';

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

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

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

public AutoLogin(): void {
const sfm: ApiV1LoginResponse = JSON.parse(localStorage.getItem('sfm'));
const sfm: ApiV1LoginResponse = JSON.parse(localStorage.getItem(this.config.storageKey));
if (!sfm) {
console.log('no auto login');
return;
}
this.loggedIn = new ApiV1LoginResponse(
this.ss.loggedIn = new ApiV1LoginResponse(
sfm.login,
sfm.machineId,
sfm.session,
@@ -38,16 +32,14 @@ export class AuthService {
);

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 {
return this.loggedIn.login;
return this.ss.loggedIn.login;
}

allowEditLoan(): boolean{
@@ -55,103 +47,55 @@ export class AuthService {
}

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 {

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 => {
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) {
this.loggedIn.User = new PeopleModel(responseData.User);
this.ss.loggedIn.User = new PeopleModel(responseData.User);

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

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

);
}

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{
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> {
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 ファイルの表示

@@ -0,0 +1,75 @@
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 ファイルの表示

@@ -5,6 +5,7 @@ import {brokerMenuItems, mainMenuItems, peopleMenuItems, userMenuItems} from '..
import {ApiV1LoginResponse} from '../models/api-v1-login-response';
import {Subscription} from 'rxjs';
import {PeopleModel} from '../models/people.model';
import {SessionService} from '../service/session.service';


@Component({
@@ -24,6 +25,7 @@ export class TopBarComponent implements OnInit , OnDestroy {
public opened = false;

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

@@ -32,15 +34,15 @@ export class TopBarComponent implements OnInit , OnDestroy {
}

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) => {
this.login = rsp.login;
this.LoggedInUser = this.authService.loggedIn.User;
this.LoggedInUser = this.ss.loggedIn.User;
this.selectMenuShow(rsp.role);
}
);
@@ -101,7 +103,7 @@ export class TopBarComponent implements OnInit , OnDestroy {
}

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 {

+ 43
- 27
src/app/websocket.ts ファイルの表示

@@ -1,48 +1,64 @@
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()
export class WebSocketService {
export class WebSocketService extends Subject<string>{

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();
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);
}

// 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);
}

// 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 {
this.ws.send(message);

+ 4
- 13
src/index.html ファイルの表示

@@ -13,21 +13,12 @@
server="https://sc5016.biukop.com.au:8080/"
version="0.9.1"
>
eyJTZXJ2ZXIiOiJodHRwczpcL1wvYzUwMTYuYml1a29wLmNvbS5h
dTo4MDgwXC9hcGlcL3YxXC8iLCJTb2NrZXQiOiJ3c3M6XC9cL2M1
MDE2LmJpdWtvcC5jb20uYXU6ODA4MFwvYXBpXC92MVwvd3MifQ==
eyJTZXJ2ZXIiOiJodHRwczpcL1wvYzUwMTYuYml1a29wLmNvbS5hd
To4MDgwXC9hcGlcL3YxXC8iLCJTb2NrZXQiOiJ3c3M6XC9cL2M1MD
E2LmJpdWtvcC5jb20uYXU6ODA4MFwvYXBpXC92MVwvd3MiLCJTZXN
zaW9uS2V5Ijoic2siLCJWZXJzaW9uIjoyMDIxfQ==
</script>
<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>

</html>

読み込み中…
キャンセル
保存