@brggroup/share-lib 0.0.90 → 0.0.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/brggroup-share-lib.mjs +219 -233
- package/fesm2022/brggroup-share-lib.mjs.map +1 -1
- package/lib/auth/auth.guard.d.ts.map +1 -1
- package/lib/auth/auth.service.d.ts +1 -4
- package/lib/auth/auth.service.d.ts.map +1 -1
- package/lib/auth/session-manager.service.d.ts +5 -12
- package/lib/auth/session-manager.service.d.ts.map +1 -1
- package/lib/components/layout/layout-user/layout-user.d.ts +2 -0
- package/lib/components/layout/layout-user/layout-user.d.ts.map +1 -1
- package/lib/components/login/login.component.d.ts +2 -0
- package/lib/components/login/login.component.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -543,212 +543,6 @@ class TokenStorage {
|
|
|
543
543
|
}
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
-
class SessionManagerService {
|
|
547
|
-
zone;
|
|
548
|
-
constructor(zone) {
|
|
549
|
-
this.zone = zone;
|
|
550
|
-
}
|
|
551
|
-
handlers;
|
|
552
|
-
idleTimer;
|
|
553
|
-
refreshTimer;
|
|
554
|
-
heartbeatTimer;
|
|
555
|
-
static IDLE_MIN = 15;
|
|
556
|
-
REFRESH_BEFORE = 120;
|
|
557
|
-
get IDLE_TIME() {
|
|
558
|
-
return (SessionManagerService.IDLE_MIN || 0) * 60 * 1000;
|
|
559
|
-
}
|
|
560
|
-
LEADER_KEY = 'APP_SESSION_LEADER';
|
|
561
|
-
HEARTBEAT_KEY = 'APP_SESSION_HEARTBEAT';
|
|
562
|
-
ACTIVITY_KEY = 'APP_LAST_ACTIVITY';
|
|
563
|
-
SESSION_EVENT = 'APP_SESSION_EVENT';
|
|
564
|
-
LOGIN_EVENT = 'APP_LOGIN_EVENT';
|
|
565
|
-
LOGOUT_EVENT = 'APP_LOGOUT_EVENT';
|
|
566
|
-
ACTIVITY_EVENT = 'APP_ACTIVITY_EVENT';
|
|
567
|
-
TOKEN_REFRESH_EVENT = 'APP_TOKEN_REFRESH_EVENT';
|
|
568
|
-
tabId = crypto.randomUUID();
|
|
569
|
-
isLeader = false;
|
|
570
|
-
refreshLock = false;
|
|
571
|
-
channel = null;
|
|
572
|
-
/* -------------------------------- START -------------------------------- */
|
|
573
|
-
start(handlers) {
|
|
574
|
-
if (this.IDLE_TIME <= 0)
|
|
575
|
-
return;
|
|
576
|
-
this.handlers = handlers;
|
|
577
|
-
if ('BroadcastChannel' in window) {
|
|
578
|
-
this.channel = new BroadcastChannel('APP_SESSION');
|
|
579
|
-
this.listenChannel();
|
|
580
|
-
}
|
|
581
|
-
this.listenActivity();
|
|
582
|
-
this.updateActivity();
|
|
583
|
-
this.resetIdle();
|
|
584
|
-
this.electLeader();
|
|
585
|
-
}
|
|
586
|
-
stop() {
|
|
587
|
-
clearTimeout(this.idleTimer);
|
|
588
|
-
clearTimeout(this.refreshTimer);
|
|
589
|
-
clearInterval(this.heartbeatTimer);
|
|
590
|
-
}
|
|
591
|
-
/* -------------------------------- ACTIVITY -------------------------------- */
|
|
592
|
-
listenActivity() {
|
|
593
|
-
const events = ['mousemove', 'keydown', 'click', 'scroll'];
|
|
594
|
-
events.forEach((e) => {
|
|
595
|
-
window.addEventListener(e, this.onActivity, true);
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
onActivity = this.debounce(() => {
|
|
599
|
-
this.updateActivity();
|
|
600
|
-
this.resetIdle();
|
|
601
|
-
this.broadcast(this.ACTIVITY_EVENT);
|
|
602
|
-
}, 1000);
|
|
603
|
-
updateActivity() {
|
|
604
|
-
localStorage.setItem(this.ACTIVITY_KEY, Date.now().toString());
|
|
605
|
-
}
|
|
606
|
-
/* -------------------------------- IDLE -------------------------------- */
|
|
607
|
-
resetIdle() {
|
|
608
|
-
clearTimeout(this.idleTimer);
|
|
609
|
-
const last = Number(localStorage.getItem(this.ACTIVITY_KEY) || Date.now());
|
|
610
|
-
const remain = this.IDLE_TIME - (Date.now() - last);
|
|
611
|
-
if (remain <= 0) {
|
|
612
|
-
this.logout();
|
|
613
|
-
return;
|
|
614
|
-
}
|
|
615
|
-
this.zone.runOutsideAngular(() => {
|
|
616
|
-
this.idleTimer = setTimeout(() => {
|
|
617
|
-
this.zone.run(() => this.logout());
|
|
618
|
-
}, remain);
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
/* -------------------------------- LEADER -------------------------------- */
|
|
622
|
-
electLeader() {
|
|
623
|
-
const leader = localStorage.getItem(this.LEADER_KEY);
|
|
624
|
-
if (!leader) {
|
|
625
|
-
this.becomeLeader();
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
this.checkLeaderHeartbeat();
|
|
629
|
-
}
|
|
630
|
-
becomeLeader() {
|
|
631
|
-
this.isLeader = true;
|
|
632
|
-
localStorage.setItem(this.LEADER_KEY, this.tabId);
|
|
633
|
-
this.startHeartbeat();
|
|
634
|
-
this.scheduleRefresh();
|
|
635
|
-
}
|
|
636
|
-
startHeartbeat() {
|
|
637
|
-
this.heartbeatTimer = setInterval(() => {
|
|
638
|
-
localStorage.setItem(this.HEARTBEAT_KEY, Date.now().toString());
|
|
639
|
-
}, 2000);
|
|
640
|
-
}
|
|
641
|
-
checkLeaderHeartbeat() {
|
|
642
|
-
setTimeout(() => {
|
|
643
|
-
const beat = Number(localStorage.getItem(this.HEARTBEAT_KEY) || 0);
|
|
644
|
-
if (Date.now() - beat > 5000) {
|
|
645
|
-
this.becomeLeader();
|
|
646
|
-
}
|
|
647
|
-
}, 3000);
|
|
648
|
-
}
|
|
649
|
-
/* -------------------------------- REFRESH TOKEN -------------------------------- */
|
|
650
|
-
scheduleRefresh() {
|
|
651
|
-
if (!this.isLeader)
|
|
652
|
-
return;
|
|
653
|
-
clearTimeout(this.refreshTimer);
|
|
654
|
-
const token = this.handlers.getToken();
|
|
655
|
-
if (!token)
|
|
656
|
-
return;
|
|
657
|
-
const exp = this.parseJwt(token).exp * 1000;
|
|
658
|
-
const delay = exp - Date.now() - this.REFRESH_BEFORE * 1000;
|
|
659
|
-
if (delay <= 0) {
|
|
660
|
-
this.refreshToken();
|
|
661
|
-
return;
|
|
662
|
-
}
|
|
663
|
-
this.refreshTimer = setTimeout(() => {
|
|
664
|
-
this.refreshToken();
|
|
665
|
-
}, delay);
|
|
666
|
-
}
|
|
667
|
-
async refreshToken() {
|
|
668
|
-
if (!this.isLeader || this.refreshLock)
|
|
669
|
-
return;
|
|
670
|
-
this.refreshLock = true;
|
|
671
|
-
try {
|
|
672
|
-
const res = await this.handlers.refreshToken();
|
|
673
|
-
if (res?.IsSuccess) {
|
|
674
|
-
this.broadcast(this.TOKEN_REFRESH_EVENT);
|
|
675
|
-
this.scheduleRefresh();
|
|
676
|
-
}
|
|
677
|
-
else {
|
|
678
|
-
this.logout();
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
catch {
|
|
682
|
-
this.logout();
|
|
683
|
-
}
|
|
684
|
-
finally {
|
|
685
|
-
this.refreshLock = false;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
/* -------------------------------- CHANNEL -------------------------------- */
|
|
689
|
-
listenChannel() {
|
|
690
|
-
if (!this.channel)
|
|
691
|
-
return;
|
|
692
|
-
this.channel.onmessage = (msg) => {
|
|
693
|
-
const type = msg.data?.type;
|
|
694
|
-
if (type === this.ACTIVITY_EVENT) {
|
|
695
|
-
this.resetIdle();
|
|
696
|
-
}
|
|
697
|
-
if (type === this.LOGOUT_EVENT) {
|
|
698
|
-
console.log('APP_SESSION CHANNEL: ', this.LOGOUT_EVENT);
|
|
699
|
-
this.handlers.logout();
|
|
700
|
-
}
|
|
701
|
-
if (type === this.LOGIN_EVENT) {
|
|
702
|
-
console.log('APP_SESSION CHANNEL: ', this.LOGIN_EVENT);
|
|
703
|
-
location.reload();
|
|
704
|
-
}
|
|
705
|
-
if (type === this.TOKEN_REFRESH_EVENT) {
|
|
706
|
-
console.log('APP_SESSION CHANNEL: ', this.TOKEN_REFRESH_EVENT);
|
|
707
|
-
this.scheduleRefresh();
|
|
708
|
-
}
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
broadcast(type) {
|
|
712
|
-
if (this.channel) {
|
|
713
|
-
this.channel.postMessage({ type });
|
|
714
|
-
}
|
|
715
|
-
else {
|
|
716
|
-
localStorage.setItem(this.SESSION_EVENT, JSON.stringify({ type, t: Date.now() }));
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
broadcastLogin() {
|
|
720
|
-
this.broadcast(this.LOGIN_EVENT);
|
|
721
|
-
}
|
|
722
|
-
broadcastLogout() {
|
|
723
|
-
this.broadcast(this.LOGOUT_EVENT);
|
|
724
|
-
}
|
|
725
|
-
/* -------------------------------- LOGOUT -------------------------------- */
|
|
726
|
-
logout() {
|
|
727
|
-
this.handlers.logout();
|
|
728
|
-
this.broadcast(this.LOGOUT_EVENT);
|
|
729
|
-
}
|
|
730
|
-
/* -------------------------------- UTILS -------------------------------- */
|
|
731
|
-
debounce(fn, delay) {
|
|
732
|
-
let timer;
|
|
733
|
-
return () => {
|
|
734
|
-
clearTimeout(timer);
|
|
735
|
-
timer = setTimeout(() => fn(), delay);
|
|
736
|
-
};
|
|
737
|
-
}
|
|
738
|
-
parseJwt(token) {
|
|
739
|
-
const payload = token.split('.')[1];
|
|
740
|
-
return JSON.parse(atob(payload));
|
|
741
|
-
}
|
|
742
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: SessionManagerService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
743
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: SessionManagerService, providedIn: 'root' });
|
|
744
|
-
}
|
|
745
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: SessionManagerService, decorators: [{
|
|
746
|
-
type: Injectable,
|
|
747
|
-
args: [{
|
|
748
|
-
providedIn: 'root',
|
|
749
|
-
}]
|
|
750
|
-
}], ctorParameters: () => [{ type: i0.NgZone }] });
|
|
751
|
-
|
|
752
546
|
const URLs$4 = {
|
|
753
547
|
login: '/api/Auth/Login',
|
|
754
548
|
register: '/api/Auth/Register',
|
|
@@ -762,7 +556,6 @@ class AuthService extends HTTPService {
|
|
|
762
556
|
commonService = inject(CommonService);
|
|
763
557
|
router = inject(Router);
|
|
764
558
|
translate = inject(TranslateService);
|
|
765
|
-
sessionManager = inject(SessionManagerService);
|
|
766
559
|
/* ----------------------------------------
|
|
767
560
|
TOKEN
|
|
768
561
|
---------------------------------------- */
|
|
@@ -808,7 +601,6 @@ class AuthService extends HTTPService {
|
|
|
808
601
|
}
|
|
809
602
|
this.notiService.success('Đăng nhập thành công');
|
|
810
603
|
TokenStorage.saveToken(res);
|
|
811
|
-
this.sessionManager.broadcastLogin();
|
|
812
604
|
if (returnUrl) {
|
|
813
605
|
this.router.navigateByUrl(returnUrl);
|
|
814
606
|
}
|
|
@@ -824,28 +616,11 @@ class AuthService extends HTTPService {
|
|
|
824
616
|
headers: new HttpHeaders().set('Content-Type', 'application/json'),
|
|
825
617
|
}));
|
|
826
618
|
}
|
|
827
|
-
/* ----------------------------------------
|
|
828
|
-
INIT SESSION (reload page)
|
|
829
|
-
---------------------------------------- */
|
|
830
|
-
initSession() {
|
|
831
|
-
const token = TokenStorage.getToken();
|
|
832
|
-
if (token) {
|
|
833
|
-
this.sessionManager.start({
|
|
834
|
-
refreshToken: () => this.refreshToken(),
|
|
835
|
-
logout: () => this.signOut(),
|
|
836
|
-
getToken: () => this.getToken(),
|
|
837
|
-
});
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
619
|
/* ----------------------------------------
|
|
841
620
|
LOGOUT
|
|
842
621
|
---------------------------------------- */
|
|
843
|
-
signOut(
|
|
622
|
+
signOut() {
|
|
844
623
|
TokenStorage.clearToken();
|
|
845
|
-
if (broadcastEvent) {
|
|
846
|
-
this.sessionManager.broadcastLogout();
|
|
847
|
-
}
|
|
848
|
-
this.sessionManager.stop();
|
|
849
624
|
const currentUrl = this.router.routerState.snapshot.url;
|
|
850
625
|
this.router.navigate(['/login'], {
|
|
851
626
|
queryParams: { returnUrl: currentUrl || '/' },
|
|
@@ -964,7 +739,12 @@ class AuthGuard {
|
|
|
964
739
|
}
|
|
965
740
|
TokenStorage.clearToken();
|
|
966
741
|
if (state.url != '/') {
|
|
967
|
-
|
|
742
|
+
if (!state.url.startsWith('/login')) {
|
|
743
|
+
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
|
|
744
|
+
}
|
|
745
|
+
else {
|
|
746
|
+
this.router.navigate([state.url]);
|
|
747
|
+
}
|
|
968
748
|
}
|
|
969
749
|
else {
|
|
970
750
|
this.router.navigate(['/login']);
|
|
@@ -1149,6 +929,209 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImpor
|
|
|
1149
929
|
}]
|
|
1150
930
|
}] });
|
|
1151
931
|
|
|
932
|
+
class SessionManagerService {
|
|
933
|
+
zone;
|
|
934
|
+
constructor(zone) {
|
|
935
|
+
this.zone = zone;
|
|
936
|
+
}
|
|
937
|
+
authService = inject(AuthService);
|
|
938
|
+
idleTimer;
|
|
939
|
+
refreshTimer;
|
|
940
|
+
heartbeatTimer;
|
|
941
|
+
static IDLE_MIN = 15;
|
|
942
|
+
REFRESH_BEFORE = 120;
|
|
943
|
+
get IDLE_TIME() {
|
|
944
|
+
return (SessionManagerService.IDLE_MIN || 0) * 60 * 1000;
|
|
945
|
+
}
|
|
946
|
+
LEADER_KEY = 'APP_SESSION_LEADER';
|
|
947
|
+
HEARTBEAT_KEY = 'APP_SESSION_HEARTBEAT';
|
|
948
|
+
ACTIVITY_KEY = 'APP_LAST_ACTIVITY';
|
|
949
|
+
SESSION_EVENT = 'APP_SESSION_EVENT';
|
|
950
|
+
LOGIN_EVENT = 'APP_LOGIN_EVENT';
|
|
951
|
+
LOGOUT_EVENT = 'APP_LOGOUT_EVENT';
|
|
952
|
+
ACTIVITY_EVENT = 'APP_ACTIVITY_EVENT';
|
|
953
|
+
TOKEN_REFRESH_EVENT = 'APP_TOKEN_REFRESH_EVENT';
|
|
954
|
+
tabId = crypto.randomUUID();
|
|
955
|
+
isLeader = false;
|
|
956
|
+
refreshLock = false;
|
|
957
|
+
channel = null;
|
|
958
|
+
/* -------------------------------- START -------------------------------- */
|
|
959
|
+
start() {
|
|
960
|
+
if (this.IDLE_TIME <= 0)
|
|
961
|
+
return;
|
|
962
|
+
console.log('SessionManagerService > start > IDLE_TIME:', SessionManagerService.IDLE_MIN);
|
|
963
|
+
if ('BroadcastChannel' in window) {
|
|
964
|
+
this.channel = new BroadcastChannel('APP_SESSION');
|
|
965
|
+
this.listenChannel();
|
|
966
|
+
}
|
|
967
|
+
this.listenActivity();
|
|
968
|
+
this.updateActivity();
|
|
969
|
+
this.resetIdle();
|
|
970
|
+
this.electLeader();
|
|
971
|
+
}
|
|
972
|
+
// stop() {
|
|
973
|
+
// clearTimeout(this.idleTimer);
|
|
974
|
+
// clearTimeout(this.refreshTimer);
|
|
975
|
+
// clearInterval(this.heartbeatTimer);
|
|
976
|
+
// }
|
|
977
|
+
async login(username, password, orgid, returnUrl) {
|
|
978
|
+
var ret = await this.authService.signIn(username, password, orgid, returnUrl);
|
|
979
|
+
if (ret) {
|
|
980
|
+
console.log('SessionManagerService > broadcast LOGIN');
|
|
981
|
+
this.broadcast(this.LOGIN_EVENT);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
logout() {
|
|
985
|
+
this.authService.signOut();
|
|
986
|
+
this.broadcast(this.LOGOUT_EVENT);
|
|
987
|
+
}
|
|
988
|
+
/* -------------------------------- ACTIVITY -------------------------------- */
|
|
989
|
+
listenActivity() {
|
|
990
|
+
const events = ['mousemove', 'keydown', 'click', 'scroll'];
|
|
991
|
+
events.forEach((e) => {
|
|
992
|
+
window.addEventListener(e, this.onActivity, true);
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
onActivity = this.debounce(() => {
|
|
996
|
+
this.updateActivity();
|
|
997
|
+
this.resetIdle();
|
|
998
|
+
this.broadcast(this.ACTIVITY_EVENT);
|
|
999
|
+
}, 1000);
|
|
1000
|
+
updateActivity() {
|
|
1001
|
+
localStorage.setItem(this.ACTIVITY_KEY, Date.now().toString());
|
|
1002
|
+
}
|
|
1003
|
+
/* -------------------------------- IDLE -------------------------------- */
|
|
1004
|
+
resetIdle() {
|
|
1005
|
+
clearTimeout(this.idleTimer);
|
|
1006
|
+
const last = Number(localStorage.getItem(this.ACTIVITY_KEY) || Date.now());
|
|
1007
|
+
const remain = this.IDLE_TIME - (Date.now() - last);
|
|
1008
|
+
if (remain <= 0) {
|
|
1009
|
+
this.authService.signOut();
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
this.zone.runOutsideAngular(() => {
|
|
1013
|
+
this.idleTimer = setTimeout(() => {
|
|
1014
|
+
this.zone.run(() => this.authService.signOut());
|
|
1015
|
+
}, remain);
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
/* -------------------------------- LEADER -------------------------------- */
|
|
1019
|
+
electLeader() {
|
|
1020
|
+
const leader = localStorage.getItem(this.LEADER_KEY);
|
|
1021
|
+
if (!leader) {
|
|
1022
|
+
this.becomeLeader();
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
this.checkLeaderHeartbeat();
|
|
1026
|
+
}
|
|
1027
|
+
becomeLeader() {
|
|
1028
|
+
this.isLeader = true;
|
|
1029
|
+
localStorage.setItem(this.LEADER_KEY, this.tabId);
|
|
1030
|
+
this.startHeartbeat();
|
|
1031
|
+
this.scheduleRefresh();
|
|
1032
|
+
}
|
|
1033
|
+
startHeartbeat() {
|
|
1034
|
+
this.heartbeatTimer = setInterval(() => {
|
|
1035
|
+
localStorage.setItem(this.HEARTBEAT_KEY, Date.now().toString());
|
|
1036
|
+
}, 2000);
|
|
1037
|
+
}
|
|
1038
|
+
checkLeaderHeartbeat() {
|
|
1039
|
+
setTimeout(() => {
|
|
1040
|
+
const beat = Number(localStorage.getItem(this.HEARTBEAT_KEY) || 0);
|
|
1041
|
+
if (Date.now() - beat > 5000) {
|
|
1042
|
+
this.becomeLeader();
|
|
1043
|
+
}
|
|
1044
|
+
}, 3000);
|
|
1045
|
+
}
|
|
1046
|
+
/* -------------------------------- REFRESH TOKEN -------------------------------- */
|
|
1047
|
+
scheduleRefresh() {
|
|
1048
|
+
if (!this.isLeader)
|
|
1049
|
+
return;
|
|
1050
|
+
clearTimeout(this.refreshTimer);
|
|
1051
|
+
const token = this.authService.getToken();
|
|
1052
|
+
if (!token)
|
|
1053
|
+
return;
|
|
1054
|
+
const exp = this.parseJwt(token).exp * 1000;
|
|
1055
|
+
const delay = exp - Date.now() - this.REFRESH_BEFORE * 1000;
|
|
1056
|
+
if (delay <= 0) {
|
|
1057
|
+
this.refreshToken();
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
this.refreshTimer = setTimeout(() => {
|
|
1061
|
+
this.refreshToken();
|
|
1062
|
+
}, delay);
|
|
1063
|
+
}
|
|
1064
|
+
async refreshToken() {
|
|
1065
|
+
if (!this.isLeader || this.refreshLock)
|
|
1066
|
+
return;
|
|
1067
|
+
this.refreshLock = true;
|
|
1068
|
+
try {
|
|
1069
|
+
const res = await this.authService.refreshToken();
|
|
1070
|
+
if (res?.IsSuccess) {
|
|
1071
|
+
this.broadcast(this.TOKEN_REFRESH_EVENT);
|
|
1072
|
+
this.scheduleRefresh();
|
|
1073
|
+
}
|
|
1074
|
+
else {
|
|
1075
|
+
this.logout();
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
catch {
|
|
1079
|
+
this.logout();
|
|
1080
|
+
}
|
|
1081
|
+
finally {
|
|
1082
|
+
this.refreshLock = false;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
/* -------------------------------- CHANNEL -------------------------------- */
|
|
1086
|
+
listenChannel() {
|
|
1087
|
+
if (!this.channel)
|
|
1088
|
+
return;
|
|
1089
|
+
this.channel.onmessage = (msg) => {
|
|
1090
|
+
const type = msg.data?.type;
|
|
1091
|
+
if (type === this.ACTIVITY_EVENT) {
|
|
1092
|
+
this.resetIdle();
|
|
1093
|
+
}
|
|
1094
|
+
if (type === this.LOGOUT_EVENT) {
|
|
1095
|
+
location.reload();
|
|
1096
|
+
}
|
|
1097
|
+
if (type === this.LOGIN_EVENT) {
|
|
1098
|
+
location.reload();
|
|
1099
|
+
}
|
|
1100
|
+
if (type === this.TOKEN_REFRESH_EVENT) {
|
|
1101
|
+
this.scheduleRefresh();
|
|
1102
|
+
}
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
broadcast(type) {
|
|
1106
|
+
if (this.channel) {
|
|
1107
|
+
this.channel.postMessage({ type });
|
|
1108
|
+
}
|
|
1109
|
+
else {
|
|
1110
|
+
localStorage.setItem(this.SESSION_EVENT, JSON.stringify({ type, t: Date.now() }));
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
/* -------------------------------- UTILS -------------------------------- */
|
|
1114
|
+
debounce(fn, delay) {
|
|
1115
|
+
let timer;
|
|
1116
|
+
return () => {
|
|
1117
|
+
clearTimeout(timer);
|
|
1118
|
+
timer = setTimeout(() => fn(), delay);
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
parseJwt(token) {
|
|
1122
|
+
const payload = token.split('.')[1];
|
|
1123
|
+
return JSON.parse(atob(payload));
|
|
1124
|
+
}
|
|
1125
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: SessionManagerService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1126
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: SessionManagerService, providedIn: 'root' });
|
|
1127
|
+
}
|
|
1128
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: SessionManagerService, decorators: [{
|
|
1129
|
+
type: Injectable,
|
|
1130
|
+
args: [{
|
|
1131
|
+
providedIn: 'root',
|
|
1132
|
+
}]
|
|
1133
|
+
}], ctorParameters: () => [{ type: i0.NgZone }] });
|
|
1134
|
+
|
|
1152
1135
|
class CustomModalService {
|
|
1153
1136
|
modal;
|
|
1154
1137
|
constructor(modal) {
|
|
@@ -6358,6 +6341,7 @@ const fadeSlide = trigger('fadeSlide', [
|
|
|
6358
6341
|
class LayoutUser extends BaseComponent {
|
|
6359
6342
|
cms = inject(CommonService);
|
|
6360
6343
|
authService = inject(AuthService);
|
|
6344
|
+
sessionManager = inject(SessionManagerService);
|
|
6361
6345
|
breakpointObserver = inject(BreakpointObserver);
|
|
6362
6346
|
TokenStorage = TokenStorage;
|
|
6363
6347
|
isXSmall = false;
|
|
@@ -6389,10 +6373,10 @@ class LayoutUser extends BaseComponent {
|
|
|
6389
6373
|
this.goto('/admin/user_profile');
|
|
6390
6374
|
}
|
|
6391
6375
|
logout() {
|
|
6392
|
-
this.authService.signOut(
|
|
6376
|
+
this.sessionManager.authService.signOut();
|
|
6393
6377
|
}
|
|
6394
6378
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: LayoutUser, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
6395
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.7", type: LayoutUser, isStandalone: true, selector: "layout-user", usesInheritance: true, ngImport: i0, template: "<nz-badge [nzSize]=\"'small'\" [nzCount]=\"0\">\n <button nz-button nzType=\"text\" nzSize=\"small\">\n <nz-icon nzType=\"bell\" nzTheme=\"outline\" style=\"color: #ffffff\" />\n </button>\n</nz-badge>\n\n<button\n *ngIf=\"!isXSmall && TokenStorage.getOrgName()\"\n [@fadeInOut]\n nz-button\n nzType=\"text\"\n nz-dropdown\n [nzDropdownMenu]=\"menuOrg\"\n style=\"height: 50px; color: #ffffff\"\n>\n <nz-icon nzType=\"cluster\" nzTheme=\"outline\" />\n {{ TokenStorage.getOrgName() }}\n</button>\n\n<nz-dropdown-menu #menuOrg=\"nzDropdownMenu\">\n <ul nz-menu>\n @for (org of lstOrg; track $index) {\n <li *ngIf=\"$index > 0\" nz-menu-divider></li>\n <li nz-menu-item (click)=\"changeOrg(org)\">\n <nz-icon nzType=\"swap\" nzTheme=\"outline\" /> {{ org.Name }}\n </li>\n }\n </ul>\n</nz-dropdown-menu>\n\n<button
|
|
6379
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.7", type: LayoutUser, isStandalone: true, selector: "layout-user", usesInheritance: true, ngImport: i0, template: "<nz-badge [nzSize]=\"'small'\" [nzCount]=\"0\">\n <button nz-button nzType=\"text\" nzSize=\"small\">\n <nz-icon nzType=\"bell\" nzTheme=\"outline\" style=\"color: #ffffff\" />\n </button>\n</nz-badge>\n\n<button\n *ngIf=\"!isXSmall && TokenStorage.getOrgName()\"\n [@fadeInOut]\n nz-button\n nzType=\"text\"\n nz-dropdown\n [nzDropdownMenu]=\"menuOrg\"\n [nzTrigger]=\"'click'\"\n style=\"height: 50px; color: #ffffff\"\n>\n <nz-icon nzType=\"cluster\" nzTheme=\"outline\" />\n {{ TokenStorage.getOrgName() }}\n</button>\n\n<nz-dropdown-menu #menuOrg=\"nzDropdownMenu\">\n <ul nz-menu>\n @for (org of lstOrg; track $index) {\n <li *ngIf=\"$index > 0\" nz-menu-divider></li>\n <li nz-menu-item (click)=\"changeOrg(org)\">\n <nz-icon nzType=\"swap\" nzTheme=\"outline\" /> {{ org.Name }}\n </li>\n }\n </ul>\n</nz-dropdown-menu>\n\n<button\n nz-button\n nzType=\"text\"\n nz-dropdown\n [nzDropdownMenu]=\"menuUser\"\n [nzTrigger]=\"'click'\"\n style=\"height: 50px; color: #ffffff\"\n>\n <nz-icon nzType=\"user\" nzTheme=\"outline\" />\n {{ TokenStorage.getUserFullname() }}\n</button>\n\n<nz-dropdown-menu #menuUser=\"nzDropdownMenu\">\n <ul nz-menu>\n <li *ngIf=\"!(!isXSmall && TokenStorage.getOrgName())\" nz-menu-item>\n <nz-icon nzType=\"cluster\" nzTheme=\"outline\" /> {{ TokenStorage.getOrgName() }}\n </li>\n <li *ngIf=\"!(!isXSmall && TokenStorage.getOrgName())\" nz-menu-divider></li>\n <li nz-menu-item (click)=\"gotoSetting()\">\n <nz-icon nzType=\"setting\" nzTheme=\"outline\" /> {{ TranslateKey.SETTING | translate }}\n </li>\n <li nz-menu-divider></li>\n <li nz-menu-item (click)=\"logout()\">\n <nz-icon nzType=\"logout\" nzTheme=\"outline\" /> {{ TranslateKey.LOGOUT | translate }}\n </li>\n </ul>\n</nz-dropdown-menu>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: NzLayoutModule }, { kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i1$2.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "ngmodule", type: NzDropDownModule }, { kind: "directive", type: i4$2.NzMenuDirective, selector: "[nz-menu]", inputs: ["nzInlineIndent", "nzTheme", "nzMode", "nzInlineCollapsed", "nzSelectable"], outputs: ["nzClick"], exportAs: ["nzMenu"] }, { kind: "component", type: i4$2.NzMenuItemComponent, selector: "[nz-menu-item]", inputs: ["nzPaddingLeft", "nzDisabled", "nzSelected", "nzDanger", "nzMatchRouterExact", "nzMatchRouter"], exportAs: ["nzMenuItem"] }, { kind: "directive", type: i4$2.NzMenuDividerDirective, selector: "[nz-menu-divider]", exportAs: ["nzMenuDivider"] }, { kind: "directive", type: i5$3.NzDropDownDirective, selector: "[nz-dropdown]", inputs: ["nzDropdownMenu", "nzTrigger", "nzMatchWidthElement", "nzBackdrop", "nzClickHide", "nzDisabled", "nzVisible", "nzOverlayClassName", "nzOverlayStyle", "nzPlacement"], outputs: ["nzVisibleChange"], exportAs: ["nzDropdown"] }, { kind: "component", type: i5$3.NzDropdownMenuComponent, selector: "nz-dropdown-menu", exportAs: ["nzDropdownMenu"] }, { kind: "directive", type: i5$3.NzDropdownButtonDirective, selector: "[nz-button][nz-dropdown]" }, { kind: "ngmodule", type: NzGridModule }, { kind: "ngmodule", type: NzFlexModule }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i8.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i9.ɵNzTransitionPatchDirective, selector: "[nz-button], nz-button-group, [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "ngmodule", type: NzTreeModule }, { kind: "ngmodule", type: NzBackTopModule }, { kind: "ngmodule", type: NzDrawerModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: NzInputModule }, { kind: "ngmodule", type: NzSegmentedModule }, { kind: "ngmodule", type: NzBadgeModule }, { kind: "component", type: i8$1.NzBadgeComponent, selector: "nz-badge", inputs: ["nzShowZero", "nzShowDot", "nzStandalone", "nzDot", "nzOverflowCount", "nzColor", "nzStyle", "nzText", "nzTitle", "nzStatus", "nzCount", "nzOffset", "nzSize"], exportAs: ["nzBadge"] }], animations: [fadeInOut] });
|
|
6396
6380
|
}
|
|
6397
6381
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: LayoutUser, decorators: [{
|
|
6398
6382
|
type: Component,
|
|
@@ -6413,7 +6397,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImpor
|
|
|
6413
6397
|
NzTreeModule,
|
|
6414
6398
|
NzSegmentedModule,
|
|
6415
6399
|
NzBadgeModule,
|
|
6416
|
-
], animations: [fadeInOut], template: "<nz-badge [nzSize]=\"'small'\" [nzCount]=\"0\">\n <button nz-button nzType=\"text\" nzSize=\"small\">\n <nz-icon nzType=\"bell\" nzTheme=\"outline\" style=\"color: #ffffff\" />\n </button>\n</nz-badge>\n\n<button\n *ngIf=\"!isXSmall && TokenStorage.getOrgName()\"\n [@fadeInOut]\n nz-button\n nzType=\"text\"\n nz-dropdown\n [nzDropdownMenu]=\"menuOrg\"\n style=\"height: 50px; color: #ffffff\"\n>\n <nz-icon nzType=\"cluster\" nzTheme=\"outline\" />\n {{ TokenStorage.getOrgName() }}\n</button>\n\n<nz-dropdown-menu #menuOrg=\"nzDropdownMenu\">\n <ul nz-menu>\n @for (org of lstOrg; track $index) {\n <li *ngIf=\"$index > 0\" nz-menu-divider></li>\n <li nz-menu-item (click)=\"changeOrg(org)\">\n <nz-icon nzType=\"swap\" nzTheme=\"outline\" /> {{ org.Name }}\n </li>\n }\n </ul>\n</nz-dropdown-menu>\n\n<button
|
|
6400
|
+
], animations: [fadeInOut], template: "<nz-badge [nzSize]=\"'small'\" [nzCount]=\"0\">\n <button nz-button nzType=\"text\" nzSize=\"small\">\n <nz-icon nzType=\"bell\" nzTheme=\"outline\" style=\"color: #ffffff\" />\n </button>\n</nz-badge>\n\n<button\n *ngIf=\"!isXSmall && TokenStorage.getOrgName()\"\n [@fadeInOut]\n nz-button\n nzType=\"text\"\n nz-dropdown\n [nzDropdownMenu]=\"menuOrg\"\n [nzTrigger]=\"'click'\"\n style=\"height: 50px; color: #ffffff\"\n>\n <nz-icon nzType=\"cluster\" nzTheme=\"outline\" />\n {{ TokenStorage.getOrgName() }}\n</button>\n\n<nz-dropdown-menu #menuOrg=\"nzDropdownMenu\">\n <ul nz-menu>\n @for (org of lstOrg; track $index) {\n <li *ngIf=\"$index > 0\" nz-menu-divider></li>\n <li nz-menu-item (click)=\"changeOrg(org)\">\n <nz-icon nzType=\"swap\" nzTheme=\"outline\" /> {{ org.Name }}\n </li>\n }\n </ul>\n</nz-dropdown-menu>\n\n<button\n nz-button\n nzType=\"text\"\n nz-dropdown\n [nzDropdownMenu]=\"menuUser\"\n [nzTrigger]=\"'click'\"\n style=\"height: 50px; color: #ffffff\"\n>\n <nz-icon nzType=\"user\" nzTheme=\"outline\" />\n {{ TokenStorage.getUserFullname() }}\n</button>\n\n<nz-dropdown-menu #menuUser=\"nzDropdownMenu\">\n <ul nz-menu>\n <li *ngIf=\"!(!isXSmall && TokenStorage.getOrgName())\" nz-menu-item>\n <nz-icon nzType=\"cluster\" nzTheme=\"outline\" /> {{ TokenStorage.getOrgName() }}\n </li>\n <li *ngIf=\"!(!isXSmall && TokenStorage.getOrgName())\" nz-menu-divider></li>\n <li nz-menu-item (click)=\"gotoSetting()\">\n <nz-icon nzType=\"setting\" nzTheme=\"outline\" /> {{ TranslateKey.SETTING | translate }}\n </li>\n <li nz-menu-divider></li>\n <li nz-menu-item (click)=\"logout()\">\n <nz-icon nzType=\"logout\" nzTheme=\"outline\" /> {{ TranslateKey.LOGOUT | translate }}\n </li>\n </ul>\n</nz-dropdown-menu>\n" }]
|
|
6417
6401
|
}] });
|
|
6418
6402
|
|
|
6419
6403
|
const URLs$2 = {
|
|
@@ -7090,6 +7074,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImpor
|
|
|
7090
7074
|
class LoginComponent extends BaseComponent {
|
|
7091
7075
|
fb = inject(FormBuilder);
|
|
7092
7076
|
authService = inject(AuthService);
|
|
7077
|
+
sessionManager = inject(SessionManagerService);
|
|
7093
7078
|
orgService = inject(OrgService);
|
|
7094
7079
|
settingService = inject(SettingService);
|
|
7095
7080
|
vscService = inject(VscService);
|
|
@@ -7133,6 +7118,7 @@ class LoginComponent extends BaseComponent {
|
|
|
7133
7118
|
}
|
|
7134
7119
|
}, (err) => this.handleError(err));
|
|
7135
7120
|
this.vscService.clearInterval();
|
|
7121
|
+
// this.sessionManager.stop();
|
|
7136
7122
|
}
|
|
7137
7123
|
getLstOrg() {
|
|
7138
7124
|
const username = this.loginForm.controls['username'].value;
|
|
@@ -7155,7 +7141,7 @@ class LoginComponent extends BaseComponent {
|
|
|
7155
7141
|
this.loginForm.controls[i].updateValueAndValidity();
|
|
7156
7142
|
}
|
|
7157
7143
|
if (this.loginForm.valid) {
|
|
7158
|
-
this.
|
|
7144
|
+
this.sessionManager.login(this.loginForm.value.username, this.loginForm.value.password, this.loginForm.value.orgid, this.returnUrl);
|
|
7159
7145
|
}
|
|
7160
7146
|
this.vscService.checkVersion();
|
|
7161
7147
|
}
|
|
@@ -7171,8 +7157,8 @@ class LoginComponent extends BaseComponent {
|
|
|
7171
7157
|
e.target.style.display = 'none';
|
|
7172
7158
|
}
|
|
7173
7159
|
logoUrl$ = this.fileService
|
|
7174
|
-
.getFileVersion('
|
|
7175
|
-
.pipe(map((res) => `${AppGlobals.apiEndpoint}/api/file/image?code=
|
|
7160
|
+
.getFileVersion('LOGO_LOGIN')
|
|
7161
|
+
.pipe(map((res) => `${AppGlobals.apiEndpoint}/api/file/image?code=LOGO_LOGIN&v=${res || ''}`));
|
|
7176
7162
|
bgUrl$ = this.fileService
|
|
7177
7163
|
.getFileVersion('LOGIN_BACKGROUND')
|
|
7178
7164
|
.pipe(map((res) => `${AppGlobals.apiEndpoint}/api/file/image?code=LOGIN_BACKGROUND&v=${res || ''}`));
|