🐛 add interface access permissions

This commit is contained in:
landaiqing
2024-09-04 19:00:21 +08:00
parent 9b3a6d37de
commit ec6b0a9c9f
12 changed files with 94 additions and 54 deletions

View File

@@ -15,3 +15,20 @@ export const getUserDevice = (userId: string) => {
}
);
};
/**
* 生成客户端id
*/
export const generateClientId = () => {
return service.Get('/api/client/generate_client_id',
{
meta: {
ignoreToken: true,
},
cacheFor: {
mode: "restore",
expire: 1000 * 60 * 60 * 24 * 30 // 30天
}
}
);
};

View File

@@ -1,21 +1,5 @@
import {service} from "@/utils/alova/service.ts";
/**
* 生成客户端id
*/
export const generateClientId = () => {
return service.Get('/api/oauth/wechat/generate_client_id',
{
meta: {
ignoreToken: true,
},
cacheFor: {
mode: "restore",
expire: 1000 * 60 * 60 * 24 * 30 // 30天
}
}
);
};
/**
* 获取临时二维码
* @param clientId

View File

@@ -55,6 +55,7 @@ export const phoneLoginApi = (param: PhoneLogin) => {
return service.Post('/api/user/phone_login', {
phone: param.phone,
captcha: param.captcha,
auto_login: param.auto_login
},
{
meta: {
@@ -72,6 +73,7 @@ export const accountLoginApi = (param: AccountLogin) => {
return service.Post('/api/user/login', {
account: param.account,
password: param.password,
auto_login: param.auto_login
},
{
meta: {
@@ -99,3 +101,18 @@ export const resetPasswordApi = (param: ResetPassword) => {
}
);
};
/**
* 获取用户权限
* @param user_id
*/
export const getUserPermissions = (user_id: string) => {
return service.Get('/api/auth/permission/get_user_permissions', {
params: {
user_id: user_id
},
meta: {
ignoreToken: false,
}
}
);
};

View File

@@ -77,6 +77,6 @@ export default {
authTokenExpired: "认证过期,请重新登录!",
loginExpired: "登录已过期!",
pleaseLogin: "请先登录!",
loginExpiredDesc: "该账号在其他地方登录,请重新登录!"
loginExpiredDesc: "该账号在其他地方登录,请刷新后重新登录!"
}
};

View File

@@ -28,11 +28,13 @@ const router: Router = createRouter({
router.beforeEach((to, _from, next) => {
start();
const user = useStore().user;
const client = useStore().client;
const token: string | undefined = user.user.refreshToken;
const userId: string | undefined = user.user.userId;
const clientId: string | undefined = client.getClientId();
// 检查用户是否已登录
const isLoggedIn: boolean = token !== "" && userId !== "";
const isLoggedIn: boolean = token !== "" && userId !== "" && clientId !== "";
if (to.path === '/login' || to.path === '/qrlogin' || to.path === '/resetpass') {
if (isLoggedIn) {

View File

@@ -35,13 +35,13 @@ const {onAuthRequired, onResponseRefreshToken} = createServerTokenAuthentication
} else {
message.error(i18n.global.t('error.loginExpired'));
localStorage.removeItem('user');
await router.push('/login');
router.push('/login').then();
}
} catch (error: any) {
console.error(error);
message.error(i18n.global.t('error.loginExpired'));
localStorage.removeItem('user');
await router.push('/login');
router.push('/login').then();
}
}
}
@@ -68,27 +68,33 @@ export const service = createAlova({
}
const lang = useStore().lang;
method.config.headers['Accept-Language'] = lang.lang || 'zh';
const client = useStore().client;
method.config.headers['X-Request-Id'] = client.getClientId() || '';
}),
// 响应拦截器
responded: onResponseRefreshToken({
onSuccess: async (response: AxiosResponse, _method: any) => {
if (response.data instanceof Blob) {
return response;
} else {
if (response.data.code === 403) {
notification.error({
placement: 'topRight',
message: i18n.global.t('error.loginExpired'),
description: i18n.global.t('error.loginExpiredDesc'),
onClose: () => {
localStorage.removeItem('user');
router.push('/login');
}
});
} else {
return response.data;
}
}
const {code} = response.data;
if (code === 403) {
notification.error({
placement: 'topRight',
duration: 5,
message: i18n.global.t('error.loginExpired'),
description: i18n.global.t('error.loginExpiredDesc'),
onClose: () => {
localStorage.removeItem('user');
router.push('/login').then();
}
});
throw new Error('Authentication Expired');
} else {
return response.data;
}
},
onError:
(error: AxiosError, _method: any) => {

View File

@@ -6,6 +6,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.400"),
duration: 5,
type: "error",
})
.then();
@@ -14,6 +15,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.401"),
duration: 5,
type: "error",
})
.then();
@@ -22,6 +24,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.403"),
duration: 5,
type: "error",
})
.then();
@@ -30,6 +33,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.404"),
duration: 5,
type: "error",
})
.then();
@@ -38,6 +42,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.408"),
duration: 5,
type: "error",
})
.then();
@@ -46,6 +51,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.500"),
duration: 5,
type: "error",
})
.then();
@@ -54,6 +60,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.501"),
duration: 5,
type: "error",
})
.then();
@@ -62,6 +69,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.502"),
duration: 5,
type: "error",
})
.then();
@@ -70,6 +78,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.503"),
duration: 5,
type: "error",
})
.then();
@@ -78,6 +87,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.504"),
duration: 5,
type: "error",
})
.then();
@@ -86,6 +96,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.505"),
duration: 5,
type: "error",
})
.then();
@@ -94,6 +105,7 @@ export function handleCode(code: number): void {
message
.open({
content: i18n.global.t("error.other") + `(${code})`,
duration: 5,
type: "error",
})
.then();

View File

@@ -27,10 +27,9 @@ import {getGiteeUrl} from "@/api/oauth/gitee.ts";
import useStore from "@/store";
import {message} from "ant-design-vue";
import gitee from "@/assets/svgs/gitee.svg";
import {generateClientId} from "@/api/oauth/wechat.ts";
import {getQQUrl} from "@/api/oauth/qq.ts";
import {useDebounceFn} from "@vueuse/core";
import {getUserDevice} from "@/api/oauth";
import {generateClientId, getUserDevice} from "@/api/oauth";
const router = useRouter();
const {t} = useI18n();

View File

@@ -333,7 +333,7 @@ async function sendCaptcha() {
/**
* 账号登录 防抖
*/
const accountLoginSubmitDebounce = useDebounceFn(accountLoginSubmit, 3000);
const accountLoginSubmitDebounce = useDebounceFn(accountLoginSubmit, 1000);
/**
* 账号登录提交
@@ -354,7 +354,7 @@ async function accountLoginSubmit() {
/**
* 手机登录提交 防抖
*/
const phoneLoginSubmitDebounce = useDebounceFn(phoneLoginSubmit, 3000);
const phoneLoginSubmitDebounce = useDebounceFn(phoneLoginSubmit, 1000);
/**
* 手机登录提交

View File

@@ -1,19 +1,23 @@
<template>
<div>
<h1>Welcome to Main Page</h1>
<!-- <AButton @click="handleClick">获取用户数据</AButton>-->
<AButton @click="handleClick">获取登录用户角色</AButton>
{{ data }}
</div>
</template>
<script setup lang="ts">
// import {useRequest} from "alova/client";
// import {getUserInfo} from "@/api/user";
//
// const {data, send} = useRequest(getUserInfo, {
// immediate: false
// });
// const handleClick = () => {
// send();
// };
import {useRequest} from "alova/client";
import {getUserPermissions} from "@/api/user";
import useStore from "@/store";
const {data, send} = useRequest(getUserPermissions, {
immediate: false
});
const handleClick = () => {
const userInfo = useStore().user;
const userId: string = userInfo.user.uid;
send(userId);
};
</script>
<style scoped>

View File

@@ -57,13 +57,13 @@ import {useI18n} from "vue-i18n";
import BoxDog from "@/components/BoxDog/BoxDog.vue";
import QRLoginFooter from "@/views/QRLogin/QRLoginFooter.vue";
import {useRouter} from 'vue-router';
import {generateClientId, generateQrCode} from "@/api/oauth/wechat.ts";
import {generateQrCode} from "@/api/oauth/wechat.ts";
import {onMounted, onUnmounted, ref} from "vue";
import logo from "@/assets/svgs/logo-schisandra.svg";
import useWebSocket from "@/utils/websocket/websocket.ts";
import useStore from "@/store";
import {message} from "ant-design-vue";
import {getUserDevice} from "@/api/oauth";
import {generateClientId, getUserDevice} from "@/api/oauth";
const {t} = useI18n();
@@ -94,7 +94,7 @@ async function getQrCode() {
await getClientId();
await getQrCode();
} else {
const res: any = await generateQrCode(client.getClientId() as string);
const res: any = await generateQrCode(client.getClientId() || "");
if (res.code === 0 && res.data) {
status.value = 'active';
qrcode.value = res.data;
@@ -118,7 +118,7 @@ function getLocalClientId() {
}
const wsOptions = {
url: import.meta.env.VITE_WEB_SOCKET_URL as string + "?client_id=" + getLocalClientId(),
url: import.meta.env.VITE_WEB_SOCKET_URL + "?client_id=" + getLocalClientId(),
};
const {open, close, on} = useWebSocket(wsOptions);

View File

@@ -27,10 +27,9 @@ import {getGiteeUrl} from "@/api/oauth/gitee.ts";
import useStore from "@/store";
import {message} from "ant-design-vue";
import gitee from "@/assets/svgs/gitee.svg";
import {generateClientId} from "@/api/oauth/wechat.ts";
import {getQQUrl} from "@/api/oauth/qq.ts";
import {useDebounceFn} from "@vueuse/core";
import {getUserDevice} from "@/api/oauth";
import {generateClientId, getUserDevice} from "@/api/oauth";
const router = useRouter();
const {t} = useI18n();