Browse Source

增加接口细颗粒度权限配置

tycoding 1 năm trước cách đây
mục cha
commit
c84ed4e8df

+ 2 - 1
langchat-core/src/main/java/cn/tycoding/langchat/core/provider/ProviderListener.java

@@ -19,7 +19,8 @@ public class ProviderListener {
 
     @EventListener
     public void providerEvent(ProviderRefreshEvent event) {
-        log.info("refresh provider beans");
+        log.info("refresh provider beans begin......");
         providerInitialize.init();
+        log.info("refresh provider beans success......");
     }
 }

+ 10 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcConversationController.java

@@ -1,9 +1,11 @@
 package cn.tycoding.langchat.server.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.tycoding.langchat.biz.entity.AigcConversation;
 import cn.tycoding.langchat.biz.entity.AigcMessage;
 import cn.tycoding.langchat.biz.service.AigcMessageService;
 import cn.tycoding.langchat.biz.utils.ClientAuthUtil;
+import cn.tycoding.langchat.common.annotation.ApiLog;
 import cn.tycoding.langchat.common.utils.MybatisUtil;
 import cn.tycoding.langchat.common.utils.QueryPage;
 import cn.tycoding.langchat.common.utils.R;
@@ -44,12 +46,16 @@ public class AigcConversationController {
     }
 
     @PostMapping
+    @ApiLog("添加会话窗口")
+    @SaCheckPermission("aigc:conversation:add")
     public R addConversation(@RequestBody AigcConversation conversation) {
         conversation.setUserId(ClientAuthUtil.getUserId());
         return R.ok(aigcMessageService.addConversation(conversation));
     }
 
     @PutMapping
+    @ApiLog("更新会话窗口")
+    @SaCheckPermission("aigc:conversation:update")
     public R updateConversation(@RequestBody AigcConversation conversation) {
         if (conversation.getId() == null) {
             return R.fail("conversation id is null");
@@ -59,12 +65,16 @@ public class AigcConversationController {
     }
 
     @DeleteMapping("/{conversationId}")
+    @ApiLog("删除会话窗口")
+    @SaCheckPermission("aigc:conversation:delete")
     public R delConversation(@PathVariable String conversationId) {
         aigcMessageService.delConversation(conversationId);
         return R.ok();
     }
 
     @DeleteMapping("/message/{conversationId}")
+    @ApiLog("清空会话窗口数据")
+    @SaCheckPermission("aigc:conversation:clear")
     public R clearMessage(@PathVariable String conversationId) {
         aigcMessageService.clearMessage(conversationId);
         return R.ok();

+ 8 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcDocsController.java

@@ -1,7 +1,9 @@
 package cn.tycoding.langchat.server.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.tycoding.langchat.biz.entity.AigcDocs;
 import cn.tycoding.langchat.biz.mapper.AigcDocsMapper;
+import cn.tycoding.langchat.common.annotation.ApiLog;
 import cn.tycoding.langchat.common.utils.MybatisUtil;
 import cn.tycoding.langchat.common.utils.QueryPage;
 import cn.tycoding.langchat.common.utils.R;
@@ -44,18 +46,24 @@ public class AigcDocsController {
     }
 
     @PostMapping
+    @ApiLog("新增文档")
+    @SaCheckPermission("aigc:docs:add")
     public R add(@RequestBody AigcDocs data) {
         docsMapper.insert(data);
         return R.ok();
     }
 
     @PutMapping
+    @ApiLog("修改文档")
+    @SaCheckPermission("aigc:docs:update")
     public R update(@RequestBody AigcDocs data) {
         docsMapper.updateById(data);
         return R.ok();
     }
 
     @DeleteMapping("/{id}")
+    @ApiLog("删除文档")
+    @SaCheckPermission("aigc:docs:delete")
     public R delete(@PathVariable String id) {
         docsMapper.deleteById(id);
         return R.ok();

+ 8 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcDocsSliceController.java

@@ -1,7 +1,9 @@
 package cn.tycoding.langchat.server.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.tycoding.langchat.biz.entity.AigcDocsSlice;
 import cn.tycoding.langchat.biz.mapper.AigcDocsSliceMapper;
+import cn.tycoding.langchat.common.annotation.ApiLog;
 import cn.tycoding.langchat.common.utils.MybatisUtil;
 import cn.tycoding.langchat.common.utils.QueryPage;
 import cn.tycoding.langchat.common.utils.R;
@@ -45,6 +47,8 @@ public class AigcDocsSliceController {
     }
 
     @PostMapping
+    @ApiLog("新增切片数据")
+    @SaCheckPermission("aigc:docs:slice:add")
     public R add(@RequestBody AigcDocsSlice data) {
         data.setCreateTime(new Date());
         docsSliceMapper.insert(data);
@@ -52,12 +56,16 @@ public class AigcDocsSliceController {
     }
 
     @PutMapping
+    @ApiLog("修改切片数据")
+    @SaCheckPermission("aigc:docs:slice:update")
     public R update(@RequestBody AigcDocsSlice data) {
         docsSliceMapper.updateById(data);
         return R.ok();
     }
 
     @DeleteMapping("/{id}")
+    @ApiLog("删除切片数据")
+    @SaCheckPermission("aigc:docs:slice:delete")
     public R delete(@PathVariable String id) {
         docsSliceMapper.deleteById(id);
         return R.ok();

+ 8 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcKnowledgeController.java

@@ -1,10 +1,12 @@
 package cn.tycoding.langchat.server.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.StrUtil;
 import cn.tycoding.langchat.biz.entity.AigcDocs;
 import cn.tycoding.langchat.biz.entity.AigcKnowledge;
 import cn.tycoding.langchat.biz.mapper.AigcDocsMapper;
 import cn.tycoding.langchat.biz.service.AigcKnowledgeService;
+import cn.tycoding.langchat.common.annotation.ApiLog;
 import cn.tycoding.langchat.common.utils.MybatisUtil;
 import cn.tycoding.langchat.common.utils.QueryPage;
 import cn.tycoding.langchat.common.utils.R;
@@ -77,6 +79,8 @@ public class AigcKnowledgeController {
     }
 
     @PostMapping
+    @ApiLog("新增知识库")
+    @SaCheckPermission("aigc:knowledge:add")
     public R add(@RequestBody AigcKnowledge data) {
         data.setCreateTime(String.valueOf(System.currentTimeMillis()));
         kbService.save(data);
@@ -84,12 +88,16 @@ public class AigcKnowledgeController {
     }
 
     @PutMapping
+    @ApiLog("更新知识库")
+    @SaCheckPermission("aigc:knowledge:update")
     public R update(@RequestBody AigcKnowledge data) {
         kbService.updateById(data);
         return R.ok();
     }
 
     @DeleteMapping("/{id}")
+    @ApiLog("删除知识库")
+    @SaCheckPermission("aigc:knowledge:delete")
     public R delete(@PathVariable String id) {
         kbService.removeById(id);
         return R.ok();

+ 4 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcMessageController.java

@@ -1,8 +1,10 @@
 package cn.tycoding.langchat.server.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.StrUtil;
 import cn.tycoding.langchat.biz.entity.AigcMessage;
 import cn.tycoding.langchat.biz.service.AigcMessageService;
+import cn.tycoding.langchat.common.annotation.ApiLog;
 import cn.tycoding.langchat.common.utils.MybatisUtil;
 import cn.tycoding.langchat.common.utils.QueryPage;
 import cn.tycoding.langchat.common.utils.R;
@@ -40,6 +42,8 @@ public class AigcMessageController {
     }
 
     @DeleteMapping("/{id}")
+    @ApiLog("删除会话消息")
+    @SaCheckPermission("aigc:message:delete")
     public R del(@PathVariable String id) {
         return R.ok(aigcMessageService.removeById(id));
     }

+ 8 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcModelController.java

@@ -1,9 +1,11 @@
 package cn.tycoding.langchat.server.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.StrUtil;
 import cn.tycoding.langchat.biz.component.ProviderRefreshEvent;
 import cn.tycoding.langchat.biz.entity.AigcModel;
 import cn.tycoding.langchat.biz.service.AigcModelService;
+import cn.tycoding.langchat.common.annotation.ApiLog;
 import cn.tycoding.langchat.common.component.SpringContextHolder;
 import cn.tycoding.langchat.common.utils.MybatisUtil;
 import cn.tycoding.langchat.common.utils.QueryPage;
@@ -79,6 +81,8 @@ public class AigcModelController {
     }
 
     @PostMapping
+    @ApiLog("添加模型")
+    @SaCheckPermission("aigc:model:add")
     public R add(@RequestBody AigcModel data) {
         modelService.save(data);
         SpringContextHolder.publishEvent(new ProviderRefreshEvent(data));
@@ -86,6 +90,8 @@ public class AigcModelController {
     }
 
     @PutMapping
+    @ApiLog("修改模型")
+    @SaCheckPermission("aigc:model:update")
     public R update(@RequestBody AigcModel data) {
         modelService.updateById(data);
         SpringContextHolder.publishEvent(new ProviderRefreshEvent(data));
@@ -93,6 +99,8 @@ public class AigcModelController {
     }
 
     @DeleteMapping("/{id}")
+    @ApiLog("删除模型")
+    @SaCheckPermission("aigc:model:delete")
     public R delete(@PathVariable String id) {
         modelService.removeById(id);
 

+ 4 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcOssController.java

@@ -2,6 +2,7 @@ package cn.tycoding.langchat.server.controller;
 
 import cn.tycoding.langchat.biz.entity.AigcOss;
 import cn.tycoding.langchat.biz.service.AigcOssService;
+import cn.tycoding.langchat.common.annotation.ApiLog;
 import cn.tycoding.langchat.common.utils.R;
 import cn.tycoding.langchat.upms.utils.AuthUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -32,17 +33,20 @@ public class AigcOssController {
     }
 
     @PostMapping("/upload")
+    @ApiLog("上传OSS文件")
     public R upload(MultipartFile file) {
         return R.ok(aigcOssService.upload(file, String.valueOf(AuthUtil.getUserId())));
     }
 
     @PutMapping
+    @ApiLog("更新OSS文件资源")
     public R update(@RequestBody AigcOss data) {
         aigcOssService.updateById(data);
         return R.ok();
     }
 
     @DeleteMapping("/{id}")
+    @ApiLog("删除OSS文件资源")
     public R delete(@PathVariable String id) {
         aigcOssService.removeById(id);
         return R.ok();

+ 8 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcPromptController.java

@@ -1,8 +1,10 @@
 package cn.tycoding.langchat.server.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.StrUtil;
 import cn.tycoding.langchat.biz.entity.AigcPrompt;
 import cn.tycoding.langchat.biz.service.AigcPromptService;
+import cn.tycoding.langchat.common.annotation.ApiLog;
 import cn.tycoding.langchat.common.utils.MybatisUtil;
 import cn.tycoding.langchat.common.utils.QueryPage;
 import cn.tycoding.langchat.common.utils.R;
@@ -47,17 +49,23 @@ public class AigcPromptController {
     }
 
     @PostMapping
+    @ApiLog("添加Prompt")
+    @SaCheckPermission("aigc:prompt:add")
     public R add(@RequestBody AigcPrompt data) {
         data.setCreateTime(new Date());
         return R.ok(aigcPromptService.save(data));
     }
 
     @PutMapping
+    @ApiLog("更新Prompt")
+    @SaCheckPermission("aigc:prompt:update")
     public R update(@RequestBody AigcPrompt data) {
         return R.ok(aigcPromptService.updateById(data));
     }
 
     @DeleteMapping("/{id}")
+    @ApiLog("删除Prompt")
+    @SaCheckPermission("aigc:prompt:delete")
     public R del(@PathVariable String id) {
         return R.ok(aigcPromptService.removeById(id));
     }

+ 4 - 0
langchat-server/src/main/java/cn/tycoding/langchat/server/controller/AigcUserController.java

@@ -1,5 +1,6 @@
 package cn.tycoding.langchat.server.controller;
 
+import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.lang.Dict;
 import cn.tycoding.langchat.biz.entity.AigcUser;
 import cn.tycoding.langchat.biz.service.AigcUserService;
@@ -54,6 +55,7 @@ public class AigcUserController {
 
     @PostMapping
     @ApiLog("新增客户端用户")
+    @SaCheckPermission("aigc:user:add")
     public R<AigcUser> add(@RequestBody AigcUser data) {
         userService.save(data);
         return R.ok();
@@ -61,6 +63,7 @@ public class AigcUserController {
 
     @PutMapping
     @ApiLog("修改客户端用户")
+    @SaCheckPermission("aigc:user:update")
     public R update(@RequestBody AigcUser data) {
         userService.updateById(data);
         return R.ok();
@@ -68,6 +71,7 @@ public class AigcUserController {
 
     @DeleteMapping("/{id}")
     @ApiLog("删除客户端用户")
+    @SaCheckPermission("aigc:user:delete")
     public R delete(@PathVariable Long id) {
         AigcUser user = userService.getById(id);
         if (user != null) {

+ 16 - 26
langchat-ui-client/src/layout/Sider.vue

@@ -1,4 +1,4 @@
-<script setup lang="ts">
+<script lang="ts" setup>
   import { SvgIcon } from '@/components/common';
   import { computed } from 'vue';
   import { useDialog } from 'naive-ui';
@@ -25,19 +25,9 @@
   });
   const languageOptions: { label: string; key: Language; value: Language }[] = [
     { label: '简体中文', key: 'zh-CN', value: 'zh-CN' },
-    { label: '繁體中文', key: 'zh-TW', value: 'zh-TW' },
     { label: 'English', key: 'en-US', value: 'en-US' },
-    { label: '한국어', key: 'ko-KR', value: 'ko-KR' },
-    { label: 'Русский язык', key: 'ru-RU', value: 'ru-RU' },
   ];
 
-  const routerName = computed({
-    get() {
-      return router.currentRoute.value.name;
-    },
-    set() {},
-  });
-
   async function onLogout() {
     await userStore.logout();
     await router.push({ name: 'Login' });
@@ -61,15 +51,15 @@
       <div class="flex flex-col gap-3 border-neutral-800 pt-3 pl-3 pr-3">
         <n-button
           v-for="item in routesConst"
-          text
           :key="item.name"
-          @click="router.push({ name: item.name })"
           :class="router.currentRoute.value.name == item.name ? '!text-[#7fe7c4]' : ''"
+          text
+          @click="router.push({ name: item.name })"
         >
           <div
             class="rounded-[10px] bg-white dark:bg-[#34373f] w-[60px] pt-2 pb-1 flex justify-center items-center cursor-pointer flex-col"
           >
-            <SvgIcon class="text-2xl" :icon="item.meta?.icon" />
+            <SvgIcon :icon="item.meta?.icon" class="text-2xl" />
             <div class="mt-1 mb-1 text-[11px]"> {{ item.meta?.label }} </div>
           </div>
         </n-button>
@@ -77,13 +67,13 @@
     </n-scrollbar>
 
     <div class="m-2 flex flex-col justify-center items-center gap-2 mb-4 bottom-0">
-      <n-space vertical class="mb-2">
-        <n-popover trigger="hover" placement="right">
+      <n-space class="mb-2" vertical>
+        <n-popover placement="right" trigger="hover">
           <template #trigger>
             <n-button
-              text
               v-if="appStore.theme == 'light'"
               size="small"
+              text
               @click="appStore.setTheme('dark')"
             >
               <template #icon>
@@ -91,9 +81,9 @@
               </template>
             </n-button>
             <n-button
-              text
               v-if="appStore.theme == 'dark'"
               size="small"
+              text
               @click="appStore.setTheme('light')"
             >
               <template #icon>
@@ -106,8 +96,8 @@
 
         <n-popselect
           v-model:value="language"
-          placement="right"
           :options="languageOptions"
+          placement="right"
           trigger="click"
           @update-value="(value) => appStore.setLanguage(value)"
         >
@@ -121,19 +111,19 @@
         <n-avatar class="cursor-pointer" round>
           <SvgIcon class="text-lg" icon="solar:user-broken" />
         </n-avatar>
-        <n-button @click="onLogin()" size="tiny" type="success" secondary>
+        <n-button secondary size="tiny" type="success" @click="onLogin()">
           {{ t('side.login') }}
         </n-button>
       </template>
       <template v-else>
-        <n-popover trigger="hover" placement="right">
+        <n-popover placement="right" trigger="hover">
           <template #trigger>
             <n-avatar
-              @click="router.push({ name: 'Profile' })"
-              class="cursor-pointer"
-              :src="user.avatar ?? '/avatar.jpg'"
               :fallback-src="defaultAvatar"
+              :src="user.avatar ?? '/avatar.jpg'"
+              class="cursor-pointer"
               round
+              @click="router.push({ name: 'Profile' })"
             />
           </template>
           <span>{{ t('side.profile') }}</span>
@@ -141,7 +131,7 @@
         <n-ellipsis style="max-width: 70px">
           {{ user.username }}
         </n-ellipsis>
-        <n-button @click="onLogout()" size="tiny" secondary type="warning">
+        <n-button secondary size="tiny" type="warning" @click="onLogout()">
           {{ t('side.logout') }}
         </n-button>
       </template>
@@ -149,4 +139,4 @@
   </div>
 </template>
 
-<style scoped lang="less"></style>
+<style lang="less" scoped></style>

+ 7 - 5
langchat-ui-client/src/utils/request/index.ts

@@ -3,6 +3,7 @@ import request from './axios';
 import { router } from '@/router';
 import { useUserStore } from '@/store';
 import { isNullOrWhitespace } from '@/utils/is';
+import { t } from '@/locales';
 
 export interface HttpOption {
   url: string;
@@ -78,19 +79,20 @@ function axios<T = any>({
       // await router.push({ name: 'Login' });
 
       if (isNullOrWhitespace(userStore.token)) {
+        $dialog!.destroyAll();
         $dialog!.warning({
-          title: 'Tips',
-          content: 'You have not logged in or the login is invalid',
-          positiveText: 'Login',
-          negativeText: 'Cancel',
+          title: t('login.title'),
+          content: t('login.content'),
+          positiveText: t('login.positiveText'),
+          negativeText: t('login.negativeText'),
           onPositiveClick: async () => {
             await router.push({ name: 'Login' });
           },
         });
+        throw new Error('unthorization');
       } else {
         $message!.warning('当前账号没有操作权限,请联系管理员授权');
       }
-
       return;
     }
 

+ 2 - 2
langchat-ui-client/src/views/login/Login.vue

@@ -14,8 +14,8 @@
   const router = useRouter();
 
   const form = reactive({
-    username: '',
-    password: '',
+    username: 'langchat@outlook.com',
+    password: '123456',
   });
 
   const handleSubmit = (e: any) => {