mirror of https://github.com/certd/certd
perf: 支持设置用户有效期
parent
82d08e2153
commit
6ac3bc564f
|
@ -16,6 +16,7 @@ export class SysPublicSettings extends BaseSettings {
|
|||
static __access__ = 'public';
|
||||
|
||||
registerEnabled = false;
|
||||
userValidTimeEnabled?:boolean = false;
|
||||
passwordLoginEnabled = true;
|
||||
usernameRegisterEnabled = true;
|
||||
mobileRegisterEnabled = false;
|
||||
|
|
|
@ -15,6 +15,7 @@ import PemInput from "./pem-input.vue";
|
|||
import { defineAsyncComponent } from "vue";
|
||||
import NotificationSelector from "../views/certd/notification/notification-selector/index.vue";
|
||||
import EmailSelector from "./email-selector/index.vue";
|
||||
import ValidTimeFormat from "./valid-time-format.vue";
|
||||
export default {
|
||||
install(app: any) {
|
||||
app.component(
|
||||
|
@ -27,6 +28,7 @@ export default {
|
|||
app.component("TextEditable", TextEditable);
|
||||
app.component("FileInput", FileInput);
|
||||
app.component("PemInput", PemInput);
|
||||
app.component("ValidTimeFormat", ValidTimeFormat);
|
||||
// app.component("CodeEditor", CodeEditor);
|
||||
|
||||
app.component("CronLight", CronLight);
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<template>
|
||||
<div class="valid-time-format">
|
||||
<a-tag v-if="isExpired" color="red">{{ prefix || "" }}已过期</a-tag>
|
||||
<a-tag v-if="isValid" color="green" :title="date">
|
||||
<fs-time-humanize v-if="humanize" :model-value="modelValue" :options="{ largest: 1, units: ['y', 'd', 'h'] }" :use-format-greater="30000000000" />
|
||||
<template v-else> {{ prefix || "" }}{{ date }} </template>
|
||||
</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: number;
|
||||
humanize?: boolean;
|
||||
prefix?: string;
|
||||
}>();
|
||||
|
||||
const date = computed(() => {
|
||||
return dayjs(props.modelValue || 0).format("YYYY-MM-DD");
|
||||
});
|
||||
|
||||
const isValid = computed(() => {
|
||||
return props.modelValue > 0 && props.modelValue > new Date().getTime();
|
||||
});
|
||||
|
||||
const isExpired = computed(() => {
|
||||
return props.modelValue > 0 && props.modelValue < new Date().getTime();
|
||||
});
|
||||
</script>
|
|
@ -30,6 +30,7 @@ export type PlusInfo = {
|
|||
};
|
||||
export type SysPublicSetting = {
|
||||
registerEnabled?: boolean;
|
||||
userValidTimeEnabled?: boolean;
|
||||
usernameRegisterEnabled?: boolean;
|
||||
mobileRegisterEnabled?: boolean;
|
||||
emailRegisterEnabled?: boolean;
|
||||
|
|
|
@ -27,6 +27,8 @@ export interface UserInfoRes {
|
|||
avatar?: string;
|
||||
roleIds: number[];
|
||||
isWeak?: boolean;
|
||||
validTime?: number;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface LoginRes {
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
<a-divider type="vertical" />
|
||||
<suite-card class="m-0"></suite-card>
|
||||
</template>
|
||||
<template v-if="settingsStore.isPlus && settingsStore.sysPublic.userValidTimeEnabled === true && userInfo.validTime">
|
||||
<a-divider type="vertical" />
|
||||
<valid-time-format class="flex-o" prefix="账户有效期:" :model-value="userInfo.validTime" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq,
|
|||
import { useUserStore } from "/@/store/user";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
import dayjs from "dayjs";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
|
||||
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
|
@ -22,6 +23,10 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
|
|||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const settingStore = useSettingStore();
|
||||
const userValidTimeEnabled = compute(() => {
|
||||
return settingStore.sysPublic.userValidTimeEnabled === true;
|
||||
});
|
||||
return {
|
||||
crudOptions: {
|
||||
request: {
|
||||
|
@ -213,20 +218,28 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
|
|||
},
|
||||
validTime: {
|
||||
title: "有效期",
|
||||
type: ["date", "time-humanize"],
|
||||
type: "date",
|
||||
form: {
|
||||
show: userValidTimeEnabled,
|
||||
},
|
||||
column: {
|
||||
align: "center",
|
||||
sorter: true,
|
||||
width: 100,
|
||||
component: {
|
||||
title: compute(({ row }) => {
|
||||
return dayjs(row.validTime).format("YYYY-MM-DD");
|
||||
}),
|
||||
useFormatGreater: 30000000000,
|
||||
options: {
|
||||
largest: 1,
|
||||
units: ["y", "d", "h"],
|
||||
},
|
||||
show: userValidTimeEnabled,
|
||||
cellRender({ value }) {
|
||||
if (value == null || value === 0) {
|
||||
return "";
|
||||
}
|
||||
if (value < dayjs().valueOf()) {
|
||||
return <a-tag color={"red"}>已过期</a-tag>;
|
||||
}
|
||||
const date = dayjs(value).format("YYYY-MM-DD");
|
||||
return (
|
||||
<a-tag color={"green"} title={date}>
|
||||
<fs-time-humanize modelValue={value} options={{ largest: 1, units: ["y", "d", "h"] }} useFormatGreater={30000000000} />
|
||||
</a-tag>
|
||||
);
|
||||
},
|
||||
},
|
||||
valueBuilder({ value, row, key }) {
|
||||
|
|
|
@ -11,6 +11,13 @@
|
|||
<a-form-item label="开启自助注册" :name="['public', 'registerEnabled']">
|
||||
<a-switch v-model:checked="formState.public.registerEnabled" />
|
||||
</a-form-item>
|
||||
<a-form-item label="开启用户有效期" :name="['public', 'userValidTimeEnabled']">
|
||||
<div class="flex-o">
|
||||
<a-switch v-model:checked="formState.public.userValidTimeEnabled" :disabled="!settingsStore.isPlus" />
|
||||
<vip-button class="ml-5" mode="button"></vip-button>
|
||||
</div>
|
||||
<div class="helper">有效期内用户可正常使用,失效后流水线将被停用</div>
|
||||
</a-form-item>
|
||||
<template v-if="formState.public.registerEnabled">
|
||||
<a-form-item label="开启用户名注册" :name="['public', 'usernameRegisterEnabled']">
|
||||
<a-switch v-model:checked="formState.public.usernameRegisterEnabled" />
|
||||
|
@ -154,6 +161,14 @@ async function loadSysSettings() {
|
|||
if (data?.private.sms?.type) {
|
||||
await loadTypeDefine(data.private.sms.type);
|
||||
}
|
||||
if (!settingsStore.isPlus) {
|
||||
formState.public.userValidTimeEnabled = false;
|
||||
formState.public.emailRegisterEnabled = false;
|
||||
}
|
||||
|
||||
if (!settingsStore.isComm) {
|
||||
formState.public.smsLoginEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
const saveLoading = ref(false);
|
||||
|
|
|
@ -329,6 +329,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
if (isComm()) {
|
||||
await this.checkHasDeployCount(id, entity.userId);
|
||||
}
|
||||
await this.checkUserStatus(entity.userId)
|
||||
this.cron.register({
|
||||
name: `pipeline.${id}.trigger.once`,
|
||||
cron: null,
|
||||
|
@ -446,6 +447,13 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
if (isComm()) {
|
||||
suite = await this.checkHasDeployCount(id, entity.userId);
|
||||
}
|
||||
try{
|
||||
await this.checkUserStatus(entity.userId)
|
||||
}catch (e) {
|
||||
logger.info(e.message)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
const pipeline = JSON.parse(entity.content);
|
||||
if (!pipeline.id) {
|
||||
|
@ -745,5 +753,25 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private async checkUserStatus(userId: number) {
|
||||
const userEntity = await this.userService.info(userId);
|
||||
if(userEntity == null){
|
||||
throw new Error('用户不存在');
|
||||
}
|
||||
if(userEntity.status === 0){
|
||||
const message = `账户${userId}已被禁用,禁止运行流水线`
|
||||
throw new Error(message)
|
||||
}
|
||||
const sysPublic = await this.sysSettingsService.getPublicSettings()
|
||||
if(isPlus() && sysPublic.userValidTimeEnabled === true){
|
||||
//校验用户有效期是否设置
|
||||
if(userEntity.validTime!= null && userEntity.validTime > 0){
|
||||
if(userEntity.validTime < new Date().getTime()){
|
||||
//用户已过期
|
||||
const message = `账户${userId}已过有效期,禁止运行流水线`
|
||||
throw new Error(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue