diff --git a/README.md b/README.md
index cecb6b14..42b6f4d1 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,9 @@ Certd 是一个免费全自动申请和自动部署更新SSL证书的管理系
* 支持SQLite,PostgreSQL、MySQL数据库
-
+>
+> 流水线数量现已调整为无限制,欢迎大家使用
+>
## 二、在线体验
@@ -202,13 +204,14 @@ https://afdian.com/a/greper
专业版特权对比
-| 功能 | 基础版 | 专业版 |
-|---------|-----------------|-------------------|
-| 免费证书申请 | 免费无限制 | 无限制 |
+| 功能 | 基础版 | 专业版 |
+|------|-----------------|-------------------|
+| 免费证书申请 | 免费无限制 | 无限制 |
+| 域名数量 | 免费无限制 | 无限制 |
| 证书流水线条数 | 免费无限制 | 无限制 |
-| 站点证书监控 | 1条 | 无限制 |
-| 自动部署插件 | 阿里云、腾讯云、七牛云、SSH | 支持群晖、宝塔、1Panel等,持续开发中 |
-| 通知 | 邮件、webhook | server酱、企微、anpush、钉钉等 |
+| 站点证书监控 | 1条 | 无限制 |
+| 自动部署插件 | 阿里云、腾讯云、七牛云、SSH | 支持群晖、宝塔、1Panel等,持续开发中 |
+| 通知 | 邮件、webhook | server酱、企微、anpush等 |
************************
diff --git a/packages/libs/lib-server/src/user/access/service/encrypt-service.ts b/packages/libs/lib-server/src/user/access/service/encrypt-service.ts
index 5cf0ec8b..5e787ec2 100644
--- a/packages/libs/lib-server/src/user/access/service/encrypt-service.ts
+++ b/packages/libs/lib-server/src/user/access/service/encrypt-service.ts
@@ -6,7 +6,7 @@ import { SysPrivateSettings, SysSettingsService } from '../../../system/index.js
* 授权
*/
@Provide()
-@Scope(ScopeEnum.Request, { allowDowngrade: true })
+@Scope(ScopeEnum.Singleton)
export class EncryptService {
secretKey: Buffer;
diff --git a/packages/ui/certd-client/src/components/vip-button/index.vue b/packages/ui/certd-client/src/components/vip-button/index.vue
index 5ac458b3..75720d26 100644
--- a/packages/ui/certd-client/src/components/vip-button/index.vue
+++ b/packages/ui/certd-client/src/components/vip-button/index.vue
@@ -229,27 +229,41 @@ function openUpgrade() {
const vipTypeDefine = {
free: {
title: "基础版",
- desc: "免费使用",
+ desc: "社区免费版",
type: "free",
- privilege: ["证书申请功能无限制", "证书流水线数量无限制", "常用的主机、云平台、cdn等部署插件"]
+ privilege: ["证书申请无限制", "域名数量无限制", "证书流水线数量无限制", "常用的主机、云平台、cdn等部署插件", "邮件、webhook通知方式"]
},
plus: {
title: "专业版",
- desc: "功能增强,适用于个人企业内部使用",
+ desc: "开源需要您的赞助支持",
type: "plus",
- privilege: ["可加VIP群,需求优先实现", "宝塔、群晖、1Panel、易盾等部署插件", "站点证书监控", "更多通知种类"],
+ privilege: ["可加VIP群,您需求将优先实现", "站点证书监控无限制", "更多通知方式", "更多强大部署插件,宝塔、群晖、1Panel等"],
trial: {
- title: "7天试用",
+ title: "点击获取7天试用",
click: () => {
openStarModal();
}
+ },
+ price: 29.9,
+ get() {
+ return (
+
+
+ 爱发电赞助后获取
+
+
+ );
}
},
comm: {
title: "商业版",
desc: "商业授权,可对外运营",
type: "comm",
- privilege: ["拥有专业版所有特权", "允许商用,可修改logo、标题", "数据统计", "插件管理", "多用户无限制", "支持用户支付(敬请期待)"]
+ privilege: ["拥有专业版所有特权", "允许商用,可修改logo、标题", "数据统计", "插件管理", "多用户无限制", "支持用户支付"],
+ price: 399,
+ get() {
+ return 请联系作者获取;
+ }
}
};
@@ -260,28 +274,16 @@ function openUpgrade() {
},
maskClosable: true,
okText: "激活",
- width: 900,
+ width: 1000,
content: () => {
- let activationCodeGetWay: any = null;
- if (settingStore.siteEnv.agent.enabled != null) {
- const agent = settingStore.siteEnv.agent;
- if (agent.enabled === false) {
- activationCodeGetWay = (
-
-
- 爱发电赞助“VIP会员(¥29.9)”后获取一年期专业版激活码
-
- 商业版请直接联系作者
-
- );
- } else {
- activationCodeGetWay = (
-
- {agent.contactText}
-
- );
- }
- }
+ let activationCodeGetWay = (
+
+
+ 爱发电赞助“VIP会员”后获取一年期专业版激活码
+
+ 商业版请直接联系作者
+
+ );
const vipLabel = settingStore.vipLabel;
const slots = [];
for (const key in vipTypeDefine) {
@@ -301,15 +303,31 @@ function openUpgrade() {
)}
-
{item.desc}
-
+ {item.desc}
+
{item.privilege.map((p: string) => (
- -
+
-
{p}
))}
+
);
@@ -372,10 +390,12 @@ onMounted(() => {
.vip-active-modal {
.vip-block {
+ display: flex;
+ flex-direction: column;
padding: 10px;
border: 1px solid #eee;
border-radius: 5px;
- height: 195px;
+ height: 250px;
//background-color: rgba(250, 237, 167, 0.79);
&.current {
border-color: green;
@@ -389,6 +409,16 @@ onMounted(() => {
font-wight: 400;
}
}
+
+ .footer {
+ padding-top: 5px;
+ margin-top: 0px;
+ border-top: 1px solid #eee;
+ .price-text {
+ font-size: 18px;
+ color: red;
+ }
+ }
}
ul {
diff --git a/packages/ui/certd-client/src/router/source/modules/certd.ts b/packages/ui/certd-client/src/router/source/modules/certd.ts
index 6e7dee96..8e1a2047 100644
--- a/packages/ui/certd-client/src/router/source/modules/certd.ts
+++ b/packages/ui/certd-client/src/router/source/modules/certd.ts
@@ -46,10 +46,6 @@ export const certdResources = [
path: "/certd/monitor/site",
component: "/certd/monitor/site/index.vue",
meta: {
- show: () => {
- const settingStore = useSettingStore();
- return settingStore.isPlus;
- },
icon: "ion:videocam-outline",
auth: true
}
diff --git a/packages/ui/certd-client/src/store/modules/settings.ts b/packages/ui/certd-client/src/store/modules/settings.ts
index 45704d3d..63b4b9ef 100644
--- a/packages/ui/certd-client/src/store/modules/settings.ts
+++ b/packages/ui/certd-client/src/store/modules/settings.ts
@@ -160,7 +160,7 @@ export const useSettingStore = defineStore({
async checkUrlBound() {
const userStore = useUserStore();
const settingStore = useSettingStore();
- if (!userStore.isAdmin || !settingStore.isPlus) {
+ if (!userStore.isAdmin) {
return;
}
diff --git a/packages/ui/certd-client/src/style/common.less b/packages/ui/certd-client/src/style/common.less
index b14c3f45..14e5cb06 100644
--- a/packages/ui/certd-client/src/style/common.less
+++ b/packages/ui/certd-client/src/style/common.less
@@ -54,15 +54,25 @@ h1, h2, h3, h4, h5, h6 {
justify-content: center;
align-items: center;
}
-
+.flex-vc{
+ align-items: center;
+}
+.flex-vb{
+ align-items: baseline;
+}
.flex-o {
display: flex !important;
align-items: center;
}
+.flex-baseline{
+ display: flex !important;
+ align-items: baseline;
+}
.flex-between {
display: flex;
justify-content: space-between;
+ align-items: baseline;
}
.flex {
diff --git a/packages/ui/certd-client/src/views/framework/home/dashboard/index.vue b/packages/ui/certd-client/src/views/framework/home/dashboard/index.vue
index c5d7c06e..5691a562 100644
--- a/packages/ui/certd-client/src/views/framework/home/dashboard/index.vue
+++ b/packages/ui/certd-client/src/views/framework/home/dashboard/index.vue
@@ -23,8 +23,10 @@
-
-
+
+
+
+
@@ -92,7 +94,7 @@
-
+
@@ -101,6 +103,7 @@
{{ item.title }}
+
@@ -158,7 +161,7 @@ const settingStore = useSettingStore();
const siteInfo: Ref = computed(() => {
return settingStore.siteInfo;
});
-
+const settingsStore = useSettingStore();
const userStore = useUserStore();
const userInfo: ComputedRef = computed(() => {
return userStore.getUserInfo;
diff --git a/packages/ui/certd-client/src/views/framework/home/dashboard/suite-card.vue b/packages/ui/certd-client/src/views/framework/home/dashboard/suite-card.vue
index ea85acee..0f170c46 100644
--- a/packages/ui/certd-client/src/views/framework/home/dashboard/suite-card.vue
+++ b/packages/ui/certd-client/src/views/framework/home/dashboard/suite-card.vue
@@ -1,5 +1,5 @@
-
+
@@ -52,6 +52,7 @@ type SuiteValue = {
used: number;
};
type SuiteDetail = {
+ enabled?: boolean;
suites?: any[];
expiresTime?: number;
pipelineCount?: SuiteValue;
diff --git a/packages/ui/certd-server/package.json b/packages/ui/certd-server/package.json
index 0eae82e5..e6dc6b6c 100644
--- a/packages/ui/certd-server/package.json
+++ b/packages/ui/certd-server/package.json
@@ -9,7 +9,7 @@
"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-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-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",
diff --git a/packages/ui/certd-server/src/controller/sys/plus/plus-controller.ts b/packages/ui/certd-server/src/controller/sys/plus/plus-controller.ts
index 44aea646..b5af9427 100644
--- a/packages/ui/certd-server/src/controller/sys/plus/plus-controller.ts
+++ b/packages/ui/certd-server/src/controller/sys/plus/plus-controller.ts
@@ -24,6 +24,7 @@ export class SysPlusController extends BaseController {
async bindUrl(@Body(ALL) body: { url: string }) {
const { url } = body;
+ await this.plusService.register();
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
await this.plusService.bindUrl(url);
diff --git a/packages/ui/certd-server/src/modules/auto/auto-init-site.ts b/packages/ui/certd-server/src/modules/auto/auto-a-init-site.ts
similarity index 98%
rename from packages/ui/certd-server/src/modules/auto/auto-init-site.ts
rename to packages/ui/certd-server/src/modules/auto/auto-a-init-site.ts
index a804af81..55c4c743 100644
--- a/packages/ui/certd-server/src/modules/auto/auto-init-site.ts
+++ b/packages/ui/certd-server/src/modules/auto/auto-a-init-site.ts
@@ -7,7 +7,7 @@ import crypto from 'crypto';
@Autoload()
@Scope(ScopeEnum.Request, { allowDowngrade: true })
-export class AutoInitSite {
+export class AutoAInitSite {
@Inject()
userService: UserService;
diff --git a/packages/ui/certd-server/src/modules/auto/auto-register-cron.ts b/packages/ui/certd-server/src/modules/auto/auto-c-register-cron.ts
similarity index 98%
rename from packages/ui/certd-server/src/modules/auto/auto-register-cron.ts
rename to packages/ui/certd-server/src/modules/auto/auto-c-register-cron.ts
index 1894b82c..b6d7b9fb 100644
--- a/packages/ui/certd-server/src/modules/auto/auto-register-cron.ts
+++ b/packages/ui/certd-server/src/modules/auto/auto-c-register-cron.ts
@@ -7,7 +7,7 @@ import { Cron } from '../cron/cron.js';
@Autoload()
@Scope(ScopeEnum.Request, { allowDowngrade: true })
-export class AutoRegisterCron {
+export class AutoCRegisterCron {
@Inject()
pipelineService: PipelineService;
diff --git a/packages/ui/certd-server/src/modules/auto/auto-d-mitter-register.ts b/packages/ui/certd-server/src/modules/auto/auto-d-mitter-register.ts
new file mode 100644
index 00000000..438d1703
--- /dev/null
+++ b/packages/ui/certd-server/src/modules/auto/auto-d-mitter-register.ts
@@ -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);
+ });
+ }
+}
diff --git a/packages/ui/certd-server/src/modules/auto/auto-z.ts b/packages/ui/certd-server/src/modules/auto/auto-z.ts
index 373a239f..7718259f 100644
--- a/packages/ui/certd-server/src/modules/auto/auto-z.ts
+++ b/packages/ui/certd-server/src/modules/auto/auto-z.ts
@@ -24,7 +24,9 @@ export class AutoZPrint {
async init() {
//监听https
this.startHttpsServer();
-
+ if (isDev()) {
+ this.startHeapLog();
+ }
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
logger.info('=========================================');
logger.info('当前站点ID:', installInfo.siteId);
@@ -36,9 +38,6 @@ export class AutoZPrint {
}
logger.info('Certd已启动');
logger.info('=========================================');
- if (isDev()) {
- this.startHeapLog();
- }
}
startHeapLog() {
@@ -50,7 +49,7 @@ export class AutoZPrint {
}, 60000);
}
- async startHttpsServer() {
+ startHttpsServer() {
if (!this.httpsConfig.enabled) {
logger.info('Https server is not enabled');
return;
diff --git a/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts b/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts
index 1a57a49a..4308eaa0 100644
--- a/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts
+++ b/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts
@@ -1,5 +1,5 @@
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 { Repository } from 'typeorm';
import { SiteInfoEntity } from '../entity/site-info.js';
@@ -8,6 +8,8 @@ import dayjs from 'dayjs';
import { logger } from '@certd/basic';
import { PeerCertificate } from 'tls';
import { NotificationService } from '../../pipeline/service/notification-service.js';
+import { isComm, isPlus } from '@certd/plus-core';
+import { UserSuiteService } from '@certd/commercial-core';
@Provide()
export class SiteInfoService extends BaseService {
@@ -17,11 +19,41 @@ export class SiteInfoService extends BaseService {
@Inject()
notificationService: NotificationService;
+ @Inject()
+ sysSettingsService: SysSettingsService;
+
+ @Inject()
+ userSuiteService: UserSuiteService;
+
//@ts-ignore
getRepository() {
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);
+ 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) {
if (!userId) {
throw new Error('userId is required');
diff --git a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts
index 0b73b4ec..52143b6e 100644
--- a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts
+++ b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts
@@ -205,11 +205,11 @@ export class PipelineService extends BaseService {
if (isComm()) {
//校验pipelineCount
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}条流水线,请购买或升级套餐`);
}
- 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}个域名,请购买或升级套餐`);
}
}
@@ -222,7 +222,7 @@ export class PipelineService extends BaseService {
const sysPublic = await this.sysSettingsService.getSetting(SysPublicSettings);
const limitUserPipelineCount = sysPublic.limitUserPipelineCount;
if (limitUserPipelineCount && limitUserPipelineCount > 0 && count >= limitUserPipelineCount) {
- throw new NeedVIPException(`您最多只能创建${limitUserPipelineCount}条流水线`);
+ throw new NeedVIPException(`普通用户最多只能创建${limitUserPipelineCount}条流水线`);
}
}
}