mirror of https://github.com/certd/certd
chore: 1
parent
b817cb4a1b
commit
0165ccbaac
|
@ -1,7 +1,7 @@
|
|||
import crypto from "crypto";
|
||||
import crypto from 'crypto';
|
||||
|
||||
function md5(data: string) {
|
||||
return crypto.createHash("md5").update(data).digest("hex");
|
||||
return crypto.createHash('md5').update(data).digest('hex');
|
||||
}
|
||||
|
||||
export const hashUtils = {
|
||||
|
|
|
@ -71,6 +71,9 @@ export class Registry<T> {
|
|||
if (define?.deprecated) {
|
||||
continue;
|
||||
}
|
||||
if (!isDev() && define.name.startsWith("demo")) {
|
||||
continue;
|
||||
}
|
||||
list.push({ ...define, key });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,12 @@ function createService() {
|
|||
}
|
||||
// dataAxios 是 axios 返回数据中的 data
|
||||
const dataAxios = response.data;
|
||||
|
||||
if (response.config.unpack === false) {
|
||||
//如果不需要解包
|
||||
return dataAxios;
|
||||
}
|
||||
|
||||
// 这个状态码是和后端约定的
|
||||
const { code } = dataAxios;
|
||||
// 根据 code 进行判断
|
||||
|
@ -40,10 +46,6 @@ function createService() {
|
|||
case 0:
|
||||
// [ 示例 ] code === 0 代表没有错误
|
||||
// @ts-ignore
|
||||
if (response.config.unpack === false) {
|
||||
//如果不需要解包
|
||||
return dataAxios;
|
||||
}
|
||||
return dataAxios.data;
|
||||
default:
|
||||
// 不是正确的 code
|
||||
|
|
|
@ -65,6 +65,9 @@ const onError = (error: any) => {
|
|||
};
|
||||
|
||||
const nextTime = computed(() => {
|
||||
if (props.modelValue == null) {
|
||||
return "请先设置正确的cron表达式";
|
||||
}
|
||||
try {
|
||||
const interval = parser.parseExpression(props.modelValue);
|
||||
const next = interval.next().getTime();
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
<div class="description mt-5">
|
||||
<div v-for="desc of currentStepItem.descriptions">{{ desc }}</div>
|
||||
</div>
|
||||
<div v-if="currentStepItem.body">
|
||||
<fs-render :render-func="currentStepItem.body" />
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="currentStepItem.image">
|
||||
<div class="image-box">
|
||||
|
@ -17,13 +20,15 @@
|
|||
</div>
|
||||
|
||||
<div class="flex-center actions">
|
||||
<fs-button class="m-10" icon="mingcute:arrow-left-fill" @click="prev()">上一步</fs-button>
|
||||
<fs-button class="m-10" type="primary" icon-right="mingcute:arrow-right-fill" @click="next()">下一步</fs-button>
|
||||
<fs-button class="m-10" icon="ion:arrow-back-outline" @click="prev()">上一步</fs-button>
|
||||
<fs-button class="m-10" type="primary" icon-right="ion:arrow-forward-outline" @click="next()">下一步</fs-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { FsRender } from "@fast-crud/fast-crud";
|
||||
import SimpleSteps from "./simple-steps.vue";
|
||||
type Step = {
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
|
@ -34,6 +39,7 @@ type StepItems = {
|
|||
image?: string;
|
||||
title: string;
|
||||
descriptions?: string[];
|
||||
body?: () => JSX.Element;
|
||||
};
|
||||
|
||||
import { computed, nextTick, ref } from "vue";
|
||||
|
@ -45,7 +51,10 @@ const steps = ref<Step[]>([
|
|||
items: [
|
||||
{
|
||||
title: "教程演示内容",
|
||||
descriptions: ["本教程演示如何自动申请证书并部署到Nginx上"]
|
||||
descriptions: ["本教程演示如何自动申请证书并部署到Nginx上", "仅需3步,全自动申请部署证书"],
|
||||
body: () => {
|
||||
return <SimpleSteps></SimpleSteps>;
|
||||
}
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/1-add.png",
|
||||
|
@ -290,5 +299,9 @@ function previewMask() {
|
|||
font-size: 12px !important;
|
||||
color: #999 !important;
|
||||
}
|
||||
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<a-dropdown>
|
||||
<div class="fs-user-info">您好,{{ userStore.getUserInfo?.nickName }}</div>
|
||||
<div class="fs-user-info">您好,{{ userStore.getUserInfo?.nickName || userStore.getUserInfo?.username }}</div>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
|
|
|
@ -48,7 +48,7 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
|
|||
wrapper: {
|
||||
width: 1350,
|
||||
saveRemind: false,
|
||||
title: "创建证书申请流水线"
|
||||
title: "创建证书流水线"
|
||||
}
|
||||
},
|
||||
columns: {
|
||||
|
@ -113,6 +113,7 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
|
|||
}),
|
||||
form: {
|
||||
order: 101,
|
||||
value: true,
|
||||
helper: {
|
||||
render: () => {
|
||||
if (settingStore.isPlus) {
|
||||
|
@ -120,7 +121,7 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
|
|||
}
|
||||
return (
|
||||
<div>
|
||||
建议启用,需要配置<router-link to={{ path: "/sys/settings/email" }}>邮件服务器</router-link>才能发送邮件(专业版请忽略)
|
||||
建议启用,需要配置<router-link to={{ path: "/sys/settings/email" }}>邮件服务器</router-link>才能发送邮件
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { request } from "/@/api/service";
|
||||
import { LocalStorage } from "/@/utils/util.storage";
|
||||
|
||||
export async function GetStatisticCount() {
|
||||
return await request({
|
||||
|
@ -6,3 +7,23 @@ export async function GetStatisticCount() {
|
|||
method: "POST"
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetLatestVersion() {
|
||||
const latest = LocalStorage.get("latestVersion");
|
||||
if (latest) {
|
||||
return latest;
|
||||
}
|
||||
const res = await request({
|
||||
url: "https://registry.npmmirror.com/@certd/pipeline",
|
||||
method: "GET",
|
||||
unpack: false
|
||||
});
|
||||
try {
|
||||
const latest = res["dist-tags"].latest;
|
||||
LocalStorage.set("latestVersion", latest, 60 * 60 * 24);
|
||||
return latest;
|
||||
} catch (e: any) {
|
||||
console.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,23 +13,26 @@
|
|||
<span>您好,{{ userInfo.nickName || userInfo.username }}, 欢迎使用 【{{ siteInfo.title }}】</span>
|
||||
</div>
|
||||
<div>
|
||||
<a-tag color="green" class="flex-inline"> <fs-icon icon="ion:time-outline" class="mr-5"></fs-icon> {{ now }}</a-tag>
|
||||
<a-tag color="blue" class="flex-inline"> <fs-icon icon="ion:rocket-outline" class="mr-5"></fs-icon> v{{ version }}</a-tag>
|
||||
<a-tag color="green" class="flex-inline pointer"> <fs-icon icon="ion:time-outline" class="mr-5"></fs-icon> {{ now }}</a-tag>
|
||||
<a-badge v-if="userStore.isAdmin" :dot="hasNewVersion">
|
||||
<a-tag color="blue" class="flex-inline pointer" :title="'最新版本:' + latestVersion">
|
||||
<fs-icon icon="ion:rocket-outline" class="mr-5"></fs-icon>
|
||||
v{{ version }}
|
||||
</a-tag>
|
||||
</a-badge>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="suggest">
|
||||
<div>
|
||||
<tutorial-button class="flex-center">
|
||||
<a-tooltip title="点击查看详细教程">
|
||||
<a-tag color="blue" class="flex-center">
|
||||
仅需3步,全自动申请部署证书
|
||||
<fs-icon class="font-size-16 ml-5" icon="mingcute:question-line"></fs-icon>
|
||||
</a-tag>
|
||||
</a-tooltip>
|
||||
</tutorial-button>
|
||||
<simple-steps></simple-steps>
|
||||
</div>
|
||||
<tutorial-button class="flex-center mt-10">
|
||||
<a-tooltip title="点击查看详细教程">
|
||||
<a-tag color="blue" class="flex-center">
|
||||
仅需3步,全自动申请部署证书
|
||||
<fs-icon class="font-size-16 ml-5" icon="mingcute:question-line"></fs-icon>
|
||||
</a-tag>
|
||||
</a-tooltip>
|
||||
</tutorial-button>
|
||||
<SimpleSteps></SimpleSteps>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!settingStore.isComm" class="warning">
|
||||
|
@ -49,12 +52,12 @@
|
|||
<statistic-card title="证书流水线数量" :count="count.pipelineCount">
|
||||
<template v-if="count.pipelineCount === 0" #default>
|
||||
<div class="flex-center flex-1 flex-col">
|
||||
<div style="font-size: 20px; font-weight: 700">您还没有证书流水线</div>
|
||||
<fs-button class="mt-10" icon="ion:add-circle-outline" type="primary" @click="goPipeline">立即添加</fs-button>
|
||||
<div style="font-size: 18px; font-weight: 700">您还没有证书流水线</div>
|
||||
<fs-button type="primary" class="mt-10" icon="ion:add-circle-outline" @click="goPipeline">立即创建</fs-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<router-link to="/certd/pipeline" class="flex"><fs-icon icon="ion:add-circle-outline" class="mr-5 fs-16" /> 管理流水线</router-link>
|
||||
<router-link to="/certd/pipeline" class="flex"><fs-icon icon="ion:settings-outline" class="mr-5 fs-16" /> 管理流水线</router-link>
|
||||
</template>
|
||||
</statistic-card>
|
||||
</a-col>
|
||||
|
@ -104,7 +107,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { FsIcon } from "@fast-crud/fast-crud";
|
||||
import SimpleSteps from "./simple-steps.vue";
|
||||
import SimpleSteps from "/@/components/tutorial/simple-steps.vue";
|
||||
import { useUserStore } from "/@/store/modules/user";
|
||||
import { computed, ComputedRef, onMounted, Ref, ref } from "vue";
|
||||
import dayjs from "dayjs";
|
||||
|
@ -121,12 +124,31 @@ import { SiteInfo } from "/@/api/modules/api.basic";
|
|||
import { UserInfoRes } from "/@/api/modules/api.user";
|
||||
import { GetStatisticCount } from "/@/views/framework/home/dashboard/api";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import * as api from "./api";
|
||||
defineOptions({
|
||||
name: "DashboardUser"
|
||||
});
|
||||
|
||||
const version = ref(import.meta.env.VITE_APP_VERSION);
|
||||
const latestVersion = ref();
|
||||
const hasNewVersion = computed(() => {
|
||||
if (!latestVersion.value) {
|
||||
return false;
|
||||
}
|
||||
//分段比较
|
||||
const current = version.value.split(".");
|
||||
const latest = latestVersion.value.split(".");
|
||||
for (let i = 0; i < current.length; i++) {
|
||||
if (parseInt(latest[i]) > parseInt(current[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
async function loadLatestVersion() {
|
||||
latestVersion.value = await api.GetLatestVersion();
|
||||
console.log("latestVersion", latestVersion.value);
|
||||
}
|
||||
const settingStore = useSettingStore();
|
||||
const siteInfo: Ref<SiteInfo> = computed(() => {
|
||||
return settingStore.siteInfo;
|
||||
|
@ -183,6 +205,7 @@ async function loadPluginGroups() {
|
|||
|
||||
const pluginGroups = ref();
|
||||
onMounted(async () => {
|
||||
await loadLatestVersion();
|
||||
await loadCount();
|
||||
await loadPluginGroups();
|
||||
});
|
||||
|
@ -204,7 +227,7 @@ onMounted(async () => {
|
|||
background-color: #fff;
|
||||
|
||||
.avatar {
|
||||
margin-right: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.text {
|
||||
flex: 1;
|
||||
|
|
|
@ -73,7 +73,6 @@
|
|||
"lodash-es": "^4.17.21",
|
||||
"log4js": "^6.7.1",
|
||||
"lru-cache": "^11.0.1",
|
||||
"md5": "^2.3.0",
|
||||
"mwtsc": "^1.4.0",
|
||||
"nanoid": "^5.0.7",
|
||||
"node-forge": "^1.3.1",
|
||||
|
@ -89,10 +88,11 @@
|
|||
"ssh2": "^1.15.0",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"svg-captcha": "^1.4.0",
|
||||
"syno": "^2.2.0",
|
||||
"tencentcloud-sdk-nodejs": "^4.0.44",
|
||||
"typeorm": "^0.3.20",
|
||||
"uuid": "^10.0.0"
|
||||
"uuid": "^10.0.0",
|
||||
"mwts": "^1.3.0",
|
||||
"cross-env": "^7.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@midwayjs/mock": "~3.17.1",
|
||||
|
@ -106,9 +106,7 @@
|
|||
"@types/nodemailer": "^6.4.8",
|
||||
"@types/ssh2": "^1.15.0",
|
||||
"c8": "^10.1.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"mocha": "^10.2.0",
|
||||
"mwts": "^1.3.0",
|
||||
"prettier": "^3.3.3",
|
||||
"rimraf": "^5.0.5",
|
||||
"ts-node": "^10.9.2",
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import { Controller, Get, Provide } from '@midwayjs/core';
|
||||
import { BaseController, Constants } from '@certd/lib-server';
|
||||
import { http, logger } from '@certd/pipeline';
|
||||
/**
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/app/')
|
||||
export class AppController extends BaseController {
|
||||
@Get('/latest', { summary: Constants.per.authOnly })
|
||||
async latest(): Promise<any> {
|
||||
const res = await http.request({
|
||||
url: 'https://registry.npmmirror.com/@certd/pipeline',
|
||||
method: 'get',
|
||||
});
|
||||
try {
|
||||
const latest = res['dist-tags'].latest;
|
||||
return this.ok(latest);
|
||||
} catch (e: any) {
|
||||
logger.error(e);
|
||||
return this.ok('');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
import { MidwayEnvironmentService } from '@midwayjs/core';
|
||||
import { Controller, Get, Inject, Provide } from '@midwayjs/core';
|
||||
import { Controller, Get, Inject, MidwayEnvironmentService, Provide } from '@midwayjs/core';
|
||||
import { logger } from '@certd/pipeline';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { CrudController } from '@certd/lib-server';
|
||||
import { Constants, CrudController } from '@certd/lib-server';
|
||||
import { AccessService } from '../../modules/pipeline/service/access-service.js';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
|
||||
/**
|
||||
* 授权
|
||||
|
@ -78,9 +77,6 @@ export class AccessController extends CrudController<AccessService> {
|
|||
const list = this.service.getDefineList();
|
||||
const dict = [];
|
||||
for (const item of list) {
|
||||
if (item?.deprecated) {
|
||||
continue;
|
||||
}
|
||||
dict.push({
|
||||
value: item.name,
|
||||
label: item.title,
|
||||
|
|
|
@ -49,6 +49,9 @@ export class RoleService extends BaseService<RoleEntity> {
|
|||
}
|
||||
|
||||
async getPermissionByRoleIds(roleIds: any) {
|
||||
if (!roleIds || roleIds.length === 0) {
|
||||
return [];
|
||||
}
|
||||
return await this.permissionService.repository
|
||||
.createQueryBuilder('permission')
|
||||
.innerJoinAndSelect(RolePermissionEntity, 'rp', 'rp.permissionId = permission.id and rp.roleId in (:...roleIds)', { roleIds })
|
||||
|
|
|
@ -3,7 +3,6 @@ import { InjectEntityModel } from '@midwayjs/typeorm';
|
|||
import { MoreThan, Repository } from 'typeorm';
|
||||
import { UserEntity } from '../entity/user.js';
|
||||
import * as _ from 'lodash-es';
|
||||
import md5 from 'md5';
|
||||
import { BaseService, CommonException, Constants, FileService, SysInstallInfo, SysSettingsService } from '@certd/lib-server';
|
||||
import { RoleService } from './role-service.js';
|
||||
import { PermissionService } from './permission-service.js';
|
||||
|
@ -13,7 +12,7 @@ import bcrypt from 'bcryptjs';
|
|||
import { RandomUtil } from '../../../../utils/random.js';
|
||||
import dayjs from 'dayjs';
|
||||
import { DbAdapter } from '../../../db/index.js';
|
||||
|
||||
import { utils } from '@certd/pipeline';
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
|
@ -116,7 +115,7 @@ export class UserService extends BaseService<UserEntity> {
|
|||
|
||||
private async genPassword(rawPassword: any, passwordVersion: number) {
|
||||
if (passwordVersion == null || passwordVersion <= 1) {
|
||||
return md5(rawPassword);
|
||||
return utils.hash.md5(rawPassword);
|
||||
}
|
||||
const salt = bcrypt.genSaltSync(10);
|
||||
const plainPassword = await this.buildPlainPassword(rawPassword);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline';
|
||||
import { isDev } from "../../utils/env.js";
|
||||
import { isDev } from '../../utils/env.js';
|
||||
|
||||
/**
|
||||
* 这个注解将注册一个授权配置
|
||||
|
|
Loading…
Reference in New Issue