Browse Source

feat: integrate frontend resources (#6)

master
vran 3 years ago
committed by GitHub
parent
commit
77fcf3011a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      Dockerfile
  2. 44
      README.md
  3. 10
      api/build.gradle
  4. 14
      api/src/main/java/com/databasir/api/IndexController.java
  5. 4
      api/src/main/java/com/databasir/api/LoginController.java
  6. 1
      api/src/main/java/com/databasir/api/config/SecurityConfig.java
  7. 10
      api/src/main/java/com/databasir/api/config/security/DatabasirJwtTokenFilter.java
  8. 1
      api/src/main/resources/static/css/app.fc57c576.css
  9. 1
      api/src/main/resources/static/css/chunk-0e34b2c6.06814884.css
  10. 1
      api/src/main/resources/static/css/chunk-588dbed6.e51aa148.css
  11. 1
      api/src/main/resources/static/css/chunk-7efe8be4.00ac37b1.css
  12. 1
      api/src/main/resources/static/css/chunk-vendors.d4aa889d.css
  13. BIN
      api/src/main/resources/static/favicon.ico
  14. BIN
      api/src/main/resources/static/img/logo.bed2a90a.png
  15. 1
      api/src/main/resources/static/index.html
  16. 2
      api/src/main/resources/static/js/app.d3ac1eb1.js
  17. 1
      api/src/main/resources/static/js/app.d3ac1eb1.js.map
  18. 2
      api/src/main/resources/static/js/chunk-0e34b2c6.7af33675.js
  19. 1
      api/src/main/resources/static/js/chunk-0e34b2c6.7af33675.js.map
  20. 2
      api/src/main/resources/static/js/chunk-2d0a47bb.baec3bc7.js
  21. 1
      api/src/main/resources/static/js/chunk-2d0a47bb.baec3bc7.js.map
  22. 2
      api/src/main/resources/static/js/chunk-2d0cc811.c5d1ef9e.js
  23. 1
      api/src/main/resources/static/js/chunk-2d0cc811.c5d1ef9e.js.map
  24. 2
      api/src/main/resources/static/js/chunk-48cebeac.162363c9.js
  25. 1
      api/src/main/resources/static/js/chunk-48cebeac.162363c9.js.map
  26. 2
      api/src/main/resources/static/js/chunk-588dbed6.ba7725b2.js
  27. 1
      api/src/main/resources/static/js/chunk-588dbed6.ba7725b2.js.map
  28. 2
      api/src/main/resources/static/js/chunk-7efe8be4.815f1aa1.js
  29. 1
      api/src/main/resources/static/js/chunk-7efe8be4.815f1aa1.js.map
  30. 2
      api/src/main/resources/static/js/chunk-9622a6d8.d116da54.js
  31. 1
      api/src/main/resources/static/js/chunk-9622a6d8.d116da54.js.map
  32. 2
      api/src/main/resources/static/js/chunk-abb10c56.c12963e3.js
  33. 1
      api/src/main/resources/static/js/chunk-abb10c56.c12963e3.js.map
  34. 2
      api/src/main/resources/static/js/chunk-fffb1b64.1ffb9f27.js
  35. 1
      api/src/main/resources/static/js/chunk-fffb1b64.1ffb9f27.js.map
  36. 8
      api/src/main/resources/static/js/chunk-vendors.42fcab1c.js
  37. 1
      api/src/main/resources/static/js/chunk-vendors.42fcab1c.js.map
  38. 2
      core/src/main/java/com/databasir/core/domain/DomainErrors.java
  39. 12
      core/src/main/java/com/databasir/core/domain/login/service/LoginService.java
  40. 2
      core/src/main/java/com/databasir/core/domain/system/service/SystemService.java

5
api/Dockerfile → Dockerfile

@ -1,3 +1,8 @@
FROM gradle:7.3-jdk11 as build
WORKDIR /app
ADD . /app
RUN gradle api:build
FROM openjdk:11.0.13-jre FROM openjdk:11.0.13-jre
ARG service_name_folder ARG service_name_folder
WORKDIR /app WORKDIR /app

44
README.md

@ -1,13 +1,11 @@
# Databasir # Databasir
## 规划 ## 规划
项目目前还属于 MVP (可行性验证)阶段,功能、文档等尚未完备,功能也处于随时调整的阶段 项目目前还属于 MVP (可行性验证)阶段,功能处于随时调整的阶段
以下功能尚在开发中 以下功能尚在开发中
- [x] 定时文档同步
- [ ] 表字段协同注释 - [ ] 表字段协同注释
- [ ] 操作审计日志 - [ ] 操作审计日志
- [ ] 容器化部署
## 简介 ## 简介
@ -18,13 +16,49 @@
3. 精细化:团队成员可以协同为文档做更精细化的注释 3. 精细化:团队成员可以协同为文档做更精细化的注释
4. 扁平化:权限管理扁平,减少冗余流程,价值最大化 4. 扁平化:权限管理扁平,减少冗余流程,价值最大化
## 部署 TODO ## 部署
Databasir 采用了前后端分离的模式进行开发和部署,前端和后端需要独立部署 Databasir 采用了前后端分离的模式进行开发和部署,前端和后端可以独立部署,也可以采用只部署已整合前端资源的后端应用
- 后端应用: https://github.com/vran-dev/databasir - 后端应用: https://github.com/vran-dev/databasir
- 前端应用: https://github.com/vran-dev/databasir-frontend - 前端应用: https://github.com/vran-dev/databasir-frontend
### JAR 模式部署
注意:
1. 使用 JAR 模式部署需要系统环境有 Java 环境,最低版本为 Java11。
2. 应用使用 MYSQL 作为数据存储,所以也需要准备好数据库。
部署:
1. 在 [Github RELEASE](https://github.com/vran-dev/databasir/releases) 页面下载最新版应用 Databasir.jar (你也可以选择克隆项目后自行构建)
2. 将 Databasir.jar 上传到服务器
3. 在 Databasir.jar 所在目录创建 config 目录,并在目录下创建 `application.properties` 配置,配置中配置 MYSQL 的用户名、密码和连接
```properties
# 端口号,默认8080
server.port=8080
# 数据库用户名
databasir.datasource.username=root
# 数据库密码
databasir.datasource.password=123456
# 数据库地址
databasir.datasource.url=127.0.0.1:3306
```
4. 通过 java -jar Databasir.jar 启动应用即可
应用启动后会默认创建 Databasir 管理员用户
- 用户名:databasir
- 密码:databasir
通过该账号登录应用既可以进行管理
### Docker 部署
TODO
## 展示 ## 展示

10
api/build.gradle

@ -31,13 +31,3 @@ dependencies {
} }
/**
* Docker
*/
task copyDockerfile(type: Copy) {
from("Dockerfile")
into("build/libs")
}
bootJar.finalizedBy copyDockerfile
assemble.finalizedBy copyDockerfile

14
api/src/main/java/com/databasir/api/IndexController.java

@ -0,0 +1,14 @@
package com.databasir.api;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class IndexController {
@GetMapping("/")
public String index() {
return "index.html";
}
}

4
api/src/main/java/com/databasir/api/LoginController.java

@ -43,8 +43,8 @@ public class LoginController {
try { try {
return JsonData.ok(loginService.refreshAccessTokens(request)); return JsonData.ok(loginService.refreshAccessTokens(request));
} catch (DatabasirException e) { } catch (DatabasirException e) {
if (Objects.equals(e.getErrCode(), DomainErrors.ACCESS_TOKEN_REFRESH_INVALID.getErrCode())) { if (Objects.equals(e.getErrCode(), DomainErrors.INVALID_REFRESH_TOKEN_OPERATION.getErrCode())) {
throw new InvalidTokenException(DomainErrors.ACCESS_TOKEN_REFRESH_INVALID); throw new InvalidTokenException(DomainErrors.INVALID_REFRESH_TOKEN_OPERATION);
} }
if (Objects.equals(e.getErrCode(), DomainErrors.REFRESH_TOKEN_EXPIRED.getErrCode())) { if (Objects.equals(e.getErrCode(), DomainErrors.REFRESH_TOKEN_EXPIRED.getErrCode())) {
throw new InvalidTokenException(DomainErrors.REFRESH_TOKEN_EXPIRED); throw new InvalidTokenException(DomainErrors.REFRESH_TOKEN_EXPIRED);

1
api/src/main/java/com/databasir/api/config/SecurityConfig.java

@ -45,6 +45,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.and() .and()
.authorizeRequests() .authorizeRequests()
.antMatchers("/login", Routes.Login.REFRESH_ACCESS_TOKEN).permitAll() .antMatchers("/login", Routes.Login.REFRESH_ACCESS_TOKEN).permitAll()
.antMatchers("/", "/*.html", "/js/**", "/css/**", "/img/**", "/*.ico").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
.and() .and()
.exceptionHandling().authenticationEntryPoint(databasirAuthenticationEntryPoint); .exceptionHandling().authenticationEntryPoint(databasirAuthenticationEntryPoint);

10
api/src/main/java/com/databasir/api/config/security/DatabasirJwtTokenFilter.java

@ -7,6 +7,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -46,7 +47,14 @@ public class DatabasirJwtTokenFilter extends OncePerRequestFilter {
} }
String username = jwtTokens.getUsername(token); String username = jwtTokens.getUsername(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(username); UserDetails userDetails = null;
try {
userDetails = userDetailsService.loadUserByUsername(username);
} catch (UsernameNotFoundException e) {
logger.warn("username not found after token verified: " + e.getMessage());
filterChain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

1
api/src/main/resources/static/css/app.fc57c576.css

@ -0,0 +1 @@
.left-menu:not(.el-menu--collapse){height:100vh}.el-aside{display:block;position:fixed;left:0;bottom:0;top:0;width:200px}.databasir-main-header{display:flex;justify-content:space-between;align-items:center;position:fixed;top:0;right:0;left:220px;padding:30px;background:#fff;z-index:100;border-color:#eee;border-width:0 0 1px 0;border-style:solid}.databasir-main{margin-left:200px;margin-top:80px;--el-main-padding:0px 20px 20px 20px}.databasir-main-content{max-width:95%;--el-main-padding:0px 20px 20px 20px}

1
api/src/main/resources/static/css/chunk-0e34b2c6.06814884.css

@ -0,0 +1 @@
.el-row{margin-top:33px}

1
api/src/main/resources/static/css/chunk-588dbed6.e51aa148.css

@ -0,0 +1 @@
.login-main{margin:0 auto;margin-top:200px}.login-input{border-width:0 0 1px 0;border-style:solid;width:100%;min-height:33px}.login-input::-moz-placeholder{color:hsla(0,0%,70.6%,.808)}.login-input:-ms-input-placeholder{color:hsla(0,0%,70.6%,.808)}.login-input::placeholder{color:hsla(0,0%,70.6%,.808)}.login-input:focus{outline:none;border-color:#000}.login-card{max-width:600px;min-width:500px;border-color:#000}

1
api/src/main/resources/static/css/chunk-7efe8be4.00ac37b1.css

@ -0,0 +1 @@
.card-header{display:flex;justify-content:space-between;align-items:center}.el-row{margin-bottom:20px}.el-row:last-child{margin-bottom:0}

1
api/src/main/resources/static/css/chunk-vendors.d4aa889d.css

File diff suppressed because one or more lines are too long

BIN
api/src/main/resources/static/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
api/src/main/resources/static/img/logo.bed2a90a.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

1
api/src/main/resources/static/index.html

@ -0,0 +1 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir-frontend</title><link href="/css/chunk-0e34b2c6.06814884.css" rel="prefetch"><link href="/css/chunk-588dbed6.e51aa148.css" rel="prefetch"><link href="/css/chunk-7efe8be4.00ac37b1.css" rel="prefetch"><link href="/js/chunk-0e34b2c6.7af33675.js" rel="prefetch"><link href="/js/chunk-2d0a47bb.baec3bc7.js" rel="prefetch"><link href="/js/chunk-2d0cc811.c5d1ef9e.js" rel="prefetch"><link href="/js/chunk-48cebeac.162363c9.js" rel="prefetch"><link href="/js/chunk-588dbed6.ba7725b2.js" rel="prefetch"><link href="/js/chunk-7efe8be4.815f1aa1.js" rel="prefetch"><link href="/js/chunk-9622a6d8.d116da54.js" rel="prefetch"><link href="/js/chunk-abb10c56.c12963e3.js" rel="prefetch"><link href="/js/chunk-fffb1b64.1ffb9f27.js" rel="prefetch"><link href="/css/app.fc57c576.css" rel="preload" as="style"><link href="/css/chunk-vendors.d4aa889d.css" rel="preload" as="style"><link href="/js/app.d3ac1eb1.js" rel="preload" as="script"><link href="/js/chunk-vendors.42fcab1c.js" rel="preload" as="script"><link href="/css/chunk-vendors.d4aa889d.css" rel="stylesheet"><link href="/css/app.fc57c576.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but databasir-frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.42fcab1c.js"></script><script src="/js/app.d3ac1eb1.js"></script></body></html>

2
api/src/main/resources/static/js/app.d3ac1eb1.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/app.d3ac1eb1.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-0e34b2c6.7af33675.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-0e34b2c6.7af33675.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-2d0a47bb.baec3bc7.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-2d0a47bb.baec3bc7.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-2d0cc811.c5d1ef9e.js

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0cc811"],{"4de0":function(e,t,r){"use strict";r.r(t);var n=r("7a23"),o=Object(n["createTextVNode"])(" : "),u=Object(n["createTextVNode"])("保存");function l(e,t,r,l,a,c){var s=Object(n["resolveComponent"])("el-input"),i=Object(n["resolveComponent"])("el-form-item"),d=Object(n["resolveComponent"])("el-col"),m=Object(n["resolveComponent"])("el-button"),f=Object(n["resolveComponent"])("el-form"),p=Object(n["resolveComponent"])("el-card"),b=Object(n["resolveComponent"])("el-main"),j=Object(n["resolveComponent"])("el-container");return Object(n["openBlock"])(),Object(n["createBlock"])(j,null,{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(b,null,{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(p,null,{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(f,{model:a.form,"label-position":"top",rules:a.formRule,ref:"formRef",style:{"max-width":"900px"}},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(i,{label:"邮箱账号",prop:"username"},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(s,{modelValue:a.form.username,"onUpdate:modelValue":t[0]||(t[0]=function(e){return a.form.username=e})},null,8,["modelValue"])]})),_:1}),Object(n["createVNode"])(i,{label:"邮箱密码",prop:"password"},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(s,{modelValue:a.form.password,"onUpdate:modelValue":t[1]||(t[1]=function(e){return a.form.password=e}),type:"password",placeholder:"请输入密码","show-password":""},null,8,["modelValue"])]})),_:1}),Object(n["createVNode"])(i,{label:"SMTP",prop:"smtpHost"},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(d,{span:12},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(s,{modelValue:a.form.smtpHost,"onUpdate:modelValue":t[2]||(t[2]=function(e){return a.form.smtpHost=e}),placeholder:"SMTP Host"},null,8,["modelValue"])]})),_:1}),Object(n["createVNode"])(d,{span:1,style:{"text-align":"center"}},{default:Object(n["withCtx"])((function(){return[o]})),_:1}),Object(n["createVNode"])(d,{span:6},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(s,{modelValue:a.form.smtpPort,"onUpdate:modelValue":t[3]||(t[3]=function(e){return a.form.smtpPort=e}),placeholder:"SMTP Port"},null,8,["modelValue"])]})),_:1})]})),_:1}),Object(n["createVNode"])(i,{style:{"margin-top":"38px"}},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(m,{type:"primary",onClick:t[4]||(t[4]=function(e){return c.onSubmit("formRef")})},{default:Object(n["withCtx"])((function(){return[u]})),_:1})]})),_:1})]})),_:1},8,["model","rules"])]})),_:1})]})),_:1})]})),_:1})}var a=r("1da1"),c=(r("96cf"),r("1c1e")),s="/api/v1.0/settings",i=function(){return c["a"].get(s+"/sys_email")},d=function(e){return c["a"].post(s+"/sys_email",e)},m={data:function(){return{form:{smtpHost:null,smtpPort:null,username:null,password:null},formRule:{username:[this.requiredInputValidRule("请输入邮箱账号"),{type:"email",message:"邮箱格式不正确",trigger:"blur"}],password:[this.requiredInputValidRule("请输入邮箱密码")],smtpHost:[this.requiredInputValidRule("请输入 SMTP 地址")],smtpPort:[this.requiredInputValidRule("请输入 SMTP 端口"),{min:1,max:65535,message:"端口有效值为 1~65535",trigger:"blur"}]}}},mounted:function(){this.fetchSysMail()},methods:{requiredInputValidRule:function(e){return{required:!0,message:e,trigger:"blur"}},fetchSysMail:function(){var e=this;return Object(a["a"])(regeneratorRuntime.mark((function t(){var r;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:return t.next=2,i().then((function(e){return e.data}));case 2:r=t.sent,r&&(e.form=r);case 4:case"end":return t.stop()}}),t)})))()},onSubmit:function(){var e=this;this.$refs.formRef.validate((function(t){return t?(d(e.form).then((function(t){t.errCode||e.$message.success("更新成功")})),!0):(e.$message.error("请完善表单相关信息!"),!1)}))}}},f=r("6b0d"),p=r.n(f);const b=p()(m,[["render",l]]);t["default"]=b}}]);
//# sourceMappingURL=chunk-2d0cc811.c5d1ef9e.js.map

1
api/src/main/resources/static/js/chunk-2d0cc811.c5d1ef9e.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-48cebeac.162363c9.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-48cebeac.162363c9.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-588dbed6.ba7725b2.js

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-588dbed6"],{"4dd4":function(e,t,n){},a1af:function(e,t,n){"use strict";n("4dd4")},a55b:function(e,t,n){"use strict";n.r(t);var r=n("7a23"),o={class:"login-card"},c=Object(r["createElementVNode"])("h1",null,"Databasir",-1),a=Object(r["createTextVNode"])(" 登录 "),u=Object(r["createTextVNode"])(" 忘记密码? ");function l(e,t,n,l,i,d){var s=Object(r["resolveComponent"])("el-header"),f=Object(r["resolveComponent"])("el-link"),b=Object(r["resolveComponent"])("el-divider"),m=Object(r["resolveComponent"])("el-form-item"),p=Object(r["resolveComponent"])("el-button"),j=Object(r["resolveComponent"])("el-space"),O=Object(r["resolveComponent"])("el-form"),h=Object(r["resolveComponent"])("el-main"),w=Object(r["resolveComponent"])("el-footer"),C=Object(r["resolveComponent"])("el-container");return Object(r["openBlock"])(),Object(r["createBlock"])(C,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(s),Object(r["createVNode"])(h,{class:"login-main"},{default:Object(r["withCtx"])((function(){return[Object(r["createElementVNode"])("div",o,[Object(r["createVNode"])(O,{ref:"formRef",rules:i.formRule,model:i.form,style:{border:"none"}},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(m,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(b,{"content-position":"left"},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(f,{href:"https://github.com/vran-dev/databasir",target:"_blank",underline:!1,type:"info"},{default:Object(r["withCtx"])((function(){return[c]})),_:1})]})),_:1})]})),_:1}),Object(r["createVNode"])(m,{prop:"username"},{default:Object(r["withCtx"])((function(){return[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"text",class:"login-input",placeholder:"用户名或邮箱","onUpdate:modelValue":t[0]||(t[0]=function(e){return i.form.username=e})},null,512),[[r["vModelText"],i.form.username]])]})),_:1}),Object(r["createVNode"])(m,{prop:"password"},{default:Object(r["withCtx"])((function(){return[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"password",class:"login-input",placeholder:"密码","onUpdate:modelValue":t[1]||(t[1]=function(e){return i.form.password=e})},null,512),[[r["vModelText"],i.form.password]])]})),_:1}),Object(r["createVNode"])(m,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(j,{size:32},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(p,{style:{width:"120px","margin-top":"10px"},color:"#000",onClick:t[2]||(t[2]=function(e){return d.onLogin("formRef")}),plain:"",round:""},{default:Object(r["withCtx"])((function(){return[a]})),_:1}),Object(r["createVNode"])(f,{href:"#",target:"_blank",underline:!1,type:"info"},{default:Object(r["withCtx"])((function(){return[u]})),_:1})]})),_:1})]})),_:1})]})),_:1},8,["rules","model"])])]})),_:1}),Object(r["createVNode"])(w,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(j)]})),_:1})]})),_:1})}var i=n("b0af"),d=n("5f87"),s={data:function(){return{form:{username:null,password:null},formRule:{username:[{required:!0,message:"请输入用户名或邮箱",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"}]}}},methods:{toIndexPage:function(){this.$router.push({path:"/groups"})},onLogin:function(){var e=this;this.$refs.formRef.validate((function(t){t&&Object(i["a"])(e.form).then((function(t){t.errCode||(d["b"].saveUserLoginData(t.data),e.$store.commit("userUpdate",{nickname:t.data.nickname,username:t.data.username,email:t.data.email}),e.toIndexPage())}))}))}}},f=(n("a1af"),n("6b0d")),b=n.n(f);const m=b()(s,[["render",l]]);t["default"]=m}}]);
//# sourceMappingURL=chunk-588dbed6.ba7725b2.js.map

1
api/src/main/resources/static/js/chunk-588dbed6.ba7725b2.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-7efe8be4.815f1aa1.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-7efe8be4.815f1aa1.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-9622a6d8.d116da54.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-9622a6d8.d116da54.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-abb10c56.c12963e3.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-abb10c56.c12963e3.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-fffb1b64.1ffb9f27.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-fffb1b64.1ffb9f27.js.map

File diff suppressed because one or more lines are too long

8
api/src/main/resources/static/js/chunk-vendors.42fcab1c.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-vendors.42fcab1c.js.map

File diff suppressed because one or more lines are too long

2
core/src/main/java/com/databasir/core/domain/DomainErrors.java

@ -9,7 +9,7 @@ import lombok.RequiredArgsConstructor;
@Getter @Getter
public enum DomainErrors implements DatabasirErrors { public enum DomainErrors implements DatabasirErrors {
REFRESH_TOKEN_EXPIRED("X_0001", "refresh token expired"), REFRESH_TOKEN_EXPIRED("X_0001", "refresh token expired"),
ACCESS_TOKEN_REFRESH_INVALID("X_0002", "invalid refresh token operation"), INVALID_REFRESH_TOKEN_OPERATION("X_0002", "invalid refresh token operation"),
NOT_SUPPORT_DATABASE_TYPE("A_10000", "不支持的数据库类型, 请检查项目配置"), NOT_SUPPORT_DATABASE_TYPE("A_10000", "不支持的数据库类型, 请检查项目配置"),
PROJECT_NOT_FOUND("A_10001", "项目不存在"), PROJECT_NOT_FOUND("A_10001", "项目不存在"),

12
core/src/main/java/com/databasir/core/domain/login/service/LoginService.java

@ -32,7 +32,7 @@ public class LoginService {
public AccessTokenRefreshResponse refreshAccessTokens(AccessTokenRefreshRequest request) { public AccessTokenRefreshResponse refreshAccessTokens(AccessTokenRefreshRequest request) {
LoginPojo login = loginDao.selectByRefreshToken(request.getRefreshToken()) LoginPojo login = loginDao.selectByRefreshToken(request.getRefreshToken())
.orElseThrow(DomainErrors.ACCESS_TOKEN_REFRESH_INVALID::exception); .orElseThrow(DomainErrors.INVALID_REFRESH_TOKEN_OPERATION::exception);
// refresh-token 已过期 // refresh-token 已过期
if (login.getRefreshTokenExpireAt().isBefore(LocalDateTime.now())) { if (login.getRefreshTokenExpireAt().isBefore(LocalDateTime.now())) {
throw DomainErrors.REFRESH_TOKEN_EXPIRED.exception(); throw DomainErrors.REFRESH_TOKEN_EXPIRED.exception();
@ -41,9 +41,15 @@ public class LoginService {
if (login.getAccessTokenExpireAt().isAfter(LocalDateTime.now())) { if (login.getAccessTokenExpireAt().isAfter(LocalDateTime.now())) {
log.warn("invalid access token refresh operation: request = {}, login = {}", request, login); log.warn("invalid access token refresh operation: request = {}, login = {}", request, login);
loginDao.deleteByUserId(login.getUserId()); loginDao.deleteByUserId(login.getUserId());
throw DomainErrors.ACCESS_TOKEN_REFRESH_INVALID.exception(); throw DomainErrors.INVALID_REFRESH_TOKEN_OPERATION.exception();
} }
UserPojo user = userDao.selectById(login.getUserId());
// refresh-token 对应的用户已被删除
UserPojo user = userDao.selectOptionalById(login.getUserId())
.orElseThrow(() -> {
log.warn("user not exists but refresh token exists for " + login.getRefreshToken());
return DomainErrors.INVALID_REFRESH_TOKEN_OPERATION.exception();
});
String accessToken = jwtTokens.accessToken(user.getEmail()); String accessToken = jwtTokens.accessToken(user.getEmail());
LocalDateTime accessTokenExpireAt = jwtTokens.expireAt(accessToken); LocalDateTime accessTokenExpireAt = jwtTokens.expireAt(accessToken);
loginDao.updateAccessToken(accessToken, accessTokenExpireAt, user.getId()); loginDao.updateAccessToken(accessToken, accessTokenExpireAt, user.getId());

2
core/src/main/java/com/databasir/core/domain/system/service/SystemService.java

@ -48,7 +48,7 @@ public class SystemService {
return pojo; return pojo;
}); });
String email = "admin@databasir.com"; String email = "N/A";
String username = "databasir"; String username = "databasir";
Optional<UserPojo> userOpt = userDao.selectByEmail(email); Optional<UserPojo> userOpt = userDao.selectByEmail(email);
if (!userOpt.isPresent()) { if (!userOpt.isPresent()) {

Loading…
Cancel
Save