1
0

16 Commits

Author SHA1 Message Date
dbdf9c59bb feat(ware): 上架数据产品功能
- 新增数据产品上架相关的对话框组件和页面功能
- 实现数据产品的添加、编辑和详情查看功能
- 添加数据产品相关的实体类、控制器、服务类和仓库接口
2024-12-13 18:18:49 +08:00
8202a27f55 refactor(web): 减少文件夹层级 2024-12-13 17:26:17 +08:00
db05b69122 refactor(web):优化确认服务和数据资源服务的查询逻辑 2024-12-13 17:02:55 +08:00
8abd31cd97 feat(web): 调整权限管理界面和功能 2024-12-12 15:57:49 +08:00
6fad39443c refactor(web): 优化用户对话框字段布局
- 调整角色和账号状态字段的布局方式
- 增加 control 组件以改善字段显示效果
- 在 constants.js 中添加 label属性以支持新布局
2024-12-12 15:53:27 +08:00
6e4baed23f refactor(web): 重构列表查询逻辑
- 修改 listPredicate 方法返回类型为 ImmutableList<Predicate>
-优化非管理员用户的数据查询条件- 统一使用 Eclipse Collections 的 Lists 工厂方法
-调整代码结构,提高可读性和可维护性
2024-12-10 18:51:01 +08:00
3d1970ec09 feat(web): 优化数据资源和数据文件查询逻辑
- 新增 listPredicate 方法统一处理查询逻辑- 优化了 DataResourceService 和 DataFileService 的查询性能
- 重构了 EntityHelper 类,增加了 checkNeededEntityPrediction 方法
- 调整了 AuthenticationService、CheckOrderService 和 ConfirmationService 的查询逻辑
- 更新了前端 dialog-permission.js 组件
2024-12-09 18:37:36 +08:00
3e43d437e6 refactor(web): 重构审核流程
- 移除 AuthenticationRepository 和 ConfirmationRepository 中的 updateStateById 方法
- 更新 AuthenticationService 和 ConfirmationService 中的状态更新逻辑
- 修改 CheckOrder 实体,使用 State 枚举替代布尔型 over 字段
- 更新相关前端组件,适应新的审核状态
2024-12-09 10:38:21 +08:00
6ec672ebfa feat(web): 实现授权申请功能
- 新增授权申请提交和撤销功能
- 实现授权申请的审核流程
- 优化授权申请的列表和详情展示- 添加时间格式配置
2024-12-06 20:01:07 +08:00
28d70e5f9a feat(web): 修复逻辑删除,增加可选查询 2024-12-05 17:58:38 +08:00
6a68085870 feat(authentication): 为 Authentication 实体添加软删除功能
- 在 Authentication 类中添加 @SQLDelete 和 @Where 注解,实现软删除
- 移除 target 和 evidences 关联中的 @Where 注解,避免重复应用软删除逻辑
2024-12-05 17:57:27 +08:00
15b6f98598 refactor(web): 移除用户和数据文件创建时的冗余信息
- 移除了 DataFileService 中设置创建和修改用户的代码- 更新了 UserService 中的当前登录用户获取方式,增加了 Optional 类型的方法
- 移除了 EntityHelper 中填充创建者和修改者的代码
2024-12-05 17:56:59 +08:00
9d6e977d93 feat(web): 添加实体审计功能并配置审计用户
- 在 SimpleEntity 中添加 @CreatedBy 和 @LastModifiedBy 注解
- 在 WebApplication 中添加 AuditorAware Bean
- 使用 UserService 的 currentLoginUserOptional 方法获取当前登录用户
2024-12-05 17:54:58 +08:00
a6c128da64 feat(web): 增加REST统一查询参数 2024-12-03 13:00:16 +08:00
1ec345e18d feat(web): 增加授权相关界面 2024-12-02 19:07:22 +08:00
e7918f9039 feat(web): 避免h2的数据库关键字 2024-12-02 16:27:01 +08:00
77 changed files with 1875 additions and 485 deletions

4
.idea/compiler.xml generated
View File

@@ -7,8 +7,8 @@
<sourceOutputDir name="target/generated-sources/annotations" /> <sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" /> <outputRelativeToContentRoot value="true" />
<module name="gringotts-web" />
<module name="gringotts-chain" /> <module name="gringotts-chain" />
<module name="gringotts-web" />
<module name="gringotts-core" /> <module name="gringotts-core" />
<module name="gringotts-gateway" /> <module name="gringotts-gateway" />
<module name="gringotts-forest" /> <module name="gringotts-forest" />
@@ -24,7 +24,7 @@
<module name="gringotts-core" options="-parameters" /> <module name="gringotts-core" options="-parameters" />
<module name="gringotts-forest" options="-parameters" /> <module name="gringotts-forest" options="-parameters" />
<module name="gringotts-gateway" options="-parameters" /> <module name="gringotts-gateway" options="-parameters" />
<module name="gringotts-web" options="-parameters" /> <module name="gringotts-web" options="-parameters -processor lombok.launch.AnnotationProcessorHider$AnnotationProcessor,org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor" />
</option> </option>
</component> </component>
</project> </project>

View File

@@ -2,6 +2,10 @@ package com.eshore.gringotts.configuration;
import com.fasterxml.jackson.datatype.eclipsecollections.EclipseCollectionsModule; import com.fasterxml.jackson.datatype.eclipsecollections.EclipseCollectionsModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
@@ -21,9 +25,17 @@ public class JacksonConfiguration {
@Bean @Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> { return builder -> {
/*
* 配置时间格式
*/
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
builder.modules( builder.modules(
new EclipseCollectionsModule(), new EclipseCollectionsModule(),
new JavaTimeModule() javaTimeModule
); );
}; };
} }

View File

@@ -1,5 +1,5 @@
const information = { export const information = {
debug: true, debug: false,
// baseUrl: '', // baseUrl: '',
baseUrl: 'http://127.0.0.1:20080', baseUrl: 'http://127.0.0.1:20080',
title: '可信供给中心', title: '可信供给中心',
@@ -17,6 +17,7 @@ export function useAmis(amisObject) {
struct, struct,
{ {
data: { data: {
debug: information.debug,
base: information.baseUrl, base: information.baseUrl,
}, },
}, },
@@ -98,6 +99,7 @@ export function inputFileFormItemCommonOptions(accept = '*', maxSize = size5MB)
accept: accept, accept: accept,
maxSize: maxSize, maxSize: maxSize,
autoUpload: false, autoUpload: false,
drag: true,
startChunkApi: apiPost('${base}/upload/start'), startChunkApi: apiPost('${base}/upload/start'),
chunkApi: apiPost('${base}/upload/slice'), chunkApi: apiPost('${base}/upload/slice'),
finishChunkApi: apiPost('${base}/upload/finish'), finishChunkApi: apiPost('${base}/upload/finish'),
@@ -129,6 +131,7 @@ export function copyField(field, label, tips = '复制', ignoreLength = 0, extra
} }
return { return {
name: field, name: field,
label: label,
type: 'wrapper', type: 'wrapper',
size: 'none', size: 'none',
className: 'nowrap', className: 'nowrap',
@@ -197,7 +200,7 @@ export function stringField(field, label, width = undefined, wrap = false) {
if (width) { if (width) {
data['width'] = width data['width'] = width
} }
if (wrap) { if (!wrap) {
data['className'] = 'nowrap' data['className'] = 'nowrap'
} }
return data return data
@@ -247,10 +250,11 @@ export const userStateMapping = [
mappingItem('禁用', 'DISABLED', 'bg-danger'), mappingItem('禁用', 'DISABLED', 'bg-danger'),
] ]
export const confirmationStateMapping = [ export const permissionStateMapping = [
mappingItem('未确权', 'NONE'), mappingItem('未确权', 'NONE'),
mappingItem('草稿', 'DRAFT', 'bg-primary'), mappingItem('草稿', 'DRAFT', 'bg-primary'),
mappingItem('审查中', 'CHECKING', 'bg-warning'), mappingItem('审查中', 'CHECKING', 'bg-warning'),
mappingItem('用户审查中', 'OWNER_CHECKING', 'bg-warning'),
mappingItem('通过', 'NORMAL', 'bg-success'), mappingItem('通过', 'NORMAL', 'bg-success'),
mappingItem('驳回', 'REJECT', 'bg-danger'), mappingItem('驳回', 'REJECT', 'bg-danger'),
] ]
@@ -261,8 +265,9 @@ export const checkTypeMapping = [
] ]
export const checkOverMapping = [ export const checkOverMapping = [
mappingItem('完结', 'true', 'bg-success'), mappingItem('进行中', 'CHECKING', 'bg-warning'),
mappingItem('进行中', 'false', 'bg-primary'), mappingItem('已撤销', 'RETRACT', 'bg-primary'),
mappingItem('已办结', 'OVER', 'bg-success'),
] ]
function api(method, url) { function api(method, url) {
@@ -291,10 +296,11 @@ export function arrayOutCheck(array, field) {
return `\${!ARRAYINCLUDES(['${array.join("','")}'], ${field})}` return `\${!ARRAYINCLUDES(['${array.join("','")}'], ${field})}`
} }
export const confirmationState = { export const checkState = {
none: 'NONE', none: 'NONE',
draft: 'DRAFT', draft: 'DRAFT',
checking: 'CHECKING', checking: 'CHECKING',
ownerChecking: 'OWNER_CHECKING',
normal: 'NORMAL', normal: 'NORMAL',
} }

View File

@@ -6,14 +6,29 @@ import {
formInputClearable, formInputClearable,
formInputMultiFileStatic, formInputMultiFileStatic,
horizontalFormOptions, horizontalFormOptions,
information,
inputFileFormItemCommonOptions, inputFileFormItemCommonOptions,
size100MB size100MB
} from "../constants.js"; } from "../constants.js";
import {resourceList} from "../../pages/index/tab-data.js"; import {resourceList} from "../../pages/index/tab-data.js";
import {resourceDetailDialog} from "../resource/dialog-resource.js"; import {resourceDetailDialog} from "../resource/dialog-resource.js";
function detailForm(showCreatedUserAndModifiedUser = false) { const CONFIRMATION_TYPE = 'confirmation'
const AUTHENTICATION_TYPE = 'authentication'
const CONFIRMATION = {
type: 'confirmation',
pickerApi: apiGet('${base}/data_resource/list_no_confirmation')
}
const AUTHENTICATION = {
type: 'authentication',
pickerApi: apiGet('${base}/data_resource/list_no_authentication')
}
function detailForm(pickerApi = apiGet('${base}/data_resource/list'), showCreatedUserAndModifiedUser = false) {
return { return {
debug: information.debug,
id: 'permission_form', id: 'permission_form',
type: 'form', type: 'form',
...horizontalFormOptions(), ...horizontalFormOptions(),
@@ -34,7 +49,7 @@ function detailForm(showCreatedUserAndModifiedUser = false) {
size: 'md', size: 'md',
valueField: 'id', valueField: 'id',
labelField: 'name', labelField: 'name',
source: apiGet('${base}/data_resource/list'), source: pickerApi,
pickerSchema: { pickerSchema: {
...resourceList(), ...resourceList(),
}, },
@@ -55,6 +70,7 @@ function detailForm(showCreatedUserAndModifiedUser = false) {
}, },
{ {
type: 'textarea', type: 'textarea',
placeholder: '请输入确权说明',
label: '确权说明', label: '确权说明',
name: 'description', name: 'description',
...formInputClearable, ...formInputClearable,
@@ -70,12 +86,38 @@ function detailForm(showCreatedUserAndModifiedUser = false) {
joinValues: false, joinValues: false,
...inputFileFormItemCommonOptions(undefined, size100MB), ...inputFileFormItemCommonOptions(undefined, size100MB),
}, },
{
visibleOn: `\${${AUTHENTICATION_TYPE}}`,
type: 'input-datetime-range',
name: 'activeTime',
extraName: 'expiredTime',
label: '授权时间',
required: true,
format: 'YYYY-MM-DD HH:mm:ss',
shortcuts: [
'7dayslater',
'14dayslater',
'30dayslater',
'180dayslater',
'365dayslater',
]
},
...(showCreatedUserAndModifiedUser ? formCreatedUserAndModifiedUser() : []) ...(showCreatedUserAndModifiedUser ? formCreatedUserAndModifiedUser() : [])
] ]
} }
} }
export function permissionAddDialog() { export function confirmationAddDialog() {
return permissionAddDialog(CONFIRMATION)
}
export function authenticationAddDialog() {
return permissionAddDialog(AUTHENTICATION)
}
function permissionAddDialog(config) {
let data = {add: true}
data[config.type] = true
return { return {
actionType: 'dialog', actionType: 'dialog',
dialog: { dialog: {
@@ -93,17 +135,25 @@ export function permissionAddDialog() {
} }
], ],
body: { body: {
...detailForm(), ...detailForm(config.pickerApi),
api: apiPost('${base}/confirmation/save'), api: apiPost(`\${base}/${config.type}/save`),
data: { data: data,
add: true,
},
} }
} }
} }
} }
export function permissionDetailDialog(field = 'id', actions = []) { export function confirmationDetailDialog(field = 'id', actions = []) {
return permissionDetailDialog(CONFIRMATION, field, actions)
}
export function authenticationDetailDialog(field = 'id', actions = []) {
return permissionDetailDialog(AUTHENTICATION, field, actions)
}
function permissionDetailDialog(config, field = 'id', actions = []) {
let data = {detail: true}
data[config.type] = true
return { return {
actionType: 'dialog', actionType: 'dialog',
dialog: { dialog: {
@@ -111,18 +161,26 @@ export function permissionDetailDialog(field = 'id', actions = []) {
size: 'md', size: 'md',
actions: actions, actions: actions,
body: { body: {
...detailForm(true), ...detailForm(config.pickerApi, true),
initApi: apiGet(`\${base}/confirmation/detail/\${${field}}`), initApi: apiGet(`\${base}/${config.type}/detail/\${${field}}`),
static: true, static: true,
data: { data: data,
detail: true,
},
} }
} }
} }
} }
export function permissionEditeDialog(field = 'id') { export function confirmationEditeDialog(field = 'id') {
return permissionEditeDialog(CONFIRMATION, field)
}
export function authenticationEditeDialog(field = 'id') {
return permissionEditeDialog(AUTHENTICATION, field)
}
function permissionEditeDialog(config, field = 'id') {
let data = {edit: true}
data[config.type] = true
return { return {
actionType: 'dialog', actionType: 'dialog',
dialog: { dialog: {
@@ -140,12 +198,10 @@ export function permissionEditeDialog(field = 'id') {
} }
], ],
body: { body: {
...detailForm(), ...detailForm(config.pickerApi),
api: apiPost('${base}/confirmation/save'), api: apiPost(`\${base}/${config.type}/save`),
initApi: apiGet(`\${base}/confirmation/detail/\${${field}}`), initApi: apiGet(`\${base}/${config.type}/detail/\${${field}}`),
data: { data: data,
edit: true,
}
}, },
} }
} }

View File

@@ -16,8 +16,16 @@ const dialogBody = [
{ {
type: 'group', type: 'group',
body: [ body: [
mappingField('role', '角色', userRoleMapping), {
mappingField('state', '账号状态', userStateMapping), type: 'control',
label: '角色',
body: mappingField('role', '角色', userRoleMapping, 120),
},
{
type: 'control',
label: '账号状态',
body: mappingField('state', '账号状态', userStateMapping),
}
] ]
}, },
...formCreatedUserAndModifiedUser(), ...formCreatedUserAndModifiedUser(),

View File

@@ -0,0 +1,3 @@
textarea {
resize: none !important;
}

View File

@@ -0,0 +1,119 @@
import './dialog-ware.css'
import {apiGet, apiPost, formInputClearable, horizontalFormOptions, information} from "../constants.js";
function detailForm() {
return {
debug: information.debug,
type: 'form',
...horizontalFormOptions(),
horizontal: {
left: 2,
},
body: [
{
type: 'hidden',
name: 'id',
},
{
type: 'input-image',
name: 'icon',
label: '图标',
},
{
type: 'input-text',
name: 'name',
label: '商品名称',
maxLength: 10,
showCounter: true,
required: true,
...formInputClearable,
},
{
type: 'textarea',
name: 'description',
label: '商品简介',
required: true,
...formInputClearable,
showCounter: true,
trimContents: true,
minRows: 2,
maxRows: 2,
},
{
type: 'input-rich-text',
name: 'content',
label: '商品详情',
required: true,
options: {
min_height: 300,
}
}
]
}
}
export function wareAddDialog() {
return {
actionType: 'dialog',
dialog: {
title: '上架数据产品',
size: 'md',
actions: [
{
type: 'reset',
label: '重置',
},
{
type: 'submit',
label: '确定',
level: 'primary',
}
],
body: {
...detailForm(),
api: apiPost(`\${base}/ware/save`),
}
}
}
}
export function wareDetailDialog() {
return {
actionType: 'dialog',
dialog: {
title: '确权申请详情',
size: 'md',
body: {
...detailForm(),
initApi: apiGet(`\${base}/ware/detail/\${id}`),
static: true,
}
}
}
}
export function wareEditeDialog() {
return {
actionType: 'dialog',
dialog: {
title: '确权申请详情',
size: 'md',
actions: [
{
type: 'reset',
label: '重置',
},
{
type: 'submit',
label: '确定',
level: 'primary',
}
],
body: {
...detailForm(),
api: apiPost(`\${base}/ware/save`),
initApi: apiGet(`\${base}/ware/detail/\${${field}}`),
},
}
}
}

View File

@@ -5,6 +5,7 @@ import {tabData} from "./tab-data.js";
import {tabSettings} from "./tab-settings.js"; import {tabSettings} from "./tab-settings.js";
import {tabCheck} from "./tab-check.js"; import {tabCheck} from "./tab-check.js";
import {tabPermissions} from "./tab-permissions.js"; import {tabPermissions} from "./tab-permissions.js";
import {tabMarket} from "./tab-market.js";
useAmis(information => { useAmis(information => {
return { return {
@@ -58,10 +59,10 @@ useAmis(information => {
tabsMode: 'vertical', tabsMode: 'vertical',
tabs: [ tabs: [
// tabOverview(), // tabOverview(),
// tabMarket(), tabMarket(),
tabPermissions(),
tabCheck(), tabCheck(),
tabData(), tabData(),
tabPermissions(),
tabUser(), tabUser(),
tabSettings(), tabSettings(),
] ]

View File

@@ -9,7 +9,7 @@ import {
stringField, stringField,
timeField, timeField,
} from "../../components/constants.js"; } from "../../components/constants.js";
import {permissionDetailDialog} from "../../components/permission/dialog-permission.js"; import {authenticationDetailDialog, confirmationDetailDialog} from "../../components/permission/dialog-permission.js";
export function tabCheck() { export function tabCheck() {
return { return {
@@ -29,18 +29,18 @@ export function tabCheck() {
columns: [ columns: [
stringField('description', '描述'), stringField('description', '描述'),
mappingField('type', '类型', checkTypeMapping), mappingField('type', '类型', checkTypeMapping),
mappingField('over', '状态', checkOverMapping), mappingField('state', '状态', checkOverMapping),
timeField('createdTime', '创建时间'), timeField('createdTime', '创建时间'),
stringField('createdUsername', '创建人', 100), stringField('createdUsername', '创建人', 100),
timeField('modifiedTime', '最后修改时间'), timeField('modifiedTime', '最后修改时间'),
stringField('modifiedUsername', '最后操作人', 100), stringField('modifiedUsername', '最后操作人', 100),
operationField('操作', undefined, [ operationField('操作', undefined, [
{ {
visibleOn: '${!over}', visibleOn: `\${type === 'CONFIRMATION' && state === 'CHECKING'}`,
type: 'action', type: 'action',
label: '处理', label: '处理',
level: 'link', level: 'link',
...permissionDetailDialog( ...confirmationDetailDialog(
'parameters.confirmationId', 'parameters.confirmationId',
[ [
{ {
@@ -63,11 +63,45 @@ export function tabCheck() {
), ),
}, },
{ {
visibleOn: '${over}', visibleOn: `\${type === 'CONFIRMATION' && state !== NORMAL}`,
type: 'action', type: 'action',
label: '查看', label: '查看',
level: 'link', level: 'link',
...permissionDetailDialog('parameters.confirmationId'), ...confirmationDetailDialog('parameters.confirmationId'),
},
{
visibleOn: `\${type === 'AUTHENTICATION' && state === 'CHECKING'}`,
type: 'action',
label: '处理',
level: 'link',
...authenticationDetailDialog(
'parameters.authenticationId',
[
{
type: 'action',
label: '同意',
actionType: 'ajax',
close: true,
api: apiGet('${base}/check_order/operation/${checkOrderId}/APPLY'),
reload: 'check_order_list',
},
{
type: 'action',
label: '拒绝',
actionType: 'ajax',
close: true,
api: apiGet('${base}/check_order/operation/${checkOrderId}/REJECT'),
reload: 'check_order_list',
},
],
),
},
{
visibleOn: `\${type === 'AUTHENTICATION' && state !== NORMAL}`,
type: 'action',
label: '查看',
level: 'link',
...authenticationDetailDialog('parameters.authenticationId'),
}, },
]), ]),
], ],

View File

@@ -7,11 +7,11 @@ import {
apiGet, apiGet,
arrayInCheck, arrayInCheck,
arrayOutCheck, arrayOutCheck,
confirmationState, checkState,
confirmationStateMapping,
crudCommonOptions, crudCommonOptions,
mappingField, mappingField,
operationField, operationField,
permissionStateMapping,
timeField, timeField,
userOnly userOnly
} from "../../components/constants.js"; } from "../../components/constants.js";
@@ -40,7 +40,7 @@ export function resourceList() {
label: '描述', label: '描述',
name: 'description', name: 'description',
}, },
mappingField('confirmationState', '确权状态', confirmationStateMapping), mappingField('confirmationState', '确权状态', permissionStateMapping),
timeField('createdTime', '创建时间'), timeField('createdTime', '创建时间'),
operationField('操作', undefined, [ operationField('操作', undefined, [
{ {
@@ -57,7 +57,7 @@ export function resourceList() {
trigger: 'hover', trigger: 'hover',
buttons: [ buttons: [
{ {
disabledOn: arrayOutCheck([confirmationState.none, confirmationState.draft], 'confirmationState'), disabledOn: arrayOutCheck([checkState.none, checkState.draft], 'confirmationState'),
disabledTip: '审查或确权成功后无法编辑', disabledTip: '审查或确权成功后无法编辑',
tooltipPlacement: 'top', tooltipPlacement: 'top',
type: 'action', type: 'action',
@@ -66,7 +66,7 @@ export function resourceList() {
...resourceEditeDialog(), ...resourceEditeDialog(),
}, },
{ {
disabledOn: arrayInCheck([confirmationState.checking], 'confirmationState'), disabledOn: arrayInCheck([checkState.checking], 'confirmationState'),
disabledTip: '审查中无法删除', disabledTip: '审查中无法删除',
tooltipPlacement: 'bottom', tooltipPlacement: 'bottom',
type: 'action', type: 'action',

View File

@@ -1,9 +1,16 @@
import {wareAddDialog} from "../../components/ware/dialog-ware.js";
export function tabMarket() { export function tabMarket() {
return { return {
title: '数据市场', title: '数据市场',
icon: 'fa fa-store', icon: 'fa fa-store',
body: [ body: [
'hello world' {
type: 'action',
label: '',
icon: 'fa fa-plus',
...wareAddDialog()
},
] ]
} }
} }

View File

@@ -1,9 +1,13 @@
import { import {
apiGet, apiGet,
confirmationStateMapping, arrayInCheck,
arrayOutCheck,
checkState,
crudCommonOptions, crudCommonOptions,
customerOnly,
mappingField, mappingField,
operationField, operationField,
permissionStateMapping,
providerOnly, providerOnly,
stringField, stringField,
stringWrapField, stringWrapField,
@@ -11,9 +15,12 @@ import {
userOnly, userOnly,
} from "../../components/constants.js"; } from "../../components/constants.js";
import { import {
permissionAddDialog, authenticationAddDialog,
permissionDetailDialog, authenticationDetailDialog,
permissionEditeDialog, authenticationEditeDialog,
confirmationAddDialog,
confirmationDetailDialog,
confirmationEditeDialog,
} from "../../components/permission/dialog-permission.js"; } from "../../components/permission/dialog-permission.js";
export function tabPermissions() { export function tabPermissions() {
@@ -40,20 +47,20 @@ export function tabPermissions() {
type: 'action', type: 'action',
label: '', label: '',
icon: 'fa fa-plus', icon: 'fa fa-plus',
...permissionAddDialog() ...confirmationAddDialog()
}, },
], ],
columns: [ columns: [
stringField('name', '名称', 200), stringField('name', '名称', 200),
stringWrapField('description', '描述'), stringWrapField('description', '描述'),
mappingField('state', '状态', confirmationStateMapping), mappingField('state', '状态', permissionStateMapping),
timeField('createdTime', '创建时间'), timeField('createdTime', '创建时间'),
operationField('操作', undefined, [ operationField('操作', undefined, [
{ {
type: 'action', type: 'action',
label: '查看', label: '查看',
level: 'link', level: 'link',
...permissionDetailDialog(), ...confirmationDetailDialog(),
}, },
{ {
visibleOn: "${state === 'CHECKING'}", visibleOn: "${state === 'CHECKING'}",
@@ -87,7 +94,7 @@ export function tabPermissions() {
type: 'action', type: 'action',
label: '编辑', label: '编辑',
level: 'link', level: 'link',
...permissionEditeDialog(), ...confirmationEditeDialog(),
}, },
{ {
disabledOn: "${state === 'CHECKING'}", disabledOn: "${state === 'CHECKING'}",
@@ -105,9 +112,84 @@ export function tabPermissions() {
} }
}, },
{ {
visibleOn: customerOnly,
title: '授权管理', title: '授权管理',
body: [] body: {
} type: 'crud',
api: {
...apiGet('${base}/authentication/list')
},
...crudCommonOptions(),
headerToolbar: [
'reload',
{
type: 'action',
label: '',
icon: 'fa fa-plus',
...authenticationAddDialog()
},
],
columns: [
stringField('name', '名称', 200),
stringWrapField('description', '描述'),
mappingField('state', '状态', permissionStateMapping),
timeField('createdTime', '创建时间'),
operationField('操作', undefined, [
{
type: 'action',
label: '查看',
level: 'link',
...authenticationDetailDialog(),
},
{
visibleOn: arrayInCheck([checkState.ownerChecking, checkState.checking], 'state'),
type: 'action',
label: '撤销',
level: 'link',
confirmTitle: '确认撤销',
confirmText: '确认撤销名称为「${name}」的授权申请吗?',
actionType: 'ajax',
api: apiGet('${base}/authentication/retract/${id}'),
},
{
visibleOn: arrayInCheck([checkState.draft], 'state'),
type: 'action',
label: '提交',
level: 'link',
confirmTitle: '确认提交',
confirmText: '确认提交名称为「${name}」的授权申请吗?',
actionType: 'ajax',
api: apiGet('${base}/authentication/submit/${id}'),
},
{
type: 'dropdown-button',
level: 'link',
icon: 'fa fa-ellipsis-h',
hideCaret: true,
trigger: 'hover',
buttons: [
{
disabledOn: arrayOutCheck([checkState.draft], 'state'),
type: 'action',
label: '编辑',
level: 'link',
...authenticationEditeDialog(),
},
{
disabledOn: arrayInCheck([checkState.ownerChecking, checkState.checking], 'state'),
type: 'action',
label: "删除",
confirmTitle: '确认删除',
confirmText: '确认删除名称为「${name}」的确权申请吗?删除后对应的数据资源处于未确权状态。',
actionType: 'ajax',
api: apiGet('${base}/authentication/remove/${id}'),
},
]
},
]),
]
}
},
] ]
} }
} }

View File

@@ -28,6 +28,12 @@
<groupId>com.blinkfox</groupId> <groupId>com.blinkfox</groupId>
<artifactId>fenix-spring-boot-starter</artifactId> <artifactId>fenix-spring-boot-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>${hibernate.version}</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
@@ -37,6 +43,18 @@
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<parameters>true</parameters>
<compilerArguments>
<processor>
lombok.launch.AnnotationProcessorHider$AnnotationProcessor,org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
</processor>
</compilerArguments>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>

View File

@@ -1,7 +1,8 @@
package com.eshore.gringotts.web; package com.eshore.gringotts.web;
import com.blinkfox.fenix.EnableFenix; import com.blinkfox.fenix.EnableFenix;
import com.eshore.gringotts.web.domain.user.service.UserService; import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.service.UserService;
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationRunner;
@@ -9,6 +10,8 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
@@ -41,4 +44,9 @@ public class WebApplication implements ApplicationRunner {
// 初始化系统管理员 // 初始化系统管理员
userService.initial(); userService.initial();
} }
@Bean
public AuditorAware<User> auditorAware(UserService userService) {
return userService::currentLoginUserOptional;
}
} }

View File

@@ -1,6 +1,7 @@
package com.eshore.gringotts.web.domain.base.controller; package com.eshore.gringotts.web.domain.base.controller;
import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.base.controller.query.Query;
import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.ImmutableList;
/** /**
@@ -9,4 +10,6 @@ import org.eclipse.collections.api.list.ImmutableList;
*/ */
public interface ListController<LIST_ITEM> { public interface ListController<LIST_ITEM> {
AmisResponse<ImmutableList<LIST_ITEM>> list() throws Exception; AmisResponse<ImmutableList<LIST_ITEM>> list() throws Exception;
AmisResponse<ImmutableList<LIST_ITEM>> list(Query query) throws Exception;
} }

View File

@@ -1,8 +1,12 @@
package com.eshore.gringotts.web.domain.base.controller; package com.eshore.gringotts.web.domain.base.controller;
import cn.hutool.core.util.ObjectUtil;
import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.base.controller.query.Query;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity; import com.eshore.gringotts.web.domain.base.entity.SimpleEntity;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport; import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.ImmutableList;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@@ -13,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestBody;
* @author lanyuanxiaoyao * @author lanyuanxiaoyao
* @date 2024-11-26 * @date 2024-11-26
*/ */
@Slf4j
public abstract class SimpleControllerSupport<ENTITY extends SimpleEntity, SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> implements SimpleController<SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> { public abstract class SimpleControllerSupport<ENTITY extends SimpleEntity, SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> implements SimpleController<SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> {
protected static final String SAVE = "/save"; protected static final String SAVE = "/save";
protected static final String LIST = "/list"; protected static final String LIST = "/list";
@@ -33,7 +38,7 @@ public abstract class SimpleControllerSupport<ENTITY extends SimpleEntity, SAVE_
@GetMapping(LIST) @GetMapping(LIST)
@Override @Override
public AmisResponse<ImmutableList<LIST_ITEM>> list() { public AmisResponse<ImmutableList<LIST_ITEM>> list() throws Exception {
return AmisResponse.responseSuccess(service.list().collect(entity -> { return AmisResponse.responseSuccess(service.list().collect(entity -> {
try { try {
return toListItem(entity); return toListItem(entity);
@@ -43,10 +48,25 @@ public abstract class SimpleControllerSupport<ENTITY extends SimpleEntity, SAVE_
})); }));
} }
@PostMapping(LIST)
@Override
public AmisResponse<ImmutableList<LIST_ITEM>> list(@RequestBody Query query) throws Exception {
if (ObjectUtil.isNull(query)) {
return AmisResponse.responseSuccess(Lists.immutable.empty());
}
return AmisResponse.responseSuccess(service.list(query).collect(entity -> {
try {
return toListItem(entity);
} catch (Exception e) {
throw new RuntimeException(e);
}
}));
}
@GetMapping(DETAIL) @GetMapping(DETAIL)
@Override @Override
public AmisResponse<DETAIL_ITEM> detail(@PathVariable Long id) throws Exception { public AmisResponse<DETAIL_ITEM> detail(@PathVariable Long id) throws Exception {
return AmisResponse.responseSuccess(toDetailItem(service.detail(id))); return AmisResponse.responseSuccess(toDetailItem(service.detailOrThrow(id)));
} }
@GetMapping(REMOVE) @GetMapping(REMOVE)

View File

@@ -0,0 +1,61 @@
package com.eshore.gringotts.web.domain.base.controller.query;
import lombok.Data;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.map.ImmutableMap;
/**
* 统一查询
*
* @author lanyuanxiaoyao
* @date 2024-12-03
*/
@Data
public class Query {
private Queryable query;
private ImmutableList<Sortable> sort;
private Pageable page;
@Data
public static class Queryable {
private ImmutableList<String> nullEqual;
private ImmutableList<String> notNullEqual;
private ImmutableList<String> empty;
private ImmutableList<String> notEmpty;
private ImmutableMap<String, ?> equal;
private ImmutableMap<String, ?> notEqual;
private ImmutableMap<String, String> like;
private ImmutableMap<String, String> notLike;
private ImmutableMap<String, ?> great;
private ImmutableMap<String, ?> less;
private ImmutableMap<String, ?> greatEqual;
private ImmutableMap<String, ?> lessEqual;
private ImmutableMap<String, ImmutableList<?>> in;
private ImmutableMap<String, ImmutableList<?>> notIn;
private ImmutableMap<String, Between> between;
private ImmutableMap<String, Between> notBetween;
@Data
public static class Between {
private String start;
private String end;
}
}
@Data
public static class Sortable {
private String column;
private Direction direction;
public enum Direction {
ASC,
DESC,
}
}
@Data
public static class Pageable {
private Integer page;
private Integer size;
}
}

View File

@@ -1,10 +1,14 @@
package com.eshore.gringotts.web.domain.base.entity; package com.eshore.gringotts.web.domain.base.entity;
import com.eshore.gringotts.web.domain.entity.CheckOrder;
import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.EntityListeners; import javax.persistence.EntityListeners;
import javax.persistence.EnumType; import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
import javax.persistence.OneToOne;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@@ -22,6 +26,10 @@ public class CheckingNeededEntity extends LogicDeleteEntity {
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private State state = State.DRAFT; private State state = State.DRAFT;
@OneToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
@ToString.Exclude
private CheckOrder order;
public enum State { public enum State {
/** /**
* 无确权 * 无确权
@@ -35,6 +43,10 @@ public class CheckingNeededEntity extends LogicDeleteEntity {
* 审查中 * 审查中
*/ */
CHECKING, CHECKING,
/**
* 用户审核
*/
OWNER_CHECKING,
/** /**
* 正常 * 正常
*/ */

View File

@@ -1,6 +1,6 @@
package com.eshore.gringotts.web.domain.base.entity; package com.eshore.gringotts.web.domain.base.entity;
import com.eshore.gringotts.web.domain.upload.entity.DataFile; import com.eshore.gringotts.web.domain.entity.DataFile;
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationContext;

View File

@@ -1,6 +1,6 @@
package com.eshore.gringotts.web.domain.base.entity; package com.eshore.gringotts.web.domain.base.entity;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.entity.User;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.EntityListeners; import javax.persistence.EntityListeners;
@@ -12,7 +12,9 @@ import javax.persistence.OneToOne;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@@ -33,11 +35,13 @@ public class SimpleEntity extends IdOnlyEntity {
@OneToOne(fetch = FetchType.LAZY) @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude @ToString.Exclude
@CreatedBy
private User createdUser; private User createdUser;
@LastModifiedDate @LastModifiedDate
private LocalDateTime modifiedTime; private LocalDateTime modifiedTime;
@OneToOne(fetch = FetchType.LAZY) @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude @ToString.Exclude
@LastModifiedBy
private User modifiedUser; private User modifiedUser;
} }

View File

@@ -3,6 +3,7 @@ package com.eshore.gringotts.web.domain.base.repository;
import com.blinkfox.fenix.jpa.FenixJpaRepository; import com.blinkfox.fenix.jpa.FenixJpaRepository;
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor; import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.QueryByExampleExecutor;
/** /**
* 整合一下 * 整合一下
@@ -11,5 +12,5 @@ import org.springframework.data.repository.NoRepositoryBean;
* @date 2024-11-21 * @date 2024-11-21
*/ */
@NoRepositoryBean @NoRepositoryBean
public interface SimpleRepository<E, ID> extends FenixJpaRepository<E, ID>, FenixJpaSpecificationExecutor<E> { public interface SimpleRepository<E, ID> extends FenixJpaRepository<E, ID>, FenixJpaSpecificationExecutor<E>, QueryByExampleExecutor<E> {
} }

View File

@@ -1,6 +1,6 @@
package com.eshore.gringotts.web.domain.base.service; package com.eshore.gringotts.web.domain.base.service;
import com.eshore.gringotts.web.domain.check.entity.CheckOrder; import com.eshore.gringotts.web.domain.entity.CheckOrder;
import org.eclipse.collections.api.map.ImmutableMap; import org.eclipse.collections.api.map.ImmutableMap;
/** /**

View File

@@ -4,7 +4,7 @@ import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.user.service.UserService; import com.eshore.gringotts.web.domain.service.UserService;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
@@ -13,7 +13,6 @@ import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.ImmutableList;
/** /**
@@ -30,13 +29,8 @@ public abstract class LogicDeleteService<ENTITY extends LogicDeleteEntity> exten
} }
@Override @Override
protected ImmutableList<Predicate> extraListPredicates(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) { protected ImmutableList<Predicate> listPredicate(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
return Lists.immutable.of(builder.equal(root.get("deleted"), false)); return super.listPredicate(root, query, builder).newWith(builder.equal(root.get("deleted"), false));
}
@Override
protected ImmutableList<Predicate> extraDetailPredicates(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
return Lists.immutable.of(builder.equal(root.get("deleted"), false));
} }
@Transactional(rollbackOn = Throwable.class) @Transactional(rollbackOn = Throwable.class)

View File

@@ -1,5 +1,6 @@
package com.eshore.gringotts.web.domain.base.service; package com.eshore.gringotts.web.domain.base.service;
import com.eshore.gringotts.web.domain.base.controller.query.Query;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity; import com.eshore.gringotts.web.domain.base.entity.SimpleEntity;
import java.util.Optional; import java.util.Optional;
import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.ImmutableList;
@@ -16,6 +17,8 @@ public interface SimpleService<ENTITY extends SimpleEntity> {
ImmutableList<ENTITY> list(ImmutableSet<Long> ids) throws Exception; ImmutableList<ENTITY> list(ImmutableSet<Long> ids) throws Exception;
ImmutableList<ENTITY> list(Query query) throws Exception;
Optional<ENTITY> detailOptional(Long id) throws Exception; Optional<ENTITY> detailOptional(Long id) throws Exception;
ENTITY detail(Long id) throws Exception; ENTITY detail(Long id) throws Exception;

View File

@@ -2,15 +2,20 @@ package com.eshore.gringotts.web.domain.base.service;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.eshore.gringotts.web.domain.base.controller.query.Query;
import com.eshore.gringotts.web.domain.base.entity.IdOnlyEntity_;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity; import com.eshore.gringotts.web.domain.base.entity.SimpleEntity;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity_;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.user.service.UserService; import com.eshore.gringotts.web.domain.service.UserService;
import java.util.Optional; import java.util.Optional;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import javax.transaction.Transactional; import javax.transaction.Transactional;
@@ -45,57 +50,144 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
entity, entity,
targetEntity, targetEntity,
CopyOptions.create() CopyOptions.create()
.setIgnoreProperties("id", "createdUser", "createdTime", "modifiedUser", "modifiedTime") .setIgnoreProperties(
IdOnlyEntity_.ID,
SimpleEntity_.CREATED_USER,
SimpleEntity_.CREATED_TIME,
SimpleEntity_.MODIFIED_USER,
SimpleEntity_.MODIFIED_TIME
)
); );
entity = targetEntity; entity = targetEntity;
} }
User user = userService.currentLoginUser();
if (ObjectUtil.isNull(entity.getCreatedUser())) {
entity.setCreatedUser(user);
}
entity.setModifiedUser(user);
entity = repository.save(entity); entity = repository.save(entity);
return entity.getId(); return entity.getId();
} }
@Override @Override
public ImmutableList<ENTITY> list() { public ImmutableList<ENTITY> list() throws Exception {
return Lists.immutable.ofAll(repository.findAll( return Lists.immutable.ofAll(repository.findAll(
(root, query, builder) -> { (root, query, builder) ->
MutableList<Predicate> predicates = Lists.mutable.empty(); builder.and(
User user = userService.currentLoginUser(); listPredicate(root, query, builder)
if (User.isNotAdministrator(user)) { .reject(ObjectUtil::isNull)
predicates.add(builder.equal(root.get("createdUser"), user)); .toArray(new Predicate[]{})
} )
predicates.addAllIterable(extraListPredicates(root, query, builder));
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
},
Sort.by("createdTime").descending()
)); ));
} }
@Override @Override
public ImmutableList<ENTITY> list(ImmutableSet<Long> ids) { public ImmutableList<ENTITY> list(ImmutableSet<Long> ids) throws Exception {
return Lists.immutable.ofAll(repository.findAll( return Lists.immutable.ofAll(repository.findAll(
(root, query, builder) -> { (root, query, builder) -> {
MutableList<Predicate> predicates = Lists.mutable.of( MutableList<Predicate> predicates = Lists.mutable.ofAll(listPredicate(root, query, builder));
builder.in(root.get("id")).value(ids.select(ObjectUtil::isNotNull)) predicates.add(builder.in(root.get("id")).value(ids));
); return builder.and(predicates.reject(ObjectUtil::isNull).toArray(new Predicate[predicates.size()]));
User user = userService.currentLoginUser(); }
if (User.isNotAdministrator(user)) {
predicates.add(builder.equal(root.get("createdUser"), user));
}
predicates.addAllIterable(extraListPredicates(root, query, builder));
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
},
Sort.by("createdTime").descending()
)); ));
} }
protected ImmutableList<Predicate> extraListPredicates(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) { private <Y> Path<Y> column(Root<ENTITY> root, String column) {
String[] columns = StrUtil.splitToArray(column, "/");
Path<Y> path = root.get(columns[0]);
for (int i = 1; i < columns.length; i++) {
path = path.get(columns[i]);
}
return path;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private <Y> Object value(Path<Y> column, Object value) {
Class<?> javaType = column.getJavaType();
if (EnumUtil.isEnum(javaType)) {
return EnumUtil.fromString((Class<Enum>) javaType, (String) value);
}
return value;
}
@SuppressWarnings("unchecked")
private ImmutableList<Predicate> queryPredicates(Query.Queryable queryable, Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
MutableList<Predicate> predicates = Lists.mutable.empty();
if (ObjectUtil.isEmpty(queryable)) {
return predicates.toImmutable();
}
if (ObjectUtil.isNotEmpty(queryable.getNullEqual())) {
queryable.getNullEqual().forEach(column -> predicates.add(builder.isNull(column(root, column))));
}
if (ObjectUtil.isNotEmpty(queryable.getNotNullEqual())) {
queryable.getNotNullEqual().forEach(column -> predicates.add(builder.isNull(column(root, column))));
}
if (ObjectUtil.isNotEmpty(queryable.getEmpty())) {
queryable.getEmpty().forEach(column -> predicates.add(builder.isEmpty(column(root, column))));
}
if (ObjectUtil.isNotEmpty(queryable.getNotEmpty())) {
queryable.getNotEmpty().forEach(column -> predicates.add(builder.isNotEmpty(column(root, column))));
}
if (ObjectUtil.isNotEmpty(queryable.getEqual())) {
queryable.getEqual().forEachKeyValue((column, value) -> {
Path<Object> path = column(root, column);
predicates.add(builder.equal(path, value(path, value)));
});
}
if (ObjectUtil.isNotEmpty(queryable.getNotEqual())) {
queryable.getEqual().forEachKeyValue((column, value) -> {
Path<Object> path = column(root, column);
predicates.add(builder.notEqual(path, value(path, value)));
});
}
if (ObjectUtil.isNotEmpty(queryable.getLike())) {
queryable.getLike().forEachKeyValue((column, value) -> predicates.add(builder.like(column(root, column), value)));
}
if (ObjectUtil.isNotEmpty(queryable.getNotLike())) {
queryable.getNotLike().forEachKeyValue((column, value) -> predicates.add(builder.notLike(column(root, column), value)));
}
if (ObjectUtil.isNotEmpty(queryable.getGreat())) {
queryable.getGreat().forEachKeyValue((column, value) -> predicates.add(builder.greaterThan(column(root, column), (Comparable<Object>) value)));
}
if (ObjectUtil.isNotEmpty(queryable.getLess())) {
queryable.getLess().forEachKeyValue((column, value) -> predicates.add(builder.lessThan(column(root, column), (Comparable<Object>) value)));
}
if (ObjectUtil.isNotEmpty(queryable.getGreatEqual())) {
queryable.getGreatEqual().forEachKeyValue((column, value) -> predicates.add(builder.greaterThanOrEqualTo(column(root, column), (Comparable<Object>) value)));
}
if (ObjectUtil.isNotEmpty(queryable.getLessEqual())) {
queryable.getLessEqual().forEachKeyValue((column, value) -> predicates.add(builder.lessThanOrEqualTo(column(root, column), (Comparable<Object>) value)));
}
if (ObjectUtil.isNotEmpty(queryable.getIn())) {
queryable.getIn().forEachKeyValue((column, value) -> predicates.add(builder.in(column(root, column)).value(value)));
}
if (ObjectUtil.isNotEmpty(queryable.getNotIn())) {
queryable.getNotIn().forEachKeyValue((column, value) -> predicates.add(builder.in(column(root, column)).value(value).not()));
}
if (ObjectUtil.isNotEmpty(queryable.getBetween())) {
queryable.getBetween().forEachKeyValue((column, value) -> predicates.add(builder.between(column(root, column), value.getStart(), value.getEnd())));
}
if (ObjectUtil.isNotEmpty(queryable.getNotBetween())) {
queryable.getNotBetween().forEachKeyValue((column, value) -> predicates.add(builder.between(column(root, column), value.getStart(), value.getEnd())));
}
return predicates.toImmutable();
}
protected ImmutableList<Predicate> listPredicate(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
User user = userService.currentLoginUser();
if (User.isNotAdministrator(user)) {
return Lists.immutable.of(builder.equal(root.get(SimpleEntity_.createdUser), user));
}
return Lists.immutable.empty(); return Lists.immutable.empty();
} }
@Override
public ImmutableList<ENTITY> list(Query listQuery) throws Exception {
return Lists.immutable.ofAll(repository.findAll(
(root, query, builder) -> {
MutableList<Predicate> predicates = Lists.mutable.ofAll(listPredicate(root, query, builder));
predicates.addAllIterable(queryPredicates(listQuery.getQuery(), root, query, builder));
return builder.and(predicates.reject(ObjectUtil::isNull).toArray(new Predicate[predicates.size()]));
},
Sort.by(SimpleEntity_.CREATED_TIME).descending()
));
}
@Override @Override
public Optional<ENTITY> detailOptional(Long id) { public Optional<ENTITY> detailOptional(Long id) {
if (ObjectUtil.isNull(id)) { if (ObjectUtil.isNull(id)) {
@@ -103,23 +195,13 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
} }
return repository.findOne( return repository.findOne(
(root, query, builder) -> { (root, query, builder) -> {
MutableList<Predicate> predicates = Lists.mutable.of( MutableList<Predicate> predicates = Lists.mutable.ofAll(listPredicate(root, query, builder));
builder.equal(root.get("id"), id) predicates.add(builder.equal(root.get(IdOnlyEntity_.id), id));
); return builder.and(predicates.reject(ObjectUtil::isNull).toArray(new Predicate[predicates.size()]));
User user = userService.currentLoginUser();
if (User.isNotAdministrator(user)) {
predicates.add(builder.equal(root.get("createdUser"), user));
}
predicates.addAllIterable(extraDetailPredicates(root, query, builder));
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
} }
); );
} }
protected ImmutableList<Predicate> extraDetailPredicates(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
return Lists.immutable.empty();
}
@Override @Override
public ENTITY detail(Long id) { public ENTITY detail(Long id) {
return detailOrNull(id); return detailOrNull(id);
@@ -144,6 +226,10 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
} }
public static final class IdNotFoundException extends RuntimeException { public static final class IdNotFoundException extends RuntimeException {
public IdNotFoundException() {
super("资源不存在");
}
public IdNotFoundException(Long id) { public IdNotFoundException(Long id) {
super(StrUtil.format("ID为{}的资源不存在", id)); super(StrUtil.format("ID为{}的资源不存在", id));
} }

View File

@@ -1,92 +0,0 @@
package com.eshore.gringotts.web.domain.confirmation.service;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.eshore.gringotts.web.domain.base.service.CheckingService;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.check.entity.CheckOrder;
import com.eshore.gringotts.web.domain.check.service.CheckOrderService;
import com.eshore.gringotts.web.domain.confirmation.entity.Confirmation;
import com.eshore.gringotts.web.domain.confirmation.repository.ConfirmationRepository;
import com.eshore.gringotts.web.domain.user.entity.User;
import com.eshore.gringotts.web.domain.user.service.UserService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.map.ImmutableMap;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Service;
/**
* @author lanyuanxiaoyao
* @date 2024-11-26
*/
@Slf4j
@Service("com.eshore.gringotts.web.domain.confirmation.service.ConfirmationService")
public class ConfirmationService extends SimpleServiceSupport<Confirmation> implements CheckingService {
private final ConfirmationRepository confirmationRepository;
private final UserService userService;
private final CheckOrderService checkOrderService;
private final ObjectMapper mapper;
public ConfirmationService(ConfirmationRepository confirmationRepository, UserService userService, CheckOrderService checkOrderService, Jackson2ObjectMapperBuilder builder) {
super(confirmationRepository, userService);
this.confirmationRepository = confirmationRepository;
this.userService = userService;
this.checkOrderService = checkOrderService;
this.mapper = builder.build();
}
@Override
public Long save(Confirmation entity) {
if (ObjectUtil.isNull(entity.getId()) && confirmationRepository.existsByTarget_Id(entity.getTarget().getId())) {
throw new ConfirmationDuplicatedException();
}
return super.save(entity);
}
@Transactional(rollbackOn = Throwable.class)
public void submit(Long id) throws JsonProcessingException {
Confirmation confirmation = detailOrThrow(id);
log.info("confirmation: {}", confirmation);
confirmation.setState(Confirmation.State.CHECKING);
checkOrderService.save(new CheckOrder(
"confirmation_check",
StrUtil.format("数据资源「{}」的确权申请", confirmation.getTarget().getName()),
CheckOrder.Type.CONFIRMATION,
mapper.writeValueAsString(Maps.immutable.of("confirmationId", confirmation.getId())),
"com.eshore.gringotts.web.domain.confirmation.service.ConfirmationService",
User.Role.ADMINISTRATOR
));
save(confirmation);
}
public void retract(Long id) {
confirmationRepository.updateStateById(id, Confirmation.State.DRAFT, userService.currentLoginUser());
}
@Override
public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap<String, Object> parameters) {
if (StrUtil.equals(order.getKey(), "confirmation_check")) {
Long id = (Long) parameters.get("confirmationId");
switch (operation) {
case APPLY:
confirmationRepository.updateStateById(id, Confirmation.State.NORMAL, userService.currentLoginUser());
checkOrderService.over(order.getId());
break;
case REJECT:
confirmationRepository.updateStateById(id, Confirmation.State.DRAFT, userService.currentLoginUser());
checkOrderService.over(order.getId());
break;
}
}
}
public static final class ConfirmationDuplicatedException extends RuntimeException {
public ConfirmationDuplicatedException() {
super("数据资源已绑定确权申请,无法再次申请");
}
}
}

View File

@@ -0,0 +1,130 @@
package com.eshore.gringotts.web.domain.controller;
import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport;
import com.eshore.gringotts.web.domain.base.entity.FileInfo;
import com.eshore.gringotts.web.domain.base.entity.SimpleListItem;
import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem;
import com.eshore.gringotts.web.domain.entity.Authentication;
import com.eshore.gringotts.web.domain.service.AuthenticationService;
import com.eshore.gringotts.web.domain.service.DataFileService;
import com.eshore.gringotts.web.domain.service.DataResourceService;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Sets;
import org.eclipse.collections.api.set.ImmutableSet;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author lanyuanxiaoyao
* @date 2024-12-02
*/
@Slf4j
@RestController
@RequestMapping("authentication")
public class AuthenticationController extends SimpleControllerSupport<Authentication, AuthenticationController.SaveItem, AuthenticationController.ListItem, AuthenticationController.DetailItem> {
private final AuthenticationService authenticationService;
private final DataResourceService dataResourceService;
private final DataFileService dataFileService;
public AuthenticationController(AuthenticationService service, DataResourceService dataResourceService, DataFileService dataFileService) {
super(service);
this.authenticationService = service;
this.dataResourceService = dataResourceService;
this.dataFileService = dataFileService;
}
@GetMapping("/submit/{id}")
public AmisResponse<Object> submit(@PathVariable Long id) throws JsonProcessingException {
authenticationService.submit(id);
return AmisResponse.responseSuccess();
}
@GetMapping("/retract/{id}")
public AmisResponse<Object> retract(@PathVariable Long id) {
authenticationService.retract(id);
return AmisResponse.responseSuccess();
}
@Override
protected Authentication fromSaveItem(SaveItem item) throws Exception {
Authentication authentication = new Authentication();
authentication.setId(item.getId());
authentication.setDescription(item.getDescription());
authentication.setTarget(dataResourceService.detailOrThrow(item.getTargetId()));
authentication.setEvidences(dataFileService.list(item.getEvidenceFiles().collect(FileInfo::getValue)).toSet());
authentication.setActiveTime(item.getActiveTime());
authentication.setExpiredTime(item.getExpiredTime());
return authentication;
}
@Override
protected ListItem toListItem(Authentication entity) {
return new ListItem(entity);
}
@Override
protected DetailItem toDetailItem(Authentication entity) {
return new DetailItem(entity);
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class SaveItem extends SimpleSaveItem<Authentication> {
private Long targetId;
private String description;
private ImmutableSet<FileInfo> evidenceFiles;
private LocalDateTime activeTime;
private LocalDateTime expiredTime;
}
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public static final class ListItem extends SimpleListItem<Authentication> {
private String name;
private String description;
private String state;
public ListItem(Authentication authentication) {
this.setId(authentication.getId());
this.setName(authentication.getTarget().getName());
this.setDescription(authentication.getDescription());
this.setState(authentication.getState().name());
this.setCreatedUsername(authentication.getCreatedUser().getUsername());
this.setCreatedTime(authentication.getCreatedTime());
}
}
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public static final class DetailItem extends SaveItem {
private String targetName;
private LocalDateTime createdTime;
private String createdUsername;
private LocalDateTime modifiedTime;
private String modifiedUsername;
public DetailItem(Authentication authentication) {
this.setId(authentication.getId());
this.setTargetId(authentication.getTarget().getId());
this.setTargetName(authentication.getTarget().getName());
this.setDescription(authentication.getDescription());
this.setEvidenceFiles(Sets.immutable.ofAll(authentication.getEvidences()).collect(FileInfo::new));
this.setActiveTime(authentication.getActiveTime());
this.setExpiredTime(authentication.getExpiredTime());
this.setCreatedTime(authentication.getCreatedTime());
this.setCreatedUsername(authentication.getCreatedUser().getUsername());
this.setModifiedTime(authentication.getModifiedTime());
this.setModifiedUsername(authentication.getModifiedUser().getUsername());
}
}
}

View File

@@ -1,9 +1,10 @@
package com.eshore.gringotts.web.domain.check.controller; package com.eshore.gringotts.web.domain.controller;
import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.base.controller.ListController; import com.eshore.gringotts.web.domain.base.controller.ListController;
import com.eshore.gringotts.web.domain.check.entity.CheckOrder; import com.eshore.gringotts.web.domain.base.controller.query.Query;
import com.eshore.gringotts.web.domain.check.service.CheckOrderService; import com.eshore.gringotts.web.domain.entity.CheckOrder;
import com.eshore.gringotts.web.domain.service.CheckOrderService;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@@ -16,6 +17,8 @@ import org.eclipse.collections.api.map.ImmutableMap;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -43,6 +46,12 @@ public class CheckOrderController implements ListController<CheckOrderController
return AmisResponse.responseSuccess(checkOrderService.list().collect(this::toListItem)); return AmisResponse.responseSuccess(checkOrderService.list().collect(this::toListItem));
} }
@PostMapping("/list")
@Override
public AmisResponse<ImmutableList<ListItem>> list(@RequestBody Query query) throws Exception {
return AmisResponse.responseSuccess(checkOrderService.list().collect(this::toListItem));
}
@SneakyThrows @SneakyThrows
private ListItem toListItem(CheckOrder order) { private ListItem toListItem(CheckOrder order) {
ListItem item = new ListItem(); ListItem item = new ListItem();
@@ -50,7 +59,7 @@ public class CheckOrderController implements ListController<CheckOrderController
item.setDescription(order.getDescription()); item.setDescription(order.getDescription());
item.setType(order.getType()); item.setType(order.getType());
item.setParameters(mapper.readValue(order.getParameters(), new TypeReference<>() {})); item.setParameters(mapper.readValue(order.getParameters(), new TypeReference<>() {}));
item.setOver(order.getOver()); item.setState(order.getState());
item.setCreatedUsername(order.getCreatedUser().getUsername()); item.setCreatedUsername(order.getCreatedUser().getUsername());
item.setCreatedTime(order.getCreatedTime()); item.setCreatedTime(order.getCreatedTime());
item.setModifiedUsername(order.getModifiedUser().getUsername()); item.setModifiedUsername(order.getModifiedUser().getUsername());
@@ -71,7 +80,7 @@ public class CheckOrderController implements ListController<CheckOrderController
private String description; private String description;
private CheckOrder.Type type; private CheckOrder.Type type;
private ImmutableMap<String, Object> parameters; private ImmutableMap<String, Object> parameters;
private Boolean over; private CheckOrder.State state;
private LocalDateTime createdTime; private LocalDateTime createdTime;
private String createdUsername; private String createdUsername;
private LocalDateTime modifiedTime; private LocalDateTime modifiedTime;

View File

@@ -1,14 +1,14 @@
package com.eshore.gringotts.web.domain.confirmation.controller; package com.eshore.gringotts.web.domain.controller;
import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport; import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport;
import com.eshore.gringotts.web.domain.base.entity.FileInfo; import com.eshore.gringotts.web.domain.base.entity.FileInfo;
import com.eshore.gringotts.web.domain.base.entity.SimpleListItem; import com.eshore.gringotts.web.domain.base.entity.SimpleListItem;
import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem; import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem;
import com.eshore.gringotts.web.domain.confirmation.entity.Confirmation; import com.eshore.gringotts.web.domain.entity.Confirmation;
import com.eshore.gringotts.web.domain.confirmation.service.ConfirmationService; import com.eshore.gringotts.web.domain.service.ConfirmationService;
import com.eshore.gringotts.web.domain.resource.service.DataResourceService; import com.eshore.gringotts.web.domain.service.DataFileService;
import com.eshore.gringotts.web.domain.upload.service.DataFileService; import com.eshore.gringotts.web.domain.service.DataResourceService;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import lombok.Data; import lombok.Data;
@@ -53,7 +53,7 @@ public class ConfirmationController extends SimpleControllerSupport<Confirmation
} }
@Override @Override
protected Confirmation fromSaveItem(SaveItem item) { protected Confirmation fromSaveItem(SaveItem item) throws Exception {
Confirmation confirmation = new Confirmation(); Confirmation confirmation = new Confirmation();
confirmation.setId(item.getId()); confirmation.setId(item.getId());
confirmation.setDescription(item.getDescription()); confirmation.setDescription(item.getDescription());
@@ -64,14 +64,7 @@ public class ConfirmationController extends SimpleControllerSupport<Confirmation
@Override @Override
protected ListItem toListItem(Confirmation entity) { protected ListItem toListItem(Confirmation entity) {
ListItem item = new ListItem(); return new ListItem(entity);
item.setId(entity.getId());
item.setName(entity.getTarget().getName());
item.setDescription(entity.getDescription());
item.setState(entity.getState().name());
item.setCreatedUsername(entity.getCreatedUser().getUsername());
item.setCreatedTime(entity.getCreatedTime());
return item;
} }
@Override @Override
@@ -89,10 +82,19 @@ public class ConfirmationController extends SimpleControllerSupport<Confirmation
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public static class ListItem extends SimpleListItem<Confirmation> { public static final class ListItem extends SimpleListItem<Confirmation> {
private String name; private String name;
private String description; private String description;
private String state; private String state;
public ListItem(Confirmation confirmation) {
this.setId(confirmation.getId());
this.setName(confirmation.getTarget().getName());
this.setDescription(confirmation.getDescription());
this.setState(confirmation.getState().name());
this.setCreatedUsername(confirmation.getCreatedUser().getUsername());
this.setCreatedTime(confirmation.getCreatedTime());
}
} }
@Data @Data

View File

@@ -1,11 +1,11 @@
package com.eshore.gringotts.web.domain.upload.controller; package com.eshore.gringotts.web.domain.controller;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import com.eshore.gringotts.web.configuration.UploadConfiguration; import com.eshore.gringotts.web.configuration.UploadConfiguration;
import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.upload.service.DataFileService; import com.eshore.gringotts.web.domain.service.DataFileService;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;

View File

@@ -1,28 +1,29 @@
package com.eshore.gringotts.web.domain.resource.controller; package com.eshore.gringotts.web.domain.controller;
import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport; import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport;
import com.eshore.gringotts.web.domain.base.entity.FileInfo; import com.eshore.gringotts.web.domain.base.entity.FileInfo;
import com.eshore.gringotts.web.domain.base.entity.SimpleListItem; import com.eshore.gringotts.web.domain.base.entity.SimpleListItem;
import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem; import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem;
import com.eshore.gringotts.web.domain.confirmation.entity.Confirmation; import com.eshore.gringotts.web.domain.entity.Confirmation;
import com.eshore.gringotts.web.domain.resource.entity.DataResource; import com.eshore.gringotts.web.domain.entity.DataFile;
import com.eshore.gringotts.web.domain.resource.entity.format.CsvResourceFormat; import com.eshore.gringotts.web.domain.entity.DataResource;
import com.eshore.gringotts.web.domain.resource.entity.format.JsonLineResourceFormat; import com.eshore.gringotts.web.domain.entity.format.CsvResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.format.JsonResourceFormat; import com.eshore.gringotts.web.domain.entity.format.JsonLineResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.format.LineResourceFormat; import com.eshore.gringotts.web.domain.entity.format.JsonResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.format.NoneResourceFormat; import com.eshore.gringotts.web.domain.entity.format.LineResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.format.ResourceFormat; import com.eshore.gringotts.web.domain.entity.format.NoneResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.type.ApiResourceType; import com.eshore.gringotts.web.domain.entity.format.ResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.type.DatabaseResourceType; import com.eshore.gringotts.web.domain.entity.type.ApiResourceType;
import com.eshore.gringotts.web.domain.resource.entity.type.FileResourceType; import com.eshore.gringotts.web.domain.entity.type.DatabaseResourceType;
import com.eshore.gringotts.web.domain.resource.entity.type.FtpResourceType; import com.eshore.gringotts.web.domain.entity.type.FileResourceType;
import com.eshore.gringotts.web.domain.resource.entity.type.HDFSResourceType; import com.eshore.gringotts.web.domain.entity.type.FtpResourceType;
import com.eshore.gringotts.web.domain.resource.entity.type.ResourceType; import com.eshore.gringotts.web.domain.entity.type.HDFSResourceType;
import com.eshore.gringotts.web.domain.resource.service.DataResourceService; import com.eshore.gringotts.web.domain.entity.type.ResourceType;
import com.eshore.gringotts.web.domain.upload.entity.DataFile; import com.eshore.gringotts.web.domain.service.DataFileService;
import com.eshore.gringotts.web.domain.upload.service.DataFileService; import com.eshore.gringotts.web.domain.service.DataResourceService;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -30,7 +31,9 @@ import java.util.Map;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.list.ImmutableList;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -45,14 +48,38 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/data_resource") @RequestMapping("/data_resource")
public class DataResourceController extends SimpleControllerSupport<DataResource, DataResourceController.SaveItem, DataResourceController.ListItem, DataResourceController.DetailItem> { public class DataResourceController extends SimpleControllerSupport<DataResource, DataResourceController.SaveItem, DataResourceController.ListItem, DataResourceController.DetailItem> {
private final ObjectMapper mapper; private final ObjectMapper mapper;
private final DataResourceService dataResourceService;
private final DataFileService dataFileService; private final DataFileService dataFileService;
public DataResourceController(DataResourceService dataResourceService, DataFileService dataFileService, Jackson2ObjectMapperBuilder builder) { public DataResourceController(DataResourceService dataResourceService, DataFileService dataFileService, Jackson2ObjectMapperBuilder builder) {
super(dataResourceService); super(dataResourceService);
this.dataResourceService = dataResourceService;
this.dataFileService = dataFileService; this.dataFileService = dataFileService;
this.mapper = builder.build(); this.mapper = builder.build();
} }
@GetMapping(LIST + "_no_confirmation")
public AmisResponse<ImmutableList<ListItem>> listNoConfirmation() {
return AmisResponse.responseSuccess(dataResourceService.listNoConfirmation().collect(entity -> {
try {
return toListItem(entity);
} catch (Exception e) {
throw new RuntimeException(e);
}
}));
}
@GetMapping(LIST + "_no_authentication")
public AmisResponse<ImmutableList<ListItem>> listNoAuthentication() {
return AmisResponse.responseSuccess(dataResourceService.listNoAuthentication().collect(entity -> {
try {
return toListItem(entity);
} catch (Exception e) {
throw new RuntimeException(e);
}
}));
}
@Override @Override
protected DataResource fromSaveItem(SaveItem item) throws JsonProcessingException { protected DataResource fromSaveItem(SaveItem item) throws JsonProcessingException {
ResourceType type = generateResourceType(item); ResourceType type = generateResourceType(item);

View File

@@ -1,11 +1,9 @@
package com.eshore.gringotts.web.domain.user.controller; package com.eshore.gringotts.web.domain.controller;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.user.service.UserService; import com.eshore.gringotts.web.domain.service.UserService;
import lombok.Data; import lombok.Data;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -1,10 +1,10 @@
package com.eshore.gringotts.web.domain.user.controller; package com.eshore.gringotts.web.domain.controller;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.eshore.gringotts.web.configuration.amis.AmisListResponse; import com.eshore.gringotts.web.configuration.amis.AmisListResponse;
import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.user.service.UserService; import com.eshore.gringotts.web.domain.service.UserService;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import lombok.Data; import lombok.Data;
import org.slf4j.Logger; import org.slf4j.Logger;

View File

@@ -0,0 +1,98 @@
package com.eshore.gringotts.web.domain.controller;
import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport;
import com.eshore.gringotts.web.domain.base.entity.FileInfo;
import com.eshore.gringotts.web.domain.base.entity.SimpleListItem;
import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem;
import com.eshore.gringotts.web.domain.entity.Ware;
import com.eshore.gringotts.web.domain.service.DataFileService;
import com.eshore.gringotts.web.domain.service.DataResourceService;
import com.eshore.gringotts.web.domain.service.WareService;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author lanyuanxiaoyao
* @date 2024-12-13
*/
@Slf4j
@RestController
@RequestMapping("ware")
public class WareController extends SimpleControllerSupport<Ware, WareController.SaveItem, WareController.ListItem, WareController.DetailItem> {
private final DataResourceService dataResourceService;
private final DataFileService dataFileService;
public WareController(WareService service, DataResourceService dataResourceService, DataFileService dataFileService) {
super(service);
this.dataResourceService = dataResourceService;
this.dataFileService = dataFileService;
}
@Override
protected Ware fromSaveItem(SaveItem saveItem) throws Exception {
Ware ware = new Ware();
ware.setResource(dataResourceService.detailOrThrow(saveItem.getResourceId()));
ware.setName(ware.getName());
ware.setDescription(saveItem.getDescription());
ware.setIcon(dataFileService.detailOrThrow(saveItem.getIcon().getValue()));
ware.setContent(saveItem.getContent());
return ware;
}
@Override
protected ListItem toListItem(Ware entity) throws Exception {
return new ListItem(entity);
}
@Override
protected DetailItem toDetailItem(Ware entity) throws Exception {
return new DetailItem(entity);
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class SaveItem extends SimpleSaveItem<Ware> {
private Long resourceId;
private String name;
private String description;
private FileInfo icon;
private String content;
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class ListItem extends SimpleListItem<Ware> {
private String name;
private String description;
public ListItem(Ware ware) {
this.setId(ware.getId());
this.setName(ware.getName());
this.setDescription(ware.getDescription());
this.setCreatedTime(ware.getCreatedTime());
this.setCreatedUsername(ware.getCreatedUser().getUsername());
}
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class DetailItem extends SaveItem {
private LocalDateTime createdTime;
private String createdUsername;
private LocalDateTime modifiedTime;
private String modifiedUsername;
public DetailItem(Ware ware) {
this.setId(ware.getId());
this.setResourceId(ware.getResource().getId());
this.setName(ware.getName());
this.setDescription(ware.getDescription());
this.setIcon(new FileInfo(ware.getIcon()));
this.setContent(ware.getContent());
}
}
}

View File

@@ -1,12 +1,12 @@
package com.eshore.gringotts.web.domain.authentication.entity; package com.eshore.gringotts.web.domain.entity;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity; import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity;
import com.eshore.gringotts.web.domain.resource.entity.DataResource; import java.time.LocalDateTime;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import java.util.Set; import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EntityListeners; import javax.persistence.EntityListeners;
@@ -23,6 +23,7 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@@ -49,14 +50,24 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@NamedAttributeNode(value = "createdUser"), @NamedAttributeNode(value = "createdUser"),
@NamedAttributeNode(value = "modifiedUser"), @NamedAttributeNode(value = "modifiedUser"),
}) })
@SQLDelete(sql = "update " + Constants.TABLE_PREFIX + "authentication" + " set deleted = true where id = ?")
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
public class Authentication extends CheckingNeededEntity { public class Authentication extends CheckingNeededEntity {
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private DataResource target; private DataResource target;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude @ToString.Exclude
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private Set<DataFile> evidences; private Set<DataFile> evidences;
/**
* 生效时间
*/
@Column(nullable = false)
private LocalDateTime activeTime = LocalDateTime.now();
/**
* 过期时间
*/
@Column(nullable = false)
private LocalDateTime expiredTime = LocalDateTime.now().plusDays(1);
} }

View File

@@ -1,8 +1,7 @@
package com.eshore.gringotts.web.domain.check.entity; package com.eshore.gringotts.web.domain.entity;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity; import com.eshore.gringotts.web.domain.base.entity.SimpleEntity;
import com.eshore.gringotts.web.domain.user.entity.User;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
@@ -45,7 +44,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@NoArgsConstructor @NoArgsConstructor
public class CheckOrder extends SimpleEntity { public class CheckOrder extends SimpleEntity {
@Column(nullable = false) @Column(nullable = false)
private String key; private String keyword;
@Column(nullable = false) @Column(nullable = false)
private String description; private String description;
@Column(nullable = false) @Column(nullable = false)
@@ -70,17 +69,18 @@ public class CheckOrder extends SimpleEntity {
private User.Role targetRole; private User.Role targetRole;
@Column(nullable = false) @Column(nullable = false)
private Boolean over = false; @Enumerated(EnumType.STRING)
private State state = State.CHECKING;
public CheckOrder( public CheckOrder(
String key, String keyword,
String description, String description,
Type type, Type type,
String parameters, String parameters,
String targetClass, String targetClass,
User targetUser User targetUser
) { ) {
this.key = key; this.keyword = keyword;
this.description = description; this.description = description;
this.type = type; this.type = type;
this.parameters = parameters; this.parameters = parameters;
@@ -90,14 +90,14 @@ public class CheckOrder extends SimpleEntity {
} }
public CheckOrder( public CheckOrder(
String key, String keyword,
String description, String description,
Type type, Type type,
String parameters, String parameters,
String targetClass, String targetClass,
User.Role targetRole User.Role targetRole
) { ) {
this.key = key; this.keyword = keyword;
this.description = description; this.description = description;
this.type = type; this.type = type;
this.parameters = parameters; this.parameters = parameters;
@@ -120,4 +120,10 @@ public class CheckOrder extends SimpleEntity {
USER, USER,
ROLE, ROLE,
} }
public enum State {
CHECKING,
RETRACT,
OVER,
}
} }

View File

@@ -1,10 +1,8 @@
package com.eshore.gringotts.web.domain.confirmation.entity; package com.eshore.gringotts.web.domain.entity;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity; import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity;
import com.eshore.gringotts.web.domain.resource.entity.DataResource;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import java.util.Set; import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
@@ -55,11 +53,9 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
public class Confirmation extends CheckingNeededEntity { public class Confirmation extends CheckingNeededEntity {
@OneToOne(fetch = FetchType.EAGER) @OneToOne(fetch = FetchType.EAGER)
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private DataResource target; private DataResource target;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude @ToString.Exclude
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private Set<DataFile> evidences; private Set<DataFile> evidences;
} }

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.upload.entity; package com.eshore.gringotts.web.domain.entity;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity;

View File

@@ -1,12 +1,9 @@
package com.eshore.gringotts.web.domain.resource.entity; package com.eshore.gringotts.web.domain.entity;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.authentication.entity.Authentication;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity;
import com.eshore.gringotts.web.domain.confirmation.entity.Confirmation; import com.eshore.gringotts.web.domain.entity.format.ResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.format.ResourceFormat; import com.eshore.gringotts.web.domain.entity.type.ResourceType;
import com.eshore.gringotts.web.domain.resource.entity.type.ResourceType;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import java.util.Set; import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
@@ -59,24 +56,19 @@ public class DataResource extends LogicDeleteEntity {
@OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY) @OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude @ToString.Exclude
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private ResourceType type; private ResourceType type;
@OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY) @OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude @ToString.Exclude
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private ResourceFormat format; private ResourceFormat format;
@OneToOne(fetch = FetchType.LAZY) @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude @ToString.Exclude
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private DataFile example; private DataFile example;
@OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy = "target") @OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy = "target")
@ToString.Exclude @ToString.Exclude
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private Confirmation confirmation; private Confirmation confirmation;
@OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy = "target") @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy = "target")
@ToString.Exclude @ToString.Exclude
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private Set<Authentication> authentications; private Set<Authentication> authentications;
} }

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.user.entity; package com.eshore.gringotts.web.domain.entity;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity; import com.eshore.gringotts.web.domain.base.entity.SimpleEntity;

View File

@@ -0,0 +1,70 @@
package com.eshore.gringotts.web.domain.entity;
import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
/**
* 商品
*
* @author lanyuanxiaoyao
* @date 2024-12-13
*/
@Getter
@Setter
@ToString(callSuper = true)
@Entity
@EntityListeners(AuditingEntityListener.class)
@DynamicUpdate
@Table(name = Constants.TABLE_PREFIX + "ware")
@NamedEntityGraph(name = "ware.list", attributeNodes = {
@NamedAttributeNode(value = "createdUser"),
})
@NamedEntityGraph(name = "ware.detail", attributeNodes = {
@NamedAttributeNode(value = "icon"),
@NamedAttributeNode(value = "content"),
@NamedAttributeNode(value = "createdUser"),
@NamedAttributeNode(value = "modifiedUser"),
})
@SQLDelete(sql = "update " + Constants.TABLE_PREFIX + "ware" + " set deleted = true where id = ?")
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
public class Ware extends SimpleEntity {
@OneToOne(cascade = CascadeType.DETACH, fetch = FetchType.EAGER)
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude
private DataResource resource;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String description;
@OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@ToString.Exclude
private DataFile icon;
@Lob
@Basic(fetch = FetchType.LAZY)
@ToString.Exclude
@Column(nullable = false)
private String content;
}

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.format; package com.eshore.gringotts.web.domain.entity.format;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.format; package com.eshore.gringotts.web.domain.entity.format;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.format; package com.eshore.gringotts.web.domain.entity.format;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.format; package com.eshore.gringotts.web.domain.entity.format;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.format; package com.eshore.gringotts.web.domain.entity.format;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.format; package com.eshore.gringotts.web.domain.entity.format;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;
@@ -27,6 +27,8 @@ import org.hibernate.annotations.Where;
@SQLDelete(sql = "update " + Constants.TABLE_PREFIX + "resource_format" + " set deleted = true where id = ?") @SQLDelete(sql = "update " + Constants.TABLE_PREFIX + "resource_format" + " set deleted = true where id = ?")
@Where(clause = LogicDeleteIdOnlyEntity.LOGIC_DELETE_CLAUSE) @Where(clause = LogicDeleteIdOnlyEntity.LOGIC_DELETE_CLAUSE)
public abstract class ResourceFormat extends LogicDeleteIdOnlyEntity { public abstract class ResourceFormat extends LogicDeleteIdOnlyEntity {
public abstract Type getFormatType();
public enum Type { public enum Type {
NONE, NONE,
LINE, LINE,
@@ -34,6 +36,4 @@ public abstract class ResourceFormat extends LogicDeleteIdOnlyEntity {
JSON_LINE, JSON_LINE,
CSV, CSV,
} }
public abstract Type getFormatType();
} }

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.type; package com.eshore.gringotts.web.domain.entity.type;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.type; package com.eshore.gringotts.web.domain.entity.type;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -1,8 +1,8 @@
package com.eshore.gringotts.web.domain.resource.entity.type; package com.eshore.gringotts.web.domain.entity.type;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;
import com.eshore.gringotts.web.domain.upload.entity.DataFile; import com.eshore.gringotts.web.domain.entity.DataFile;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.ForeignKey; import javax.persistence.ForeignKey;

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.type; package com.eshore.gringotts.web.domain.entity.type;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -1,8 +1,8 @@
package com.eshore.gringotts.web.domain.resource.entity.type; package com.eshore.gringotts.web.domain.entity.type;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;
import com.eshore.gringotts.web.domain.upload.entity.DataFile; import com.eshore.gringotts.web.domain.entity.DataFile;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.ForeignKey; import javax.persistence.ForeignKey;

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.resource.entity.type; package com.eshore.gringotts.web.domain.entity.type;
import com.eshore.gringotts.core.Constants; import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteIdOnlyEntity;

View File

@@ -0,0 +1,30 @@
package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.entity.Authentication;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.stereotype.Repository;
/**
* @author lanyuanxiaoyao
* @date 2024-12-02
*/
@SuppressWarnings("NullableProblems")
@Repository
public interface AuthenticationRepository extends SimpleRepository<Authentication, Long> {
@Override
@EntityGraph(value = "authentication.list", type = EntityGraph.EntityGraphType.FETCH)
List<Authentication> findAll(Specification<Authentication> specification);
@Override
@EntityGraph(value = "authentication.list", type = EntityGraph.EntityGraphType.FETCH)
List<Authentication> findAll(Specification<Authentication> specification, Sort sort);
@Override
@EntityGraph(value = "authentication.detail", type = EntityGraph.EntityGraphType.FETCH)
Optional<Authentication> findOne(Specification<Authentication> specification);
}

View File

@@ -1,8 +1,8 @@
package com.eshore.gringotts.web.domain.check.repository; package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.check.entity.CheckOrder; import com.eshore.gringotts.web.domain.entity.CheckOrder;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.entity.User;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.transaction.Transactional; import javax.transaction.Transactional;
@@ -34,6 +34,6 @@ public interface CheckOrderRepository extends SimpleRepository<CheckOrder, Long>
@Transactional @Transactional
@Modifying @Modifying
@Query("update CheckOrder check set check.over = true, check.modifiedUser = ?2, check.modifiedTime = current_timestamp where check.id = ?1") @Query("update CheckOrder check set check.state = ?2, check.modifiedUser = ?3, check.modifiedTime = current_timestamp where check.id = ?1")
void overById(Long id, User modifiedUser); void overById(Long id, CheckOrder.State state, User modifiedUser);
} }

View File

@@ -1,16 +1,12 @@
package com.eshore.gringotts.web.domain.confirmation.repository; package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.confirmation.entity.Confirmation; import com.eshore.gringotts.web.domain.entity.Confirmation;
import com.eshore.gringotts.web.domain.user.entity.User;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.transaction.Transactional;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
/** /**
@@ -33,13 +29,4 @@ public interface ConfirmationRepository extends SimpleRepository<Confirmation, L
Optional<Confirmation> findOne(Specification<Confirmation> specification); Optional<Confirmation> findOne(Specification<Confirmation> specification);
Boolean existsByTarget_Id(Long id); Boolean existsByTarget_Id(Long id);
@Transactional
@Modifying
@Query("update Confirmation confirmation \n" +
"set confirmation.state = ?2, \n" +
" confirmation.modifiedUser = ?3, \n" +
" confirmation.modifiedTime = current_timestamp \n" +
"where confirmation.id = ?1")
void updateStateById(Long id, Confirmation.State state, User modifiedUser);
} }

View File

@@ -1,7 +1,7 @@
package com.eshore.gringotts.web.domain.upload.repository; package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.upload.entity.DataFile; import com.eshore.gringotts.web.domain.entity.DataFile;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository @Repository

View File

@@ -1,7 +1,7 @@
package com.eshore.gringotts.web.domain.resource.repository; package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.resource.entity.DataResource; import com.eshore.gringotts.web.domain.entity.DataResource;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
@@ -12,10 +12,17 @@ import org.springframework.stereotype.Repository;
@SuppressWarnings("NullableProblems") @SuppressWarnings("NullableProblems")
@Repository @Repository
public interface DataResourceRepository extends SimpleRepository<DataResource, Long> { public interface DataResourceRepository extends SimpleRepository<DataResource, Long> {
@Override
@EntityGraph(value = "data_resource.list", type = EntityGraph.EntityGraphType.FETCH)
List<DataResource> findAll(Specification<DataResource> specification);
@Override @Override
@EntityGraph(value = "data_resource.list", type = EntityGraph.EntityGraphType.FETCH) @EntityGraph(value = "data_resource.list", type = EntityGraph.EntityGraphType.FETCH)
List<DataResource> findAll(Specification<DataResource> specification, Sort sort); List<DataResource> findAll(Specification<DataResource> specification, Sort sort);
@EntityGraph(value = "data_resource.list", type = EntityGraph.EntityGraphType.FETCH)
List<DataResource> findAllByConfirmationIsNull();
@Override @Override
@EntityGraph(value = "data_resource.detail", type = EntityGraph.EntityGraphType.FETCH) @EntityGraph(value = "data_resource.detail", type = EntityGraph.EntityGraphType.FETCH)
Optional<DataResource> findOne(Specification<DataResource> specification); Optional<DataResource> findOne(Specification<DataResource> specification);

View File

@@ -0,0 +1,9 @@
package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.entity.format.ResourceFormat;
import org.springframework.stereotype.Repository;
@Repository
public interface ResourceFormatRepository extends SimpleRepository<ResourceFormat, Long> {
}

View File

@@ -0,0 +1,9 @@
package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.entity.type.ResourceType;
import org.springframework.stereotype.Repository;
@Repository
public interface ResourceTypeRepository extends SimpleRepository<ResourceType, Long> {
}

View File

@@ -1,7 +1,7 @@
package com.eshore.gringotts.web.domain.user.repository; package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.entity.User;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.EntityGraph;
@@ -21,6 +21,7 @@ public interface UserRepository extends SimpleRepository<User, Long> {
List<User> findAll(); List<User> findAll();
Boolean existsByUsername(String username); Boolean existsByUsername(String username);
@EntityGraph(value = "user.detail", type = EntityGraph.EntityGraphType.FETCH) @EntityGraph(value = "user.detail", type = EntityGraph.EntityGraphType.FETCH)
Optional<User> findByUsername(String username); Optional<User> findByUsername(String username);
} }

View File

@@ -0,0 +1,26 @@
package com.eshore.gringotts.web.domain.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.entity.Ware;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.stereotype.Repository;
@SuppressWarnings("NullableProblems")
@Repository
public interface WareRepository extends SimpleRepository<Ware, Long> {
@Override
@EntityGraph(value = "ware.list", type = EntityGraph.EntityGraphType.FETCH)
List<Ware> findAll(Specification<Ware> specification);
@Override
@EntityGraph(value = "ware.list", type = EntityGraph.EntityGraphType.FETCH)
List<Ware> findAll(Specification<Ware> specification, Sort sort);
@Override
@EntityGraph(value = "ware.detail", type = EntityGraph.EntityGraphType.FETCH)
Optional<Ware> findOne(Specification<Ware> specification);
}

View File

@@ -1,12 +0,0 @@
package com.eshore.gringotts.web.domain.resource.repository;
import com.blinkfox.fenix.jpa.FenixJpaRepository;
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.resource.entity.format.ResourceFormat;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface ResourceFormatRepository extends SimpleRepository<ResourceFormat, Long> {
}

View File

@@ -1,12 +0,0 @@
package com.eshore.gringotts.web.domain.resource.repository;
import com.blinkfox.fenix.jpa.FenixJpaRepository;
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.resource.entity.type.ResourceType;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface ResourceTypeRepository extends SimpleRepository<ResourceType, Long> {
}

View File

@@ -1,39 +0,0 @@
package com.eshore.gringotts.web.domain.resource.service;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.resource.entity.DataResource;
import com.eshore.gringotts.web.domain.resource.entity.format.ResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.type.ResourceType;
import com.eshore.gringotts.web.domain.resource.repository.DataResourceRepository;
import com.eshore.gringotts.web.domain.resource.repository.ResourceFormatRepository;
import com.eshore.gringotts.web.domain.resource.repository.ResourceTypeRepository;
import com.eshore.gringotts.web.domain.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 数据资源服务
*
* @author lanyuanxiaoyao
*/
@Slf4j
@Service
public class DataResourceService extends SimpleServiceSupport<DataResource> {
private final ResourceTypeRepository resourceTypeRepository;
private final ResourceFormatRepository resourceFormatRepository;
public DataResourceService(DataResourceRepository repository, ResourceTypeRepository resourceTypeRepository, ResourceFormatRepository resourceFormatRepository, UserService userService) {
super(repository, userService);
this.resourceTypeRepository = resourceTypeRepository;
this.resourceFormatRepository = resourceFormatRepository;
}
@Override
public Long save(DataResource entity) {
ResourceType type = resourceTypeRepository.save(entity.getType());
ResourceFormat format = resourceFormatRepository.save(entity.getFormat());
entity.setType(type);
entity.setFormat(format);
return super.save(entity);
}
}

View File

@@ -0,0 +1,153 @@
package com.eshore.gringotts.web.domain.service;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity;
import com.eshore.gringotts.web.domain.base.service.CheckingService;
import com.eshore.gringotts.web.domain.base.service.LogicDeleteService;
import com.eshore.gringotts.web.domain.entity.Authentication;
import com.eshore.gringotts.web.domain.entity.Authentication_;
import com.eshore.gringotts.web.domain.entity.CheckOrder;
import com.eshore.gringotts.web.domain.entity.CheckOrder_;
import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.repository.AuthenticationRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.map.ImmutableMap;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Service;
/**
* @author lanyuanxiaoyao
* @date 2024-12-02
*/
@Slf4j
@Service("com.eshore.gringotts.web.domain.service.AuthenticationService")
public class AuthenticationService extends LogicDeleteService<Authentication> implements CheckingService {
private final AuthenticationRepository authenticationRepository;
private final UserService userService;
private final CheckOrderService checkOrderService;
private final ObjectMapper mapper;
public AuthenticationService(AuthenticationRepository repository, UserService userService, EntityManager manager, CheckOrderService checkOrderService, Jackson2ObjectMapperBuilder builder) {
super(repository, userService, manager);
this.authenticationRepository = repository;
this.userService = userService;
this.checkOrderService = checkOrderService;
this.mapper = builder.build();
}
@Override
protected ImmutableList<Predicate> listPredicate(Root<Authentication> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
User loginUser = userService.currentLoginUser();
if (User.isAdministrator(loginUser)) {
return Lists.immutable.empty();
}
return Lists.immutable.of(builder.or(
builder.equal(root.get(Authentication_.createdUser), loginUser),
builder.and(
builder.equal(root.get(Authentication_.order).get(CheckOrder_.target), CheckOrder.Target.ROLE),
builder.equal(root.get(Authentication_.order).get(CheckOrder_.targetRole), loginUser.getRole())
),
builder.and(
builder.equal(root.get(Authentication_.order).get(CheckOrder_.target), CheckOrder.Target.USER),
builder.equal(root.get(Authentication_.order).get(CheckOrder_.targetUser), loginUser)
)
));
}
@Override
public Long save(Authentication entity) {
if (ObjectUtil.isNull(entity.getId()) && authenticationRepository.findOne(
(root, query, criteriaBuilder) -> {
// TODO 同一个资源的授权时间是否重合
// 查询是否存在createdUser为当前登陆用户并且绑定的数据资源是同一个的授权申请
return criteriaBuilder.and(
criteriaBuilder.equal(root.get("createdUser"), userService.currentLoginUser()),
criteriaBuilder.equal(root.get("target"), entity.getTarget())
);
}
).isPresent()) {
throw new AuthenticationDuplicatedException();
}
return super.save(entity);
}
@Transactional(rollbackOn = Throwable.class)
public void submit(Long id) throws JsonProcessingException {
Authentication authentication = detailOrThrow(id);
authentication.setState(CheckingNeededEntity.State.OWNER_CHECKING);
Long orderId = checkOrderService.save(new CheckOrder(
"authentication_owner_check",
StrUtil.format("数据资源「{}」的授权申请", authentication.getTarget().getName()),
CheckOrder.Type.AUTHENTICATION,
mapper.writeValueAsString(Maps.immutable.of("authenticationId", authentication.getId())),
"com.eshore.gringotts.web.domain.service.AuthenticationService",
authentication.getCreatedUser()
));
CheckOrder order = checkOrderService.detailOrThrow(orderId);
authentication.setOrder(order);
save(authentication);
}
@Transactional(rollbackOn = Throwable.class)
public void retract(Long id) {
Authentication authentication = detailOrThrow(id);
authentication.setState(Authentication.State.DRAFT);
save(authentication);
CheckOrder order = authentication.getOrder();
order.setState(CheckOrder.State.RETRACT);
checkOrderService.save(order);
}
@Override
@Transactional(rollbackOn = Throwable.class)
public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap<String, Object> parameters) {
Long id = (Long) parameters.get("authenticationId");
Authentication authentication = detailOrThrow(id);
if (StrUtil.equals(order.getKeyword(), "authentication_owner_check")) {
switch (operation) {
case APPLY:
authentication.setState(Authentication.State.CHECKING);
order.setKeyword("authentication_checker_check");
order.setTarget(CheckOrder.Target.ROLE);
order.setTargetRole(User.Role.CHECKER);
break;
case REJECT:
authentication.setState(Authentication.State.DRAFT);
order.setState(CheckOrder.State.OVER);
break;
}
} else if (StrUtil.equals(order.getKeyword(), "authentication_checker_check")) {
switch (operation) {
case APPLY:
authentication.setState(Authentication.State.NORMAL);
order.setState(CheckOrder.State.OVER);
break;
case REJECT:
authentication.setState(Authentication.State.DRAFT);
order.setState(CheckOrder.State.OVER);
break;
}
}
save(authentication);
checkOrderService.save(order);
}
public static final class AuthenticationDuplicatedException extends RuntimeException {
public AuthenticationDuplicatedException() {
super("数据资源已绑定该账号的授权申请,无法再次申请");
}
}
}

View File

@@ -1,16 +1,23 @@
package com.eshore.gringotts.web.domain.check.service; package com.eshore.gringotts.web.domain.service;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.eshore.gringotts.web.domain.base.service.CheckingService; import com.eshore.gringotts.web.domain.base.service.CheckingService;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport; import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.check.entity.CheckOrder; import com.eshore.gringotts.web.domain.entity.CheckOrder;
import com.eshore.gringotts.web.domain.check.repository.CheckOrderRepository; import com.eshore.gringotts.web.domain.entity.CheckOrder_;
import com.eshore.gringotts.web.domain.user.service.UserService; import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.repository.CheckOrderRepository;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.map.ImmutableMap; import org.eclipse.collections.api.map.ImmutableMap;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
@@ -36,6 +43,25 @@ public class CheckOrderService extends SimpleServiceSupport<CheckOrder> {
this.userService = userService; this.userService = userService;
} }
@Override
protected ImmutableList<Predicate> listPredicate(Root<CheckOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
User user = userService.currentLoginUser();
if (User.isAdministrator(user)) {
return Lists.immutable.empty();
}
return Lists.immutable.of(builder.or(
builder.equal(root.get(CheckOrder_.createdUser), user),
builder.and(
builder.equal(root.get(CheckOrder_.target), CheckOrder.Target.USER),
builder.equal(root.get(CheckOrder_.targetUser), user)
),
builder.and(
builder.equal(root.get(CheckOrder_.target), CheckOrder.Target.ROLE),
builder.equal(root.get(CheckOrder_.targetRole), user.getRole())
)
));
}
public void operation(Long id, CheckOrder.Operation operation) throws JsonProcessingException { public void operation(Long id, CheckOrder.Operation operation) throws JsonProcessingException {
CheckOrder order = detailOrThrow(id); CheckOrder order = detailOrThrow(id);
CheckingService service = applicationContext.getBean(order.getTargetClass(), CheckingService.class); CheckingService service = applicationContext.getBean(order.getTargetClass(), CheckingService.class);
@@ -46,7 +72,11 @@ public class CheckOrderService extends SimpleServiceSupport<CheckOrder> {
service.onChecked(order, operation, parameters); service.onChecked(order, operation, parameters);
} }
public void retract(Long id) {
checkOrderRepository.overById(id, CheckOrder.State.RETRACT, userService.currentLoginUser());
}
public void over(Long id) { public void over(Long id) {
checkOrderRepository.overById(id, userService.currentLoginUser()); checkOrderRepository.overById(id, CheckOrder.State.OVER, userService.currentLoginUser());
} }
} }

View File

@@ -0,0 +1,136 @@
package com.eshore.gringotts.web.domain.service;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity;
import com.eshore.gringotts.web.domain.base.service.CheckingService;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.entity.CheckOrder;
import com.eshore.gringotts.web.domain.entity.CheckOrder_;
import com.eshore.gringotts.web.domain.entity.Confirmation;
import com.eshore.gringotts.web.domain.entity.Confirmation_;
import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.repository.ConfirmationRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.map.ImmutableMap;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Service;
/**
* @author lanyuanxiaoyao
* @date 2024-11-26
*/
@Slf4j
@Service("com.eshore.gringotts.web.domain.service.ConfirmationService")
public class ConfirmationService extends SimpleServiceSupport<Confirmation> implements CheckingService {
private final ConfirmationRepository confirmationRepository;
private final CheckOrderService checkOrderService;
private final ObjectMapper mapper;
public ConfirmationService(ConfirmationRepository confirmationRepository, UserService userService, CheckOrderService checkOrderService, Jackson2ObjectMapperBuilder builder) {
super(confirmationRepository, userService);
this.confirmationRepository = confirmationRepository;
this.checkOrderService = checkOrderService;
this.mapper = builder.build();
}
@Override
protected ImmutableList<Predicate> listPredicate(Root<Confirmation> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
User loginUser = userService.currentLoginUser();
if (User.isAdministrator(loginUser)) {
return Lists.immutable.empty();
}
Join<Confirmation, CheckOrder> orderJoin = root.join(Confirmation_.order, JoinType.LEFT);
return Lists.immutable.of(builder.or(
builder.equal(root.get(Confirmation_.createdUser), loginUser),
builder.and(
builder.isNotNull(orderJoin),
builder.or(
builder.and(
builder.equal(orderJoin.get(CheckOrder_.target), CheckOrder.Target.ROLE),
builder.equal(orderJoin.get(CheckOrder_.targetRole), loginUser.getRole())
),
builder.and(
builder.equal(orderJoin.get(CheckOrder_.target), CheckOrder.Target.USER),
builder.equal(orderJoin.get(CheckOrder_.targetUser), loginUser)
)
)
)
));
}
@Override
public Long save(Confirmation entity) {
if (ObjectUtil.isNull(entity.getId()) && confirmationRepository.existsByTarget_Id(entity.getTarget().getId())) {
throw new ConfirmationDuplicatedException();
}
return super.save(entity);
}
@Transactional(rollbackOn = Throwable.class)
public void submit(Long id) throws JsonProcessingException {
Confirmation confirmation = detailOrThrow(id);
confirmation.setState(Confirmation.State.CHECKING);
Long orderId = checkOrderService.save(new CheckOrder(
"confirmation_check",
StrUtil.format("数据资源「{}」的确权申请", confirmation.getTarget().getName()),
CheckOrder.Type.CONFIRMATION,
mapper.writeValueAsString(Maps.immutable.of("confirmationId", confirmation.getId())),
"com.eshore.gringotts.web.domain.service.ConfirmationService",
User.Role.CHECKER
));
CheckOrder order = checkOrderService.detailOrThrow(orderId);
confirmation.setOrder(order);
save(confirmation);
}
@Transactional(rollbackOn = Throwable.class)
public void retract(Long id) {
Confirmation confirmation = detailOrThrow(id);
confirmation.setState(CheckingNeededEntity.State.DRAFT);
save(confirmation);
CheckOrder order = confirmation.getOrder();
order.setState(CheckOrder.State.RETRACT);
checkOrderService.save(order);
}
@Override
@Transactional(rollbackOn = Throwable.class)
public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap<String, Object> parameters) {
if (StrUtil.equals(order.getKeyword(), "confirmation_check")) {
Long id = (Long) parameters.get("confirmationId");
Confirmation confirmation = detailOrThrow(id);
switch (operation) {
case APPLY:
confirmation.setState(Confirmation.State.NORMAL);
order.setState(CheckOrder.State.OVER);
break;
case REJECT:
confirmation.setState(Confirmation.State.DRAFT);
order.setState(CheckOrder.State.OVER);
break;
}
save(confirmation);
checkOrderService.save(order);
}
}
public static final class ConfirmationDuplicatedException extends RuntimeException {
public ConfirmationDuplicatedException() {
super("数据资源已绑定确权申请,无法再次申请");
}
}
}

View File

@@ -0,0 +1,98 @@
package com.eshore.gringotts.web.domain.service;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.entity.Authentication;
import com.eshore.gringotts.web.domain.entity.Authentication_;
import com.eshore.gringotts.web.domain.entity.Confirmation;
import com.eshore.gringotts.web.domain.entity.Confirmation_;
import com.eshore.gringotts.web.domain.entity.DataFile;
import com.eshore.gringotts.web.domain.entity.DataFile_;
import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.repository.DataFileRepository;
import com.eshore.gringotts.web.helper.EntityHelper;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.springframework.stereotype.Service;
/**
* 上传服务
*
* @author lanyuanxiaoyao
* @date 2024-11-21
*/
@Slf4j
@Service
public class DataFileService extends SimpleServiceSupport<DataFile> {
private final DataFileRepository dataFileRepository;
private final UserService userService;
public DataFileService(DataFileRepository dataFileRepository, UserService userService) {
super(dataFileRepository, userService);
this.dataFileRepository = dataFileRepository;
this.userService = userService;
}
@Override
protected ImmutableList<Predicate> listPredicate(Root<DataFile> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
User loginUser = userService.currentLoginUser();
if (User.isAdministrator(loginUser)) {
return Lists.immutable.empty();
}
Subquery<Confirmation> confirmationSubquery = query.subquery(Confirmation.class);
Root<Confirmation> confirmationRoot = confirmationSubquery.from(Confirmation.class);
confirmationSubquery.select(confirmationRoot)
.where(
builder.isMember(root, confirmationRoot.get(Confirmation_.evidences)),
EntityHelper.checkNeededEntityPrediction(confirmationRoot, builder, loginUser)
);
Subquery<Authentication> authenticationSubquery = query.subquery(Authentication.class);
Root<Authentication> authenticationRoot = authenticationSubquery.from(Authentication.class);
authenticationSubquery.select(authenticationRoot)
.where(
builder.isMember(root, authenticationRoot.get(Authentication_.evidences)),
EntityHelper.checkNeededEntityPrediction(authenticationRoot, builder, loginUser)
);
return Lists.immutable.of(builder.or(
builder.equal(root.get(DataFile_.createdUser), loginUser),
builder.exists(confirmationSubquery),
builder.exists(authenticationSubquery)
));
}
public Long initialDataFile(String filename) {
DataFile dataFile = new DataFile();
dataFile.setFilename(filename);
return dataFileRepository.save(dataFile).getId();
}
public void updateDataFile(Long id, String path, Long size, String md5) {
DataFile dataFile = dataFileRepository.findById(id).orElseThrow(UpdateDataFileFailedException::new);
dataFile.setSize(size);
dataFile.setMd5(md5);
dataFile.setPath(path);
User loginUser = userService.currentLoginUser();
dataFile.setModifiedUser(loginUser);
dataFileRepository.save(dataFile);
}
public static final class DataFileNotFoundException extends RuntimeException {
public DataFileNotFoundException() {
super("文件未找到,请重新上传");
}
}
public static final class UpdateDataFileFailedException extends RuntimeException {
public UpdateDataFileFailedException() {
super("更新文件信息失败,请重新上传");
}
}
}

View File

@@ -0,0 +1,121 @@
package com.eshore.gringotts.web.domain.service;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.entity.Authentication;
import com.eshore.gringotts.web.domain.entity.Authentication_;
import com.eshore.gringotts.web.domain.entity.Confirmation;
import com.eshore.gringotts.web.domain.entity.Confirmation_;
import com.eshore.gringotts.web.domain.entity.DataResource;
import com.eshore.gringotts.web.domain.entity.DataResource_;
import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.entity.format.ResourceFormat;
import com.eshore.gringotts.web.domain.entity.type.ResourceType;
import com.eshore.gringotts.web.domain.repository.DataResourceRepository;
import com.eshore.gringotts.web.domain.repository.ResourceFormatRepository;
import com.eshore.gringotts.web.domain.repository.ResourceTypeRepository;
import com.eshore.gringotts.web.helper.EntityHelper;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.springframework.stereotype.Service;
/**
* 数据资源服务
*
* @author lanyuanxiaoyao
*/
@Slf4j
@Service
public class DataResourceService extends SimpleServiceSupport<DataResource> {
private final DataResourceRepository dataResourceRepository;
private final ResourceTypeRepository resourceTypeRepository;
private final ResourceFormatRepository resourceFormatRepository;
private final UserService userService;
public DataResourceService(DataResourceRepository repository, ResourceTypeRepository resourceTypeRepository, ResourceFormatRepository resourceFormatRepository, UserService userService) {
super(repository, userService);
this.dataResourceRepository = repository;
this.resourceTypeRepository = resourceTypeRepository;
this.resourceFormatRepository = resourceFormatRepository;
this.userService = userService;
}
@Override
protected ImmutableList<Predicate> listPredicate(Root<DataResource> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
User loginUser = userService.currentLoginUser();
if (User.isAdministrator(loginUser)) {
return Lists.immutable.empty();
}
Subquery<Confirmation> confirmationSubquery = query.subquery(Confirmation.class);
Root<Confirmation> confirmationRoot = confirmationSubquery.from(Confirmation.class);
confirmationSubquery.select(confirmationRoot)
.where(
builder.equal(confirmationRoot.get(Confirmation_.target), root),
EntityHelper.checkNeededEntityPrediction(confirmationRoot, builder, loginUser)
);
Subquery<Authentication> authenticationSubquery = query.subquery(Authentication.class);
Root<Authentication> authenticationRoot = authenticationSubquery.from(Authentication.class);
authenticationSubquery.select(authenticationRoot)
.where(
builder.equal(authenticationRoot.get(Authentication_.target), root),
EntityHelper.checkNeededEntityPrediction(authenticationRoot, builder, loginUser)
);
return Lists.immutable.of(builder.or(
builder.equal(root.get(DataResource_.createdUser), loginUser),
builder.exists(confirmationSubquery),
builder.exists(authenticationSubquery)
));
}
public ImmutableList<DataResource> listNoConfirmation() {
return Lists.immutable.ofAll(dataResourceRepository.findAll(
(root, query, builder) -> {
Join<DataResource, Confirmation> confirmationJoin = root.join(DataResource_.confirmation, JoinType.LEFT);
return builder.and(
builder.isNull(confirmationJoin.get(Confirmation_.id)),
builder.equal(root.get(DataResource_.createdUser), userService.currentLoginUser())
);
}
));
}
public ImmutableList<DataResource> listNoAuthentication() {
return Lists.immutable.ofAll(dataResourceRepository.findAll(
(root, query, builder) -> {
Join<DataResource, Confirmation> confirmationJoin = root.join(DataResource_.confirmation, JoinType.LEFT);
confirmationJoin.on(builder.equal(confirmationJoin.get(Confirmation_.state), Confirmation.State.NORMAL));
Subquery<Authentication> authenticationSubquery = query.subquery(Authentication.class);
Root<Authentication> authenticationRoot = authenticationSubquery.from(Authentication.class);
authenticationSubquery.select(authenticationRoot)
.where(
builder.equal(authenticationRoot.get(Authentication_.target), root),
builder.equal(authenticationRoot.get(Authentication_.createdUser), userService.currentLoginUser())
);
return builder.and(
builder.exists(authenticationSubquery).not(),
builder.equal(root.get(DataResource_.createdUser), userService.currentLoginUser())
);
}
));
}
@Override
public Long save(DataResource entity) {
ResourceType type = resourceTypeRepository.save(entity.getType());
ResourceFormat format = resourceFormatRepository.save(entity.getFormat());
entity.setType(type);
entity.setFormat(format);
return super.save(entity);
}
}

View File

@@ -1,15 +1,14 @@
package com.eshore.gringotts.web.domain.user.service; package com.eshore.gringotts.web.domain.service;
import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.user.repository.UserRepository; import com.eshore.gringotts.web.domain.repository.UserRepository;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.Optional;
import lombok.Data; import lombok.Data;
import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.ImmutableList;
@@ -73,7 +72,15 @@ public class UserService {
} }
public User currentLoginUser() { public User currentLoginUser() {
return userRepository.findById(StpUtil.getLoginIdAsLong()).orElseThrow(LoginNotFoundException::new); return currentLoginUserOptional().orElseThrow(LoginNotFoundException::new);
}
public Optional<User> currentLoginUserOptional() {
try {
return userRepository.findById(StpUtil.getLoginIdAsLong());
} catch (Throwable throwable) {
return Optional.empty();
}
} }
private User findUserByUsername(String username) { private User findUserByUsername(String username) {
@@ -129,7 +136,6 @@ public class UserService {
*/ */
public void registerFromAdministrator(String username, String password, User.Role role) { public void registerFromAdministrator(String username, String password, User.Role role) {
User loginUser = currentLoginUser(); User loginUser = currentLoginUser();
User user = new User(); User user = new User();
user.setUsername(username); user.setUsername(username);
user.setPassword(encryptPassword(password)); user.setPassword(encryptPassword(password));
@@ -137,8 +143,6 @@ public class UserService {
user.setState(User.State.NORMAL); user.setState(User.State.NORMAL);
user.setCheckedUser(loginUser); user.setCheckedUser(loginUser);
user.setCheckedTime(LocalDateTime.now()); user.setCheckedTime(LocalDateTime.now());
user.setCreatedUser(loginUser);
user.setModifiedUser(loginUser);
userRepository.save(user); userRepository.save(user);
} }

View File

@@ -0,0 +1,19 @@
package com.eshore.gringotts.web.domain.service;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.entity.Ware;
import com.eshore.gringotts.web.domain.repository.WareRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @author lanyuanxiaoyao
* @date 2024-12-13
*/
@Slf4j
@Service
public class WareService extends SimpleServiceSupport<Ware> {
public WareService(WareRepository repository, UserService userService) {
super(repository, userService);
}
}

View File

@@ -1,66 +0,0 @@
package com.eshore.gringotts.web.domain.upload.service;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import com.eshore.gringotts.web.domain.upload.repository.DataFileRepository;
import com.eshore.gringotts.web.domain.user.entity.User;
import com.eshore.gringotts.web.domain.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 上传服务
*
* @author lanyuanxiaoyao
* @date 2024-11-21
*/
@Slf4j
@Service
public class DataFileService extends SimpleServiceSupport<DataFile> {
private final DataFileRepository dataFileRepository;
private final UserService userService;
public DataFileService(DataFileRepository dataFileRepository, UserService userService) {
super(dataFileRepository, userService);
this.dataFileRepository = dataFileRepository;
this.userService = userService;
}
public DataFile detail(String id) {
if (id == null) {
return null;
}
return detail(Long.valueOf(id));
}
public Long initialDataFile(String filename) {
DataFile dataFile = new DataFile();
dataFile.setFilename(filename);
User loginUser = userService.currentLoginUser();
dataFile.setCreatedUser(loginUser);
dataFile.setModifiedUser(loginUser);
return dataFileRepository.save(dataFile).getId();
}
public void updateDataFile(Long id, String path, Long size, String md5) {
DataFile dataFile = dataFileRepository.findById(id).orElseThrow(UpdateDataFileFailedException::new);
dataFile.setSize(size);
dataFile.setMd5(md5);
dataFile.setPath(path);
User loginUser = userService.currentLoginUser();
dataFile.setModifiedUser(loginUser);
dataFileRepository.save(dataFile);
}
public static final class DataFileNotFoundException extends RuntimeException {
public DataFileNotFoundException() {
super("文件未找到,请重新上传");
}
}
public static final class UpdateDataFileFailedException extends RuntimeException {
public UpdateDataFileFailedException() {
super("更新文件信息失败,请重新上传");
}
}
}

View File

@@ -1,10 +1,15 @@
package com.eshore.gringotts.web.helper; package com.eshore.gringotts.web.helper;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity; import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity_;
import com.eshore.gringotts.web.domain.user.service.UserService; import com.eshore.gringotts.web.domain.entity.CheckOrder;
import com.eshore.gringotts.web.domain.entity.CheckOrder_;
import com.eshore.gringotts.web.domain.entity.User;
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
/** /**
@@ -21,12 +26,16 @@ public class EntityHelper {
} }
} }
public static <E extends SimpleEntity> E fillCreatorAndModifier(E entity, UserService service) { public static Predicate checkNeededEntityPrediction(Root<? extends CheckingNeededEntity> root, CriteriaBuilder builder, User loginUser) {
User user = service.currentLoginUser(); return builder.or(
if (ObjectUtil.isNull(entity.getCreatedUser())) { builder.and(
entity.setCreatedUser(user); builder.equal(root.get(CheckingNeededEntity_.order).get(CheckOrder_.target), CheckOrder.Target.ROLE),
} builder.equal(root.get(CheckingNeededEntity_.order).get(CheckOrder_.targetRole), loginUser.getRole())
entity.setModifiedUser(user); ),
return entity; builder.and(
builder.equal(root.get(CheckingNeededEntity_.order).get(CheckOrder_.target), CheckOrder.Target.USER),
builder.equal(root.get(CheckingNeededEntity_.order).get(CheckOrder_.targetUser), loginUser)
)
);
} }
} }

View File

@@ -17,6 +17,8 @@ spring:
multipart: multipart:
max-file-size: 10MB max-file-size: 10MB
max-request-size: 20MB max-request-size: 20MB
jackson:
date-format: 'yyyy-MM-dd HH:mm:ss'
fenix: fenix:
print-banner: false print-banner: false
print-sql: false print-sql: false

View File

@@ -0,0 +1,68 @@
package com.eshore.gringotts.web;
import com.eshore.gringotts.web.domain.base.controller.query.Query;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.eclipsecollections.EclipseCollectionsModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
/**
* @author lanyuanxiaoyao
* @date 2024-12-03
*/
public class TestQueryParse {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new EclipseCollectionsModule());
mapper.registerModule(new JavaTimeModule());
// language=JSON
System.out.println(mapper.readValue("{}", Query.class));
// language=JSON
System.out.println(mapper.readValue("{\n" +
" \"query\": {\n" +
" \"equal\": {\n" +
" \"name\": \"lanyuanxiaoyao\"\n" +
" }\n" +
" }\n" +
"}", Query.class));
// language=JSON
System.out.println(mapper.readValue("{\n" +
" \"query\": {\n" +
" \"equal\": {\n" +
" \"name\": \"lanyuanxiaoyao\"\n" +
" },\n" +
" \"notEqual\": {\n" +
" \"username\": \"lanyuanxiaoyao@qq.com\",\n" +
" \"password\": \"mingland87\"\n" +
" },\n" +
" \"great\": {\n" +
" \"age\": 12,\n" +
" \"createTime\": \"2020-10-12 00:00:00\"\n" +
" },\n" +
" \"in\": {\n" +
" \"age\": [\n" +
" 15,\n" +
" 18,\n" +
" 20\n" +
" ]\n" +
" },\n" +
" \"between\": {\n" +
" \"createTime\": {\n" +
" \"start\": \"2024-12-03 00:00:00\",\n" +
" \"end\": \"2024-12-03 00:00:00\"\n" +
" }\n" +
" }\n" +
" },\n" +
" \"sort\": [\n" +
" {\n" +
" \"column\": \"createTime\",\n" +
" \"direction\": \"ASC\"\n" +
" }\n" +
" ],\n" +
" \"page\": {\n" +
" \"size\": 10,\n" +
" \"page\": 1\n" +
" }\n" +
"}", Query.class));
}
}

27
pom.xml
View File

@@ -29,6 +29,8 @@
<hutool.version>5.8.32</hutool.version> <hutool.version>5.8.32</hutool.version>
<fisco.sdk.version>2.10.0</fisco.sdk.version> <fisco.sdk.version>2.10.0</fisco.sdk.version>
<eclipse-collections.version>11.1.0</eclipse-collections.version> <eclipse-collections.version>11.1.0</eclipse-collections.version>
<querydsl.version>5.1.0</querydsl.version>
<hibernate.version>5.6.15.Final</hibernate.version>
</properties> </properties>
<dependencies> <dependencies>
@@ -103,6 +105,17 @@
<artifactId>fenix-spring-boot-starter</artifactId> <artifactId>fenix-spring-boot-starter</artifactId>
<version>2.7.0</version> <version>2.7.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>
<!-- Others --> <!-- Others -->
<dependency> <dependency>
@@ -144,7 +157,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration> <configuration>
<parameters>true</parameters> <parameters>true</parameters>
</configuration> </configuration>
@@ -152,11 +164,24 @@
</plugins> </plugins>
<pluginManagement> <pluginManagement>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version> <version>${spring-boot.version}</version>
</plugin> </plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
</plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
</build> </build>