mirror of https://github.com/certd/certd
feat: 基础版不再限制流水线数量
parent
bb4910f4e5
commit
cb27d4b490
17
README.md
17
README.md
|
@ -16,7 +16,9 @@ Certd 是一个免费全自动申请和自动部署更新SSL证书的管理系
|
||||||
* 支持SQLite,PostgreSQL、MySQL数据库
|
* 支持SQLite,PostgreSQL、MySQL数据库
|
||||||
|
|
||||||
|
|
||||||
|
>
|
||||||
|
> 流水线数量现已调整为无限制,欢迎大家使用
|
||||||
|
>
|
||||||
|
|
||||||
## 二、在线体验
|
## 二、在线体验
|
||||||
|
|
||||||
|
@ -202,13 +204,14 @@ https://afdian.com/a/greper
|
||||||
|
|
||||||
专业版特权对比
|
专业版特权对比
|
||||||
|
|
||||||
| 功能 | 基础版 | 专业版 |
|
| 功能 | 基础版 | 专业版 |
|
||||||
|---------|-----------------|-------------------|
|
|------|-----------------|-------------------|
|
||||||
| 免费证书申请 | 免费无限制 | 无限制 |
|
| 免费证书申请 | 免费无限制 | 无限制 |
|
||||||
|
| 域名数量 | 免费无限制 | 无限制 |
|
||||||
| 证书流水线条数 | 免费无限制 | 无限制 |
|
| 证书流水线条数 | 免费无限制 | 无限制 |
|
||||||
| 站点证书监控 | 1条 | 无限制 |
|
| 站点证书监控 | 1条 | 无限制 |
|
||||||
| 自动部署插件 | 阿里云、腾讯云、七牛云、SSH | 支持群晖、宝塔、1Panel等,持续开发中 |
|
| 自动部署插件 | 阿里云、腾讯云、七牛云、SSH | 支持群晖、宝塔、1Panel等,持续开发中 |
|
||||||
| 通知 | 邮件、webhook | server酱、企微、anpush、钉钉等 |
|
| 通知 | 邮件、webhook | server酱、企微、anpush等 |
|
||||||
|
|
||||||
************************
|
************************
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { SysPrivateSettings, SysSettingsService } from '../../../system/index.js
|
||||||
* 授权
|
* 授权
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
@Scope(ScopeEnum.Singleton)
|
||||||
export class EncryptService {
|
export class EncryptService {
|
||||||
secretKey: Buffer;
|
secretKey: Buffer;
|
||||||
|
|
||||||
|
|
|
@ -229,27 +229,41 @@ function openUpgrade() {
|
||||||
const vipTypeDefine = {
|
const vipTypeDefine = {
|
||||||
free: {
|
free: {
|
||||||
title: "基础版",
|
title: "基础版",
|
||||||
desc: "免费使用",
|
desc: "社区免费版",
|
||||||
type: "free",
|
type: "free",
|
||||||
privilege: ["证书申请功能无限制", "证书流水线数量无限制", "常用的主机、云平台、cdn等部署插件"]
|
privilege: ["证书申请无限制", "域名数量无限制", "证书流水线数量无限制", "常用的主机、云平台、cdn等部署插件", "邮件、webhook通知方式"]
|
||||||
},
|
},
|
||||||
plus: {
|
plus: {
|
||||||
title: "专业版",
|
title: "专业版",
|
||||||
desc: "功能增强,适用于个人企业内部使用",
|
desc: "开源需要您的赞助支持",
|
||||||
type: "plus",
|
type: "plus",
|
||||||
privilege: ["可加VIP群,需求优先实现", "宝塔、群晖、1Panel、易盾等部署插件", "站点证书监控", "更多通知种类"],
|
privilege: ["可加VIP群,您需求将优先实现", "站点证书监控无限制", "更多通知方式", "更多强大部署插件,宝塔、群晖、1Panel等"],
|
||||||
trial: {
|
trial: {
|
||||||
title: "7天试用",
|
title: "点击获取7天试用",
|
||||||
click: () => {
|
click: () => {
|
||||||
openStarModal();
|
openStarModal();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
price: 29.9,
|
||||||
|
get() {
|
||||||
|
return (
|
||||||
|
<a-tooltip title="爱发电赞助“VIP会员”后获取一年期专业版激活码,开源需要您的支持">
|
||||||
|
<a-button size="small" type="primary" href="https://afdian.com/a/greper" target="_blank">
|
||||||
|
爱发电赞助后获取
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
comm: {
|
comm: {
|
||||||
title: "商业版",
|
title: "商业版",
|
||||||
desc: "商业授权,可对外运营",
|
desc: "商业授权,可对外运营",
|
||||||
type: "comm",
|
type: "comm",
|
||||||
privilege: ["拥有专业版所有特权", "允许商用,可修改logo、标题", "数据统计", "插件管理", "多用户无限制", "支持用户支付(敬请期待)"]
|
privilege: ["拥有专业版所有特权", "允许商用,可修改logo、标题", "数据统计", "插件管理", "多用户无限制", "支持用户支付"],
|
||||||
|
price: 399,
|
||||||
|
get() {
|
||||||
|
return <a-button size="small">请联系作者获取</a-button>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -260,28 +274,16 @@ function openUpgrade() {
|
||||||
},
|
},
|
||||||
maskClosable: true,
|
maskClosable: true,
|
||||||
okText: "激活",
|
okText: "激活",
|
||||||
width: 900,
|
width: 1000,
|
||||||
content: () => {
|
content: () => {
|
||||||
let activationCodeGetWay: any = null;
|
let activationCodeGetWay = (
|
||||||
if (settingStore.siteEnv.agent.enabled != null) {
|
<span>
|
||||||
const agent = settingStore.siteEnv.agent;
|
<a href="https://afdian.com/a/greper" target="_blank">
|
||||||
if (agent.enabled === false) {
|
爱发电赞助“VIP会员”后获取一年期专业版激活码
|
||||||
activationCodeGetWay = (
|
</a>
|
||||||
<span>
|
<span> 商业版请直接联系作者</span>
|
||||||
<a href="https://afdian.com/a/greper" target="_blank">
|
</span>
|
||||||
爱发电赞助“VIP会员(¥29.9)”后获取一年期专业版激活码
|
);
|
||||||
</a>
|
|
||||||
<span> 商业版请直接联系作者</span>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
activationCodeGetWay = (
|
|
||||||
<a href={agent.contactLink} target="_blank">
|
|
||||||
{agent.contactText}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const vipLabel = settingStore.vipLabel;
|
const vipLabel = settingStore.vipLabel;
|
||||||
const slots = [];
|
const slots = [];
|
||||||
for (const key in vipTypeDefine) {
|
for (const key in vipTypeDefine) {
|
||||||
|
@ -301,15 +303,31 @@ function openUpgrade() {
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</h3>
|
</h3>
|
||||||
<div>{item.desc}</div>
|
<div style="color:green">{item.desc}</div>
|
||||||
<ul>
|
<ul class="flex-1">
|
||||||
{item.privilege.map((p: string) => (
|
{item.privilege.map((p: string) => (
|
||||||
<li>
|
<li class="flex-baseline">
|
||||||
<fs-icon class="color-green" icon="ion:checkmark-sharp" />
|
<fs-icon class="color-green" icon="ion:checkmark-sharp" />
|
||||||
{p}
|
{p}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="footer flex-between flex-vc">
|
||||||
|
<div class="price-show">
|
||||||
|
{item.price && (
|
||||||
|
<span>
|
||||||
|
<span class="price-text">¥{item.price}</span>
|
||||||
|
/年
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{!item.price && (
|
||||||
|
<span>
|
||||||
|
<span class="price-text">免费</span>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="get-show">{item.get && <div>{item.get()}</div>}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
);
|
);
|
||||||
|
@ -372,10 +390,12 @@ onMounted(() => {
|
||||||
|
|
||||||
.vip-active-modal {
|
.vip-active-modal {
|
||||||
.vip-block {
|
.vip-block {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #eee;
|
border: 1px solid #eee;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
height: 195px;
|
height: 250px;
|
||||||
//background-color: rgba(250, 237, 167, 0.79);
|
//background-color: rgba(250, 237, 167, 0.79);
|
||||||
&.current {
|
&.current {
|
||||||
border-color: green;
|
border-color: green;
|
||||||
|
@ -389,6 +409,16 @@ onMounted(() => {
|
||||||
font-wight: 400;
|
font-wight: 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding-top: 5px;
|
||||||
|
margin-top: 0px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
.price-text {
|
||||||
|
font-size: 18px;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
|
|
|
@ -46,10 +46,6 @@ export const certdResources = [
|
||||||
path: "/certd/monitor/site",
|
path: "/certd/monitor/site",
|
||||||
component: "/certd/monitor/site/index.vue",
|
component: "/certd/monitor/site/index.vue",
|
||||||
meta: {
|
meta: {
|
||||||
show: () => {
|
|
||||||
const settingStore = useSettingStore();
|
|
||||||
return settingStore.isPlus;
|
|
||||||
},
|
|
||||||
icon: "ion:videocam-outline",
|
icon: "ion:videocam-outline",
|
||||||
auth: true
|
auth: true
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ export const useSettingStore = defineStore({
|
||||||
async checkUrlBound() {
|
async checkUrlBound() {
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const settingStore = useSettingStore();
|
const settingStore = useSettingStore();
|
||||||
if (!userStore.isAdmin || !settingStore.isPlus) {
|
if (!userStore.isAdmin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,15 +54,25 @@ h1, h2, h3, h4, h5, h6 {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.flex-vc{
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.flex-vb{
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
.flex-o {
|
.flex-o {
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.flex-baseline{
|
||||||
|
display: flex !important;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-between {
|
.flex-between {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex {
|
.flex {
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-badge>
|
</a-badge>
|
||||||
</template>
|
</template>
|
||||||
<a-divider type="vertical" />
|
<template v-if="settingsStore.isComm">
|
||||||
<suite-card class="m-0"></suite-card>
|
<a-divider type="vertical" />
|
||||||
|
<suite-card class="m-0"></suite-card>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -92,7 +94,7 @@
|
||||||
<a-row :gutter="10">
|
<a-row :gutter="10">
|
||||||
<a-col v-for="item of pluginGroups.groups.all.plugins" :key="item.name" class="plugin-item-col" :span="4">
|
<a-col v-for="item of pluginGroups.groups.all.plugins" :key="item.name" class="plugin-item-col" :span="4">
|
||||||
<a-card>
|
<a-card>
|
||||||
<a-tooltip :title="item.desc">
|
<a-tooltip :title="item.desc" class="flex-between">
|
||||||
<div class="plugin-item pointer">
|
<div class="plugin-item pointer">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<fs-icon :icon="item.icon" class="font-size-16 color-blue" />
|
<fs-icon :icon="item.icon" class="font-size-16 color-blue" />
|
||||||
|
@ -101,6 +103,7 @@
|
||||||
<div class="title">{{ item.title }}</div>
|
<div class="title">{{ item.title }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-o"><vip-button v-if="item.needPlus" mode="icon" class="" /></div>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
@ -158,7 +161,7 @@ const settingStore = useSettingStore();
|
||||||
const siteInfo: Ref<SiteInfo> = computed(() => {
|
const siteInfo: Ref<SiteInfo> = computed(() => {
|
||||||
return settingStore.siteInfo;
|
return settingStore.siteInfo;
|
||||||
});
|
});
|
||||||
|
const settingsStore = useSettingStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const userInfo: ComputedRef<UserInfoRes> = computed(() => {
|
const userInfo: ComputedRef<UserInfoRes> = computed(() => {
|
||||||
return userStore.getUserInfo;
|
return userStore.getUserInfo;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="my-suite-card">
|
<div v-if="detail.enabled" class="my-suite-card">
|
||||||
<div class="flex-o">
|
<div class="flex-o">
|
||||||
<a-popover>
|
<a-popover>
|
||||||
<template #content>
|
<template #content>
|
||||||
|
@ -52,6 +52,7 @@ type SuiteValue = {
|
||||||
used: number;
|
used: number;
|
||||||
};
|
};
|
||||||
type SuiteDetail = {
|
type SuiteDetail = {
|
||||||
|
enabled?: boolean;
|
||||||
suites?: any[];
|
suites?: any[];
|
||||||
expiresTime?: number;
|
expiresTime?: number;
|
||||||
pipelineCount?: SuiteValue;
|
pipelineCount?: SuiteValue;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"dev": "cross-env NODE_ENV=local mwtsc --watch --run @midwayjs/mock/app",
|
"dev": "cross-env NODE_ENV=local mwtsc --watch --run @midwayjs/mock/app",
|
||||||
"dev-commlocal": "cross-env NODE_ENV=dev-commlocal mwtsc --watch --run @midwayjs/mock/app",
|
"dev-commlocal": "cross-env NODE_ENV=dev-commlocal mwtsc --watch --run @midwayjs/mock/app",
|
||||||
"dev-commpro": "cross-env NODE_ENV=dev-commpro mwtsc --watch --run @midwayjs/mock/app",
|
"dev-commpro": "cross-env NODE_ENV=dev-commpro mwtsc --watch --run @midwayjs/mock/app",
|
||||||
"dev-pgd": "cross-env NODE_ENV=dev-pgd mwtsc --watch --run @midwayjs/mock/app",
|
"dev-pg": "cross-env NODE_ENV=dev-pg mwtsc --watch --run @midwayjs/mock/app",
|
||||||
"dev-mysql": "cross-env NODE_ENV=dev-mysql mwtsc --watch --run @midwayjs/mock/app",
|
"dev-mysql": "cross-env NODE_ENV=dev-mysql mwtsc --watch --run @midwayjs/mock/app",
|
||||||
"dev-localplus": "cross-env NODE_ENV=dev-localplus mwtsc --watch --run @midwayjs/mock/app",
|
"dev-localplus": "cross-env NODE_ENV=dev-localplus mwtsc --watch --run @midwayjs/mock/app",
|
||||||
"dev-pgpl": "cross-env NODE_ENV=dev-pgpl mwtsc --watch --run @midwayjs/mock/app",
|
"dev-pgpl": "cross-env NODE_ENV=dev-pgpl mwtsc --watch --run @midwayjs/mock/app",
|
||||||
|
|
|
@ -24,6 +24,7 @@ export class SysPlusController extends BaseController {
|
||||||
async bindUrl(@Body(ALL) body: { url: string }) {
|
async bindUrl(@Body(ALL) body: { url: string }) {
|
||||||
const { url } = body;
|
const { url } = body;
|
||||||
|
|
||||||
|
await this.plusService.register();
|
||||||
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
||||||
await this.plusService.bindUrl(url);
|
await this.plusService.bindUrl(url);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import crypto from 'crypto';
|
||||||
|
|
||||||
@Autoload()
|
@Autoload()
|
||||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class AutoInitSite {
|
export class AutoAInitSite {
|
||||||
@Inject()
|
@Inject()
|
||||||
userService: UserService;
|
userService: UserService;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Cron } from '../cron/cron.js';
|
||||||
|
|
||||||
@Autoload()
|
@Autoload()
|
||||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class AutoRegisterCron {
|
export class AutoCRegisterCron {
|
||||||
@Inject()
|
@Inject()
|
||||||
pipelineService: PipelineService;
|
pipelineService: PipelineService;
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { logger, utils } from '@certd/basic';
|
||||||
|
import { UserSuiteService } from '@certd/commercial-core';
|
||||||
|
import { Autoload, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
|
|
||||||
|
@Autoload()
|
||||||
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
|
export class AutoDMitterRegister {
|
||||||
|
@Inject()
|
||||||
|
userSuiteService: UserSuiteService;
|
||||||
|
|
||||||
|
@Init()
|
||||||
|
async init() {
|
||||||
|
await this.registerOnNewUser();
|
||||||
|
}
|
||||||
|
async registerOnNewUser() {
|
||||||
|
utils.mitter.on('register', async (req: { userId: number }) => {
|
||||||
|
logger.info('register event', req.userId);
|
||||||
|
await this.userSuiteService.presentGiftSuite(req.userId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,9 @@ export class AutoZPrint {
|
||||||
async init() {
|
async init() {
|
||||||
//监听https
|
//监听https
|
||||||
this.startHttpsServer();
|
this.startHttpsServer();
|
||||||
|
if (isDev()) {
|
||||||
|
this.startHeapLog();
|
||||||
|
}
|
||||||
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
||||||
logger.info('=========================================');
|
logger.info('=========================================');
|
||||||
logger.info('当前站点ID:', installInfo.siteId);
|
logger.info('当前站点ID:', installInfo.siteId);
|
||||||
|
@ -36,9 +38,6 @@ export class AutoZPrint {
|
||||||
}
|
}
|
||||||
logger.info('Certd已启动');
|
logger.info('Certd已启动');
|
||||||
logger.info('=========================================');
|
logger.info('=========================================');
|
||||||
if (isDev()) {
|
|
||||||
this.startHeapLog();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
startHeapLog() {
|
startHeapLog() {
|
||||||
|
@ -50,7 +49,7 @@ export class AutoZPrint {
|
||||||
}, 60000);
|
}, 60000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async startHttpsServer() {
|
startHttpsServer() {
|
||||||
if (!this.httpsConfig.enabled) {
|
if (!this.httpsConfig.enabled) {
|
||||||
logger.info('Https server is not enabled');
|
logger.info('Https server is not enabled');
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Inject, Provide } from '@midwayjs/core';
|
import { Inject, Provide } from '@midwayjs/core';
|
||||||
import { BaseService } from '@certd/lib-server';
|
import { BaseService, NeedSuiteException, NeedVIPException, SysSettingsService, SysSuiteSetting } from '@certd/lib-server';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { SiteInfoEntity } from '../entity/site-info.js';
|
import { SiteInfoEntity } from '../entity/site-info.js';
|
||||||
|
@ -8,6 +8,8 @@ import dayjs from 'dayjs';
|
||||||
import { logger } from '@certd/basic';
|
import { logger } from '@certd/basic';
|
||||||
import { PeerCertificate } from 'tls';
|
import { PeerCertificate } from 'tls';
|
||||||
import { NotificationService } from '../../pipeline/service/notification-service.js';
|
import { NotificationService } from '../../pipeline/service/notification-service.js';
|
||||||
|
import { isComm, isPlus } from '@certd/plus-core';
|
||||||
|
import { UserSuiteService } from '@certd/commercial-core';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||||
|
@ -17,11 +19,41 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||||
@Inject()
|
@Inject()
|
||||||
notificationService: NotificationService;
|
notificationService: NotificationService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
userSuiteService: UserSuiteService;
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
getRepository() {
|
getRepository() {
|
||||||
return this.repository;
|
return this.repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async add(data: SiteInfoEntity) {
|
||||||
|
if (!data.userId) {
|
||||||
|
throw new Error('userId is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPlus()) {
|
||||||
|
const count = await this.getUserMonitorCount(data.userId);
|
||||||
|
if (count >= 1) {
|
||||||
|
throw new NeedVIPException('站点监控数量已达上限,请升级专业版');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isComm()) {
|
||||||
|
const suiteSetting = await this.sysSettingsService.getSetting<SysSuiteSetting>(SysSuiteSetting);
|
||||||
|
if (suiteSetting.enabled) {
|
||||||
|
const userSuite = await this.userSuiteService.getMySuiteDetail(data.userId);
|
||||||
|
if (userSuite.monitorCount.max != -1 && userSuite.monitorCount.max <= userSuite.monitorCount.used) {
|
||||||
|
throw new NeedSuiteException('站点监控数量已达上限,请购买或升级套餐');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.repository.save(data);
|
||||||
|
}
|
||||||
|
|
||||||
async getUserMonitorCount(userId: number) {
|
async getUserMonitorCount(userId: number) {
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
throw new Error('userId is required');
|
throw new Error('userId is required');
|
||||||
|
|
|
@ -205,11 +205,11 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
if (isComm()) {
|
if (isComm()) {
|
||||||
//校验pipelineCount
|
//校验pipelineCount
|
||||||
const userSuite = await this.userSuiteService.getMySuiteDetail(bean.userId);
|
const userSuite = await this.userSuiteService.getMySuiteDetail(bean.userId);
|
||||||
if (userSuite?.pipelineCount.used + 1 > userSuite?.pipelineCount.max) {
|
if (userSuite?.pipelineCount.max != -1 && userSuite?.pipelineCount.used + 1 > userSuite?.pipelineCount.max) {
|
||||||
throw new NeedSuiteException(`对不起,您最多只能创建${userSuite?.pipelineCount.max}条流水线,请购买或升级套餐`);
|
throw new NeedSuiteException(`对不起,您最多只能创建${userSuite?.pipelineCount.max}条流水线,请购买或升级套餐`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userSuite.domainCount.used + domains.length > userSuite.domainCount.max) {
|
if (userSuite.domainCount.max != -1 && userSuite.domainCount.used + domains.length > userSuite.domainCount.max) {
|
||||||
throw new NeedSuiteException(`对不起,您最多只能添加${userSuite.domainCount.max}个域名,请购买或升级套餐`);
|
throw new NeedSuiteException(`对不起,您最多只能添加${userSuite.domainCount.max}个域名,请购买或升级套餐`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
const sysPublic = await this.sysSettingsService.getSetting<SysPublicSettings>(SysPublicSettings);
|
const sysPublic = await this.sysSettingsService.getSetting<SysPublicSettings>(SysPublicSettings);
|
||||||
const limitUserPipelineCount = sysPublic.limitUserPipelineCount;
|
const limitUserPipelineCount = sysPublic.limitUserPipelineCount;
|
||||||
if (limitUserPipelineCount && limitUserPipelineCount > 0 && count >= limitUserPipelineCount) {
|
if (limitUserPipelineCount && limitUserPipelineCount > 0 && count >= limitUserPipelineCount) {
|
||||||
throw new NeedVIPException(`您最多只能创建${limitUserPipelineCount}条流水线`);
|
throw new NeedVIPException(`普通用户最多只能创建${limitUserPipelineCount}条流水线`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue