@pubinfo-pr/module-auth 0.203.2 → 0.203.4
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.
- package/dist/auth.d.ts +1 -6
- package/dist/context.d.ts +4 -0
- package/dist/deprecated.d.ts +8 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.js +27 -15
- package/dist/interface.d.ts +4 -1
- package/dist/plugins/two-factor.d.ts +12 -2
- package/dist/plugins.js +14 -11
- package/package.json +3 -3
- package/src/auth.ts +4 -81
- package/src/components/RedirectLogin/index.ts +5 -3
- package/src/context.ts +14 -0
- package/src/core.ts +9 -3
- package/src/deprecated.ts +85 -0
- package/src/index.ts +7 -6
- package/src/interface.ts +5 -1
- package/src/plugins/two-factor.ts +46 -26
package/dist/auth.d.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import type { ModuleOptions } from 'pubinfo-pr';
|
|
2
2
|
import type { AuthClient as AuthClientInstance } from './core';
|
|
3
|
-
import type {
|
|
4
|
-
export declare const AuthClient: AuthClientInstance;
|
|
5
|
-
/**
|
|
6
|
-
* @deprecated 请使用 `createAuthModule` 和 `createAuth` 替换
|
|
7
|
-
*/
|
|
8
|
-
export declare function auth<Plugins extends PluginOptions[]>(options: AuthOptions<Plugins>): ModuleOptions;
|
|
3
|
+
import type { CreateAuthModule } from './interface';
|
|
9
4
|
export declare function createAuthModule(authClient: AuthClientInstance, options?: CreateAuthModule): ModuleOptions;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ModuleOptions } from 'pubinfo-pr';
|
|
2
|
+
import type { AuthClient as AuthClientInstance } from './core';
|
|
3
|
+
import type { AuthOptions, PluginOptions } from './interface';
|
|
4
|
+
export declare const AuthClient: AuthClientInstance;
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated 请使用 `createAuthModule` 和 `createAuth` 替换
|
|
7
|
+
*/
|
|
8
|
+
export declare function auth<Plugins extends PluginOptions[]>(options: AuthOptions<Plugins>): ModuleOptions;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { createAuthModule } from './auth';
|
|
2
2
|
export { LoginWithFourA } from './components/LoginWithFourA';
|
|
3
3
|
export { createAuth } from './core';
|
|
4
|
+
export { auth } from './deprecated';
|
|
4
5
|
export * from './interface';
|
|
5
6
|
/**
|
|
6
|
-
* @deprecated 认证, 请使用 `
|
|
7
|
+
* @deprecated 认证, 请使用 `authClient.authenticate` 方法替代
|
|
7
8
|
*/
|
|
8
9
|
export declare const authenticate: (id: import("./interface").ThirdParty) => Promise<any>;
|
|
9
10
|
/**
|
|
10
|
-
* @deprecated 重定向至统一登录页, 请使用 `
|
|
11
|
+
* @deprecated 重定向至统一登录页, 请使用 `authClient.redirect` 方法替代
|
|
11
12
|
*/
|
|
12
13
|
export declare const redirect: () => void;
|
|
13
14
|
/**
|
|
14
|
-
* @deprecated 生成二维码, 请使用 `
|
|
15
|
+
* @deprecated 生成二维码, 请使用 `authClient.renderQRCode` 方法替代
|
|
15
16
|
*/
|
|
16
17
|
export declare const renderQRCode: (id: import("./interface").ThirdParty, options: {
|
|
17
18
|
id: string;
|
|
18
19
|
} & import("./interface").Recordable) => void;
|
|
19
20
|
/**
|
|
20
|
-
* @deprecated 前往登录, 请使用 `
|
|
21
|
+
* @deprecated 前往登录, 请使用 `authClient.signIn` 方法替代
|
|
21
22
|
*/
|
|
22
23
|
export declare const signIn: (id: import("./interface").ThirdParty, options?: import("./interface").Recordable) => Promise<any> | any;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cleanup, defineIconModule, defineRouteModule, useUserStore } from "pubinfo-pr";
|
|
2
|
-
import { defineComponent, h, onMounted, ref } from "vue";
|
|
2
|
+
import { defineComponent, h, inject, onMounted, ref } from "vue";
|
|
3
3
|
import { useRoute, useRouter } from "vue-router";
|
|
4
4
|
var _virtual_pubinfo_resolver_default = {
|
|
5
5
|
icons: {},
|
|
@@ -22,10 +22,13 @@ function createAuth(e) {
|
|
|
22
22
|
if (!t) throw Error(`Provider '${e}' is not found.`);
|
|
23
23
|
return t;
|
|
24
24
|
}
|
|
25
|
-
let a = {
|
|
25
|
+
let a = { data: {} }, o = {
|
|
26
26
|
async signIn(e, t) {
|
|
27
27
|
let n = i(e);
|
|
28
|
-
if (typeof n.signIn == "function")
|
|
28
|
+
if (typeof n.signIn == "function") {
|
|
29
|
+
let e = await n.signIn(t);
|
|
30
|
+
return a.data = e, e;
|
|
31
|
+
}
|
|
29
32
|
if (["oauth", "custom"].includes(n.type)) {
|
|
30
33
|
let e = createUrlByProvider(n);
|
|
31
34
|
window.location.replace(e);
|
|
@@ -58,8 +61,8 @@ function createAuth(e) {
|
|
|
58
61
|
},
|
|
59
62
|
getProvider: i
|
|
60
63
|
};
|
|
61
|
-
for (let e of r) Object.assign(
|
|
62
|
-
return
|
|
64
|
+
for (let e of r) Object.assign(o, e.extend?.(a));
|
|
65
|
+
return o;
|
|
63
66
|
}
|
|
64
67
|
const PageAuth = defineComponent({
|
|
65
68
|
props: {
|
|
@@ -68,7 +71,7 @@ const PageAuth = defineComponent({
|
|
|
68
71
|
authenticate: Function
|
|
69
72
|
},
|
|
70
73
|
setup(e) {
|
|
71
|
-
let t = useUserStore(), n = useRoute(), i = useRouter(),
|
|
74
|
+
let t = useUserStore(), n = useRoute(), i = useRouter(), o = ref("授权登录中...");
|
|
72
75
|
return onMounted(async () => {
|
|
73
76
|
let r = await e.authenticate?.(e.type);
|
|
74
77
|
if (r?.success) {
|
|
@@ -79,14 +82,14 @@ const PageAuth = defineComponent({
|
|
|
79
82
|
return;
|
|
80
83
|
}
|
|
81
84
|
e?.redirectTo?.();
|
|
82
|
-
} else
|
|
85
|
+
} else o.value = r?.msg ?? r?.message;
|
|
83
86
|
}), () => h("div", { style: {
|
|
84
87
|
display: "flex",
|
|
85
88
|
justifyContent: "center",
|
|
86
89
|
alignItems: "center",
|
|
87
90
|
width: "100vw",
|
|
88
91
|
height: "100vh"
|
|
89
|
-
} },
|
|
92
|
+
} }, o.value);
|
|
90
93
|
}
|
|
91
94
|
});
|
|
92
95
|
var authClient;
|
|
@@ -134,13 +137,22 @@ function auth(t) {
|
|
|
134
137
|
}
|
|
135
138
|
};
|
|
136
139
|
}
|
|
140
|
+
var key = Symbol("auth");
|
|
141
|
+
function createAuthClientContext(e, t) {
|
|
142
|
+
e.provide(key, t);
|
|
143
|
+
}
|
|
144
|
+
function useAuthClientContext() {
|
|
145
|
+
return inject(key, AuthClient);
|
|
146
|
+
}
|
|
137
147
|
function createAuthModule(t, n = {}) {
|
|
138
148
|
let { redirectTo: r = "/", pages: i = {} } = n, { signIn: a = "/login" } = i;
|
|
139
149
|
return {
|
|
140
150
|
name: "pubinfo-pr:auth",
|
|
141
151
|
enforce: "pre",
|
|
142
152
|
setup(n) {
|
|
143
|
-
let { router: i } = n
|
|
153
|
+
let { router: i, app: o } = n;
|
|
154
|
+
createAuthClientContext(o, t);
|
|
155
|
+
let s = {
|
|
144
156
|
path: "/auth/:type",
|
|
145
157
|
name: "Auth",
|
|
146
158
|
component: PageAuth,
|
|
@@ -161,8 +173,8 @@ function createAuthModule(t, n = {}) {
|
|
|
161
173
|
})
|
|
162
174
|
};
|
|
163
175
|
i.beforeEach((n) => {
|
|
164
|
-
if (!i.hasRoute(
|
|
165
|
-
n.name ===
|
|
176
|
+
if (!i.hasRoute(s.name)) return i.addRoute(s), n.fullPath;
|
|
177
|
+
n.name === s.name && cleanup(), n.path === a && t.redirect();
|
|
166
178
|
});
|
|
167
179
|
}
|
|
168
180
|
};
|
|
@@ -176,7 +188,7 @@ const RedirectLogin = defineComponent({
|
|
|
176
188
|
color: String
|
|
177
189
|
},
|
|
178
190
|
setup(e) {
|
|
179
|
-
let t =
|
|
191
|
+
let t = useAuthClientContext(), n = t.getProvider(e.id);
|
|
180
192
|
return () => h("div", [h("div", { style: { padding: "3rem" } }, h("img", {
|
|
181
193
|
src: e.src,
|
|
182
194
|
class: "w-full"
|
|
@@ -193,8 +205,8 @@ const RedirectLogin = defineComponent({
|
|
|
193
205
|
letterSpacing: "0.1em",
|
|
194
206
|
backgroundColor: e.color
|
|
195
207
|
},
|
|
196
|
-
onClick: () =>
|
|
197
|
-
}, `前往${
|
|
208
|
+
onClick: () => t.signIn(n.id)
|
|
209
|
+
}, `前往${n.name}`)]);
|
|
198
210
|
}
|
|
199
211
|
}), LoginWithFourA = defineComponent({
|
|
200
212
|
name: "LoginWithFourA",
|
|
@@ -212,4 +224,4 @@ const RedirectLogin = defineComponent({
|
|
|
212
224
|
});
|
|
213
225
|
defineRouteModule("auth", _virtual_pubinfo_resolver_default.pages), defineIconModule("auth", _virtual_pubinfo_resolver_default.icons);
|
|
214
226
|
const authenticate = AuthClient.authenticate, redirect = AuthClient.redirect, renderQRCode = AuthClient.renderQRCode, signIn = AuthClient.signIn;
|
|
215
|
-
export {
|
|
227
|
+
export { LoginWithFourA, auth, authenticate, createAuth, createAuthModule, redirect, renderQRCode, signIn };
|
package/dist/interface.d.ts
CHANGED
|
@@ -25,10 +25,13 @@ export interface CreateAuthModule {
|
|
|
25
25
|
signIn?: RouteLocationRaw;
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
+
export interface PluginContext {
|
|
29
|
+
data: Recordable;
|
|
30
|
+
}
|
|
28
31
|
export interface PluginOptions<Extend = any> {
|
|
29
32
|
/** 唯一值 */
|
|
30
33
|
id: string;
|
|
31
|
-
extend?: (context:
|
|
34
|
+
extend?: (context: PluginContext) => Extend;
|
|
32
35
|
}
|
|
33
36
|
/** 第三方类型 */
|
|
34
37
|
export type ThirdParty = string;
|
|
@@ -8,9 +8,19 @@ interface TwoFactorExtend {
|
|
|
8
8
|
}>;
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
/** 请求实例 */
|
|
11
|
+
interface DefaultOptOptions {
|
|
13
12
|
request: RequestInstance;
|
|
13
|
+
sendOtp?: TwoFactorExtend['twoFactor']['sendOtp'];
|
|
14
|
+
verifyOtp?: TwoFactorExtend['twoFactor']['verifyOtp'];
|
|
14
15
|
}
|
|
16
|
+
interface CustomOptOptions {
|
|
17
|
+
request: never;
|
|
18
|
+
sendOtp: TwoFactorExtend['twoFactor']['sendOtp'];
|
|
19
|
+
verifyOtp: TwoFactorExtend['twoFactor']['verifyOtp'];
|
|
20
|
+
}
|
|
21
|
+
export type TwoFactorOptions = DefaultOptOptions | CustomOptOptions;
|
|
22
|
+
/**
|
|
23
|
+
* `双因子认证插件`
|
|
24
|
+
*/
|
|
15
25
|
export declare function twoFactor(options: TwoFactorOptions): PluginOptions<TwoFactorExtend>;
|
|
16
26
|
export {};
|
package/dist/plugins.js
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
function twoFactor(e) {
|
|
2
|
-
let { request: t } = e;
|
|
2
|
+
let { request: t, sendOtp: n, verifyOtp: r } = e;
|
|
3
3
|
return {
|
|
4
4
|
id: "two-factor",
|
|
5
|
-
extend() {
|
|
5
|
+
extend(e) {
|
|
6
6
|
return { twoFactor: {
|
|
7
|
-
sendOtp(
|
|
8
|
-
|
|
7
|
+
sendOtp: (r) => {
|
|
8
|
+
let i = e.data?.data?.login2faCode;
|
|
9
|
+
return n ? n(r) : t.Post("/auth/2fa/prepare", {
|
|
9
10
|
fa2Type: "sms",
|
|
10
|
-
login2faCode:
|
|
11
|
-
...
|
|
11
|
+
login2faCode: i,
|
|
12
|
+
...r
|
|
12
13
|
});
|
|
13
14
|
},
|
|
14
|
-
verifyOtp(
|
|
15
|
-
let
|
|
15
|
+
verifyOtp: (n) => {
|
|
16
|
+
let i = e.data?.data?.login2faCode;
|
|
17
|
+
if (r) return r(n);
|
|
18
|
+
let { code: a, ...o } = n ?? {};
|
|
16
19
|
return t.Post("/auth/2fa/verify", {
|
|
17
20
|
fa2Type: "sms",
|
|
18
|
-
login2faCode:
|
|
19
|
-
verifyCode:
|
|
20
|
-
...
|
|
21
|
+
login2faCode: i,
|
|
22
|
+
verifyCode: a,
|
|
23
|
+
...o
|
|
21
24
|
});
|
|
22
25
|
}
|
|
23
26
|
} };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pubinfo-pr/module-auth",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.203.
|
|
4
|
+
"version": "0.203.4",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"node": "^20.19.0 || >=22.12.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"pubinfo-pr": "0.203.
|
|
34
|
+
"pubinfo-pr": "0.203.4"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"pubinfo-pr": "0.203.
|
|
37
|
+
"pubinfo-pr": "0.203.4"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"dev": "pubinfo build --watch",
|
package/src/auth.ts
CHANGED
|
@@ -1,89 +1,11 @@
|
|
|
1
1
|
import type { ModuleOptions } from 'pubinfo-pr';
|
|
2
2
|
import type { RouteRecordRaw } from 'vue-router';
|
|
3
3
|
import type { AuthClient as AuthClientInstance } from './core';
|
|
4
|
-
import type {
|
|
4
|
+
import type { CreateAuthModule } from './interface';
|
|
5
5
|
import { cleanup } from 'pubinfo-pr';
|
|
6
|
-
import {
|
|
6
|
+
import { createAuthClientContext } from './context';
|
|
7
7
|
import { PageAuth } from './pages/auth';
|
|
8
8
|
|
|
9
|
-
let authClient!: AuthClientInstance;
|
|
10
|
-
|
|
11
|
-
export const AuthClient: AuthClientInstance = {
|
|
12
|
-
signIn: (...args) => authClient.signIn(...args),
|
|
13
|
-
authenticate: (...args) => authClient.authenticate(...args),
|
|
14
|
-
renderQRCode: (...args) => authClient.renderQRCode(...args),
|
|
15
|
-
redirect: (...args) => authClient.redirect(...args),
|
|
16
|
-
getProvider: (...args) => authClient.getProvider(...args),
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @deprecated 请使用 `createAuthModule` 和 `createAuth` 替换
|
|
21
|
-
*/
|
|
22
|
-
export function auth<Plugins extends PluginOptions[]>(options: AuthOptions<Plugins>): ModuleOptions {
|
|
23
|
-
const {
|
|
24
|
-
redirectTo = '/',
|
|
25
|
-
pages = {},
|
|
26
|
-
baseURL,
|
|
27
|
-
providers,
|
|
28
|
-
plugins,
|
|
29
|
-
} = options;
|
|
30
|
-
const { signIn = '/login' } = pages;
|
|
31
|
-
|
|
32
|
-
authClient = createAuth<Plugins>({
|
|
33
|
-
baseURL,
|
|
34
|
-
providers,
|
|
35
|
-
plugins,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
name: 'pubinfo-pr:auth',
|
|
40
|
-
enforce: 'pre',
|
|
41
|
-
setup(ctx) {
|
|
42
|
-
const { router } = ctx;
|
|
43
|
-
|
|
44
|
-
const ROUTE_AUTH: RouteRecordRaw = {
|
|
45
|
-
path: '/auth/:type',
|
|
46
|
-
name: 'Auth',
|
|
47
|
-
component: PageAuth,
|
|
48
|
-
meta: {
|
|
49
|
-
whiteList: true,
|
|
50
|
-
title: '授权登录',
|
|
51
|
-
},
|
|
52
|
-
props: route => ({
|
|
53
|
-
type: route.params.type,
|
|
54
|
-
authenticate: authClient.authenticate,
|
|
55
|
-
redirectTo() {
|
|
56
|
-
if (typeof redirectTo === 'function') {
|
|
57
|
-
redirectTo();
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
router.push(redirectTo);
|
|
62
|
-
},
|
|
63
|
-
}),
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
router.beforeEach((to) => {
|
|
67
|
-
// 注册静态页面
|
|
68
|
-
if (!router.hasRoute(ROUTE_AUTH.name!)) {
|
|
69
|
-
router.addRoute(ROUTE_AUTH);
|
|
70
|
-
return to.fullPath;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// 前往单点登录前,清空登录状态
|
|
74
|
-
if (to.name === ROUTE_AUTH.name) {
|
|
75
|
-
cleanup();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// 前往登录前,重定向至统一登录页(若有)
|
|
79
|
-
if (to.path === signIn) {
|
|
80
|
-
authClient.redirect();
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
9
|
export function createAuthModule(authClient: AuthClientInstance, options: CreateAuthModule = {}): ModuleOptions {
|
|
88
10
|
const {
|
|
89
11
|
redirectTo = '/',
|
|
@@ -95,7 +17,8 @@ export function createAuthModule(authClient: AuthClientInstance, options: Create
|
|
|
95
17
|
name: 'pubinfo-pr:auth',
|
|
96
18
|
enforce: 'pre',
|
|
97
19
|
setup(ctx) {
|
|
98
|
-
const { router } = ctx;
|
|
20
|
+
const { router, app } = ctx;
|
|
21
|
+
createAuthClientContext(app, authClient);
|
|
99
22
|
|
|
100
23
|
const ROUTE_AUTH: RouteRecordRaw = {
|
|
101
24
|
path: '/auth/:type',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent, h } from 'vue';
|
|
2
|
-
import {
|
|
2
|
+
import { useAuthClientContext } from '@/context';
|
|
3
3
|
|
|
4
4
|
export const RedirectLogin = defineComponent({
|
|
5
5
|
name: 'RedirectLogin',
|
|
@@ -9,7 +9,9 @@ export const RedirectLogin = defineComponent({
|
|
|
9
9
|
color: String,
|
|
10
10
|
},
|
|
11
11
|
setup(props) {
|
|
12
|
-
const
|
|
12
|
+
const authClient = useAuthClientContext();
|
|
13
|
+
const provider = authClient.getProvider(props.id);
|
|
14
|
+
|
|
13
15
|
return () => {
|
|
14
16
|
return h('div', [
|
|
15
17
|
h(
|
|
@@ -32,7 +34,7 @@ export const RedirectLogin = defineComponent({
|
|
|
32
34
|
letterSpacing: '0.1em',
|
|
33
35
|
backgroundColor: props.color,
|
|
34
36
|
},
|
|
35
|
-
onClick: () =>
|
|
37
|
+
onClick: () => authClient.signIn(provider.id),
|
|
36
38
|
},
|
|
37
39
|
`前往${provider.name}`,
|
|
38
40
|
),
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { App } from 'vue';
|
|
2
|
+
import type { AuthClient as AuthClientInstance } from './core';
|
|
3
|
+
import { inject } from 'vue';
|
|
4
|
+
import { AuthClient } from './deprecated';
|
|
5
|
+
|
|
6
|
+
const key = Symbol('auth');
|
|
7
|
+
|
|
8
|
+
export function createAuthClientContext(app: App, authClient: AuthClientInstance) {
|
|
9
|
+
app.provide(key, authClient);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useAuthClientContext() {
|
|
13
|
+
return inject(key, AuthClient) as AuthClientInstance;
|
|
14
|
+
}
|
package/src/core.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PluginOptions, ProviderOptions, Recordable, ThirdParty } from './interface';
|
|
1
|
+
import type { PluginContext, PluginOptions, ProviderOptions, Recordable, ThirdParty } from './interface';
|
|
2
2
|
import { createUrl, createUrlByProvider } from './helper';
|
|
3
3
|
|
|
4
4
|
export interface CreateAuthOptions<Plugins extends PluginOptions[]> {
|
|
@@ -68,6 +68,10 @@ export function createAuth<Plugins extends PluginOptions[]>(options: CreateAuthO
|
|
|
68
68
|
return provider;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
const context: PluginContext = {
|
|
72
|
+
data: {},
|
|
73
|
+
};
|
|
74
|
+
|
|
71
75
|
const authClient = {
|
|
72
76
|
/**
|
|
73
77
|
* 前往登录
|
|
@@ -78,7 +82,9 @@ export function createAuth<Plugins extends PluginOptions[]>(options: CreateAuthO
|
|
|
78
82
|
const provider = getProvider(id);
|
|
79
83
|
|
|
80
84
|
if (typeof provider.signIn === 'function') {
|
|
81
|
-
|
|
85
|
+
const res = await provider.signIn(options);
|
|
86
|
+
context.data = res;
|
|
87
|
+
return res;
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
if (['oauth', 'custom'].includes(provider.type)) {
|
|
@@ -147,7 +153,7 @@ export function createAuth<Plugins extends PluginOptions[]>(options: CreateAuthO
|
|
|
147
153
|
};
|
|
148
154
|
|
|
149
155
|
for (const plugin of plugins) {
|
|
150
|
-
Object.assign(authClient, plugin.extend?.(
|
|
156
|
+
Object.assign(authClient, plugin.extend?.(context));
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
return authClient as AuthClient & PluginExtend<Plugins>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ModuleOptions } from 'pubinfo-pr';
|
|
2
|
+
import type { RouteRecordRaw } from 'vue-router';
|
|
3
|
+
import type { AuthClient as AuthClientInstance } from './core';
|
|
4
|
+
import type { AuthOptions, PluginOptions } from './interface';
|
|
5
|
+
import { cleanup } from 'pubinfo-pr';
|
|
6
|
+
import { createAuth } from './core';
|
|
7
|
+
import { PageAuth } from './pages/auth';
|
|
8
|
+
|
|
9
|
+
let authClient!: AuthClientInstance;
|
|
10
|
+
|
|
11
|
+
export const AuthClient: AuthClientInstance = {
|
|
12
|
+
signIn: (...args) => authClient.signIn(...args),
|
|
13
|
+
authenticate: (...args) => authClient.authenticate(...args),
|
|
14
|
+
renderQRCode: (...args) => authClient.renderQRCode(...args),
|
|
15
|
+
redirect: (...args) => authClient.redirect(...args),
|
|
16
|
+
getProvider: (...args) => authClient.getProvider(...args),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated 请使用 `createAuthModule` 和 `createAuth` 替换
|
|
21
|
+
*/
|
|
22
|
+
export function auth<Plugins extends PluginOptions[]>(options: AuthOptions<Plugins>): ModuleOptions {
|
|
23
|
+
const {
|
|
24
|
+
redirectTo = '/',
|
|
25
|
+
pages = {},
|
|
26
|
+
baseURL,
|
|
27
|
+
providers,
|
|
28
|
+
plugins,
|
|
29
|
+
} = options;
|
|
30
|
+
const { signIn = '/login' } = pages;
|
|
31
|
+
|
|
32
|
+
authClient = createAuth<Plugins>({
|
|
33
|
+
baseURL,
|
|
34
|
+
providers,
|
|
35
|
+
plugins,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
name: 'pubinfo-pr:auth',
|
|
40
|
+
enforce: 'pre',
|
|
41
|
+
setup(ctx) {
|
|
42
|
+
const { router } = ctx;
|
|
43
|
+
|
|
44
|
+
const ROUTE_AUTH: RouteRecordRaw = {
|
|
45
|
+
path: '/auth/:type',
|
|
46
|
+
name: 'Auth',
|
|
47
|
+
component: PageAuth,
|
|
48
|
+
meta: {
|
|
49
|
+
whiteList: true,
|
|
50
|
+
title: '授权登录',
|
|
51
|
+
},
|
|
52
|
+
props: route => ({
|
|
53
|
+
type: route.params.type,
|
|
54
|
+
authenticate: authClient.authenticate,
|
|
55
|
+
redirectTo() {
|
|
56
|
+
if (typeof redirectTo === 'function') {
|
|
57
|
+
redirectTo();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
router.push(redirectTo);
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
router.beforeEach((to) => {
|
|
67
|
+
// 注册静态页面
|
|
68
|
+
if (!router.hasRoute(ROUTE_AUTH.name!)) {
|
|
69
|
+
router.addRoute(ROUTE_AUTH);
|
|
70
|
+
return to.fullPath;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 前往单点登录前,清空登录状态
|
|
74
|
+
if (to.name === ROUTE_AUTH.name) {
|
|
75
|
+
cleanup();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 前往登录前,重定向至统一登录页(若有)
|
|
79
|
+
if (to.path === signIn) {
|
|
80
|
+
authClient.redirect();
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import { AuthClient } from './
|
|
1
|
+
import { AuthClient } from './deprecated';
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export { createAuthModule } from './auth';
|
|
4
4
|
export { LoginWithFourA } from './components/LoginWithFourA';
|
|
5
5
|
export { createAuth } from './core';
|
|
6
|
+
export { auth } from './deprecated';
|
|
6
7
|
export * from './interface';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
* @deprecated 认证, 请使用 `
|
|
10
|
+
* @deprecated 认证, 请使用 `authClient.authenticate` 方法替代
|
|
10
11
|
*/
|
|
11
12
|
export const authenticate = AuthClient.authenticate;
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
* @deprecated 重定向至统一登录页, 请使用 `
|
|
15
|
+
* @deprecated 重定向至统一登录页, 请使用 `authClient.redirect` 方法替代
|
|
15
16
|
*/
|
|
16
17
|
export const redirect = AuthClient.redirect;
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
|
-
* @deprecated 生成二维码, 请使用 `
|
|
20
|
+
* @deprecated 生成二维码, 请使用 `authClient.renderQRCode` 方法替代
|
|
20
21
|
*/
|
|
21
22
|
export const renderQRCode = AuthClient.renderQRCode;
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
|
-
* @deprecated 前往登录, 请使用 `
|
|
25
|
+
* @deprecated 前往登录, 请使用 `authClient.signIn` 方法替代
|
|
25
26
|
*/
|
|
26
27
|
export const signIn = AuthClient.signIn;
|
package/src/interface.ts
CHANGED
|
@@ -33,11 +33,15 @@ export interface CreateAuthModule {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export interface PluginContext {
|
|
37
|
+
data: Recordable
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
export interface PluginOptions<Extend = any> {
|
|
37
41
|
/** 唯一值 */
|
|
38
42
|
id: string
|
|
39
43
|
|
|
40
|
-
extend?: (context:
|
|
44
|
+
extend?: (context: PluginContext) => Extend
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
/** 第三方类型 */
|
|
@@ -8,42 +8,62 @@ interface TwoFactorExtend {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
/** 请求实例 */
|
|
11
|
+
interface DefaultOptOptions {
|
|
13
12
|
request: RequestInstance
|
|
13
|
+
sendOtp?: TwoFactorExtend['twoFactor']['sendOtp']
|
|
14
|
+
verifyOtp?: TwoFactorExtend['twoFactor']['verifyOtp']
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
interface CustomOptOptions {
|
|
18
|
+
request: never
|
|
19
|
+
sendOtp: TwoFactorExtend['twoFactor']['sendOtp']
|
|
20
|
+
verifyOtp: TwoFactorExtend['twoFactor']['verifyOtp']
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type TwoFactorOptions = DefaultOptOptions | CustomOptOptions;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `双因子认证插件`
|
|
27
|
+
*/
|
|
16
28
|
export function twoFactor(options: TwoFactorOptions): PluginOptions<TwoFactorExtend> {
|
|
17
|
-
const { request } = options;
|
|
29
|
+
const { request, sendOtp, verifyOtp } = options;
|
|
18
30
|
|
|
19
31
|
return {
|
|
20
32
|
id: 'two-factor',
|
|
21
|
-
extend() {
|
|
22
|
-
|
|
23
|
-
|
|
33
|
+
extend(context) {
|
|
34
|
+
const twoFactor: TwoFactorExtend['twoFactor'] = {
|
|
35
|
+
sendOtp: (payload) => {
|
|
36
|
+
const login2faCode = context.data?.data?.login2faCode;
|
|
37
|
+
if (sendOtp) {
|
|
38
|
+
return sendOtp(payload);
|
|
39
|
+
}
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
41
|
+
return request.Post('/auth/2fa/prepare', {
|
|
42
|
+
fa2Type: 'sms',
|
|
43
|
+
login2faCode,
|
|
44
|
+
...payload,
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
verifyOtp: (payload) => {
|
|
49
|
+
const login2faCode = context.data?.data?.login2faCode;
|
|
50
|
+
if (verifyOtp) {
|
|
51
|
+
return verifyOtp(payload);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { code, ...params } = payload ?? {};
|
|
55
|
+
return request.Post('/auth/2fa/verify', {
|
|
56
|
+
fa2Type: 'sms',
|
|
57
|
+
login2faCode,
|
|
58
|
+
verifyCode: code,
|
|
59
|
+
...params,
|
|
60
|
+
});
|
|
45
61
|
},
|
|
46
62
|
};
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
twoFactor,
|
|
66
|
+
};
|
|
47
67
|
},
|
|
48
68
|
};
|
|
49
69
|
}
|