vue-auth3
Version:
<p align="center"> <img src="./docs/public/icon.svg" width="180px"> </p>
889 lines (875 loc) • 25.7 kB
JavaScript
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