1
0

2 Commits

Author SHA1 Message Date
1ec345e18d feat(web): 增加授权相关界面 2024-12-02 19:07:22 +08:00
e7918f9039 feat(web): 避免h2的数据库关键字 2024-12-02 16:27:01 +08:00
13 changed files with 314 additions and 42 deletions

View File

@@ -98,6 +98,7 @@ export function inputFileFormItemCommonOptions(accept = '*', maxSize = size5MB)
accept: accept,
maxSize: maxSize,
autoUpload: false,
drag: true,
startChunkApi: apiPost('${base}/upload/start'),
chunkApi: apiPost('${base}/upload/slice'),
finishChunkApi: apiPost('${base}/upload/finish'),
@@ -197,7 +198,7 @@ export function stringField(field, label, width = undefined, wrap = false) {
if (width) {
data['width'] = width
}
if (wrap) {
if (!wrap) {
data['className'] = 'nowrap'
}
return data
@@ -247,10 +248,11 @@ export const userStateMapping = [
mappingItem('禁用', 'DISABLED', 'bg-danger'),
]
export const confirmationStateMapping = [
export const permissionStateMapping = [
mappingItem('未确权', 'NONE'),
mappingItem('草稿', 'DRAFT', 'bg-primary'),
mappingItem('审查中', 'CHECKING', 'bg-warning'),
mappingItem('用户审查中', 'USER_CHECKING', 'bg-warning'),
mappingItem('通过', 'NORMAL', 'bg-success'),
mappingItem('驳回', 'REJECT', 'bg-danger'),
]

View File

@@ -12,8 +12,12 @@ import {
import {resourceList} from "../../pages/index/tab-data.js";
import {resourceDetailDialog} from "../resource/dialog-resource.js";
const CONFIRMATION_TYPE = 'confirmation'
const AUTHENTICATION_TYPE = 'authentication'
function detailForm(showCreatedUserAndModifiedUser = false) {
return {
debug: true,
id: 'permission_form',
type: 'form',
...horizontalFormOptions(),
@@ -70,12 +74,38 @@ function detailForm(showCreatedUserAndModifiedUser = false) {
joinValues: false,
...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() : [])
]
}
}
export function permissionAddDialog() {
export function confirmationAddDialog() {
return permissionAddDialog(CONFIRMATION_TYPE)
}
export function authenticationAddDialog() {
return permissionAddDialog(AUTHENTICATION_TYPE)
}
function permissionAddDialog(type) {
let data = {add: true}
data[type] = true
return {
actionType: 'dialog',
dialog: {
@@ -94,16 +124,24 @@ export function permissionAddDialog() {
],
body: {
...detailForm(),
api: apiPost('${base}/confirmation/save'),
data: {
add: true,
},
api: apiPost(`\${base}/${type}/save`),
data: data,
}
}
}
}
export function permissionDetailDialog(field = 'id', actions = []) {
export function confirmationDetailDialog(field = 'id', actions = []) {
return permissionDetailDialog(CONFIRMATION_TYPE, field, actions)
}
export function authenticationDetailDialog(field = 'id', actions = []) {
return permissionDetailDialog(AUTHENTICATION_TYPE, field, actions)
}
function permissionDetailDialog(type, field = 'id', actions = []) {
let data = {detail: true}
data[type] = true
return {
actionType: 'dialog',
dialog: {
@@ -112,17 +150,25 @@ export function permissionDetailDialog(field = 'id', actions = []) {
actions: actions,
body: {
...detailForm(true),
initApi: apiGet(`\${base}/confirmation/detail/\${${field}}`),
initApi: apiGet(`\${base}/${type}/detail/\${${field}}`),
static: true,
data: {
detail: true,
},
data: data,
}
}
}
}
export function permissionEditeDialog(field = 'id') {
export function confirmationEditeDialog(field = 'id') {
return permissionEditeDialog(CONFIRMATION_TYPE, field)
}
export function authenticationEditeDialog(field = 'id') {
return permissionEditeDialog(CONFIRMATION_TYPE, field)
}
function permissionEditeDialog(type, field = 'id') {
let data = {edit: true}
data[type] = true
return {
actionType: 'dialog',
dialog: {
@@ -141,11 +187,9 @@ export function permissionEditeDialog(field = 'id') {
],
body: {
...detailForm(),
api: apiPost('${base}/confirmation/save'),
initApi: apiGet(`\${base}/confirmation/detail/\${${field}}`),
data: {
edit: true,
}
api: apiPost(`\${base}/${type}/save`),
initApi: apiGet(`\${base}/${type}/detail/\${${field}}`),
data: data,
},
}
}

View File

@@ -59,9 +59,9 @@ useAmis(information => {
tabs: [
// tabOverview(),
// tabMarket(),
tabPermissions(),
tabCheck(),
tabData(),
tabPermissions(),
tabUser(),
tabSettings(),
]

View File

@@ -9,7 +9,7 @@ import {
stringField,
timeField,
} from "../../components/constants.js";
import {permissionDetailDialog} from "../../components/permission/dialog-permission.js";
import {confirmationDetailDialog} from "../../components/permission/dialog-permission.js";
export function tabCheck() {
return {
@@ -40,7 +40,7 @@ export function tabCheck() {
type: 'action',
label: '处理',
level: 'link',
...permissionDetailDialog(
...confirmationDetailDialog(
'parameters.confirmationId',
[
{
@@ -67,7 +67,7 @@ export function tabCheck() {
type: 'action',
label: '查看',
level: 'link',
...permissionDetailDialog('parameters.confirmationId'),
...confirmationDetailDialog('parameters.confirmationId'),
},
]),
],

View File

@@ -8,10 +8,10 @@ import {
arrayInCheck,
arrayOutCheck,
confirmationState,
confirmationStateMapping,
crudCommonOptions,
mappingField,
operationField,
permissionStateMapping,
timeField,
userOnly
} from "../../components/constants.js";
@@ -40,7 +40,7 @@ export function resourceList() {
label: '描述',
name: 'description',
},
mappingField('confirmationState', '确权状态', confirmationStateMapping),
mappingField('confirmationState', '确权状态', permissionStateMapping),
timeField('createdTime', '创建时间'),
operationField('操作', undefined, [
{

View File

@@ -1,9 +1,10 @@
import {
apiGet,
confirmationStateMapping,
crudCommonOptions,
customerOnly,
mappingField,
operationField,
permissionStateMapping,
providerOnly,
stringField,
stringWrapField,
@@ -11,9 +12,12 @@ import {
userOnly,
} from "../../components/constants.js";
import {
permissionAddDialog,
permissionDetailDialog,
permissionEditeDialog,
authenticationAddDialog,
authenticationDetailDialog,
authenticationEditeDialog,
confirmationAddDialog,
confirmationDetailDialog,
confirmationEditeDialog,
} from "../../components/permission/dialog-permission.js";
export function tabPermissions() {
@@ -25,6 +29,85 @@ export function tabPermissions() {
body: {
type: 'tabs',
tabs: [
{
visibleOn: customerOnly,
title: '授权管理',
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: "${state === 'CHECKING'}",
type: 'action',
label: '撤销',
level: 'link',
confirmTitle: '确认撤销',
confirmText: '确认撤销名称为「${name}」的确权申请吗?',
actionType: 'ajax',
api: apiGet('${base}/authentication/retract/${id}'),
},
{
visibleOn: "${state === 'DRAFT' || state === 'REJECT'}",
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: "${state !== 'DRAFT'}",
type: 'action',
label: '编辑',
level: 'link',
...authenticationEditeDialog(),
},
{
disabledOn: "${state === 'CHECKING'}",
type: 'action',
label: "删除",
confirmTitle: '确认删除',
confirmText: '确认删除名称为「${name}」的确权申请吗?删除后对应的数据资源处于未确权状态。',
actionType: 'ajax',
api: apiGet('${base}/authentication/remove/${id}'),
},
]
},
]),
]
}
},
{
visibleOn: providerOnly,
title: '确权管理',
@@ -40,20 +123,20 @@ export function tabPermissions() {
type: 'action',
label: '',
icon: 'fa fa-plus',
...permissionAddDialog()
...confirmationAddDialog()
},
],
columns: [
stringField('name', '名称', 200),
stringWrapField('description', '描述'),
mappingField('state', '状态', confirmationStateMapping),
mappingField('state', '状态', permissionStateMapping),
timeField('createdTime', '创建时间'),
operationField('操作', undefined, [
{
type: 'action',
label: '查看',
level: 'link',
...permissionDetailDialog(),
...confirmationDetailDialog(),
},
{
visibleOn: "${state === 'CHECKING'}",
@@ -87,7 +170,7 @@ export function tabPermissions() {
type: 'action',
label: '编辑',
level: 'link',
...permissionEditeDialog(),
...confirmationEditeDialog(),
},
{
disabledOn: "${state === 'CHECKING'}",
@@ -104,10 +187,6 @@ export function tabPermissions() {
]
}
},
{
title: '授权管理',
body: []
}
]
}
}

View File

@@ -0,0 +1,87 @@
package com.eshore.gringotts.web.domain.authentication.controller;
import com.eshore.gringotts.web.domain.authentication.entity.Authentication;
import com.eshore.gringotts.web.domain.authentication.service.AuthenticationService;
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.resource.service.DataResourceService;
import com.eshore.gringotts.web.domain.upload.service.DataFileService;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.set.ImmutableSet;
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;
}
@Override
protected Authentication fromSaveItem(SaveItem item) {
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 null;
}
@Override
protected ListItem toListItem(Authentication entity) {
ListItem item = new ListItem();
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
protected DetailItem toDetailItem(Authentication entity) {
return null;
}
@Data
@EqualsAndHashCode(callSuper = true)
public static final class SaveItem extends SimpleSaveItem<Authentication> {
private Long targetId;
private String description;
private ImmutableSet<FileInfo> evidenceFiles;
private LocalDateTime activeTime;
private LocalDateTime expiredTime;
}
@Data
@EqualsAndHashCode(callSuper = true)
public static final class ListItem extends SimpleListItem<Authentication> {
private String name;
private String description;
private String state;
}
@Data
public static final class DetailItem {}
}

View File

@@ -5,8 +5,10 @@ import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity;
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.time.LocalDateTime;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
@@ -59,4 +61,14 @@ public class Authentication extends CheckingNeededEntity {
@ToString.Exclude
@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE)
private Set<DataFile> evidences;
/**
* 生效时间
*/
@Column(nullable = false)
private LocalDateTime activeTime = LocalDateTime.now();
/**
* 过期时间
*/
@Column(nullable = false)
private LocalDateTime expiredTime = LocalDateTime.now().plusDays(1);
}

View File

@@ -0,0 +1,13 @@
package com.eshore.gringotts.web.domain.authentication.repository;
import com.eshore.gringotts.web.domain.authentication.entity.Authentication;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import org.springframework.stereotype.Repository;
/**
* @author lanyuanxiaoyao
* @date 2024-12-02
*/
@Repository
public interface AuthenticationRepository extends SimpleRepository<Authentication, Long> {
}

View File

@@ -0,0 +1,31 @@
package com.eshore.gringotts.web.domain.authentication.service;
import com.eshore.gringotts.web.domain.authentication.entity.Authentication;
import com.eshore.gringotts.web.domain.authentication.repository.AuthenticationRepository;
import com.eshore.gringotts.web.domain.base.service.CheckingService;
import com.eshore.gringotts.web.domain.base.service.LogicDeleteService;
import com.eshore.gringotts.web.domain.check.entity.CheckOrder;
import com.eshore.gringotts.web.domain.user.service.UserService;
import javax.persistence.EntityManager;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.map.ImmutableMap;
import org.springframework.stereotype.Service;
/**
* @author lanyuanxiaoyao
* @date 2024-12-02
*/
@Slf4j
@Service
public class AuthenticationService extends LogicDeleteService<Authentication> implements CheckingService {
private final AuthenticationRepository authenticationRepository;
public AuthenticationService(AuthenticationRepository repository, UserService userService, EntityManager manager) {
super(repository, userService, manager);
this.authenticationRepository = repository;
}
@Override
public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap<String, Object> parameters) {
}
}

View File

@@ -35,6 +35,10 @@ public class CheckingNeededEntity extends LogicDeleteEntity {
* 审查中
*/
CHECKING,
/**
* 用户审核
*/
USER_CHECKING,
/**
* 正常
*/

View File

@@ -45,7 +45,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@NoArgsConstructor
public class CheckOrder extends SimpleEntity {
@Column(nullable = false)
private String key;
private String keyword;
@Column(nullable = false)
private String description;
@Column(nullable = false)
@@ -73,14 +73,14 @@ public class CheckOrder extends SimpleEntity {
private Boolean over = false;
public CheckOrder(
String key,
String keyword,
String description,
Type type,
String parameters,
String targetClass,
User targetUser
) {
this.key = key;
this.keyword = keyword;
this.description = description;
this.type = type;
this.parameters = parameters;
@@ -90,14 +90,14 @@ public class CheckOrder extends SimpleEntity {
}
public CheckOrder(
String key,
String keyword,
String description,
Type type,
String parameters,
String targetClass,
User.Role targetRole
) {
this.key = key;
this.keyword = keyword;
this.description = description;
this.type = type;
this.parameters = parameters;

View File

@@ -69,7 +69,7 @@ public class ConfirmationService extends SimpleServiceSupport<Confirmation> impl
@Override
public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap<String, Object> parameters) {
if (StrUtil.equals(order.getKey(), "confirmation_check")) {
if (StrUtil.equals(order.getKeyword(), "confirmation_check")) {
Long id = (Long) parameters.get("confirmationId");
switch (operation) {
case APPLY: