UNPKG

vue-auth3

Version:

<p align="center"> <img src="./docs/public/icon.svg" width="180px"> </p>

889 lines (875 loc) 25.7 kB
import { defineAuthDriver } from "./chunk-T4OYN7ZE.mjs"; import { defineHttpDriver } from "./chunk-JUGBTNJP.mjs"; import { defineOAuth2Driver } from "./chunk-6ZBIUENL.mjs"; import { __async, __publicField, __spreadProps, __spreadValues } from "./chunk-MI2N2CU6.mjs"; // src/index.ts import { computed, inject } from "vue"; // src/Auth.ts import { reactive, shallowRef, watch } from "vue"; // src/defaultOption.ts var __defaultOption = { // Variables rolesKey: "roles", rememberKey: "auth_remember", userKey: "auth_user", staySignedInKey: "auth_stay_signed_in", tokenDefaultKey: "auth_token_default", tokenImpersonateKey: "auth_token_impersonate", stores: ["storage", "cookie"], cookie: { path: "/", domain: void 0, secure: true, expires: 12096e5, sameSite: "None" }, // Redirects authRedirect: "/login", forbiddenRedirect: "/403", notFoundRedirect: "/404", // Http registerData: { url: "auth/register", method: "POST", redirect: "/login", autoLogin: false, staySignedIn: true }, loginData: { url: "auth/login", method: "POST", redirect: "/", fetchUser: true, staySignedIn: true }, logoutData: { url: "auth/logout", method: "POST", redirect: "/", makeRequest: true }, fetchData: { url: "auth/user", method: "GET", enabled: true }, refreshToken: { url: "auth/refresh", method: "GET", enabled: true, interval: 30 }, impersonateData: { url: "auth/impersonate", method: "POST", redirect: "/", fetchUser: true }, unimpersonateData: { url: "auth/unimpersonate", method: "POST", redirect: "/admin", fetchUser: true, makeRequest: false }, oauth2Data: { url: "auth/social", method: "POST", redirect: "/", fetchUser: true } }; var defaultOption_default = __defaultOption; // src/helpers/cookie.ts function setCookie(auth, key, value, expires, time) { const options = auth.options.cookie; let cookie2 = `${key}=${JSON.stringify(value)};`; for (const [prop, val] of Object.entries(options)) { let value2 = typeof val === "function" ? val() : val; if (value2 === false || value2 == null) { continue; } if (prop === "expires") { value2 = expires ? "" : getDate(time != null ? time : value2); } if (value2 === true) { cookie2 += `${prop};`; continue; } cookie2 += `${prop}=${value2};`; } document.cookie = cookie2; } function getDate(val) { if (typeof val === "string") { return val; } return new Date( (/* @__PURE__ */ new Date()).getTime() + (val instanceof Date ? val.getTime() : val) ).toUTCString(); } function get(auth, key) { var _a, _b; return JSON.parse( (_b = (_a = document.cookie.replace(/;\s+/g, ";").split(";").map((s) => { return s.replace(/\s+=\s+/g, "=").split("="); }).find(([keyTest]) => { return keyTest === key; })) == null ? void 0 : _a[1]) != null ? _b : '"null"' ); } function remove(auth, key) { setCookie(auth, key, "", false, -864e5); } var cookie = { get, set: setCookie, remove }; var cookie_default = cookie; // src/utils/index.ts function isObject(val) { if (val !== null && typeof val === "object" && val.constructor !== Array) { return true; } return false; } function toArray(val) { return typeof val === "string" || typeof val === "number" ? [val] : val; } function compare(one, two) { if (isObject(one) && isObject(two)) { for (const key in one) { if (compare(one[key], two[key])) { return true; } } return false; } const aone = toArray(one); const atwo = toArray(two); for (let i = 0, ii = aone.length; i < ii; i++) { if (atwo.includes(aone[i])) { return true; } } return false; } function isLocalStorage() { try { if (!window.localStorage) { throw "exception"; } localStorage.setItem("storage_test", "1"); localStorage.removeItem("storage_test"); return true; } catch (e) { return false; } } function isSessionStorage() { try { if (!window.sessionStorage) { throw "exception"; } sessionStorage.setItem("storage_test", "1"); sessionStorage.removeItem("storage_test"); return true; } catch (e) { return false; } } function isCookieStorage() { return true; } function getProperty(obj, desc) { const arr = desc.split("."); while (arr.length) { obj = obj[arr.shift()]; } return obj; } // src/helpers/storage.ts function set(key, value, expires) { const $ = JSON.stringify(value); if (expires) { sessionStorage.setItem(key, $); return; } localStorage.setItem(key, $); } function get2(key) { const $ = sessionStorage.getItem(key) || localStorage.getItem(key); if ($ === null) { return null; } return JSON.parse($); } function remove2(key) { localStorage.removeItem(key); sessionStorage.removeItem(key); } var storage = { get: get2, set, remove: remove2 }; var storage_default = storage; // src/helpers/token.ts function getTokenKey(key, auth) { key = key || auth.currentToken; if (key) { return key; } if (auth.impersonating()) { return auth.options.tokenImpersonateKey; } return auth.options.tokenDefaultKey; } function get3(auth, key) { const keyI = getTokenKey(key, auth); for (let i = 0; i < auth.options.stores.length; i++) { const store = auth.options.stores[i]; let val; if (typeof store === "object") { val = store.get(keyI); } if (store === "storage" && isLocalStorage() && isSessionStorage()) { val = storage_default.get(keyI); } if (store === "cookie" && isCookieStorage()) { val = cookie_default.get(auth, keyI); } if (val !== void 0) return val; } return null; } function set2(auth, key, value, expires) { const keyI = getTokenKey(key, auth); for (let i = 0; i < auth.options.stores.length; i++) { const store = auth.options.stores[i]; if (typeof store === "object") { store.set(keyI, value, expires, auth); } if (store === "storage" && isLocalStorage() && isSessionStorage()) { storage_default.set(keyI, value, expires); } if (store === "cookie" && isCookieStorage()) { cookie_default.set(auth, keyI, value, expires); } } } function remove3(auth, key) { for (let i = 0; i < auth.options.stores.length; i++) { const store = auth.options.stores[i]; const keyI = getTokenKey(key, auth); if (typeof store === "object") { store.remove(keyI); } if (store === "storage" && isLocalStorage() && isSessionStorage()) { storage_default.remove(keyI); } if (store === "cookie" && isCookieStorage()) { cookie_default.remove(auth, keyI); } } } var token = { get: get3, set: set2, remove: remove3 }; var token_default = token; // src/helpme/getAuthMeta.ts function getAuthMeta({ matched }) { let auth; const authRoutes = matched.filter( ({ meta }) => Object.prototype.hasOwnProperty.call(meta, "auth") ); if (authRoutes.length) { auth = authRoutes[authRoutes.length - 1].meta.auth; } return auth != null ? auth : null; } // src/injectionKey.ts var authKey = typeof Symbol !== "undefined" ? Symbol("auth") : "auth"; // src/utils/extend.ts function extend(target, deep = 1, ...objs) { objs.forEach((obj) => { for (const prop in obj) { if (deep > 0 && typeof target[prop] === "object" && target[prop] !== null && typeof obj[prop] === "object" && obj[prop] !== null) { extend(target[prop], deep - 1, obj[prop]); continue; } ; target[prop] = obj[prop]; } }); return target; } // src/Auth.ts function logout(auth, redirect) { cookie_default.remove(auth, auth.options.tokenImpersonateKey); cookie_default.remove(auth, auth.options.tokenDefaultKey); token_default.remove(auth, auth.options.tokenImpersonateKey); token_default.remove(auth, auth.options.tokenDefaultKey); token_default.remove(auth, auth.options.staySignedInKey); token_default.remove(auth, auth.options.userKey); auth.state.loaded = true; auth.state.authenticated = false; auth.state.data = null; routerPush(auth, redirect); } function routerPush(auth, redirect) { var _a, _b; if (redirect) { (_b = (_a = auth.options.plugins) == null ? void 0 : _a.router) == null ? void 0 : _b.push(redirect).catch(() => { }); } } function setUserData(auth, data, redirect) { auth.state.data = data; auth.state.loaded = true; auth.state.authenticated = true; routerPush(auth, redirect); } function processTransitionEach(auth, to, authMeta, cb) { var _a; let authRedirect = ( // eslint-disable-next-line @typescript-eslint/no-explicit-any (_a = authMeta == null ? void 0 : authMeta.redirect) != null ? _a : auth.options.authRedirect ); let forbiddenRedirect = ( // eslint-disable-next-line @typescript-eslint/no-explicit-any (authMeta == null ? void 0 : authMeta.forbiddenRedirect) || // eslint-disable-next-line @typescript-eslint/no-explicit-any (authMeta == null ? void 0 : authMeta.redirect) || auth.options.forbiddenRedirect ); let notFoundRedirect = ( // eslint-disable-next-line @typescript-eslint/no-explicit-any (authMeta == null ? void 0 : authMeta.notFoundRedirect) || // eslint-disable-next-line @typescript-eslint/no-explicit-any (authMeta == null ? void 0 : authMeta.redirect) || auth.options.notFoundRedirect ); const rolesKey = (authMeta == null ? void 0 : authMeta.rolesKey) || auth.options.rolesKey; const roles = toArray( // eslint-disable-next-line @typescript-eslint/no-explicit-any (authMeta == null ? void 0 : authMeta.roles) !== void 0 ? ( // eslint-disable-next-line @typescript-eslint/no-explicit-any authMeta.roles ) : ( // eslint-disable-next-line @typescript-eslint/no-explicit-any authMeta ) ); if (roles === true || typeof roles === "object" && roles !== null) { if (!auth.check()) { auth.tStatusType = 401; if (typeof authRedirect === "function") { authRedirect = authRedirect(to); } cb(authRedirect); return; } if (typeof roles === "object" && !compare(roles, getProperty(auth.state.data || {}, rolesKey))) { auth.tStatusType = 403; if (typeof forbiddenRedirect === "function") { forbiddenRedirect = forbiddenRedirect(to); } cb(forbiddenRedirect); return; } auth._redirect.value = auth.tStatusType ? { type: auth.tStatusType, from: auth.tPrev, to: auth.tCurrent } : null; auth.tStatusType = null; cb(); return; } if (roles === false && auth.check()) { auth.tStatusType = 404; if (typeof notFoundRedirect === "function") { notFoundRedirect = notFoundRedirect(to); } cb(notFoundRedirect); return; } auth._redirect.value = auth.tStatusType ? { type: auth.tStatusType, from: auth.tPrev, to: auth.tCurrent } : null; auth.tStatusType = null; cb(); } function setRemember(auth, val) { if (val) { token_default.set(auth, auth.options.rememberKey, val, false); auth.state.remember = val; } else { token_default.remove(auth, auth.options.rememberKey); auth.state.remember = null; } } function setStaySignedIn(auth, staySignedIn) { if (staySignedIn === true) { token_default.set(auth, auth.options.staySignedInKey, true, false); } else { token_default.remove(auth, auth.options.staySignedInKey); } } function processImpersonate(auth, defaultToken, redirect) { if (auth.token()) { token_default.set( auth, auth.options.tokenImpersonateKey, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion auth.token(), token_default.get(auth, auth.options.staySignedInKey) ? false : true ); } token_default.set( auth, auth.options.tokenDefaultKey, defaultToken, token_default.get(auth, auth.options.staySignedInKey) ? false : true ); auth.state.impersonating = true; routerPush(auth, redirect); } function processUnimpersonate(auth, redirect) { token_default.remove(auth, auth.options.tokenImpersonateKey); auth.state.impersonating = false; routerPush(auth, redirect); } function parseRedirectUri(uri = "") { if (/^https?:\/\//.test(uri)) { return uri; } const url = `${location.protocol}//${window.location.hostname}${location.port ? `:${location.port}` : ""}`; return `${url}/${uri.replace(/^\/|\/$/g, "")}`; } var isAxiosError = (err) => err == null ? void 0 : err.isAxiosError; function authErrHandler(auth, err) { var _a; const status = isAxiosError(err) ? (_a = err.response) == null ? void 0 : _a.status : err.status; if (status === 401) { const isTokenExpired = !token_default.get(auth, null); if (isTokenExpired) auth.logout().catch(() => logout(auth)); } auth.state.offline = true; } var syning = null; function syncStorage(auth) { if (syning) return syning; return syning = _syncStorage(auth); } function _syncStorage(auth) { return __async(this, null, function* () { const isTokenExpired = !token_default.get(auth, null); if (isTokenExpired && auth.state.authenticated) { logout(auth); } let promiseRefresh = null; if (!isTokenExpired && !auth.state.loaded) { if (auth.options.refreshToken.enabled) { promiseRefresh = auth.refresh().catch((err) => authErrHandler(auth, err)); if (!auth.options.refreshToken.enabledInBackground) yield promiseRefresh; } } if (auth.state.authenticated === null && token_default.get(auth, null)) { const userCache = token_default.get(auth, auth.options.userKey); if (userCache && auth.state.cacheUser) { setUserData(auth, userCache); } if (auth.options.fetchData.enabled) { let fetchPromise = null; if (auth.options.fetchData.waitRefresh && promiseRefresh) fetchPromise = promiseRefresh.then( () => auth.fetch().catch((err) => authErrHandler(auth, err)) ); else fetchPromise = auth.fetch().catch((err) => authErrHandler(auth, err)); if (!auth.options.fetchData.enabledInBackground) yield fetchPromise; } } else { token_default.remove(auth, auth.options.userKey); auth.state.loaded = true; } }); } var Auth = class { constructor(options) { __publicField(this, "state", reactive({ // eslint-disable-next-line @typescript-eslint/no-explicit-any data: null, loaded: false, offline: false, authenticated: null, // TODO: false ? impersonating: null, remember: null, cacheUser: false })); __publicField(this, "_redirect", shallowRef(null)); __publicField(this, "options"); __publicField(this, "currentToken", null); __publicField(this, "tPrev", null); __publicField(this, "tCurrent", null); __publicField(this, "tStatusType", null); __publicField(this, "__timer_load"); var _a, _b, _c; this.options = extend(defaultOption_default, 2, options); this.state.cacheUser = (_a = this.options.fetchData.cache) != null ? _a : false; let dataWatcher; watch( () => this.state.cacheUser, (value) => { if (value) { dataWatcher = watch( () => this.state.data, (data) => { if (this.token()) token_default.set(this, this.options.userKey, data, false); }, { deep: true } ); } else { dataWatcher == null ? void 0 : dataWatcher(); token_default.remove(this, this.options.userKey); } }, { immediate: true } ); if ((this.options.refreshToken.enabled || this.options.refreshToken.enabledInBackground) && this.options.refreshToken.interval !== false && this.options.refreshToken.interval !== void 0 && this.options.refreshToken.interval > 0) { setInterval(() => { if ((this.options.refreshToken.enabled || this.options.refreshToken.enabledInBackground) && !!token_default.get(this, null)) { this.refresh().catch((err) => authErrHandler(this, err)); } }, this.options.refreshToken.interval * 1e3 * 60); } if (this.options.initSync) syncStorage(this); (_c = (_b = this.options.plugins) == null ? void 0 : _b.router) == null ? void 0 : _c.beforeEach((to, from, next) => __async(this, null, function* () { this.tPrev = this.tCurrent; this.tCurrent = from; yield syncStorage(this); const authMeta = getAuthMeta(to); processTransitionEach(this, to, authMeta, (redirect) => { if (!redirect) { next(); return; } next(redirect); }); })); } install(app, key = authKey) { app.provide(key, this); app.config.globalProperties.$auth = this; } http(options) { return __async(this, null, function* () { var _a, _b, _c; if (!options.ignoreVueAuth) { let tokenName; if (options.impersonating === false && this.impersonating()) { tokenName = this.options.tokenDefaultKey; } const token3 = token_default.get(this, tokenName != null ? tokenName : null); if (token3) { const { data, headers } = this.options.drivers.auth.request( this, { data: options.data, headers: options.headers || {} }, token3 ); options.data = data; options.headers = headers; } } const response = yield this.options.drivers.http.request(options); if (options.ignoreVueAuth) { return response; } if ((_b = (_a = this.options.drivers.http).invalidToken) == null ? void 0 : _b.call(_a, this, response)) { logout(this, ((_c = this.redirect()) == null ? void 0 : _c.to) || this.options.authRedirect); } const token2 = this.options.drivers.auth.response(this, response); if (token2) { token_default.set( this, null, token2, token_default.get(this, this.options.staySignedInKey) ? false : true ); } return response; }); } ready() { return this.state.loaded; } load() { return new Promise((resolve) => { this.__timer_load = setInterval(() => { if (this.state.loaded) { clearInterval(this.__timer_load); resolve(); } }, 50); }); } cancel() { clearInterval(this.__timer_load); } redirect() { return this._redirect.value; } user(data) { if (data !== void 0) { setUserData(this, data); } return this.state.data; } offline() { return this.state.offline; } check(role, key = this.options.rolesKey) { if (this.state.authenticated) { if (role) { return compare(role, getProperty(this.state.data || {}, key)); } return true; } return false; } impersonating() { const impersonating = token_default.get(this, this.options.tokenImpersonateKey) ? true : false; if (this.state.impersonating === null) { this.state.impersonating = impersonating; } return this.state.impersonating; } token(name = null, token2, expires) { if (token2 !== void 0) { if (token2 === null) { token_default.remove(this, name); } else { expires = expires != null ? expires : token_default.get(this, this.options.staySignedInKey) ? false : true; token_default.set(this, name, token2, expires); } } return token_default.get(this, name); } /** * @request auth/user * @returns Promise<user data> info user data (exm: { * username: "Tachibana Shin", email: "asjwepit32r@duck.com" }) */ fetch(data) { return __async(this, null, function* () { var _a, _b; const fetchData = __spreadProps(__spreadValues(__spreadValues({}, this.options.fetchData), data), { cache: (_a = data == null ? void 0 : data.cache) != null ? _a : this.state.cacheUser }); const response = yield this.http(fetchData); this.state.cacheUser = (_b = fetchData.cache) != null ? _b : this.state.cacheUser; const keyUser = fetchData.keyUser; setUserData( this, keyUser ? response.data[keyUser] : response.data, data == null ? void 0 : data.redirect ); return response; }); } /** * @request auth/refresh * @returns Promise exists token refresh in Authorizer */ refresh(data) { return this.http(__spreadValues(__spreadValues({}, this.options.refreshToken), data || {})); } register(data) { return __async(this, null, function* () { const registerData = __spreadValues(__spreadValues({}, this.options.registerData), data); if (registerData.autoLogin !== true) { setRemember(this, registerData.remember); setStaySignedIn(this, registerData.staySignedIn); } const response = yield this.http(registerData); if (registerData.autoLogin) { yield this.login(data); return response; } const keyUser = "keyUser" in registerData ? registerData.keyUser : this.options.fetchData.keyUser; setUserData( this, keyUser ? response.data[keyUser] : response.data, registerData.redirect ); return response; }); } login(data) { return __async(this, null, function* () { const loginData = __spreadValues(__spreadValues({}, this.options.loginData), data); setRemember(this, loginData.remember); setStaySignedIn(this, loginData.staySignedIn); const response = yield this.http(loginData); if (loginData.fetchUser && this.options.fetchData.enabled) { yield this.fetch({ redirect: loginData.redirect, cache: loginData.cacheUser }); } else { const keyUser = "keyUser" in loginData ? loginData.keyUser : this.options.fetchData.keyUser; setUserData( this, keyUser ? response.data[keyUser] : response.data, loginData.redirect ); } return response; }); } remember(val) { if (val) { setRemember(this, val); } const remember = token_default.get(this, this.options.rememberKey); if (this.state.remember === void 0) { this.state.remember = remember != null ? remember : false; } return this.state.remember; } unremember() { setRemember(this, void 0); } logout(data) { return __async(this, null, function* () { const logoutData = __spreadValues(__spreadValues({}, this.options.logoutData), data); if (logoutData.makeRequest) { yield this.http(logoutData); } logout(this, logoutData.redirect); }); } impersonate(data) { return __async(this, null, function* () { const impersonateData = __spreadValues(__spreadValues({}, this.options.impersonateData), data); const token2 = this.token(); yield this.http(impersonateData); processImpersonate(this, token2); if (impersonateData.fetchUser || this.options.fetchData.enabled) { yield this.fetch({ redirect: impersonateData.redirect, cache: impersonateData.cacheUser }); return; } routerPush(this, impersonateData.redirect); }); } unimpersonate(data) { return __async(this, null, function* () { const unimpersonateData = __spreadValues(__spreadValues({}, this.options.unimpersonateData), data); if (unimpersonateData.makeRequest) { yield this.http(unimpersonateData); } processUnimpersonate(this); if (unimpersonateData.fetchUser || this.options.fetchData.enabled) { yield this.fetch({ redirect: unimpersonateData.redirect, cache: unimpersonateData.cacheUser }); return; } }); } oauth2(type, data) { const params = []; if (data.code) { try { if (data.state) { data.state = JSON.parse(decodeURIComponent(data.state)); } } catch (e) { console.error( "vue-auth:error There was an issue retrieving the state data." ); } data = extend(this.options.oauth2Data, 2, data.state, data); return this.login(data); } data = extend(this.options.drivers.oauth2[type], 2, data); data.params.state = JSON.stringify(data.params.state || {}); data.params.redirect_uri = parseRedirectUri(data.params.redirect_uri); Object.keys(data.params).forEach((key) => { params.push(`${key}=${encodeURIComponent(data.params[key])}`); }); window.open( `${data.url}?${params.join("&")}`, (data.window || {}).name || "_self", (data.window || {}).specs || {} ); } enableImpersonate() { if (this.impersonating()) { this.currentToken = null; } } disableImpersonate() { if (this.impersonating()) { this.currentToken = this.options.tokenDefaultKey; } } }; // src/index.ts function createAuth(options) { return new Auth(options); } function useAuth(key = authKey) { return inject(key); } function useUser(key = authKey) { const auth = useAuth(key); return computed(() => { return auth.user(); }); } export { createAuth, defineAuthDriver, defineHttpDriver, defineOAuth2Driver, useAuth, useUser }; //# sourceMappingURL=index.mjs.map