UNPKG

homebridge-config-ui-x

Version:

A web based management, configuration and control platform for Homebridge.

2 lines (1 loc) 9.16 kB
import{b as x}from"./chunk-RFCSHRPV.js";import{$ as l,Rc as $,Sa as R,X as c,Y as S,_ as j,aa as d,cd as s,d as y,dd as b,j as f,ka as D,o as v,p as I,qa as p,r as g,u as E}from"./chunk-LTGI3NYM.js";import{h}from"./chunk-B4AJQJMI.js";var M=(()=>{class o{raspberryPiThrottled=p({});formAuthEnabled=p(null);legacyOtpDetected=p(!1);static \u0275fac=function(t){return new(t||o)};static \u0275prov=c({token:o,factory:o.\u0275fac,providedIn:"root"})}return o})();var T=new j("JWT_OPTIONS"),m=(()=>{class o{constructor(e=null){this.tokenGetter=e&&e.tokenGetter||function(){}}urlBase64Decode(e){let t=e.replace(/-/g,"+").replace(/_/g,"/");switch(t.length%4){case 0:break;case 2:{t+="==";break}case 3:{t+="=";break}default:throw new Error("Illegal base64url string!")}return this.b64DecodeUnicode(t)}b64decode(e){let t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",i="";if(e=String(e).replace(/=+$/,""),e.length%4===1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(let r=0,a,n,w=0;n=e.charAt(w++);~n&&(a=r%4?a*64+n:n,r++%4)?i+=String.fromCharCode(255&a>>(-2*r&6)):0)n=t.indexOf(n);return i}b64DecodeUnicode(e){return decodeURIComponent(Array.prototype.map.call(this.b64decode(e),t=>"%"+("00"+t.charCodeAt(0).toString(16)).slice(-2)).join(""))}decodeToken(e=this.tokenGetter()){return e instanceof Promise?e.then(t=>this._decodeToken(t)):this._decodeToken(e)}_decodeToken(e){if(!e||e==="")return null;let t=e.split(".");if(t.length!==3)throw new Error("The inspected token doesn't appear to be a JWT. Check to make sure it has three parts and see https://jwt.io for more.");let i=this.urlBase64Decode(t[1]);if(!i)throw new Error("Cannot decode the token.");return JSON.parse(i)}getTokenExpirationDate(e=this.tokenGetter()){return e instanceof Promise?e.then(t=>this._getTokenExpirationDate(t)):this._getTokenExpirationDate(e)}_getTokenExpirationDate(e){let t;if(t=this.decodeToken(e),!t||!t.hasOwnProperty("exp"))return null;let i=new Date(0);return i.setUTCSeconds(t.exp),i}isTokenExpired(e=this.tokenGetter(),t){return e instanceof Promise?e.then(i=>this._isTokenExpired(i,t)):this._isTokenExpired(e,t)}_isTokenExpired(e,t){if(!e||e==="")return!0;let i=this.getTokenExpirationDate(e);return t=t||0,i===null?!1:!(i.valueOf()>new Date().valueOf()+t*1e3)}getAuthScheme(e,t){return typeof e=="function"?e(t):e}}return o.\u0275fac=function(e){return new(e||o)(l(T))},o.\u0275prov=c({token:o,factory:o.\u0275fac}),o})(),_=o=>o instanceof Promise?E(()=>o):f(o),A=(()=>{class o{constructor(e,t,i){this.jwtHelper=t,this.document=i,this.standardPorts=["80","443"],this.tokenGetter=e.tokenGetter,this.headerName=e.headerName||"Authorization",this.authScheme=e.authScheme||e.authScheme===""?e.authScheme:"Bearer ",this.allowedDomains=e.allowedDomains||[],this.disallowedRoutes=e.disallowedRoutes||[],this.throwNoTokenError=e.throwNoTokenError||!1,this.skipWhenExpired=e.skipWhenExpired}isAllowedDomain(e){let t=new URL(e.url,this.document.location.origin);if(t.host===this.document.location.host)return!0;let i=`${t.hostname}${t.port&&!this.standardPorts.includes(t.port)?":"+t.port:""}`;return this.allowedDomains.findIndex(r=>typeof r=="string"?r===i:r instanceof RegExp?r.test(i):!1)>-1}isDisallowedRoute(e){let t=new URL(e.url,this.document.location.origin);return this.disallowedRoutes.findIndex(i=>{if(typeof i=="string"){let r=new URL(i,this.document.location.origin);return r.hostname===t.hostname&&r.pathname===t.pathname}return i instanceof RegExp?i.test(e.url):!1})>-1}handleInterception(e,t,i){let r=this.jwtHelper.getAuthScheme(this.authScheme,t);if(!e&&this.throwNoTokenError)throw new Error("Could not get token from tokenGetter function.");let a=f(!1);return this.skipWhenExpired&&(a=e?_(this.jwtHelper.isTokenExpired(e)):f(!0)),e?a.pipe(I(n=>n&&this.skipWhenExpired?t.clone():t.clone({setHeaders:{[this.headerName]:`${r}${e}`}})),g(n=>i.handle(n))):i.handle(t)}intercept(e,t){if(!this.isAllowedDomain(e)||this.isDisallowedRoute(e))return t.handle(e);let i=this.tokenGetter(e);return _(i).pipe(g(r=>this.handleInterception(r,e,t)))}}return o.\u0275fac=function(e){return new(e||o)(l(T),l(m),l(D))},o.\u0275prov=c({token:o,factory:o.\u0275fac}),o})(),X=(()=>{class o{constructor(e){if(e)throw new Error("JwtModule is already loaded. It should only be imported in your application's main module.")}static forRoot(e){return{ngModule:o,providers:[{provide:$,useClass:A,multi:!0},e.jwtOptionsProvider||{provide:T,useValue:e.config},m]}}}return o.\u0275fac=function(e){return new(e||o)(l(o,12))},o.\u0275mod=R({type:o}),o.\u0275inj=S({}),o})();var O=(()=>{class o{cache=null;CACHE_DURATION_MS=6e4;constructor(){typeof window<"u"&&window.addEventListener("storage",e=>{(e.key===s.jwt.tokenKey||e.key===null)&&this.invalidateCache()})}getToken(){let e=Date.now();if(this.cache&&e-this.cache.timestamp<this.CACHE_DURATION_MS)return this.cache.token;let t=window.localStorage.getItem(s.jwt.tokenKey);return this.cache={token:t,timestamp:e},t}invalidateCache(){this.cache=null}static \u0275fac=function(t){return new(t||o)};static \u0275prov=c({token:o,factory:o.\u0275fac,providedIn:"root"})}return o})();var ae=(()=>{class o{$api=d(b);$jwtHelper=d(m);$notification=d(M);$settings=d(x);$tokenCache=d(O);token=null;user={};tokenRotated=new y;tokenReady;logoutTimer;lastRefreshTime=Date.now();isRefreshing=!1;constructor(){this.tokenReady=this.loadToken()}login(e){return h(this,null,function*(){let t=yield this.$api.post("/auth/login",e);if(!this.validateToken(t.access_token))throw new Error("Invalid username or password.");window.localStorage.setItem(s.jwt.tokenKey,t.access_token),yield this.$settings.getAppSettings()})}noauth(){return h(this,null,function*(){let e=yield this.$api.post("/auth/noauth",{});if(this.validateToken(e.access_token))window.localStorage.setItem(s.jwt.tokenKey,e.access_token),yield this.$settings.getAppSettings();else throw new Error("Invalid username or password.")})}logout(){this.user={},this.token=null,clearTimeout(this.logoutTimer),window.localStorage.removeItem(s.jwt.tokenKey),window.location.reload()}loadToken(){return h(this,null,function*(){this.$settings.settingsLoaded||(yield v(this.$settings.onSettingsLoaded));let e=window.localStorage.getItem(s.jwt.tokenKey);if(e){if(this.$jwtHelper.isTokenExpired(e,this.$settings.serverTimeOffset)){window.localStorage.removeItem(s.jwt.tokenKey),this.token=null;return}this.validateToken(e)}})}checkToken(){return h(this,null,function*(){if(!this.token||this.$jwtHelper.isTokenExpired(this.token,this.$settings.serverTimeOffset)){console.warn("Token expired on client side, logging out immediately"),this.logout();return}try{return yield this.$api.get("/auth/check")}catch(e){throw e.status===401&&(console.warn("Current token is not valid on server"),this.logout()),e}})}isLoggedIn(){return this.$settings.env.instanceId!==this.user.instanceId?(console.error("Token does not match instance"),!1):this.user&&this.token&&!this.$jwtHelper.isTokenExpired(this.token,this.$settings.serverTimeOffset)}validateToken(e){try{if(this.$jwtHelper.isTokenExpired(e,this.$settings.serverTimeOffset)){this.logout();return}return this.user=this.$jwtHelper.decodeToken(e)??{},this.token=e,this.setLogoutTimer(),this.user.otpLegacySecret&&this.$notification.legacyOtpDetected.set(!0),!0}catch(t){return window.localStorage.removeItem(s.jwt.tokenKey),this.token=null,!1}}setLogoutTimer(){if(clearTimeout(this.logoutTimer),this.token&&!this.$jwtHelper.isTokenExpired(this.token,this.$settings.serverTimeOffset)){let t=this.$settings.sessionTimeout*1e3,i=Math.min(t,2147483647);t>2147483647&&console.warn(`Inactivity timeout ${this.$settings.sessionTimeout}s exceeds the browser setTimeout limit; clamped to ~24.8 days.`),this.logoutTimer=setTimeout(()=>h(this,null,function*(){if(this.$settings.formAuth===!1){let r="uix.noauthReloadCount",n=Number(window.sessionStorage.getItem(r)??"0")+1;if(n>3){console.warn("Skipping noauth re-login reload \u2014 retry budget exhausted this session.");return}try{yield this.noauth(),window.sessionStorage.setItem(r,String(n)),window.location.reload()}catch(w){console.warn("noauth re-login failed:",w)}}else this.logout()}),i)}}checkAndRefreshIfNeeded(){return h(this,null,function*(){if(!this.$settings.formAuth||!this.$settings.sessionTimeoutInactivityBased||!this.token||!this.isLoggedIn()||this.isRefreshing)return;let t=Date.now()-this.lastRefreshTime,r=this.$settings.sessionTimeout*1e3*.7;if(t>r)try{yield this.refreshSession()}catch(a){console.error("Failed to refresh session:",a)}})}refreshSession(){return h(this,null,function*(){if(!this.isRefreshing){this.isRefreshing=!0;try{let e=yield this.$api.post("/auth/refresh",{});if(e.access_token){if(window.localStorage.setItem(s.jwt.tokenKey,e.access_token),this.$tokenCache.invalidateCache(),!this.validateToken(e.access_token))throw new Error("Refreshed access token failed validation");this.lastRefreshTime=Date.now(),this.tokenRotated.next()}}finally{this.isRefreshing=!1}}})}static \u0275fac=function(t){return new(t||o)};static \u0275prov=c({token:o,factory:o.\u0275fac,providedIn:"root"})}return o})();export{X as a,O as b,M as c,ae as d};