Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mySkill-x
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
angular
mySkill-x
Commits
b75eec55
Commit
b75eec55
authored
Apr 17, 2025
by
Ooh-Ao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tokenservice httpinceptor
parent
aff91f9f
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
203 additions
and
322 deletions
+203
-322
header.component.html
src/app/shared/components/header/header.component.html
+77
-216
auth.service.ts
src/app/shared/services/auth.service.ts
+10
-17
http-request.interceptor.ts
src/app/shared/services/http-request.interceptor.ts
+52
-63
token.service.ts
src/app/shared/services/token.service.ts
+63
-14
environment.ts
src/environments/environment.ts
+1
-12
No files found.
src/app/shared/components/header/header.component.html
View file @
b75eec55
...
...
@@ -5,11 +5,7 @@
<div
class=
"header-left"
>
<!-- Navigation Toggle -->
<div
class=
""
>
<button
type=
"button"
class=
"sidebar-toggle !w-100 !h-100"
(
click
)="
toggleSidebar
()"
>
<button
type=
"button"
class=
"sidebar-toggle !w-100 !h-100"
(
click
)="
toggleSidebar
()"
>
<span
class=
"sr-only"
>
Toggle Navigation
</span>
<i
class=
"ri-arrow-right-circle-line header-icon"
></i>
</button>
...
...
@@ -41,29 +37,17 @@
<div
class=
"header-right"
>
<div
class=
"responsive-headernav"
>
<div
class=
"header-nav-right"
>
<div
class=
"header-country hs-dropdown ti-dropdown hidden sm:block"
data-hs-dropdown-placement=
"bottom-right"
>
<button
id=
"dropdown-flag"
type=
"button"
class=
"hs-dropdown-toggle ti-dropdown-toggle p-0 flex-shrink-0 h-[2.375rem] w-[2.375rem] border-0 rounded-full shadow-none focus:ring-gray-400 text-xs dark:focus:ring-white/10"
>
<div
class=
"header-country hs-dropdown ti-dropdown hidden sm:block"
data-hs-dropdown-placement=
"bottom-right"
>
<button
id=
"dropdown-flag"
type=
"button"
class=
"hs-dropdown-toggle ti-dropdown-toggle p-0 flex-shrink-0 h-[2.375rem] w-[2.375rem] border-0 rounded-full shadow-none focus:ring-gray-400 text-xs dark:focus:ring-white/10"
>
<i
class=
"flag-icon flag-icon-th h-[1.375rem] w-[1.375rem]"
></i>
</button>
<div
class=
"hs-dropdown-menu ti-dropdown-menu min-w-[10rem]"
aria-labelledby=
"dropdown-flag"
>
<div
class=
"ti-dropdown-divider divide-y divide-gray-200 dark:divide-white/10"
>
<div
class=
"hs-dropdown-menu ti-dropdown-menu min-w-[10rem]"
aria-labelledby=
"dropdown-flag"
>
<div
class=
"ti-dropdown-divider divide-y divide-gray-200 dark:divide-white/10"
>
<div
class=
"py-2 first:pt-0 last:pb-0"
>
<div
class=
"ti-dropdown-item"
>
<div
class=
"flex items-center space-x-2 rtl:space-x-reverse w-full"
>
<div
class=
"flex items-center space-x-2 rtl:space-x-reverse w-full"
>
<div
class=
"h-[1.375rem] w-[1.375rem] rounded-sm"
>
<i
class=
"flag-icon flag-icon-th"
></i>
</div>
...
...
@@ -73,9 +57,7 @@
</div>
</div>
<div
class=
"ti-dropdown-item"
>
<div
class=
"flex items-center space-x-2 rtl:space-x-reverse w-full"
>
<div
class=
"flex items-center space-x-2 rtl:space-x-reverse w-full"
>
<div
class=
"h-[1.375rem] w-[1.375rem] rounded-sm"
>
<i
class=
"flag-icon flag-icon-us"
></i>
</div>
...
...
@@ -681,40 +663,25 @@
</div>
</div>
</div> -->
<div
class=
"header-profile hs-dropdown ti-dropdown"
data-hs-dropdown-placement=
"bottom-right"
>
<button
id=
"dropdown-profile"
type=
"button"
class=
"hs-dropdown-toggle ti-dropdown-toggle gap-2 p-0 flex-shrink-0 h-8 w-8 rounded-full shadow-none focus:ring-gray-400 text-xs dark:focus:ring-white/10"
>
<img
class=
"inline-block rounded-full ring-2 ring-white dark:ring-white/10"
src=
"./assets/img/users/1.jpg"
alt=
"Image Description"
/>
<div
class=
"header-profile hs-dropdown ti-dropdown"
data-hs-dropdown-placement=
"bottom-right"
>
<button
id=
"dropdown-profile"
type=
"button"
class=
"hs-dropdown-toggle ti-dropdown-toggle gap-2 p-0 flex-shrink-0 h-8 w-8 rounded-full shadow-none focus:ring-gray-400 text-xs dark:focus:ring-white/10"
>
<img
class=
"inline-block rounded-full ring-2 ring-white dark:ring-white/10"
src=
"./assets/img/users/1.jpg"
alt=
"Image Description"
/>
</button>
<div
class=
"hs-dropdown-menu ti-dropdown-menu border-0 w-[20rem]"
aria-labelledby=
"dropdown-profile"
>
<div
class=
"hs-dropdown-menu ti-dropdown-menu border-0 w-[20rem]"
aria-labelledby=
"dropdown-profile"
>
<div
class=
"ti-dropdown-header !bg-primary flex"
>
<div
class=
"ltr:mr-3 rtl:ml-3"
>
<img
class=
"avatar shadow-none rounded-full !ring-transparent"
src=
"./assets/img/users/1.jpg"
alt=
"profile-img"
/>
<img
class=
"avatar shadow-none rounded-full !ring-transparent"
src=
"./assets/img/users/1.jpg"
alt=
"profile-img"
/>
</div>
<div>
<p
class=
"ti-dropdown-header-title !text-white"
>
{{this.employeeProfile.thFullName?this.employeeProfile.thFullName:''}}
</p>
<p
class=
"ti-dropdown-header-content !text-white/50 "
style=
"font-size: 12px;"
>
{{tokenService.getUser
().iss?tokenService.getUser().iss:'
'}}
{{tokenService.getUser
Data().position?tokenService.getUserData().position:'-
'}}
</p>
</div>
</div>
...
...
@@ -750,12 +717,9 @@
</div>
</div>
<div
class=
"switcher-icon"
>
<button
aria-label=
"button"
type=
"button"
<button
aria-label=
"button"
type=
"button"
class=
"hs-dropdown-toggle inline-flex flex-shrink-0 justify-center items-center gap-2 h-[2.375rem] w-[2.375rem] rounded-full font-medium bg-gray-100 hover:bg-gray-200 text-gray-500 align-middle focus:outline-none focus-visible:outline-none focus:ring-0 focus:ring-gray-400 focus:ring-offset-0 focus:ring-offset-white transition-all text-xs dark:bg-bgdark dark:hover:bg-black/20 dark:text-white/70 dark:hover:text-white dark:focus:ring-white/10 dark:focus:ring-offset-white/10"
data-hs-overlay=
"#hs-overlay-switcher"
>
data-hs-overlay=
"#hs-overlay-switcher"
>
<i
class=
"ri-settings-5-line header-icon animate-spin"
></i>
</button>
</div>
...
...
@@ -778,13 +742,8 @@
<div
class=
"search-btn"
>
<i
class=
"ri ri-search-2-line search-btn-icon"
></i>
</div>
<input
type=
"text"
id=
"icon"
name=
"icon"
class=
"py-2 ltr:pl-11 rtl:pr-11 ti-form-input focus:z-10"
placeholder=
"Search by No. or Name"
/>
<input
type=
"text"
id=
"icon"
name=
"icon"
class=
"py-2 ltr:pl-11 rtl:pr-11 ti-form-input focus:z-10"
placeholder=
"Search by No. or Name"
/>
<div
class=
"voice-search"
>
<i
class=
"ri ri-mic-2-line voice-btn-icon"
></i>
</div>
...
...
@@ -794,140 +753,72 @@
</div>
</div>
<div
class=
"mt-5"
>
<p
class=
"font-semibold text-[13px] text-gray-400 dark:text-gray-200 mb-2"
>
<p
class=
"font-semibold text-[13px] text-gray-400 dark:text-gray-200 mb-2"
>
Are You Looking For...
</p>
<div
class=
"badge rounded-sm bg-secondary/20 text-secondary relative header-box me-1"
id=
"badge1"
>
<a
routerLink=
"/page/team"
class=
"w-full my-auto items-center flex space-x-2 rtl:space-x-reverse"
>
<span
class=
"inline-block text-secondary mr-1"
><i
class=
"ri ri-user-line text-sm"
></i
></span>
<div
class=
"badge rounded-sm bg-secondary/20 text-secondary relative header-box me-1"
id=
"badge1"
>
<a
routerLink=
"/page/team"
class=
"w-full my-auto items-center flex space-x-2 rtl:space-x-reverse"
>
<span
class=
"inline-block text-secondary mr-1"
><i
class=
"ri ri-user-line text-sm"
></i></span>
Team
</a>
<a
href=
"javascript:void(0);"
<a
href=
"javascript:void(0);"
class=
"header-remove-btn flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-secondary hover:bg-secondary hover:text-secondary focus:outline-none focus:bg-secondary focus:text-white"
(
click
)="
removeRow
('
badge1
')"
>
(
click
)="
removeRow
('
badge1
')"
>
<span
class=
"sr-only"
>
Remove badge
</span>
<svg
class=
"h-4 w-4 hover:fill-white"
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
fill=
"currentColor"
viewBox=
"0 0 16 16"
>
<svg
class=
"h-4 w-4 hover:fill-white"
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
fill=
"currentColor"
viewBox=
"0 0 16 16"
>
<path
d=
"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
>
</path>
d=
"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
>
</path>
</svg>
</a>
</div>
<div
id=
"badge2"
class=
"badge rounded-sm bg-secondary/20 text-secondary relative header-box me-1"
>
<a
routerLink=
"/form-module/form-elements"
class=
"w-full my-auto items-center flex space-x-2 rtl:space-x-reverse"
>
<span
class=
"inline-block text-secondary mr-1"
><i
class=
"ri ri-file-text-line text-sm"
></i
></span>
<div
id=
"badge2"
class=
"badge rounded-sm bg-secondary/20 text-secondary relative header-box me-1"
>
<a
routerLink=
"/form-module/form-elements"
class=
"w-full my-auto items-center flex space-x-2 rtl:space-x-reverse"
>
<span
class=
"inline-block text-secondary mr-1"
><i
class=
"ri ri-file-text-line text-sm"
></i></span>
Forms
</a>
<a
href=
"javascript:void(0);"
(
click
)="
removeRow
('
badge2
')"
class=
"header-remove-btn flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-secondary hover:bg-secondary hover:text-secondary focus:outline-none focus:bg-secondary focus:text-white"
>
<a
href=
"javascript:void(0);"
(
click
)="
removeRow
('
badge2
')"
class=
"header-remove-btn flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-secondary hover:bg-secondary hover:text-secondary focus:outline-none focus:bg-secondary focus:text-white"
>
<span
class=
"sr-only"
>
Remove badge
</span>
<svg
class=
"h-4 w-4 hover:fill-white"
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
fill=
"currentColor"
viewBox=
"0 0 16 16"
>
<svg
class=
"h-4 w-4 hover:fill-white"
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
fill=
"currentColor"
viewBox=
"0 0 16 16"
>
<path
d=
"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
>
</path>
d=
"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
>
</path>
</svg>
</a>
</div>
<div
id=
"badge3"
class=
"badge rounded-sm bg-secondary/20 text-secondary relative header-box me-1"
>
<a
routerLink=
"/maps/leaflet"
class=
"w-full my-auto items-center flex space-x-2 rtl:space-x-reverse"
>
<span
class=
"inline-block text-secondary mr-1"
><i
class=
"ri ri-map-pin-line text-sm"
></i
></span>
<div
id=
"badge3"
class=
"badge rounded-sm bg-secondary/20 text-secondary relative header-box me-1"
>
<a
routerLink=
"/maps/leaflet"
class=
"w-full my-auto items-center flex space-x-2 rtl:space-x-reverse"
>
<span
class=
"inline-block text-secondary mr-1"
><i
class=
"ri ri-map-pin-line text-sm"
></i></span>
Maps
</a>
<a
href=
"javascript:void(0);"
(
click
)="
removeRow
('
badge3
')"
class=
"header-remove-btn flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-secondary hover:bg-secondary hover:text-secondary focus:outline-none focus:bg-secondary focus:text-white"
>
<a
href=
"javascript:void(0);"
(
click
)="
removeRow
('
badge3
')"
class=
"header-remove-btn flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-secondary hover:bg-secondary hover:text-secondary focus:outline-none focus:bg-secondary focus:text-white"
>
<span
class=
"sr-only"
>
Remove badge
</span>
<svg
class=
"h-4 w-4 hover:fill-white"
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
fill=
"currentColor"
viewBox=
"0 0 16 16"
>
<svg
class=
"h-4 w-4 hover:fill-white"
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
fill=
"currentColor"
viewBox=
"0 0 16 16"
>
<path
d=
"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
>
</path>
d=
"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
>
</path>
</svg>
</a>
</div>
<div
id=
"badge4"
class=
"badge rounded-sm bg-secondary/20 text-secondary relative header-box me-1"
>
<a
routerLink=
"/widgets"
class=
"w-full my-auto items-center flex space-x-2 rtl:space-x-reverse"
>
<span
class=
"inline-block text-secondary mr-1"
><i
class=
"ri ri-server-line text-sm"
></i
></span>
<div
id=
"badge4"
class=
"badge rounded-sm bg-secondary/20 text-secondary relative header-box me-1"
>
<a
routerLink=
"/widgets"
class=
"w-full my-auto items-center flex space-x-2 rtl:space-x-reverse"
>
<span
class=
"inline-block text-secondary mr-1"
><i
class=
"ri ri-server-line text-sm"
></i></span>
Widgets
</a>
<a
href=
"javascript:void(0);"
(
click
)="
removeRow
('
badge4
')"
class=
"header-remove-btn flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-secondary hover:bg-secondary hover:text-secondary focus:outline-none focus:bg-secondary focus:text-white"
>
<a
href=
"javascript:void(0);"
(
click
)="
removeRow
('
badge4
')"
class=
"header-remove-btn flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-secondary hover:bg-secondary hover:text-secondary focus:outline-none focus:bg-secondary focus:text-white"
>
<span
class=
"sr-only"
>
Remove badge
</span>
<svg
class=
"h-4 w-4 hover:fill-white"
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
fill=
"currentColor"
viewBox=
"0 0 16 16"
>
<svg
class=
"h-4 w-4 hover:fill-white"
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
fill=
"currentColor"
viewBox=
"0 0 16 16"
>
<path
d=
"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
>
</path>
d=
"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
>
</path>
</svg>
</a>
</div>
...
...
@@ -936,57 +827,33 @@
<p
class=
"font-semibold text-sm text-gray-500 mb-2"
>
Recent Search :
</p>
<div
id=
"not1"
class=
"p-2 border dark:border-white/10 rounded-sm flex items-center text-gray-500 mb-1 relative header-box"
>
<a
routerLink=
"/advanced/notifications"
(
click
)="
removetheModal
()"
class=
"w-full my-auto items-center flex"
>
<div
id=
"not1"
class=
"p-2 border dark:border-white/10 rounded-sm flex items-center text-gray-500 mb-1 relative header-box"
>
<a
routerLink=
"/advanced/notifications"
(
click
)="
removetheModal
()"
class=
"w-full my-auto items-center flex"
>
<span
class=
"text-sm"
>
Notifications
</span>
</a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
class=
"ltr:ml-auto rtl:mr-auto flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-gray-500 focus:outline-none header-remove-btn"
>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
class=
"ltr:ml-auto rtl:mr-auto flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-gray-500 focus:outline-none header-remove-btn"
>
<i
class=
"ri-close-line"
(
click
)="
removeRow
('
not1
')"
></i>
</a>
</div>
<div
id=
"not2"
class=
"p-2 border dark:border-white/10 rounded-sm flex items-center text-gray-500 mb-1 relative header-box"
>
<a
routerLink=
"/components/alerts"
(
click
)="
removetheModal
()"
class=
"w-full my-auto items-center flex"
>
<div
id=
"not2"
class=
"p-2 border dark:border-white/10 rounded-sm flex items-center text-gray-500 mb-1 relative header-box"
>
<a
routerLink=
"/components/alerts"
(
click
)="
removetheModal
()"
class=
"w-full my-auto items-center flex"
>
<span
class=
"text-sm"
>
Alerts
</span>
</a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
class=
"ltr:ml-auto rtl:mr-auto flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-gray-500 focus:outline-none header-remove-btn"
>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
class=
"ltr:ml-auto rtl:mr-auto flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-gray-500 focus:outline-none header-remove-btn"
>
<i
class=
"ri-close-line"
(
click
)="
removeRow
('
not2
')"
></i>
</a>
</div>
<div
id=
"not3"
class=
"p-2 border dark:border-white/10 rounded-sm flex items-center text-gray-500 relative header-box"
>
<a
routerLink=
"/tables/basictables"
(
click
)="
removetheModal
()"
class=
"w-full my-auto items-center flex"
>
<div
id=
"not3"
class=
"p-2 border dark:border-white/10 rounded-sm flex items-center text-gray-500 relative header-box"
>
<a
routerLink=
"/tables/basictables"
(
click
)="
removetheModal
()"
class=
"w-full my-auto items-center flex"
>
<span
class=
"text-sm"
>
Tables
</span>
</a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
class=
"ltr:ml-auto rtl:mr-auto flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-gray-500 focus:outline-none header-remove-btn"
>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
class=
"ltr:ml-auto rtl:mr-auto flex-shrink-0 h-4 w-4 inline-flex items-center justify-center rounded-full text-gray-500 focus:outline-none header-remove-btn"
>
<i
class=
"ri-close-line"
(
click
)="
removeRow
('
not3
')"
></i>
</a>
</div>
...
...
@@ -994,16 +861,10 @@
</div>
<div
class=
"ti-modal-footer"
>
<div
class=
"inline-flex rounded-md shadow-sm"
>
<button
type=
"button"
class=
"ti-btn-group py-1 ti-btn-soft-primary dark:border-white/10"
>
<button
type=
"button"
class=
"ti-btn-group py-1 ti-btn-soft-primary dark:border-white/10"
>
Search
</button>
<button
type=
"button"
class=
"ti-btn-group py-1 ti-btn-primary dark:border-white/10"
>
<button
type=
"button"
class=
"ti-btn-group py-1 ti-btn-primary dark:border-white/10"
>
Clear Recents
</button>
</div>
...
...
src/app/shared/services/auth.service.ts
View file @
b75eec55
...
...
@@ -10,23 +10,15 @@ import { environment } from 'src/environments/environment';
})
export
class
AuthService
{
authState
:
any
;
api
=
"/auth"
urlApi
=
environment
.
baseUrl
+
this
.
api
apiBaseUrl
=
"/auth"
;
constructor
(
private
router
:
Router
,
private
http
:
HttpClient
)
{
constructor
(
private
router
:
Router
,
private
http
:
HttpClient
)
{
}
refreshToken
():
Observable
<
{
accessToken
:
string
;
refreshToken
:
string
}
>
{
return
this
.
http
.
post
<
{
accessToken
:
string
;
refreshToken
:
string
}
>
(
`
${
this
.
urlApi
}
/refresh-token`
,
{
refreshToken
:
sessionStorage
.
getItem
(
'refreshToken'
)
}
).
pipe
(
tap
(
response
=>
{
sessionStorage
.
setItem
(
'accessToken'
,
response
.
accessToken
);
sessionStorage
.
setItem
(
'refreshToken'
,
response
.
refreshToken
);
})
);
refreshToken
(
token
:
string
)
{
return
this
.
http
.
post
<
any
>
(
this
.
apiBaseUrl
+
"/refresh-token"
,
{
"refreshToken"
:
token
});
}
get
isUserAnonymousLoggedIn
():
boolean
{
...
...
@@ -53,14 +45,15 @@ export class AuthService {
}
}
loginWithUserPass
(
username
:
string
,
password
:
string
):
Observable
<
{
accessToken
:
string
,
refreshToken
:
string
}
>
{
loginWithUserPass
(
username
:
string
,
password
:
string
):
Observable
<
{
accessToken
:
string
,
refreshToken
:
string
}
>
{
const
body
=
{
username
:
username
,
password
:
password
}
return
this
.
http
.
post
<
{
accessToken
:
string
,
refreshToken
:
string
}
>
(
this
.
urlApi
+
"/login"
,
body
)
return
this
.
http
.
post
<
{
accessToken
:
string
,
refreshToken
:
string
}
>
(
this
.
apiBaseUrl
+
"/login"
,
body
)
}
logout
(){
logout
()
{
sessionStorage
.
clear
()
localStorage
.
clear
()
this
.
router
.
navigate
([
'/auth/login'
]);
...
...
src/app/shared/services/http-request.interceptor.ts
View file @
b75eec55
...
...
@@ -9,91 +9,80 @@ import {
import
{
BehaviorSubject
,
Observable
,
of
,
throwError
}
from
'rxjs'
;
import
{
catchError
,
filter
,
switchMap
,
take
,
tap
}
from
'rxjs/operators'
;
import
{
AuthService
}
from
'./auth.service'
;
import
{
environment
}
from
'src/environments/environment'
;
import
{
TokenService
}
from
'./token.service'
;
const
TOKEN_HEADER_KEY
=
'Authorization'
;
@
Injectable
()
export
class
HttpRequestInterceptor
{
private
isRefreshing
=
false
;
private
refreshTokenSubject
:
BehaviorSubject
<
string
|
null
>
=
new
BehaviorSubject
<
string
|
null
>
(
null
);
private
responseCache
=
new
Map
<
string
,
any
>
();
// ใช้เก็บ cache ของ response
constructor
(
private
authService
:
AuthService
)
{
}
// intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// if (req.url.startsWith("./") || !sessionStorage.getItem("accessToken")) {
// return next.handle(req);
// } else {
// const authHeader = 'Bearer ' + sessionStorage.getItem("accessToken")
// const overideReq = {
// headers: req.headers.set('Authorization', authHeader),
// url: req.url,
// };
// const authReq = req.clone(overideReq);
// return next.handle(authReq).pipe(tap(response => {
// this.responseCache.set(req.urlWithParams, response)
// }));
// }
// }
private
refreshTokenSubject
:
BehaviorSubject
<
any
>
=
new
BehaviorSubject
<
any
>
(
null
);
constructor
(
private
tokenService
:
TokenService
,
private
authService
:
AuthService
)
{
}
intercept
(
req
:
HttpRequest
<
any
>
,
next
:
HttpHandler
):
Observable
<
HttpEvent
<
any
>>
{
if
(
req
.
url
.
includes
(
'/api/auth/refresh-token'
)
||
req
.
url
.
startsWith
(
'./'
)
||
!
sessionStorage
.
getItem
(
'accessToken'
))
{
if
(
req
.
url
.
startsWith
(
"./"
))
{
return
next
.
handle
(
req
);
}
else
{
let
authReq
=
req
;
const
fullUrl
=
req
.
url
.
startsWith
(
"http"
)
?
req
.
url
:
environment
.
baseUrl
+
req
.
url
;
const
token
=
this
.
tokenService
.
getToken
()
if
(
token
!=
null
&&
!
req
.
url
.
includes
(
"/refresh-token"
))
{
authReq
=
this
.
addTokenHeader
(
req
,
token
,
fullUrl
);
}
else
{
const
overideReq
=
{
url
:
fullUrl
,
};
authReq
=
req
.
clone
(
overideReq
);
}
const
authHeader
=
'Bearer '
+
sessionStorage
.
getItem
(
'accessToken'
);
const
clonedReq
=
req
.
clone
({
headers
:
req
.
headers
.
set
(
'Authorization'
,
authHeader
)
});
return
next
.
handle
(
clonedReq
).
pipe
(
tap
(
response
=>
{
this
.
responseCache
.
set
(
req
.
urlWithParams
,
response
);
// เก็บ response cache
}),
catchError
((
error
:
HttpErrorResponse
)
=>
{
if
(
error
.
status
===
401
)
{
return
this
.
handle401Error
(
req
,
next
);
return
next
.
handle
(
authReq
).
pipe
(
catchError
(
error
=>
{
if
(
error
instanceof
HttpErrorResponse
&&
error
.
status
===
403
&&
!
fullUrl
.
includes
(
"login"
))
{
return
this
.
handle403Error
(
authReq
,
next
,
fullUrl
);
}
return
throwError
(()
=>
error
);
})
);
return
throwError
(
error
);
}));
}
private
handle401Error
(
req
:
HttpRequest
<
any
>
,
next
:
HttpHandler
):
Observable
<
HttpEvent
<
any
>>
{
if
(
this
.
isRefreshing
)
{
return
this
.
refreshTokenSubject
.
pipe
(
filter
(
token
=>
token
!==
null
),
take
(
1
),
switchMap
(
token
=>
{
const
clonedReq
=
req
.
clone
({
headers
:
req
.
headers
.
set
(
'Authorization'
,
`Bearer
${
token
}
`
)
});
return
next
.
handle
(
clonedReq
);
})
);
}
else
{
}
private
handle403Error
(
request
:
HttpRequest
<
any
>
,
next
:
HttpHandler
,
fullUrl
:
string
)
{
if
(
!
this
.
isRefreshing
)
{
this
.
isRefreshing
=
true
;
this
.
refreshTokenSubject
.
next
(
null
);
return
this
.
authService
.
refreshToken
().
pipe
(
switchMap
(
newTokens
=>
{
const
token
=
this
.
tokenService
.
getRefreshToken
();
if
(
token
)
return
this
.
authService
.
refreshToken
(
token
.
replace
(
"Bearer "
,
""
)).
pipe
(
switchMap
((
token
:
any
)
=>
{
this
.
isRefreshing
=
false
;
this
.
refreshTokenSubject
.
next
(
newTokens
.
accessToken
);
this
.
tokenService
.
saveToken
(
token
.
accessToken
);
this
.
tokenService
.
saveRefreshToken
(
token
.
refreshToken
);
this
.
refreshTokenSubject
.
next
(
token
.
accessToken
);
const
clonedReq
=
req
.
clone
({
headers
:
req
.
headers
.
set
(
'Authorization'
,
`Bearer
${
newTokens
.
accessToken
}
`
)
});
return
next
.
handle
(
clonedReq
);
return
next
.
handle
(
this
.
addTokenHeader
(
request
,
token
.
accessToken
,
fullUrl
));
}),
catchError
(
err
=>
{
catchError
((
err
)
=>
{
this
.
isRefreshing
=
false
;
this
.
authService
.
logout
();
return
throwError
(()
=>
new
Error
(
'Session expired, please log in again'
));
this
.
tokenService
.
signOut
();
return
throwError
(
err
);
})
);
}
}
}
return
this
.
refreshTokenSubject
.
pipe
(
filter
(
token
=>
token
!==
null
),
take
(
1
),
switchMap
((
token
)
=>
next
.
handle
(
this
.
addTokenHeader
(
request
,
token
,
fullUrl
)))
);
}
private
addTokenHeader
(
request
:
HttpRequest
<
any
>
,
token
:
string
,
fullUrl
:
string
)
{
/* for Spring Boot back-end */
// return request.clone({ headers: request.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + token) });
/* for Node.js Express back-end */
return
request
.
clone
({
headers
:
request
.
headers
.
set
(
TOKEN_HEADER_KEY
,
token
)
,
url
:
fullUrl
});
}
}
src/app/shared/services/token.service.ts
View file @
b75eec55
import
{
Injectable
}
from
'@angular/core'
;
import
{
EmployeeModel
,
MyEmployeeModel
}
from
'../model/employee.model'
;
import
{
Router
}
from
'@angular/router'
;
import
{
UserModel
}
from
'../model/user.model'
;
const
TOKEN_KEY
=
'auth-token'
;
const
REFRESHTOKEN_KEY
=
'auth-refreshtoken'
;
const
USER_KEY
=
'auth-user'
;
const
USER_DATA_KEY
=
'auth-user-data'
;
export
class
UserLoginModel
{
public
username
:
string
=
""
;
public
accessToken
:
string
=
""
;
public
refreshToken
:
string
=
""
;
}
const
TOKEN_KEY
=
'accessToken'
;
@
Injectable
({
providedIn
:
'root'
providedIn
:
"root"
,
})
export
class
TokenService
{
constructor
(
private
router
:
Router
)
{
}
constructor
()
{
signOut
():
void
{
window
.
localStorage
.
clear
();
localStorage
.
clear
();
this
.
router
.
navigate
([
"/auth/splash"
]);
}
public
saveToken
(
token
:
string
):
void
{
window
.
localStorage
.
removeItem
(
TOKEN_KEY
);
window
.
localStorage
.
setItem
(
TOKEN_KEY
,
token
);
const
user
=
this
.
getUser
();
if
(
user
.
accessToken
)
{
this
.
saveUser
({
...
user
,
accessToken
:
token
});
}
}
public
getUser
():
any
{
const
user
=
this
.
decodeJWT
(
window
.
sessionStorage
.
getItem
(
TOKEN_KEY
)
!
)
public
saveUser
(
user
:
any
):
void
{
window
.
localStorage
.
removeItem
(
USER_KEY
);
window
.
localStorage
.
setItem
(
USER_KEY
,
JSON
.
stringify
(
user
));
}
public
getUser
():
UserLoginModel
{
const
user
=
window
.
localStorage
.
getItem
(
USER_KEY
);
if
(
user
)
{
return
user
;
return
JSON
.
parse
(
user
);
}
return
new
UserLoginModel
();
}
return
;
public
getToken
():
string
|
null
{
return
window
.
localStorage
.
getItem
(
TOKEN_KEY
);
}
decodeJWT
(
token
:
string
)
{
let
base64Url
=
token
.
split
(
'.'
)[
1
];
// ดึงส่วนที่เป็น Payload
let
base64
=
base64Url
.
replace
(
'-'
,
'+'
).
replace
(
'_'
,
'/'
);
// แก้ไข base64 ให้ถูกต้อง
let
jsonPayload
=
decodeURIComponent
(
atob
(
base64
).
split
(
''
).
map
(
function
(
c
)
{
return
'%'
+
(
'00'
+
c
.
charCodeAt
(
0
).
toString
(
16
)).
slice
(
-
2
);
}).
join
(
''
));
return
JSON
.
parse
(
jsonPayload
);
public
saveRefreshToken
(
token
:
string
):
void
{
window
.
localStorage
.
removeItem
(
REFRESHTOKEN_KEY
);
window
.
localStorage
.
setItem
(
REFRESHTOKEN_KEY
,
token
);
}
public
getRefreshToken
():
string
|
null
{
return
window
.
localStorage
.
getItem
(
REFRESHTOKEN_KEY
);
}
public
saveUserData
(
user
:
string
):
void
{
window
.
localStorage
.
removeItem
(
USER_DATA_KEY
);
window
.
localStorage
.
setItem
(
USER_DATA_KEY
,
user
);
}
public
getUserData
():
EmployeeModel
{
// return window.localStorage.getItem(USER_DATA_KEY);
const
user
=
window
.
localStorage
.
getItem
(
USER_DATA_KEY
);
if
(
user
)
{
return
new
MyEmployeeModel
(
JSON
.
parse
(
user
));
}
return
new
MyEmployeeModel
();
}
}
src/environments/environment.ts
View file @
b75eec55
...
...
@@ -3,18 +3,7 @@
// The list of file replacements can be found in `angular.json`.
export
const
environment
=
{
production
:
false
,
firebase
:
{
apiKey
:
'********************************'
,
authDomain
:
'********************************'
,
projectId
:
'********************************'
,
storageBucket
:
'********************************'
,
messagingSenderId
:
'********************************'
,
appId
:
'********************************'
,
measurementId
:
'********************************'
,
},
// baseUrl: 'https://hrplus-std.myhr.co.th/plus',
// baseUrl: 'https://192.168.10.165/plus',
baseUrl
:
' https://myskill-x.myhr.co.th/api'
,
baseUrl
:
' https://myskill-x-uat.myhr.co.th/api'
,
};
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment