dash-button-web 0.0.21 → 0.0.23

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.
@@ -108,27 +108,44 @@ export class DashButtonComponent {
108
108
  }
109
109
  }
110
110
  }
111
+ // First, check global links
112
+ // Then, check the token's organization URL
113
+ // Finally, check against dashbutton configuration: allowedGlobalDomain and whitelistedUrls
111
114
  validateAppAccessByUrl() {
112
- var _a, _b, _c, _d;
113
- const currentUrl = window.location.href;
114
- const currentOrigin = window.location.origin;
115
+ var _a, _b, _c, _d, _e, _f;
116
+ const normalizeUrl = (url) => url.replace(/\/+$/, '');
117
+ const currentUrl = normalizeUrl(window.location.href);
118
+ const currentOrigin = normalizeUrl(window.location.origin);
115
119
  const globalLinks = ((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.menu) === null || _b === void 0 ? void 0 : _b.global) === null || _c === void 0 ? void 0 : _c.links) || [];
116
- // Check Global Links
120
+ const allowedGlobalDomain = ((_d = this.config) === null || _d === void 0 ? void 0 : _d.allowedGlobalDomain) || '';
121
+ const whitelistedUrls = ((_e = this.config) === null || _e === void 0 ? void 0 : _e.whitelistedUrls) || '';
122
+ // First, check global links
117
123
  const matchGlobal = globalLinks.some(link => {
118
124
  try {
119
- const linkOrigin = new URL(link.url).origin;
125
+ const linkOrigin = normalizeUrl(new URL(link.url).origin);
120
126
  return currentOrigin === linkOrigin;
121
127
  }
122
128
  catch (_a) {
123
129
  return false;
124
130
  }
125
131
  });
126
- // Check Token organizationUrl
127
- const tokenParsed = (_d = this.keycloak) === null || _d === void 0 ? void 0 : _d.tokenParsed;
132
+ // Then check the token organization URL
133
+ const tokenParsed = (_f = this.keycloak) === null || _f === void 0 ? void 0 : _f.tokenParsed;
128
134
  const allowedOrg = tokenParsed === null || tokenParsed === void 0 ? void 0 : tokenParsed.organizationUrl;
129
- const matchOrganization = allowedOrg && currentUrl.includes(allowedOrg);
130
- // global and org url validations
131
- const isAllowed = matchGlobal || matchOrganization;
135
+ const matchOrganization = allowedOrg && currentUrl.includes(normalizeUrl(allowedOrg));
136
+ // Check allowedGlobalDomain (single domain)
137
+ const matchAllowedDomain = allowedGlobalDomain &&
138
+ currentOrigin.includes(normalizeUrl(allowedGlobalDomain));
139
+ // Check whitelistedUrls (comma-separated string)
140
+ const whitelistedArray = whitelistedUrls
141
+ ? whitelistedUrls.split(',').map(url => normalizeUrl(url.trim()))
142
+ : [];
143
+ const matchWhitelisted = whitelistedArray.some(url => currentUrl.includes(url));
144
+ // Final validation
145
+ const isAllowed = matchGlobal ||
146
+ matchOrganization ||
147
+ matchAllowedDomain ||
148
+ matchWhitelisted;
132
149
  this.isRestricted = !isAllowed;
133
150
  }
134
151
  login() {
@@ -150,7 +167,7 @@ export class DashButtonComponent {
150
167
  }
151
168
  render() {
152
169
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
153
- return h("div", { key: 'd186318626a3fbd1d011d3532559901d1c36859e' }, h("div", { key: 'a5887ec423aabb35ca7988169cfa7a9f0bd588e6' }, (() => {
170
+ return h("div", { key: '370786aa472fafd2bf9509a18bd62c87ac2893c7' }, h("div", { key: 'c0b091b19e7981ecc48e95c03c8d91e77e7a88df' }, (() => {
154
171
  var _a, _b, _c, _d, _e, _f;
155
172
  // GLOBAL LOADING SPINNER
156
173
  if (this.isLoading) {
@@ -177,7 +194,7 @@ export class DashButtonComponent {
177
194
  else {
178
195
  return (h("button", { style: { background: this.primaryColor != undefined ? this.primaryColor : "" }, onClick: this.login.bind(this), id: "login-btn", type: "button", class: "button" }, h("span", { style: { color: this.accentColor != undefined ? this.accentColor : "" }, class: "button-text" }, "Login")));
179
196
  }
180
- })()), h("div", { key: '1ad6675f4e190df28410c54f7ad9f097578e0403', id: "appListModal", class: "modal" }, h("div", { key: '655f51c1d18372eca86610750d1ac3c8e1eeeefa', class: "modal-content" }, h("span", { key: 'bb850ddc02afdbbc04b5fbc6258d6ab2b1e92bfb', onClick: this.closeModal.bind(this), class: "close" }, "\u00D7"), h("div", { key: '4fdec67f888e554e1c8a3328ae2b55fb1a0fea4d', class: "box" }, h("input", { type: "radio", class: "tab-toggle", name: "tab-toggle", id: "tab1", checked: true }), h("ul", { key: '4317ec4e90f682b549aea49971d12426aaa5c0ef', class: "tab-list" }, h("li", { class: "tab-item" }, h("label", { class: "tab-trigger", htmlFor: "tab1" }, h("i", { class: "fa-solid fa-table-list menu-bar-icons" }), " ", this.config.menu.local.name))), h("div", { key: '8f1b8e0ec034d45a9c04776b90afcbd3cd9fea3e', class: "tab-container" }, h("div", { key: 'e59e81838b0c2fa419314503ab0c2d56143496cb', class: "tab-content" }, h("div", { key: 'f393c5497bfeddae25469d2d4475f9aacdf13629', class: "modal-body" }, !((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.menu) === null || _b === void 0 ? void 0 : _b.local) === null || _c === void 0 ? void 0 : _c.enableCustomLocalMenu) ? (
197
+ })()), h("div", { key: 'f98304920ef08f842700c5d26fe62a51cbbade96', id: "appListModal", class: "modal" }, h("div", { key: '2c4024b83e3cd0d638f4482d0e8907687ac12dd0', class: "modal-content" }, h("span", { key: '42a44145a7d7c33cae95344f02229d8163cc9607', onClick: this.closeModal.bind(this), class: "close" }, "\u00D7"), h("div", { key: 'ec3dbe646c76818ee90ec28e19671880670a2754', class: "box" }, h("input", { type: "radio", class: "tab-toggle", name: "tab-toggle", id: "tab1", checked: true }), h("ul", { key: 'c7dbcfd1b183bc6845cab0f17ef6f81dee30867f', class: "tab-list" }, h("li", { class: "tab-item" }, h("label", { class: "tab-trigger", htmlFor: "tab1" }, h("i", { class: "fa-solid fa-table-list menu-bar-icons" }), " ", this.config.menu.local.name))), h("div", { key: 'dc58df8e838c8babe3c679c6f1c498e286448cf3', class: "tab-container" }, h("div", { key: '486acbf570543ef0a92bd919e1c9c7973c87b3a7', class: "tab-content" }, h("div", { key: 'c9e093ce8d745097147405749e88ba35b1fc8679', class: "modal-body" }, !((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.menu) === null || _b === void 0 ? void 0 : _b.local) === null || _c === void 0 ? void 0 : _c.enableCustomLocalMenu) ? (
181
198
  // <div>{this.localMenuLinks}</div>
182
199
  (_d = this.localMenuLinks) === null || _d === void 0 ? void 0 : _d.map((app, index) => {
183
200
  const isDisabled = !app.url;
@@ -185,7 +202,7 @@ export class DashButtonComponent {
185
202
  })) : ((_e = this.config.menu.local.links) === null || _e === void 0 ? void 0 : _e.map((app, index) => (h("a", { key: index, class: "external-app-link", target: "_blank", rel: "noopener noreferrer", href: app.url }, h("div", { class: "modal-app" }, h("div", null, app.name)))))), !this.organizationUrl ? (h("div", null, h("h3", { class: "gray-text" }, "Organization Domain URL not set"), h("p", { class: "gray-text" }, "Please set your Organization Domain URL on the Portal profile page."))) : (((!((_h = (_g = (_f = this.config) === null || _f === void 0 ? void 0 : _f.menu) === null || _g === void 0 ? void 0 : _g.local) === null || _h === void 0 ? void 0 : _h.enableCustomLocalMenu) &&
186
203
  ((_k = (_j = this.localMenuLinks) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : 0) === 0) ||
187
204
  (((_o = (_m = (_l = this.config) === null || _l === void 0 ? void 0 : _l.menu) === null || _m === void 0 ? void 0 : _m.local) === null || _o === void 0 ? void 0 : _o.enableCustomLocalMenu) &&
188
- ((_t = (_s = (_r = (_q = (_p = this.config) === null || _p === void 0 ? void 0 : _p.menu) === null || _q === void 0 ? void 0 : _q.local) === null || _r === void 0 ? void 0 : _r.links) === null || _s === void 0 ? void 0 : _s.length) !== null && _t !== void 0 ? _t : 0) === 0)) && (h("div", null, h("h3", { class: "gray-text" }, "No installed ", ((_w = (_v = (_u = this.config) === null || _u === void 0 ? void 0 : _u.menu) === null || _v === void 0 ? void 0 : _v.local) === null || _w === void 0 ? void 0 : _w.name) || "menu", " found."), h("p", { class: "gray-text" }, "Please contact administration.")))))))))), h("div", { key: 'c47c1a2e57cbd3d42fcb19d559343a7104e092c0', id: "appPermissionErrorModal", class: "modal" }, h("div", { key: 'cd8a0b1837afc3089bda1bd4d9e7ec0c2a7c3f45', class: "modal-content" }, h("img", { key: 'e21aa2b61cbedff394e4cbbc6993fd06b3c3906e', src: "data:image/png;base64,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" }), h("h2", { key: '0ea76a87518b2a0c2a171bc0f40cb4767f6683e9', class: "green-text margin-b" }, "You don't have permission to access this application."), h("h3", { key: '1dc9d8f8f2ef3a34bf8cb887679c574a59fe5a75', class: "green-text" }, "Please contact the administration."), (this.config.defaultLink.url && this.showUnauthorizedModal) ?
205
+ ((_t = (_s = (_r = (_q = (_p = this.config) === null || _p === void 0 ? void 0 : _p.menu) === null || _q === void 0 ? void 0 : _q.local) === null || _r === void 0 ? void 0 : _r.links) === null || _s === void 0 ? void 0 : _s.length) !== null && _t !== void 0 ? _t : 0) === 0)) && (h("div", null, h("h3", { class: "gray-text" }, "No installed ", ((_w = (_v = (_u = this.config) === null || _u === void 0 ? void 0 : _u.menu) === null || _v === void 0 ? void 0 : _v.local) === null || _w === void 0 ? void 0 : _w.name) || "menu", " found."), h("p", { class: "gray-text" }, "Please contact administration.")))))))))), h("div", { key: '349c7ff69d94c988a278677f497c0a9fef85c59c', id: "appPermissionErrorModal", class: "modal" }, h("div", { key: '788004858cf2f55f4e79cce0c023895274bab9ab', class: "modal-content" }, h("img", { key: '57ea43b0a21086eeaebe0585b9501967099ec999', src: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGD0lEQVR4nO2cbU8TWRTH/W5WEAmF4nNiieFFoeBjYhQUWzUWYkpbDfGFCR9CoolvQF9aWgG3kMCG8LACC1ikuCuUh7bH/M/MmW131S2ZqTDjPcmkdub2tvPj3HP/55yJR44oU6ZMmTJlyg7YOsL9pI7+shkogGFzDqMAhhVAOsiQozwwrACS8sCwfXd+tYTDCiApDwwf/FJUSzisAJKjNhFlPzYF0KQpgCZNATRpCqBJUwBNmgJo0hRAk6YAmjQF0KkAs4uLtPz8OU2HQpRqaaFkQwPFq6v5SHo8fA7XVgYGKLu0dGC/81ABLORylB4cpInLl+nt0aP7OiauXKH00BAV8vlfE2AmkaCxpiYDSKK6mqaammjx+nX6FAzS348e0VYkwgf+jXO4Nun18lj53PuLF2kjmfx1AOa3t2mmt9cAkDxxghauXaPN3l7KxmJlHRgLmKNutzHPTCTCczsa4G4mQ6nWVr7h4WPHaL6trQTc+r17NOf30/iZMzTmdtNwVRWPA2Scm/H56FMgQNlolMfDO/9ob+cxmDPl99PuxoYzAe5mMrzcxOvWAALgolFauXmTxurry45/gPvnjRsG+LW7d3lOWdKVhHggAPPb24bnvW9ooL96evjGP4dC9NvJkwaY0fPnaa6vjzLJJG19+ED5bJY/u5NOUyYep/lnz2jk3Ll/4p/Hw/B4ru5unls8Mb+z4xyAM3rMg5cIvHRXFyVqavg8oKy+elXWjooxqy9f0luXy5gTm4xAFE+cjcWcATCTSGgxr6rKWLaAF9fj1u+BAOW2tsqeL7+7S5OdnRq8mhpaf/CA5xSI8EiJiRsjI/YGWMjlDKmCDUOWrXje3NOnRIWCaXh45biqL+f59nYjHlqtE38qwPTgoLHMeLeNRo2YB8+zEp7ExK1olI+Rujo+t/b6tX0BTugZBnQebha7rcQ8K5Ytw9O9WWKi7M7QiZKx2BJgdnHRyDDE+0SqYMOwEt7k7dvaxqJLHHwXvpMzFpeLtpeX7QdwZWCAbwjpmYhkkSrlxqVy4WEc4q1IHBbbsRhNXrjA71devLAfwOlQiH88lhJuBhkGbxx9fZbDE4NO5LTO5+OxCB14P93dbT+AKZ9P84ZgkG8GqRjeQ9ZUAh4MYhvXxs+e5fHwRBbWra32A5j0ePjHf9H1mST+2YWFisCDba+u8vV3tbWGNuT3jY32AxjXS06QFLgZKUH9aPct7O3RVFfXf+BlHj6kZG2tBq+j47tpGs5LoYKrNpGI9v74cfsDHNazg+/dvFl4sNzmprHz2x5g8l9LWMTuzsePli7bYkMBgqVMfb39l3CqpeXbm0g8XhF439xEgkGjOmN7GTOjA4XU2Be8zs6y4MFmnzzRpJLfXypjenrsK6Qnvd4SSQGxCyFtNbxiIb1+/74mpL1e+wrp7NISp1ElqZwuZZB2WQkPZqRyevz7Eg5zCc22qVxxMUGWMRL94sTfKnjYfd+dPq15261bpcWEq1fJvuWsoSEt/3W7tRZlNMolJylxWQEPJTGRP6lTpwz5YpSz3ryxcUE1nzcaSeieFTeArIKH3Fq8GSX9koJqc7O9C6owNL0lO5CKsZTfzS7bqTt3+LPxornxKu2Cz6Oj5IymUkTLCOB54iWAKOIaMRE7JXbS/zOMwYYhMQ9/gOLOnPxBZh8/dlhb06+Vs9B6FIi4cYmJInGgEyGIkbHgc8idkWHgHHRecVsTMU/mwuuY3tYcv3TJWW1NGJrdJY113WtkdxaJU84BqSK7rRFXdc/Dd+w5rbFeDHG8rc2IiQj2UmwQsY1iKFIxlKSg46AjARfnkGGISOZHO6JRnkNiHjzPsY92iGFZoultLNu6OtZs+3m4CCIZnxGpIjGvUsv2UAEUQ9NblrSUoNDDQP4KT+TH2/QWJT/eFgjwNaRnnGHI4x3NzRXZbQ89QBg0GsQ2Wo+SnZR1uFycYbBI3kdv2XEAiw35KqQMGkDoYaCeaDzi29jIuziuYYyVua1jANrFFECTpgCaNAXQpCmAJk0BNGkKoElTACsNUB39ZTFQAMMW/78xypQpU6ZMmbIjP9e+AkAlsBlIjsPOAAAAAElFTkSuQmCC" }), h("h2", { key: 'c7663fb1503a0f0713350ac2ff2e52708c5425f9', class: "green-text margin-b" }, "You don't have permission to access this application."), h("h3", { key: '925b21fffdee5437664f690254821ffa63d736cb', class: "green-text" }, "Please contact the administration."), (this.config.defaultLink.url && this.showUnauthorizedModal) ?
189
206
  h("div", null, h("h4", { class: "gray-text" }, "You will be automatically redirected to the portal."), h("div", { id: "countdown" }, h("div", { id: "countdown-number" }), h("svg", null, h("circle", { r: "18", cx: "20", cy: "20" }))))
190
207
  : h("div", null))));
191
208
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dash-button.js","sourceRoot":"","sources":["../../../src/components/my-component/dash-button.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, State, h, Element } from '@stencil/core';\nimport Keycloak from \"keycloak-js\";\nimport { toSvg } from \"jdenticon\";\nimport { AppConfig, configService } from '../../services/config';\nimport { MenuLink, menuService } from '../../services/menu';\n\n@Component({\n tag: 'dash-button',\n styleUrl: 'dash-button.css',\n shadow: true,\n})\nexport class DashButtonComponent {\n\n @Element() el;\n \n @Prop() showPostLoginText: boolean = false;\n @Prop() silentCheckSso: boolean = false;\n @Prop() redirectUri: string;\n @Prop() authMethod: string = \"check-sso\";\n\n @Prop() portalApiUrl: string = \"\";\n @Prop() plmUrl: string = \"https://productlicensemanager-zdzw.cloud.zdzw-project.com\";\n @Prop() showUnauthorizedModal: boolean = false;\n\n @Prop() primaryColor: string = \"\";\n @Prop() accentColor: string = \"\";\n\n @State() keycloak: any = null;\n\n @State() isAuth = false;\n @State() givenUserName: string = \"\";\n @State() silentCheckSsoRedirectUri: string = window.location.origin + '/assets/verificar-sso.html';\n\n @State() appList = []\n \n @State() avatarSvg = toSvg(\"init-avatar\", 40);\n\n @State() isLoading: boolean = false;\n @State() config: AppConfig;\n\n @State() localMenuLinks: MenuLink[];\n @State() organizationUrl: any;\n\n @State() isRestricted: boolean = false;\n\n async componentWillLoad() {\n\n // Fetch config from API\n this.config = await configService.fetchConfig(this.portalApiUrl);\n console.log(this.config)\n\n if (!this.config) return; // prevent Keycloak init if fetch failed\n\n // render will show spinner\n if(this.config?.loading?.isLoading) {\n this.isLoading = true;\n setTimeout(() => {\n this.isLoading = false;\n }, this.config?.loading?.duration);\n }\n\n // Initialize Keycloak\n this.keycloak = new Keycloak({\n url: this.config.keycloak.url,\n realm: this.config.keycloak.realm,\n clientId: this.config.keycloak.clientId\n });\n\n //\n // Init Keycloak\n //\n this.initKeycloak().then(() => {\n // Check if the user is authenticated\n if(this.isAuth) {\n // Get organization URL and load local menu items\n // If the user has not set an organization URL, they can configure it in the Portal profile page\n this.loadOrganizationUrlAndLinks();\n \n // Validate user access permission for the application. \n // If unauthorized, display the restricted access modal.\n this.validateAppAccessByUrl()\n\n }\n })\n }\n\n async initKeycloak() {\n // Remove the initiation time permission localstorage object\n localStorage.removeItem(\"ZDZW_app_permission\");\n\n await this.keycloak.init(\n {\n onLoad: this.authMethod,\n checkLoginIframe: false,\n silentCheckSsoRedirectUri: this.silentCheckSso ? this.silentCheckSsoRedirectUri : '',\n }).then(res => {\n if(res) {\n this.isAuth = true\n localStorage.setItem(\"keycloak\", JSON.stringify(this.keycloak));\n // document.cookie = \"DASH_BTN=\" + JSON.parse(localStorage.getItem('keycloak')).token;\n document.cookie = this.config.cookieName +\"=\" + JSON.parse(localStorage.getItem('keycloak')).token;\n\n // Set userName\n this.givenUserName = JSON.parse(localStorage.getItem('keycloak')).idTokenParsed.preferred_username\n\n // Set user avatar\n this.avatarSvg = toSvg(JSON.parse(localStorage.getItem('keycloak')).idTokenParsed.sub, 40);\n } \n });\n }\n\n async loadOrganizationUrlAndLinks() {\n // Read org URL safely\n try {\n const kc = JSON.parse(localStorage.getItem(\"keycloak\") || \"{}\");\n this.organizationUrl = kc?.idTokenParsed?.organizationUrl || null;\n } catch {\n this.organizationUrl = null;\n }\n\n // If no organization, do nothing\n if (!this.organizationUrl) return;\n\n // If config or menu not ready, skip\n if (!this.config?.menu?.local) return;\n\n // Only load when custom menu is NOT enabled\n if (!this.config.menu.local.enableCustomLocalMenu) {\n try {\n this.localMenuLinks = await menuService.getMenuLinks(\n this.organizationUrl\n );\n } catch (e) {\n console.error(\"Failed to load local menu\", e);\n this.localMenuLinks = [];\n }\n }\n }\n\n validateAppAccessByUrl() {\n const currentUrl = window.location.href;\n const currentOrigin = window.location.origin;\n\n const globalLinks = this.config?.menu?.global?.links || [];\n\n // Check Global Links\n const matchGlobal = globalLinks.some(link => {\n try {\n const linkOrigin = new URL(link.url).origin;\n return currentOrigin === linkOrigin;\n } catch {\n return false;\n }\n });\n\n // Check Token organizationUrl\n const tokenParsed = this.keycloak?.tokenParsed;\n const allowedOrg = tokenParsed?.organizationUrl;\n\n const matchOrganization =\n allowedOrg && currentUrl.includes(allowedOrg);\n\n // global and org url validations\n const isAllowed = matchGlobal || matchOrganization;\n\n this.isRestricted = !isAllowed;\n }\n\n login() { \n this.keycloak.login() \n }\n\n logout() {\n localStorage.removeItem(\"keycloak\");\n // document.cookie = \"DASH_BTN=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;\";\n document.cookie = this.config.cookieName + \"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;\";\n this.keycloak.logout() \n } \n\n showModal() {\n const appModal = this.el.shadowRoot.querySelector('#appListModal');\n appModal.style.display = \"block\";\n }\n\n closeModal() {\n const appModal = this.el.shadowRoot.querySelector('#appListModal');\n appModal.style.display = \"none\";\n }\n\n render() {\n return <div>\n <div>\n {\n (() => {\n // GLOBAL LOADING SPINNER\n if (this.isLoading) {\n return (\n <a id=\"login-btn\" class=\"button button-link\">\n <div class=\"lds-ring\"><div></div><div></div><div></div><div></div></div>\n </a>\n );\n }\n\n if (this.isRestricted) {\n return (\n <div class=\"restricted-overlay\">\n <div class=\"restricted-card\">\n\n <div class=\"restricted-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n\n <h2>Access Restricted</h2>\n <p class=\"restricted-message\">\n You do not have permission to access this application.\n Please contact your administrator if you believe this is an error.\n </p>\n\n {/* Global Applications */}\n {this.config?.menu?.global?.links?.length > 0 && (\n <div class=\"restricted-links\">\n <h4>Publicly Available Modules</h4>\n <div class=\"link-grid\">\n {this.config.menu.global.links.map(item => (\n <a href={item.url} target=\"_blank\" class=\"restricted-link\">\n <i class={item.icon}></i>\n <span>{item.name}</span>\n </a>\n ))}\n </div>\n </div>\n )}\n\n {/* Actions */}\n <div class=\"restricted-actions\">\n {this.config?.defaultLink?.url && (\n <a\n href={this.config.defaultLink.url}\n target=\"_blank\"\n class=\"btn-primary\">\n Go to Portal\n </a>\n )}\n <button class=\"btn-danger\" onClick={this.logout.bind(this)}>\n Logout\n </button>\n </div>\n\n </div>\n </div>\n );\n }\n\n if(this.isAuth && this.showPostLoginText) { \n return (\n <a style={{background: this.primaryColor != undefined? this.primaryColor : \"\"}} href={this.redirectUri} id=\"login-btn\" class=\"button button-link\">\n <span style={{color: this.accentColor != undefined? this.accentColor : \"\"}} class=\"button-text button-text-full-width\">Go to Dashboard</span>\n </a>\n )\n } else if (this.isAuth) {\n return (\n <div id=\"profile-btn\" class=\"dropdown\">\n <button style={{background: this.primaryColor != undefined? this.primaryColor : \"\"}} type=\"button\" class=\"button\">\n <span class=\"button-profile\">\n {JSON.parse(localStorage.getItem('keycloak')).idTokenParsed.imageUrl ?\n <img class=\"profile-image\" src=\"https://s-damith.github.io/test-avatar/images/e24da9c5-0b1f-46fa-82cd-7c711c77b5c7.png\"/>\n :\n <div innerHTML={this.avatarSvg}/>\n }\n </span>\n <span style={{color: this.accentColor != undefined? this.accentColor : \"\"}} id=\"given-name\" class=\"button-text\">{this.givenUserName}</span>\n <div class=\"button-icon\">\n {(this.config.menuViewType == \"grid\") ? <i class=\"fa-solid fa-grip-vertical\"></i> : <i class=\"fa-solid fa-bars\"></i>} \n </div>\n </button>\n <div class=\"dropdown-content\">\n <div class=\"dropdown-user-profile\">\n <div class=\"username\">@{this.givenUserName}</div>\n <div class=\"first-last-name\">{JSON.parse(localStorage.getItem('keycloak')).idTokenParsed.name}</div>\n </div>\n\n\n { (this.config.menuViewType == \"grid\") ? (\n <div>\n <div class=\"grid-view-menu\">\n {\n this.config.menu.global.links.map(item => {\n return (\n <a href={item.url} target='_blank' class=\"grid-view-link\">\n <i class={item.icon + \" fa-2x\"}></i> \n <div class=\"grid-view-link-text\">{item.name}</div>\n </a>\n )\n })\n }\n </div>\n \n {/* show divider */}\n {this.config.menu.global.links.length != 0 && <hr class=\"solid\"></hr>}\n\n <div class=\"grid-view-menu\" style={this.config.menu.global.links.length == 0 && {\"margin-bottom\": \"12px\"}}>\n <a onClick={this.showModal.bind(this)} class=\"grid-view-link\">\n <i class=\"fa-regular fa-window-restore fa-2x\"></i> \n <div class=\"grid-view-link-text\">Modules</div>\n </a>\n <a href={this.config.defaultLink.url} target='_blank' class=\"grid-view-link\">\n <i class=\"fa-solid fa-globe fa-2x\"></i>\n <div class=\"grid-view-link-text\">{this.config.defaultLink.name}</div>\n </a>\n <a onClick={this.logout.bind(this)} class=\"grid-view-link\">\n <i class=\"fa-solid fa-right-from-bracket fa-2x\"></i>\n <div class=\"grid-view-link-text\">Logout</div>\n </a>\n \n </div>\n\n </div>\n ) : (\n\n // List View\n <div class=\"dropdown-content-link\">\n {\n this.config.menu.global.links.map(item => {\n return (\n <a href={item.url} target='_blank' id=\"applications-btn\">\n <i class={item.icon + \" menu-bar-icons\"}></i> \n {item.name}\n </a>\n )\n })\n }\n <a onClick={this.showModal.bind(this)} id=\"applications-btn\"><i class=\"fa-regular fa-window-restore menu-bar-icons\"></i>Modules</a>\n <a href={this.config.defaultLink.url} target='_blank' id=\"applications-btn\"><i class=\"fa-solid fa-globe menu-bar-icons\"></i>{this.config.defaultLink.name}</a>\n <a onClick={this.logout.bind(this)} id=\"logout-btn\"><i class=\"fa-solid fa-right-from-bracket menu-bar-icons\"></i>Logout</a>\n </div>\n\n )}\n </div>\n </div>\n )\n } else {\n return (\n <button style={{background: this.primaryColor != undefined? this.primaryColor : \"\"}} onClick={this.login.bind(this)} id=\"login-btn\" type=\"button\" class=\"button\">\n <span style={{color: this.accentColor != undefined? this.accentColor : \"\"}} class=\"button-text\">Login</span>\n </button>\n )\n }\n })() \n } \n </div>\n \n <div id=\"appListModal\" class=\"modal\">\n \n <div class=\"modal-content\">\n <span onClick={this.closeModal.bind(this)} class=\"close\">&times;</span>\n\n <div class=\"box\">\n {<input type=\"radio\" class=\"tab-toggle\" name=\"tab-toggle\" id=\"tab1\" checked/>}\n {/* {(this.menuLinkList.length != 0) && <input type=\"radio\" class=\"tab-toggle\" name=\"tab-toggle\" id=\"tab2\" checked={this.disableApplicationTab}/>} */}\n\n <ul class=\"tab-list\">\n {<li class=\"tab-item\">\n <label class=\"tab-trigger\" htmlFor=\"tab1\"><i class=\"fa-solid fa-table-list menu-bar-icons\"></i> {this.config.menu.local.name}</label>\n </li>}\n {/* {(this.menuLinkList.length != 0) && <li class=\"tab-item\">\n <label class=\"tab-trigger\" htmlFor=\"tab2\"><i class=\"fa-solid fa-link menu-bar-icons\"></i> {this.otherLinkDisplayName}</label>\n </li>} */}\n </ul>\n \n <div class=\"tab-container\">\n <div class=\"tab-content\">\n <div class=\"modal-body\">\n\n {!this.config?.menu?.local?.enableCustomLocalMenu ? (\n // <div>{this.localMenuLinks}</div>\n this.localMenuLinks?.map((app, index) => {\n const isDisabled = !app.url;\n\n return ( \n <a\n key={index}\n class=\"external-app-link\"\n href={isDisabled ? undefined : app.url}\n target={isDisabled ? undefined : \"_blank\"}\n rel={isDisabled ? undefined : \"noopener noreferrer\"}\n onClick={isDisabled ? (e) => e.preventDefault() : undefined}\n >\n <div class=\"modal-app\">\n <div>{app.name}</div>\n </div>\n </a>\n )\n })\n ) : (\n this.config.menu.local.links?.map((app, index) => (\n <a\n key={index}\n class=\"external-app-link\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n href={app.url}\n >\n <div class=\"modal-app\">\n <div>{app.name}</div>\n </div>\n </a>\n ))\n )}\n\n {/* Error messages */}\n {!this.organizationUrl ? (\n <div>\n <h3 class=\"gray-text\">\n Organization Domain URL not set\n </h3>\n <p class=\"gray-text\">Please set your Organization Domain URL on the Portal profile page.</p>\n </div>\n ) : (\n (\n (!this.config?.menu?.local?.enableCustomLocalMenu &&\n (this.localMenuLinks?.length ?? 0) === 0) ||\n (this.config?.menu?.local?.enableCustomLocalMenu &&\n (this.config?.menu?.local?.links?.length ?? 0) === 0)\n ) && (\n <div>\n <h3 class=\"gray-text\">\n No installed {this.config?.menu?.local?.name || \"menu\"} found.\n </h3>\n <p class=\"gray-text\">Please contact administration.</p>\n </div>\n )\n )}\n\n </div>\n </div> \n {/* <div class=\"tab-content\">\n <div class=\"modal-body\">\n {\n this.menuLinkList.map(link => {\n return (\n <a class=\"external-app-link\" target='_blank' href={link.url}>\n <div class=\"modal-app\">\n <div>{link.name}</div>\n </div>\n </a>\n )\n })\n }\n </div>\n </div> */}\n </div>\n </div>\n\n </div>\n \n </div>\n\n <div id=\"appPermissionErrorModal\" class=\"modal\">\n <div class=\"modal-content\">\n <img src=\"data:image/png;base64,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\"/>\n <h2 class=\"green-text margin-b\">You don't have permission to access this application.</h2>\n <h3 class=\"green-text\">Please contact the administration.</h3>\n \n {(this.config.defaultLink.url && this.showUnauthorizedModal) ? \n <div>\n <h4 class=\"gray-text\">You will be automatically redirected to the portal.</h4>\n <div id=\"countdown\">\n <div id=\"countdown-number\"></div>\n <svg>\n <circle r=\"18\" cx=\"20\" cy=\"20\"></circle>\n </svg>\n </div>\n </div>\n : <div></div>\n }\n </div>\n </div>\n\n </div>;\n }\n}\n"]}
1
+ {"version":3,"file":"dash-button.js","sourceRoot":"","sources":["../../../src/components/my-component/dash-button.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, State, h, Element } from '@stencil/core';\nimport Keycloak from \"keycloak-js\";\nimport { toSvg } from \"jdenticon\";\nimport { AppConfig, configService } from '../../services/config';\nimport { MenuLink, menuService } from '../../services/menu';\n\n@Component({\n tag: 'dash-button',\n styleUrl: 'dash-button.css',\n shadow: true,\n})\nexport class DashButtonComponent {\n\n @Element() el;\n \n @Prop() showPostLoginText: boolean = false;\n @Prop() silentCheckSso: boolean = false;\n @Prop() redirectUri: string;\n @Prop() authMethod: string = \"check-sso\";\n\n @Prop() portalApiUrl: string = \"\";\n @Prop() plmUrl: string = \"https://productlicensemanager-zdzw.cloud.zdzw-project.com\";\n @Prop() showUnauthorizedModal: boolean = false;\n\n @Prop() primaryColor: string = \"\";\n @Prop() accentColor: string = \"\";\n\n @State() keycloak: any = null;\n\n @State() isAuth = false;\n @State() givenUserName: string = \"\";\n @State() silentCheckSsoRedirectUri: string = window.location.origin + '/assets/verificar-sso.html';\n\n @State() appList = []\n \n @State() avatarSvg = toSvg(\"init-avatar\", 40);\n\n @State() isLoading: boolean = false;\n @State() config: AppConfig;\n\n @State() localMenuLinks: MenuLink[];\n @State() organizationUrl: any;\n\n @State() isRestricted: boolean = false;\n\n async componentWillLoad() {\n\n // Fetch config from API\n this.config = await configService.fetchConfig(this.portalApiUrl);\n console.log(this.config)\n\n if (!this.config) return; // prevent Keycloak init if fetch failed\n\n // render will show spinner\n if(this.config?.loading?.isLoading) {\n this.isLoading = true;\n setTimeout(() => {\n this.isLoading = false;\n }, this.config?.loading?.duration);\n }\n\n // Initialize Keycloak\n this.keycloak = new Keycloak({\n url: this.config.keycloak.url,\n realm: this.config.keycloak.realm,\n clientId: this.config.keycloak.clientId\n });\n\n //\n // Init Keycloak\n //\n this.initKeycloak().then(() => {\n // Check if the user is authenticated\n if(this.isAuth) {\n // Get organization URL and load local menu items\n // If the user has not set an organization URL, they can configure it in the Portal profile page\n this.loadOrganizationUrlAndLinks();\n \n // Validate user access permission for the application. \n // If unauthorized, display the restricted access modal.\n this.validateAppAccessByUrl()\n\n }\n })\n }\n\n async initKeycloak() {\n // Remove the initiation time permission localstorage object\n localStorage.removeItem(\"ZDZW_app_permission\");\n\n await this.keycloak.init(\n {\n onLoad: this.authMethod,\n checkLoginIframe: false,\n silentCheckSsoRedirectUri: this.silentCheckSso ? this.silentCheckSsoRedirectUri : '',\n }).then(res => {\n if(res) {\n this.isAuth = true\n localStorage.setItem(\"keycloak\", JSON.stringify(this.keycloak));\n // document.cookie = \"DASH_BTN=\" + JSON.parse(localStorage.getItem('keycloak')).token;\n document.cookie = this.config.cookieName +\"=\" + JSON.parse(localStorage.getItem('keycloak')).token;\n\n // Set userName\n this.givenUserName = JSON.parse(localStorage.getItem('keycloak')).idTokenParsed.preferred_username\n\n // Set user avatar\n this.avatarSvg = toSvg(JSON.parse(localStorage.getItem('keycloak')).idTokenParsed.sub, 40);\n } \n });\n }\n\n async loadOrganizationUrlAndLinks() {\n // Read org URL safely\n try {\n const kc = JSON.parse(localStorage.getItem(\"keycloak\") || \"{}\");\n this.organizationUrl = kc?.idTokenParsed?.organizationUrl || null;\n } catch {\n this.organizationUrl = null;\n }\n\n // If no organization, do nothing\n if (!this.organizationUrl) return;\n\n // If config or menu not ready, skip\n if (!this.config?.menu?.local) return;\n\n // Only load when custom menu is NOT enabled\n if (!this.config.menu.local.enableCustomLocalMenu) {\n try {\n this.localMenuLinks = await menuService.getMenuLinks(\n this.organizationUrl\n );\n } catch (e) {\n console.error(\"Failed to load local menu\", e);\n this.localMenuLinks = [];\n }\n }\n }\n\n // First, check global links\n // Then, check the token's organization URL\n // Finally, check against dashbutton configuration: allowedGlobalDomain and whitelistedUrls\n validateAppAccessByUrl() {\n\n const normalizeUrl = (url: string) => url.replace(/\\/+$/, '');\n\n const currentUrl = normalizeUrl(window.location.href);\n const currentOrigin = normalizeUrl(window.location.origin);\n\n const globalLinks = this.config?.menu?.global?.links || [];\n const allowedGlobalDomain = this.config?.allowedGlobalDomain || '';\n const whitelistedUrls = this.config?.whitelistedUrls || '';\n\n // First, check global links\n const matchGlobal = globalLinks.some(link => {\n try {\n const linkOrigin = normalizeUrl(new URL(link.url).origin);\n return currentOrigin === linkOrigin;\n } catch {\n return false;\n }\n });\n\n // Then check the token organization URL\n const tokenParsed = this.keycloak?.tokenParsed;\n const allowedOrg = tokenParsed?.organizationUrl;\n const matchOrganization =\n allowedOrg && currentUrl.includes(normalizeUrl(allowedOrg));\n\n // Check allowedGlobalDomain (single domain)\n const matchAllowedDomain =\n allowedGlobalDomain &&\n currentOrigin.includes(normalizeUrl(allowedGlobalDomain));\n\n // Check whitelistedUrls (comma-separated string)\n const whitelistedArray = whitelistedUrls\n ? whitelistedUrls.split(',').map(url => normalizeUrl(url.trim()))\n : [];\n\n const matchWhitelisted = whitelistedArray.some(url =>\n currentUrl.includes(url)\n );\n\n // Final validation\n const isAllowed =\n matchGlobal ||\n matchOrganization ||\n matchAllowedDomain ||\n matchWhitelisted;\n\n this.isRestricted = !isAllowed;\n }\n\n login() { \n this.keycloak.login() \n }\n\n logout() {\n localStorage.removeItem(\"keycloak\");\n // document.cookie = \"DASH_BTN=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;\";\n document.cookie = this.config.cookieName + \"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;\";\n this.keycloak.logout() \n } \n\n showModal() {\n const appModal = this.el.shadowRoot.querySelector('#appListModal');\n appModal.style.display = \"block\";\n }\n\n closeModal() {\n const appModal = this.el.shadowRoot.querySelector('#appListModal');\n appModal.style.display = \"none\";\n }\n\n render() {\n return <div>\n <div>\n {\n (() => {\n // GLOBAL LOADING SPINNER\n if (this.isLoading) {\n return (\n <a id=\"login-btn\" class=\"button button-link\">\n <div class=\"lds-ring\"><div></div><div></div><div></div><div></div></div>\n </a>\n );\n }\n\n if (this.isRestricted) {\n return (\n <div class=\"restricted-overlay\">\n <div class=\"restricted-card\">\n\n <div class=\"restricted-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n\n <h2>Access Restricted</h2>\n <p class=\"restricted-message\">\n You do not have permission to access this application.\n Please contact your administrator if you believe this is an error.\n </p>\n\n {/* Global Applications */}\n {this.config?.menu?.global?.links?.length > 0 && (\n <div class=\"restricted-links\">\n <h4>Publicly Available Modules</h4>\n <div class=\"link-grid\">\n {this.config.menu.global.links.map(item => (\n <a href={item.url} target=\"_blank\" class=\"restricted-link\">\n <i class={item.icon}></i>\n <span>{item.name}</span>\n </a>\n ))}\n </div>\n </div>\n )}\n\n {/* Actions */}\n <div class=\"restricted-actions\">\n {this.config?.defaultLink?.url && (\n <a\n href={this.config.defaultLink.url}\n target=\"_blank\"\n class=\"btn-primary\">\n Go to Portal\n </a>\n )}\n <button class=\"btn-danger\" onClick={this.logout.bind(this)}>\n Logout\n </button>\n </div>\n\n </div>\n </div>\n );\n }\n\n if(this.isAuth && this.showPostLoginText) { \n return (\n <a style={{background: this.primaryColor != undefined? this.primaryColor : \"\"}} href={this.redirectUri} id=\"login-btn\" class=\"button button-link\">\n <span style={{color: this.accentColor != undefined? this.accentColor : \"\"}} class=\"button-text button-text-full-width\">Go to Dashboard</span>\n </a>\n )\n } else if (this.isAuth) {\n return (\n <div id=\"profile-btn\" class=\"dropdown\">\n <button style={{background: this.primaryColor != undefined? this.primaryColor : \"\"}} type=\"button\" class=\"button\">\n <span class=\"button-profile\">\n {JSON.parse(localStorage.getItem('keycloak')).idTokenParsed.imageUrl ?\n <img class=\"profile-image\" src=\"https://s-damith.github.io/test-avatar/images/e24da9c5-0b1f-46fa-82cd-7c711c77b5c7.png\"/>\n :\n <div innerHTML={this.avatarSvg}/>\n }\n </span>\n <span style={{color: this.accentColor != undefined? this.accentColor : \"\"}} id=\"given-name\" class=\"button-text\">{this.givenUserName}</span>\n <div class=\"button-icon\">\n {(this.config.menuViewType == \"grid\") ? <i class=\"fa-solid fa-grip-vertical\"></i> : <i class=\"fa-solid fa-bars\"></i>} \n </div>\n </button>\n <div class=\"dropdown-content\">\n <div class=\"dropdown-user-profile\">\n <div class=\"username\">@{this.givenUserName}</div>\n <div class=\"first-last-name\">{JSON.parse(localStorage.getItem('keycloak')).idTokenParsed.name}</div>\n </div>\n\n\n { (this.config.menuViewType == \"grid\") ? (\n <div>\n <div class=\"grid-view-menu\">\n {\n this.config.menu.global.links.map(item => {\n return (\n <a href={item.url} target='_blank' class=\"grid-view-link\">\n <i class={item.icon + \" fa-2x\"}></i> \n <div class=\"grid-view-link-text\">{item.name}</div>\n </a>\n )\n })\n }\n </div>\n \n {/* show divider */}\n {this.config.menu.global.links.length != 0 && <hr class=\"solid\"></hr>}\n\n <div class=\"grid-view-menu\" style={this.config.menu.global.links.length == 0 && {\"margin-bottom\": \"12px\"}}>\n <a onClick={this.showModal.bind(this)} class=\"grid-view-link\">\n <i class=\"fa-regular fa-window-restore fa-2x\"></i> \n <div class=\"grid-view-link-text\">Modules</div>\n </a>\n <a href={this.config.defaultLink.url} target='_blank' class=\"grid-view-link\">\n <i class=\"fa-solid fa-globe fa-2x\"></i>\n <div class=\"grid-view-link-text\">{this.config.defaultLink.name}</div>\n </a>\n <a onClick={this.logout.bind(this)} class=\"grid-view-link\">\n <i class=\"fa-solid fa-right-from-bracket fa-2x\"></i>\n <div class=\"grid-view-link-text\">Logout</div>\n </a>\n \n </div>\n\n </div>\n ) : (\n\n // List View\n <div class=\"dropdown-content-link\">\n {\n this.config.menu.global.links.map(item => {\n return (\n <a href={item.url} target='_blank' id=\"applications-btn\">\n <i class={item.icon + \" menu-bar-icons\"}></i> \n {item.name}\n </a>\n )\n })\n }\n <a onClick={this.showModal.bind(this)} id=\"applications-btn\"><i class=\"fa-regular fa-window-restore menu-bar-icons\"></i>Modules</a>\n <a href={this.config.defaultLink.url} target='_blank' id=\"applications-btn\"><i class=\"fa-solid fa-globe menu-bar-icons\"></i>{this.config.defaultLink.name}</a>\n <a onClick={this.logout.bind(this)} id=\"logout-btn\"><i class=\"fa-solid fa-right-from-bracket menu-bar-icons\"></i>Logout</a>\n </div>\n\n )}\n </div>\n </div>\n )\n } else {\n return (\n <button style={{background: this.primaryColor != undefined? this.primaryColor : \"\"}} onClick={this.login.bind(this)} id=\"login-btn\" type=\"button\" class=\"button\">\n <span style={{color: this.accentColor != undefined? this.accentColor : \"\"}} class=\"button-text\">Login</span>\n </button>\n )\n }\n })() \n } \n </div>\n \n <div id=\"appListModal\" class=\"modal\">\n \n <div class=\"modal-content\">\n <span onClick={this.closeModal.bind(this)} class=\"close\">&times;</span>\n\n <div class=\"box\">\n {<input type=\"radio\" class=\"tab-toggle\" name=\"tab-toggle\" id=\"tab1\" checked/>}\n {/* {(this.menuLinkList.length != 0) && <input type=\"radio\" class=\"tab-toggle\" name=\"tab-toggle\" id=\"tab2\" checked={this.disableApplicationTab}/>} */}\n\n <ul class=\"tab-list\">\n {<li class=\"tab-item\">\n <label class=\"tab-trigger\" htmlFor=\"tab1\"><i class=\"fa-solid fa-table-list menu-bar-icons\"></i> {this.config.menu.local.name}</label>\n </li>}\n {/* {(this.menuLinkList.length != 0) && <li class=\"tab-item\">\n <label class=\"tab-trigger\" htmlFor=\"tab2\"><i class=\"fa-solid fa-link menu-bar-icons\"></i> {this.otherLinkDisplayName}</label>\n </li>} */}\n </ul>\n \n <div class=\"tab-container\">\n <div class=\"tab-content\">\n <div class=\"modal-body\">\n\n {!this.config?.menu?.local?.enableCustomLocalMenu ? (\n // <div>{this.localMenuLinks}</div>\n this.localMenuLinks?.map((app, index) => {\n const isDisabled = !app.url;\n\n return ( \n <a\n key={index}\n class=\"external-app-link\"\n href={isDisabled ? undefined : app.url}\n target={isDisabled ? undefined : \"_blank\"}\n rel={isDisabled ? undefined : \"noopener noreferrer\"}\n onClick={isDisabled ? (e) => e.preventDefault() : undefined}\n >\n <div class=\"modal-app\">\n <div>{app.name}</div>\n </div>\n </a>\n )\n })\n ) : (\n this.config.menu.local.links?.map((app, index) => (\n <a\n key={index}\n class=\"external-app-link\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n href={app.url}\n >\n <div class=\"modal-app\">\n <div>{app.name}</div>\n </div>\n </a>\n ))\n )}\n\n {/* Error messages */}\n {!this.organizationUrl ? (\n <div>\n <h3 class=\"gray-text\">\n Organization Domain URL not set\n </h3>\n <p class=\"gray-text\">Please set your Organization Domain URL on the Portal profile page.</p>\n </div>\n ) : (\n (\n (!this.config?.menu?.local?.enableCustomLocalMenu &&\n (this.localMenuLinks?.length ?? 0) === 0) ||\n (this.config?.menu?.local?.enableCustomLocalMenu &&\n (this.config?.menu?.local?.links?.length ?? 0) === 0)\n ) && (\n <div>\n <h3 class=\"gray-text\">\n No installed {this.config?.menu?.local?.name || \"menu\"} found.\n </h3>\n <p class=\"gray-text\">Please contact administration.</p>\n </div>\n )\n )}\n\n </div>\n </div> \n {/* <div class=\"tab-content\">\n <div class=\"modal-body\">\n {\n this.menuLinkList.map(link => {\n return (\n <a class=\"external-app-link\" target='_blank' href={link.url}>\n <div class=\"modal-app\">\n <div>{link.name}</div>\n </div>\n </a>\n )\n })\n }\n </div>\n </div> */}\n </div>\n </div>\n\n </div>\n \n </div>\n\n <div id=\"appPermissionErrorModal\" class=\"modal\">\n <div class=\"modal-content\">\n <img src=\"data:image/png;base64,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\"/>\n <h2 class=\"green-text margin-b\">You don't have permission to access this application.</h2>\n <h3 class=\"green-text\">Please contact the administration.</h3>\n \n {(this.config.defaultLink.url && this.showUnauthorizedModal) ? \n <div>\n <h4 class=\"gray-text\">You will be automatically redirected to the portal.</h4>\n <div id=\"countdown\">\n <div id=\"countdown-number\"></div>\n <svg>\n <circle r=\"18\" cx=\"20\" cy=\"20\"></circle>\n </svg>\n </div>\n </div>\n : <div></div>\n }\n </div>\n </div>\n\n </div>;\n }\n}\n"]}
@@ -22,6 +22,8 @@ const DEFAULT_CONFIG = {
22
22
  isLoading: true,
23
23
  duration: 800
24
24
  },
25
+ allowedGlobalDomain: '',
26
+ whitelistedUrls: ''
25
27
  };
26
28
  // Fetch config from API
27
29
  class ConfigService {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AA2CA,MAAM,cAAc,GAAc;IAChC,QAAQ,EAAE;QACR,GAAG,EAAE,mCAAmC;QACxC,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,SAAS;KACpB;IACD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,iCAAiC,EAAE;IACvE,YAAY,EAAE,MAAM;IACpB,UAAU,EAAE,aAAa;IACzB,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,EAAE;SACV;QACD,KAAK,EAAE;YACL,IAAI,EAAE,cAAc;YACpB,qBAAqB,EAAE,IAAI;YAC3B,KAAK,EAAE,EAAE;SACV;KACF;IACD,OAAO,EAAE;QACP,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,GAAG;KACd;CACF,CAAC;AAEF,wBAAwB;AACxB,MAAM,aAAa;IAAnB;QAEU,YAAO,GAAc,cAAc,CAAC;IA6B9C,CAAC;IA3BC,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC5B,aAAa,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,YAAoB;QACpC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,YAAY,GAAG,+BAA+B,CAAC,CAAC;YACxE,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACvD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO,mCAAQ,cAAc,GAAK,IAAI,CAAE,CAAC,CAAC,+BAA+B;QAChF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,yCAAyC,EAAE,CAAC,CAAC,CAAC;YAC3D,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC,uBAAuB;QACxD,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC","sourcesContent":["export interface KeycloakConfig {\n url: string;\n realm: string;\n clientId: string;\n}\n\nexport interface LinkItem {\n name: string;\n url: string;\n icon?: string;\n}\n\nexport interface MenuSection {\n name: string;\n links: LinkItem[];\n}\n\nexport interface LocalMenuSection {\n name: string;\n enableCustomLocalMenu: boolean;\n links: LinkItem[];\n}\n\nexport interface MenuConfig {\n global: MenuSection;\n local: LocalMenuSection;\n}\n\nexport interface LoadingConfig {\n isLoading: boolean;\n duration: number; // in milliseconds\n}\n\nexport interface AppConfig {\n keycloak: KeycloakConfig;\n defaultLink: LinkItem;\n menuViewType: string;\n cookieName: string;\n menu: MenuConfig;\n loading?: LoadingConfig;\n}\n\n\nconst DEFAULT_CONFIG: AppConfig = {\n keycloak: {\n url: 'https://keycloak.ds2.icelab.cloud',\n realm: 'ds2',\n clientId: 'dashbtn'\n },\n defaultLink: { name: 'Portal', url: 'https://portal.ds2.icelab.cloud' },\n menuViewType: 'grid',\n cookieName: 'ZDZW_cookie',\n menu: {\n global: {\n name: 'Applications',\n links: []\n },\n local: {\n name: 'Applications',\n enableCustomLocalMenu: true,\n links: []\n }\n },\n loading: {\n isLoading: true,\n duration: 800\n },\n};\n\n// Fetch config from API\nclass ConfigService {\n private static instance: ConfigService;\n private _config: AppConfig = DEFAULT_CONFIG;\n\n static getInstance() {\n if (!ConfigService.instance) {\n ConfigService.instance = new ConfigService();\n }\n return ConfigService.instance;\n }\n\n async fetchConfig(portalApiUrl: string) {\n try {\n const res = await fetch(portalApiUrl + '/developer/dashbuttons/config');\n if (!res.ok) throw new Error('Failed to fetch config');\n const data = await res.json();\n this._config = { ...DEFAULT_CONFIG, ...data }; // Merge API data with defaults\n } catch (e) {\n console.warn('Using default config due to API failure', e);\n this._config = DEFAULT_CONFIG; // fallback to defaults\n }\n\n return this._config;\n }\n\n /**\n * Return cached config without calling API\n */\n get config() {\n return this._config;\n }\n}\n\nexport const configService = ConfigService.getInstance();"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AA6CA,MAAM,cAAc,GAAc;IAChC,QAAQ,EAAE;QACR,GAAG,EAAE,mCAAmC;QACxC,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,SAAS;KACpB;IACD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,iCAAiC,EAAE;IACvE,YAAY,EAAE,MAAM;IACpB,UAAU,EAAE,aAAa;IACzB,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,EAAE;SACV;QACD,KAAK,EAAE;YACL,IAAI,EAAE,cAAc;YACpB,qBAAqB,EAAE,IAAI;YAC3B,KAAK,EAAE,EAAE;SACV;KACF;IACD,OAAO,EAAE;QACP,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,GAAG;KACd;IACD,mBAAmB,EAAE,EAAE;IACvB,eAAe,EAAE,EAAE;CACpB,CAAC;AAEF,wBAAwB;AACxB,MAAM,aAAa;IAAnB;QAEU,YAAO,GAAc,cAAc,CAAC;IA6B9C,CAAC;IA3BC,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC5B,aAAa,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,YAAoB;QACpC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,YAAY,GAAG,+BAA+B,CAAC,CAAC;YACxE,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACvD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO,mCAAQ,cAAc,GAAK,IAAI,CAAE,CAAC,CAAC,+BAA+B;QAChF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,yCAAyC,EAAE,CAAC,CAAC,CAAC;YAC3D,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC,uBAAuB;QACxD,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC","sourcesContent":["export interface KeycloakConfig {\n url: string;\n realm: string;\n clientId: string;\n}\n\nexport interface LinkItem {\n name: string;\n url: string;\n icon?: string;\n}\n\nexport interface MenuSection {\n name: string;\n links: LinkItem[];\n}\n\nexport interface LocalMenuSection {\n name: string;\n enableCustomLocalMenu: boolean;\n links: LinkItem[];\n}\n\nexport interface MenuConfig {\n global: MenuSection;\n local: LocalMenuSection;\n}\n\nexport interface LoadingConfig {\n isLoading: boolean;\n duration: number; // in milliseconds\n}\n\nexport interface AppConfig {\n keycloak: KeycloakConfig;\n defaultLink: LinkItem;\n menuViewType: string;\n cookieName: string;\n menu: MenuConfig;\n loading?: LoadingConfig;\n allowedGlobalDomain: string;\n whitelistedUrls: string;\n}\n\n\nconst DEFAULT_CONFIG: AppConfig = {\n keycloak: {\n url: 'https://keycloak.ds2.icelab.cloud',\n realm: 'ds2',\n clientId: 'dashbtn'\n },\n defaultLink: { name: 'Portal', url: 'https://portal.ds2.icelab.cloud' },\n menuViewType: 'grid',\n cookieName: 'ZDZW_cookie',\n menu: {\n global: {\n name: 'Applications',\n links: []\n },\n local: {\n name: 'Applications',\n enableCustomLocalMenu: true,\n links: []\n }\n },\n loading: {\n isLoading: true,\n duration: 800\n },\n allowedGlobalDomain: '',\n whitelistedUrls: ''\n};\n\n// Fetch config from API\nclass ConfigService {\n private static instance: ConfigService;\n private _config: AppConfig = DEFAULT_CONFIG;\n\n static getInstance() {\n if (!ConfigService.instance) {\n ConfigService.instance = new ConfigService();\n }\n return ConfigService.instance;\n }\n\n async fetchConfig(portalApiUrl: string) {\n try {\n const res = await fetch(portalApiUrl + '/developer/dashbuttons/config');\n if (!res.ok) throw new Error('Failed to fetch config');\n const data = await res.json();\n this._config = { ...DEFAULT_CONFIG, ...data }; // Merge API data with defaults\n } catch (e) {\n console.warn('Using default config due to API failure', e);\n this._config = DEFAULT_CONFIG; // fallback to defaults\n }\n\n return this._config;\n }\n\n /**\n * Return cached config without calling API\n */\n get config() {\n return this._config;\n }\n}\n\nexport const configService = ConfigService.getInstance();"]}
@@ -1,6 +1,20 @@
1
+ // const getRootDomain = (hostOrUrl: string): string => {
2
+ // // Ensure we can parse it with URL
3
+ // const url = hostOrUrl.startsWith("http") ? new URL(hostOrUrl) : new URL(`https://${hostOrUrl}`);
4
+ // const hostname = url.hostname;
5
+ // const port = url.port ? `:${url.port}` : "";
6
+ // const parts = hostname.split(".");
7
+ // // localhost → return with port
8
+ // if (hostname === "localhost") return hostname + port;
9
+ // // sslip.io → keep last 3 parts
10
+ // if (hostname.endsWith(".sslip.io")) return parts.slice(-5).join(".") + port;
11
+ // // Normal domains → remove first label
12
+ // return parts.slice(1).join(".") + port;
13
+ // };
1
14
  const getRootDomain = (hostOrUrl) => {
2
- // Ensure we can parse it with URL
3
- const url = hostOrUrl.startsWith("http") ? new URL(hostOrUrl) : new URL(`https://${hostOrUrl}`);
15
+ const url = hostOrUrl.startsWith("http")
16
+ ? new URL(hostOrUrl)
17
+ : new URL(`https://${hostOrUrl}`);
4
18
  const hostname = url.hostname;
5
19
  const port = url.port ? `:${url.port}` : "";
6
20
  const parts = hostname.split(".");
@@ -10,8 +24,8 @@ const getRootDomain = (hostOrUrl) => {
10
24
  // sslip.io → keep last 3 parts
11
25
  if (hostname.endsWith(".sslip.io"))
12
26
  return parts.slice(-5).join(".") + port;
13
- // Normal domains → remove first label
14
- return parts.slice(1).join(".") + port;
27
+ // Keep full hostname
28
+ return hostname + port;
15
29
  };
16
30
  const getUrlProtocol = (url, defaultProtocol = "https://") => {
17
31
  if (!url)
@@ -1 +1 @@
1
- {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/services/menu.ts"],"names":[],"mappings":"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","sourcesContent":["export interface InstalledChartMetadata {\n category?: string;\n frontendUrlPrefix?: string;\n}\n\nexport interface InstalledChart {\n id: number;\n installChartName: string;\n metadata: InstalledChartMetadata;\n}\n\nexport interface PaginatedInstalledChartsResponse {\n data: InstalledChart[];\n total: number;\n page: number;\n perPage: number;\n totalPages: number;\n}\n\nexport interface MenuLink {\n name: string;\n url: string;\n category?: string;\n}\n\nconst getRootDomain = (hostOrUrl: string): string => {\n // Ensure we can parse it with URL\n const url = hostOrUrl.startsWith(\"http\") ? new URL(hostOrUrl) : new URL(`https://${hostOrUrl}`);\n const hostname = url.hostname;\n const port = url.port ? `:${url.port}` : \"\";\n const parts = hostname.split(\".\");\n\n // localhost → return with port\n if (hostname === \"localhost\") return hostname + port;\n\n // sslip.io → keep last 3 parts\n if (hostname.endsWith(\".sslip.io\")) return parts.slice(-5).join(\".\") + port;\n\n // Normal domains → remove first label\n return parts.slice(1).join(\".\") + port;\n};\n\nconst getUrlProtocol = (url: string, defaultProtocol = \"https://\"): string => {\n if (!url) return defaultProtocol;\n\n const trimmed = url.trim();\n\n // Match protocol (http:// or https://)\n const match = trimmed.match(/^(https?:\\/\\/)/i);\n return match ? match[1] : defaultProtocol;\n};\n\nclass MenuService {\n\n async getMenuConfig(url): Promise<PaginatedInstalledChartsResponse> {\n try {\n const res = await fetch(url);\n if (!res.ok) throw new Error('API error');\n return await res.json();\n } catch {\n return { data: [], total: 0, page: 1, perPage: 0, totalPages: 0 };\n }\n }\n\n private setDefaultProtocol(url: string): string {\n // If protocol already exists (http:// or https://), keep it\n if (/^https?:\\/\\//i.test(url)) {\n return url;\n }\n\n // Otherwise default to https\n return `https://${url}`;\n }\n\n async getMenuLinks(BASE_URL): Promise<MenuLink[]> {\n const normalizedBaseUrl = this.setDefaultProtocol(BASE_URL);\n // Create a URL object from normalizedBaseUrl\n const urlObj = new URL(normalizedBaseUrl);\n\n // Add the 'containerisationbackend' subdomain\n urlObj.hostname = `containerisationbackend.${urlObj.hostname}`;\n \n const { data } = await this.getMenuConfig(`${urlObj.origin}/developer/charts/installed`);\n\n return data.map(d => {\n const frontendUrlPrefix = d.metadata?.frontendUrlPrefix;\n\n const rootDomain = getRootDomain(BASE_URL);\n const generatedUrl = `${getUrlProtocol(BASE_URL)}${frontendUrlPrefix}.${rootDomain}`;\n \n return {\n name: d.installChartName,\n url: frontendUrlPrefix ? generatedUrl : \"\",\n category: d.metadata?.category ?? \"\",\n };\n });\n }\n}\n\nexport const menuService = new MenuService();"]}
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/services/menu.ts"],"names":[],"mappings":"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","sourcesContent":["export interface InstalledChartMetadata {\n category?: string;\n frontendUrlPrefix?: string;\n}\n\nexport interface InstalledChart {\n id: number;\n installChartName: string;\n metadata: InstalledChartMetadata;\n}\n\nexport interface PaginatedInstalledChartsResponse {\n data: InstalledChart[];\n total: number;\n page: number;\n perPage: number;\n totalPages: number;\n}\n\nexport interface MenuLink {\n name: string;\n url: string;\n category?: string;\n}\n\n// const getRootDomain = (hostOrUrl: string): string => {\n// // Ensure we can parse it with URL\n// const url = hostOrUrl.startsWith(\"http\") ? new URL(hostOrUrl) : new URL(`https://${hostOrUrl}`);\n// const hostname = url.hostname;\n// const port = url.port ? `:${url.port}` : \"\";\n// const parts = hostname.split(\".\");\n\n// // localhost → return with port\n// if (hostname === \"localhost\") return hostname + port;\n\n// // sslip.io → keep last 3 parts\n// if (hostname.endsWith(\".sslip.io\")) return parts.slice(-5).join(\".\") + port;\n\n// // Normal domains → remove first label\n// return parts.slice(1).join(\".\") + port;\n// };\n\nconst getRootDomain = (hostOrUrl: string): string => {\n const url = hostOrUrl.startsWith(\"http\")\n ? new URL(hostOrUrl)\n : new URL(`https://${hostOrUrl}`);\n\n const hostname = url.hostname;\n const port = url.port ? `:${url.port}` : \"\";\n const parts = hostname.split(\".\");\n\n // localhost → return with port\n if (hostname === \"localhost\") return hostname + port;\n\n // sslip.io → keep last 3 parts\n if (hostname.endsWith(\".sslip.io\")) return parts.slice(-5).join(\".\") + port;\n\n // Keep full hostname\n return hostname + port;\n};\n\n\nconst getUrlProtocol = (url: string, defaultProtocol = \"https://\"): string => {\n if (!url) return defaultProtocol;\n\n const trimmed = url.trim();\n\n // Match protocol (http:// or https://)\n const match = trimmed.match(/^(https?:\\/\\/)/i);\n return match ? match[1] : defaultProtocol;\n};\n\nclass MenuService {\n\n async getMenuConfig(url): Promise<PaginatedInstalledChartsResponse> {\n try {\n const res = await fetch(url);\n if (!res.ok) throw new Error('API error');\n return await res.json();\n } catch {\n return { data: [], total: 0, page: 1, perPage: 0, totalPages: 0 };\n }\n }\n\n private setDefaultProtocol(url: string): string {\n // If protocol already exists (http:// or https://), keep it\n if (/^https?:\\/\\//i.test(url)) {\n return url;\n }\n\n // Otherwise default to https\n return `https://${url}`;\n }\n\n async getMenuLinks(BASE_URL): Promise<MenuLink[]> {\n const normalizedBaseUrl = this.setDefaultProtocol(BASE_URL);\n // Create a URL object from normalizedBaseUrl\n const urlObj = new URL(normalizedBaseUrl);\n\n // Add the 'containerisationbackend' subdomain\n urlObj.hostname = `containerisationbackend.${urlObj.hostname}`;\n \n const { data } = await this.getMenuConfig(`${urlObj.origin}/developer/charts/installed`);\n\n return data.map(d => {\n const frontendUrlPrefix = d.metadata?.frontendUrlPrefix;\n\n const rootDomain = getRootDomain(BASE_URL);\n const generatedUrl = `${getUrlProtocol(BASE_URL)}${frontendUrlPrefix}.${rootDomain}`;\n \n return {\n name: d.installChartName,\n url: frontendUrlPrefix ? generatedUrl : \"\",\n category: d.metadata?.category ?? \"\",\n };\n });\n }\n}\n\nexport const menuService = new MenuService();"]}
@@ -3895,6 +3895,8 @@ const DEFAULT_CONFIG = {
3895
3895
  isLoading: true,
3896
3896
  duration: 800
3897
3897
  },
3898
+ allowedGlobalDomain: '',
3899
+ whitelistedUrls: ''
3898
3900
  };
3899
3901
  // Fetch config from API
3900
3902
  class ConfigService {
@@ -3930,9 +3932,23 @@ class ConfigService {
3930
3932
  }
3931
3933
  const configService = ConfigService.getInstance();
3932
3934
 
3935
+ // const getRootDomain = (hostOrUrl: string): string => {
3936
+ // // Ensure we can parse it with URL
3937
+ // const url = hostOrUrl.startsWith("http") ? new URL(hostOrUrl) : new URL(`https://${hostOrUrl}`);
3938
+ // const hostname = url.hostname;
3939
+ // const port = url.port ? `:${url.port}` : "";
3940
+ // const parts = hostname.split(".");
3941
+ // // localhost → return with port
3942
+ // if (hostname === "localhost") return hostname + port;
3943
+ // // sslip.io → keep last 3 parts
3944
+ // if (hostname.endsWith(".sslip.io")) return parts.slice(-5).join(".") + port;
3945
+ // // Normal domains → remove first label
3946
+ // return parts.slice(1).join(".") + port;
3947
+ // };
3933
3948
  const getRootDomain = (hostOrUrl) => {
3934
- // Ensure we can parse it with URL
3935
- const url = hostOrUrl.startsWith("http") ? new URL(hostOrUrl) : new URL(`https://${hostOrUrl}`);
3949
+ const url = hostOrUrl.startsWith("http")
3950
+ ? new URL(hostOrUrl)
3951
+ : new URL(`https://${hostOrUrl}`);
3936
3952
  const hostname = url.hostname;
3937
3953
  const port = url.port ? `:${url.port}` : "";
3938
3954
  const parts = hostname.split(".");
@@ -3942,8 +3958,8 @@ const getRootDomain = (hostOrUrl) => {
3942
3958
  // sslip.io → keep last 3 parts
3943
3959
  if (hostname.endsWith(".sslip.io"))
3944
3960
  return parts.slice(-5).join(".") + port;
3945
- // Normal domains → remove first label
3946
- return parts.slice(1).join(".") + port;
3961
+ // Keep full hostname
3962
+ return hostname + port;
3947
3963
  };
3948
3964
  const getUrlProtocol = (url, defaultProtocol = "https://") => {
3949
3965
  if (!url)
@@ -4106,27 +4122,44 @@ const DashButtonComponent = /*@__PURE__*/ proxyCustomElement(class DashButtonCom
4106
4122
  }
4107
4123
  }
4108
4124
  }
4125
+ // First, check global links
4126
+ // Then, check the token's organization URL
4127
+ // Finally, check against dashbutton configuration: allowedGlobalDomain and whitelistedUrls
4109
4128
  validateAppAccessByUrl() {
4110
- var _a, _b, _c, _d;
4111
- const currentUrl = window.location.href;
4112
- const currentOrigin = window.location.origin;
4129
+ var _a, _b, _c, _d, _e, _f;
4130
+ const normalizeUrl = (url) => url.replace(/\/+$/, '');
4131
+ const currentUrl = normalizeUrl(window.location.href);
4132
+ const currentOrigin = normalizeUrl(window.location.origin);
4113
4133
  const globalLinks = ((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.menu) === null || _b === void 0 ? void 0 : _b.global) === null || _c === void 0 ? void 0 : _c.links) || [];
4114
- // Check Global Links
4134
+ const allowedGlobalDomain = ((_d = this.config) === null || _d === void 0 ? void 0 : _d.allowedGlobalDomain) || '';
4135
+ const whitelistedUrls = ((_e = this.config) === null || _e === void 0 ? void 0 : _e.whitelistedUrls) || '';
4136
+ // First, check global links
4115
4137
  const matchGlobal = globalLinks.some(link => {
4116
4138
  try {
4117
- const linkOrigin = new URL(link.url).origin;
4139
+ const linkOrigin = normalizeUrl(new URL(link.url).origin);
4118
4140
  return currentOrigin === linkOrigin;
4119
4141
  }
4120
4142
  catch (_a) {
4121
4143
  return false;
4122
4144
  }
4123
4145
  });
4124
- // Check Token organizationUrl
4125
- const tokenParsed = (_d = this.keycloak) === null || _d === void 0 ? void 0 : _d.tokenParsed;
4146
+ // Then check the token organization URL
4147
+ const tokenParsed = (_f = this.keycloak) === null || _f === void 0 ? void 0 : _f.tokenParsed;
4126
4148
  const allowedOrg = tokenParsed === null || tokenParsed === void 0 ? void 0 : tokenParsed.organizationUrl;
4127
- const matchOrganization = allowedOrg && currentUrl.includes(allowedOrg);
4128
- // global and org url validations
4129
- const isAllowed = matchGlobal || matchOrganization;
4149
+ const matchOrganization = allowedOrg && currentUrl.includes(normalizeUrl(allowedOrg));
4150
+ // Check allowedGlobalDomain (single domain)
4151
+ const matchAllowedDomain = allowedGlobalDomain &&
4152
+ currentOrigin.includes(normalizeUrl(allowedGlobalDomain));
4153
+ // Check whitelistedUrls (comma-separated string)
4154
+ const whitelistedArray = whitelistedUrls
4155
+ ? whitelistedUrls.split(',').map(url => normalizeUrl(url.trim()))
4156
+ : [];
4157
+ const matchWhitelisted = whitelistedArray.some(url => currentUrl.includes(url));
4158
+ // Final validation
4159
+ const isAllowed = matchGlobal ||
4160
+ matchOrganization ||
4161
+ matchAllowedDomain ||
4162
+ matchWhitelisted;
4130
4163
  this.isRestricted = !isAllowed;
4131
4164
  }
4132
4165
  login() {
@@ -4148,7 +4181,7 @@ const DashButtonComponent = /*@__PURE__*/ proxyCustomElement(class DashButtonCom
4148
4181
  }
4149
4182
  render() {
4150
4183
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
4151
- return h("div", { key: 'd186318626a3fbd1d011d3532559901d1c36859e' }, h("div", { key: 'a5887ec423aabb35ca7988169cfa7a9f0bd588e6' }, (() => {
4184
+ return h("div", { key: '370786aa472fafd2bf9509a18bd62c87ac2893c7' }, h("div", { key: 'c0b091b19e7981ecc48e95c03c8d91e77e7a88df' }, (() => {
4152
4185
  var _a, _b, _c, _d, _e, _f;
4153
4186
  // GLOBAL LOADING SPINNER
4154
4187
  if (this.isLoading) {
@@ -4175,7 +4208,7 @@ const DashButtonComponent = /*@__PURE__*/ proxyCustomElement(class DashButtonCom
4175
4208
  else {
4176
4209
  return (h("button", { style: { background: this.primaryColor != undefined ? this.primaryColor : "" }, onClick: this.login.bind(this), id: "login-btn", type: "button", class: "button" }, h("span", { style: { color: this.accentColor != undefined ? this.accentColor : "" }, class: "button-text" }, "Login")));
4177
4210
  }
4178
- })()), h("div", { key: '1ad6675f4e190df28410c54f7ad9f097578e0403', id: "appListModal", class: "modal" }, h("div", { key: '655f51c1d18372eca86610750d1ac3c8e1eeeefa', class: "modal-content" }, h("span", { key: 'bb850ddc02afdbbc04b5fbc6258d6ab2b1e92bfb', onClick: this.closeModal.bind(this), class: "close" }, "\u00D7"), h("div", { key: '4fdec67f888e554e1c8a3328ae2b55fb1a0fea4d', class: "box" }, h("input", { type: "radio", class: "tab-toggle", name: "tab-toggle", id: "tab1", checked: true }), h("ul", { key: '4317ec4e90f682b549aea49971d12426aaa5c0ef', class: "tab-list" }, h("li", { class: "tab-item" }, h("label", { class: "tab-trigger", htmlFor: "tab1" }, h("i", { class: "fa-solid fa-table-list menu-bar-icons" }), " ", this.config.menu.local.name))), h("div", { key: '8f1b8e0ec034d45a9c04776b90afcbd3cd9fea3e', class: "tab-container" }, h("div", { key: 'e59e81838b0c2fa419314503ab0c2d56143496cb', class: "tab-content" }, h("div", { key: 'f393c5497bfeddae25469d2d4475f9aacdf13629', class: "modal-body" }, !((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.menu) === null || _b === void 0 ? void 0 : _b.local) === null || _c === void 0 ? void 0 : _c.enableCustomLocalMenu) ? (
4211
+ })()), h("div", { key: 'f98304920ef08f842700c5d26fe62a51cbbade96', id: "appListModal", class: "modal" }, h("div", { key: '2c4024b83e3cd0d638f4482d0e8907687ac12dd0', class: "modal-content" }, h("span", { key: '42a44145a7d7c33cae95344f02229d8163cc9607', onClick: this.closeModal.bind(this), class: "close" }, "\u00D7"), h("div", { key: 'ec3dbe646c76818ee90ec28e19671880670a2754', class: "box" }, h("input", { type: "radio", class: "tab-toggle", name: "tab-toggle", id: "tab1", checked: true }), h("ul", { key: 'c7dbcfd1b183bc6845cab0f17ef6f81dee30867f', class: "tab-list" }, h("li", { class: "tab-item" }, h("label", { class: "tab-trigger", htmlFor: "tab1" }, h("i", { class: "fa-solid fa-table-list menu-bar-icons" }), " ", this.config.menu.local.name))), h("div", { key: 'dc58df8e838c8babe3c679c6f1c498e286448cf3', class: "tab-container" }, h("div", { key: '486acbf570543ef0a92bd919e1c9c7973c87b3a7', class: "tab-content" }, h("div", { key: 'c9e093ce8d745097147405749e88ba35b1fc8679', class: "modal-body" }, !((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.menu) === null || _b === void 0 ? void 0 : _b.local) === null || _c === void 0 ? void 0 : _c.enableCustomLocalMenu) ? (
4179
4212
  // <div>{this.localMenuLinks}</div>
4180
4213
  (_d = this.localMenuLinks) === null || _d === void 0 ? void 0 : _d.map((app, index) => {
4181
4214
  const isDisabled = !app.url;
@@ -4183,7 +4216,7 @@ const DashButtonComponent = /*@__PURE__*/ proxyCustomElement(class DashButtonCom
4183
4216
  })) : ((_e = this.config.menu.local.links) === null || _e === void 0 ? void 0 : _e.map((app, index) => (h("a", { key: index, class: "external-app-link", target: "_blank", rel: "noopener noreferrer", href: app.url }, h("div", { class: "modal-app" }, h("div", null, app.name)))))), !this.organizationUrl ? (h("div", null, h("h3", { class: "gray-text" }, "Organization Domain URL not set"), h("p", { class: "gray-text" }, "Please set your Organization Domain URL on the Portal profile page."))) : (((!((_h = (_g = (_f = this.config) === null || _f === void 0 ? void 0 : _f.menu) === null || _g === void 0 ? void 0 : _g.local) === null || _h === void 0 ? void 0 : _h.enableCustomLocalMenu) &&
4184
4217
  ((_k = (_j = this.localMenuLinks) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : 0) === 0) ||
4185
4218
  (((_o = (_m = (_l = this.config) === null || _l === void 0 ? void 0 : _l.menu) === null || _m === void 0 ? void 0 : _m.local) === null || _o === void 0 ? void 0 : _o.enableCustomLocalMenu) &&
4186
- ((_t = (_s = (_r = (_q = (_p = this.config) === null || _p === void 0 ? void 0 : _p.menu) === null || _q === void 0 ? void 0 : _q.local) === null || _r === void 0 ? void 0 : _r.links) === null || _s === void 0 ? void 0 : _s.length) !== null && _t !== void 0 ? _t : 0) === 0)) && (h("div", null, h("h3", { class: "gray-text" }, "No installed ", ((_w = (_v = (_u = this.config) === null || _u === void 0 ? void 0 : _u.menu) === null || _v === void 0 ? void 0 : _v.local) === null || _w === void 0 ? void 0 : _w.name) || "menu", " found."), h("p", { class: "gray-text" }, "Please contact administration.")))))))))), h("div", { key: 'c47c1a2e57cbd3d42fcb19d559343a7104e092c0', id: "appPermissionErrorModal", class: "modal" }, h("div", { key: 'cd8a0b1837afc3089bda1bd4d9e7ec0c2a7c3f45', class: "modal-content" }, h("img", { key: 'e21aa2b61cbedff394e4cbbc6993fd06b3c3906e', src: "data:image/png;base64,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" }), h("h2", { key: '0ea76a87518b2a0c2a171bc0f40cb4767f6683e9', class: "green-text margin-b" }, "You don't have permission to access this application."), h("h3", { key: '1dc9d8f8f2ef3a34bf8cb887679c574a59fe5a75', class: "green-text" }, "Please contact the administration."), (this.config.defaultLink.url && this.showUnauthorizedModal) ?
4219
+ ((_t = (_s = (_r = (_q = (_p = this.config) === null || _p === void 0 ? void 0 : _p.menu) === null || _q === void 0 ? void 0 : _q.local) === null || _r === void 0 ? void 0 : _r.links) === null || _s === void 0 ? void 0 : _s.length) !== null && _t !== void 0 ? _t : 0) === 0)) && (h("div", null, h("h3", { class: "gray-text" }, "No installed ", ((_w = (_v = (_u = this.config) === null || _u === void 0 ? void 0 : _u.menu) === null || _v === void 0 ? void 0 : _v.local) === null || _w === void 0 ? void 0 : _w.name) || "menu", " found."), h("p", { class: "gray-text" }, "Please contact administration.")))))))))), h("div", { key: '349c7ff69d94c988a278677f497c0a9fef85c59c', id: "appPermissionErrorModal", class: "modal" }, h("div", { key: '788004858cf2f55f4e79cce0c023895274bab9ab', class: "modal-content" }, h("img", { key: '57ea43b0a21086eeaebe0585b9501967099ec999', src: "data:image/png;base64,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" }), h("h2", { key: 'c7663fb1503a0f0713350ac2ff2e52708c5425f9', class: "green-text margin-b" }, "You don't have permission to access this application."), h("h3", { key: '925b21fffdee5437664f690254821ffa63d736cb', class: "green-text" }, "Please contact the administration."), (this.config.defaultLink.url && this.showUnauthorizedModal) ?
4187
4220
  h("div", null, h("h4", { class: "gray-text" }, "You will be automatically redirected to the portal."), h("div", { id: "countdown" }, h("div", { id: "countdown-number" }), h("svg", null, h("circle", { r: "18", cx: "20", cy: "20" }))))
4188
4221
  : h("div", null))));
4189
4222
  }