mirror of
https://github.com/certd/certd.git
synced 2026-05-04 12:57:25 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d8304e859 | |||
| 6ddc23e2aa | |||
| 2fc491015e | |||
| bb0afe1fa7 | |||
| eb46f8c776 |
Vendored
+1
-1
@@ -7,7 +7,7 @@
|
||||
],
|
||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.tabSize": 2,
|
||||
"explorer.autoReveal": false,
|
||||
|
||||
@@ -3,30 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复有域名记录时,域名输入框无法关闭的bug ([54c8217](https://github.com/certd/certd/commit/54c8217808453b121abf646b004596f28932509f))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* eab从更多参数中挪到外面 ([5ea4f46](https://github.com/certd/certd/commit/5ea4f46de7ae403a7a16e9488dc1d9c7523d019a))
|
||||
* 第三方登录支持Microsoft ([beb7a4c](https://github.com/certd/certd/commit/beb7a4c99277262bb9681c5594cfcd3e36c52074))
|
||||
* 优化zerossl申请证书稳定性 ([4d86fb3](https://github.com/certd/certd/commit/4d86fb319b81dbf6fa6485982105725b1b066593))
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复新网找错域名的bug ([bd511f9](https://github.com/certd/certd/commit/bd511f97cb7fbdcaeff7ac899f0460a5c7b41826))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 当域名管理中没有域名时,创建流水线时不展开域名选择框 ([9166a57](https://github.com/certd/certd/commit/9166a579301a60750f0b72b6a42b0c8d730695fd))
|
||||
* count tip ([e19743f](https://github.com/certd/certd/commit/e19743f70553700f1f91bff76f87370f749dd247))
|
||||
* oauth支持github 和google, 修复头像显示问题 ([693a4a6](https://github.com/certd/certd/commit/693a4a663385ced3176286bf4b5f3566da83d90e))
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -3,18 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复新网找错域名的bug ([bd511f9](https://github.com/certd/certd/commit/bd511f97cb7fbdcaeff7ac899f0460a5c7b41826))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 当域名管理中没有域名时,创建流水线时不展开域名选择框 ([9166a57](https://github.com/certd/certd/commit/9166a579301a60750f0b72b6a42b0c8d730695fd))
|
||||
* count tip ([e19743f](https://github.com/certd/certd/commit/e19743f70553700f1f91bff76f87370f749dd247))
|
||||
* oauth支持github 和google, 修复头像显示问题 ([693a4a6](https://github.com/certd/certd/commit/693a4a663385ced3176286bf4b5f3566da83d90e))
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **证书申请(JS版)** | 免费通配符域名证书申请,支持多个域名打到同一个证书上 |
|
||||
| 2.| **已有证书托管** | 手动上传自定义证书后,自动部署(每次证书有更新,都需要手动上传一次) |
|
||||
| 2.| **商用证书托管** | 手动上传自定义证书后,自动部署(每次证书有更新,都需要手动上传一次) |
|
||||
| 3.| **获取阿里云订阅证书** | 从阿里云拉取订阅模式的商用证书 |
|
||||
| 4.| **证书申请(Lego)** | 支持海量DNS解析提供商,推荐使用,一样的免费通配符域名证书申请,支持多个域名打到同一个证书上 |
|
||||
## 2. 主机
|
||||
|
||||
+1
-1
@@ -9,5 +9,5 @@
|
||||
}
|
||||
},
|
||||
"npmClient": "pnpm",
|
||||
"version": "1.38.7"
|
||||
"version": "1.38.5"
|
||||
}
|
||||
|
||||
@@ -3,16 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/publishlab/node-acme-client/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 优化zerossl申请证书稳定性 ([4d86fb3](https://github.com/publishlab/node-acme-client/commit/4d86fb319b81dbf6fa6485982105725b1b066593))
|
||||
|
||||
## [1.38.6](https://github.com/publishlab/node-acme-client/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.38.5](https://github.com/publishlab/node-acme-client/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Simple and unopinionated ACME client",
|
||||
"private": false,
|
||||
"author": "nmorsman",
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"type": "module",
|
||||
"module": "scr/index.js",
|
||||
"main": "src/index.js",
|
||||
@@ -18,7 +18,7 @@
|
||||
"types"
|
||||
],
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.38.7",
|
||||
"@certd/basic": "^1.38.5",
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"asn1js": "^3.0.5",
|
||||
"axios": "^1.9.0",
|
||||
@@ -70,5 +70,5 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -600,7 +600,7 @@ class AcmeClient {
|
||||
throw new Error(`[${d}] Unexpected item status: ${resp.data.status}`);
|
||||
};
|
||||
|
||||
this.log(`[${d}] Waiting for valid status (等待valid状态): ${item.url}`, JSON.stringify(this.backoffOpts));
|
||||
this.log(`[${d}] Waiting for valid status (等待valid状态): ${item.url}`, this.backoffOpts);
|
||||
return util.retry(verifyFn, this.backoffOpts);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
@@ -1 +1 @@
|
||||
16:26
|
||||
23:59
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -47,5 +47,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/pipeline",
|
||||
"private": false,
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -18,8 +18,8 @@
|
||||
"compile": "tsc --skipLibCheck --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.38.7",
|
||||
"@certd/plus-core": "^1.38.7",
|
||||
"@certd/basic": "^1.38.5",
|
||||
"@certd/plus-core": "^1.38.5",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash-es": "^4.17.21",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
@@ -45,5 +45,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-huawei",
|
||||
"private": false,
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
"types": "./dist/d/index.d.ts",
|
||||
@@ -24,5 +24,5 @@
|
||||
"prettier": "^2.8.8",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-iframe",
|
||||
"private": false,
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -31,5 +31,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/jdcloud",
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"description": "jdcloud openApi sdk",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
@@ -56,5 +56,5 @@
|
||||
"fetch"
|
||||
]
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-k8s",
|
||||
"private": false,
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -17,7 +17,7 @@
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.38.7",
|
||||
"@certd/basic": "^1.38.5",
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -32,5 +32,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/lib-server",
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -28,11 +28,11 @@
|
||||
],
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.38.7",
|
||||
"@certd/basic": "^1.38.7",
|
||||
"@certd/pipeline": "^1.38.7",
|
||||
"@certd/plugin-lib": "^1.38.7",
|
||||
"@certd/plus-core": "^1.38.7",
|
||||
"@certd/acme-client": "^1.38.5",
|
||||
"@certd/basic": "^1.38.5",
|
||||
"@certd/pipeline": "^1.38.5",
|
||||
"@certd/plugin-lib": "^1.38.5",
|
||||
"@certd/plus-core": "^1.38.5",
|
||||
"@midwayjs/cache": "3.14.0",
|
||||
"@midwayjs/core": "3.20.11",
|
||||
"@midwayjs/i18n": "3.20.13",
|
||||
@@ -64,5 +64,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ export class SysPublicSettings extends BaseSettings {
|
||||
}> = {};
|
||||
|
||||
notice?: string;
|
||||
|
||||
adminMode?: "enterprise" | "saas" = "saas";
|
||||
}
|
||||
|
||||
export class SysPrivateSettings extends BaseSettings {
|
||||
|
||||
@@ -21,6 +21,9 @@ export class AccessEntity {
|
||||
@Column({ name: 'encrypt_setting', comment: '已加密设置', length: 10240, nullable: true })
|
||||
encryptSetting: string;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -28,6 +28,9 @@ export class AddonEntity {
|
||||
@Column({ name: 'is_default', comment: '是否默认', nullable: false, default: false })
|
||||
isDefault: boolean;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/midway-flyway-js",
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -46,5 +46,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -3,16 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* eab从更多参数中挪到外面 ([5ea4f46](https://github.com/certd/certd/commit/5ea4f46de7ae403a7a16e9488dc1d9c7523d019a))
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-cert",
|
||||
"private": false,
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -17,10 +17,10 @@
|
||||
"compile": "tsc --skipLibCheck --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.38.7",
|
||||
"@certd/basic": "^1.38.7",
|
||||
"@certd/pipeline": "^1.38.7",
|
||||
"@certd/plugin-lib": "^1.38.7",
|
||||
"@certd/acme-client": "^1.38.5",
|
||||
"@certd/basic": "^1.38.5",
|
||||
"@certd/pipeline": "^1.38.5",
|
||||
"@certd/plugin-lib": "^1.38.5",
|
||||
"psl": "^1.9.0",
|
||||
"punycode.js": "^2.3.1"
|
||||
},
|
||||
@@ -38,5 +38,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "@certd/plugin-lib";
|
||||
export * from "@certd/plugin-lib";
|
||||
@@ -3,14 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-lib",
|
||||
"private": false,
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -22,10 +22,10 @@
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
"@alicloud/tea-util": "^1.4.11",
|
||||
"@aws-sdk/client-s3": "^3.964.0",
|
||||
"@certd/acme-client": "^1.38.7",
|
||||
"@certd/basic": "^1.38.7",
|
||||
"@certd/pipeline": "^1.38.7",
|
||||
"@certd/plus-core": "^1.38.7",
|
||||
"@certd/acme-client": "^1.38.5",
|
||||
"@certd/basic": "^1.38.5",
|
||||
"@certd/pipeline": "^1.38.5",
|
||||
"@certd/plus-core": "^1.38.5",
|
||||
"@kubernetes/client-node": "0.21.0",
|
||||
"ali-oss": "^6.22.0",
|
||||
"basic-ftp": "^5.0.5",
|
||||
@@ -57,5 +57,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1368259a1e780486204e9d814c88a741a373dcca"
|
||||
"gitHead": "eeb1f27fa47ddc616451f3e5a8fb8d1de345d252"
|
||||
}
|
||||
|
||||
@@ -3,24 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复有域名记录时,域名输入框无法关闭的bug ([54c8217](https://github.com/certd/certd/commit/54c8217808453b121abf646b004596f28932509f))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* eab从更多参数中挪到外面 ([5ea4f46](https://github.com/certd/certd/commit/5ea4f46de7ae403a7a16e9488dc1d9c7523d019a))
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 当域名管理中没有域名时,创建流水线时不展开域名选择框 ([9166a57](https://github.com/certd/certd/commit/9166a579301a60750f0b72b6a42b0c8d730695fd))
|
||||
* count tip ([e19743f](https://github.com/certd/certd/commit/e19743f70553700f1f91bff76f87370f749dd247))
|
||||
* oauth支持github 和google, 修复头像显示问题 ([693a4a6](https://github.com/certd/certd/commit/693a4a663385ced3176286bf4b5f3566da83d90e))
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-client",
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --open",
|
||||
@@ -106,8 +106,8 @@
|
||||
"zod-defaults": "^0.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/lib-iframe": "^1.38.7",
|
||||
"@certd/pipeline": "^1.38.7",
|
||||
"@certd/lib-iframe": "^1.38.5",
|
||||
"@certd/pipeline": "^1.38.5",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@types/chai": "^4.3.12",
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<div class="flex flex-row">
|
||||
<a-select
|
||||
class="domain-select-input"
|
||||
:popup-class-name="popupClassName"
|
||||
:dropdown-style="dropdownStyle"
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
:options="optionsRef"
|
||||
:value="value"
|
||||
v-bind="attrs"
|
||||
:open="openProp"
|
||||
@click="onClick"
|
||||
@update:value="emit('update:value', $event)"
|
||||
>
|
||||
@@ -56,7 +56,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, defineComponent, onMounted, ref, Ref, useAttrs } from "vue";
|
||||
import { computed, defineComponent, ref, Ref, useAttrs } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Dicts } from "../lib/dicts";
|
||||
import { request } from "/@/api/service";
|
||||
@@ -83,6 +83,7 @@ const props = defineProps<{
|
||||
search?: boolean;
|
||||
pager?: boolean;
|
||||
value?: any[];
|
||||
open?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -93,11 +94,11 @@ const attrs = useAttrs();
|
||||
|
||||
const hasOptions: Ref = ref(null);
|
||||
|
||||
const popupClassName = computed(() => {
|
||||
if (!hasOptions.value) {
|
||||
return "hidden-important";
|
||||
const openProp = computed(() => {
|
||||
if (hasOptions.value == null) {
|
||||
return false;
|
||||
}
|
||||
return "";
|
||||
return hasOptions.value;
|
||||
});
|
||||
|
||||
const searchKeyRef = ref("");
|
||||
@@ -154,7 +155,6 @@ const getOptions = async () => {
|
||||
|
||||
optionsRef.value = options;
|
||||
if (hasOptions.value == null) {
|
||||
//初始设置一次
|
||||
if (options.length > 0) {
|
||||
hasOptions.value = true;
|
||||
} else {
|
||||
@@ -223,10 +223,6 @@ function openDomainImportDialog() {
|
||||
const dropdownStyle = ref({
|
||||
zIndex: 2000,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
refreshOptions();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less"></style>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="params-show">
|
||||
<a-tag v-for="item of params" :key="item.value" type="primary" color="green" class="item">
|
||||
<a-tag type="primary" color="green" v-for="item of params" :key="item.value" class="item">
|
||||
<span class="label">{{ item.label }}=</span>
|
||||
<fs-copyable :model-value="`\$\{${item.value}\}`" :button="{ show: false }" :inline="true"></fs-copyable>
|
||||
<fs-copyable :modelValue="`\$\{${item.value}\}`" :button="{show:false}" :inline="true"></fs-copyable>
|
||||
</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -8,20 +8,9 @@
|
||||
<div class="flex flex-col order-count-text weight-bold">
|
||||
<div class="count-text ml-4 flex items-center">
|
||||
<fs-icon icon="noto:fire" class="fs-20 mr-2"></fs-icon>
|
||||
<template v-if="stage.vipTotal > 0">
|
||||
<span> 已有 </span>
|
||||
<span class="count-number color-red font-bold text-2xl ml-1 mr-1"> {{ stage.vipTotal }} </span> 位小伙伴赞助,
|
||||
<span>
|
||||
{{ stage.title }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span> 今日赞助 </span>
|
||||
<span class="count-number color-red font-bold text-2xl ml-1 mr-1"> {{ stage.orderCount }} </span> 人,
|
||||
<span>
|
||||
{{ stage.title }}
|
||||
</span>
|
||||
</template>
|
||||
<span> 今日赞助 </span>
|
||||
<span class="count-number color-red font-bold text-2xl ml-1 mr-1"> {{ stage.orderCount }} </span>人,
|
||||
<span> {{ stage.title }} </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -120,13 +109,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, onMounted, reactive, Ref, ref } from "vue";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import dayjs from "dayjs";
|
||||
import { computed, nextTick, onMounted, onUnmounted, reactive, Ref, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouter } from "vue-router";
|
||||
import * as api from "./api";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import * as api from "./api";
|
||||
import { utils } from "/@/utils";
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
@@ -240,13 +230,12 @@ const vipTypeDefine: any = {
|
||||
},
|
||||
};
|
||||
|
||||
const TodayVipOrderCountRef: Ref = ref({ enabled: false, current: 0, stages: [] });
|
||||
const TodayVipOrderCountRef: Ref = ref({});
|
||||
|
||||
async function getTodayVipOrderCount() {
|
||||
const res = await api.getTodayVipOrderCount();
|
||||
if (res) {
|
||||
TodayVipOrderCountRef.value = res;
|
||||
TodayVipOrderCountRef.value.current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,50 +248,31 @@ const todayOrderCount = computed(() => {
|
||||
}
|
||||
const lastStage = countInfo?.stages?.[countInfo?.stages?.length - 1] || {};
|
||||
lastStage.orderCount = orderCount;
|
||||
|
||||
const stages: any = [];
|
||||
stages.push({
|
||||
title: countInfo.title,
|
||||
vipTotal: countInfo?.vipTotal || 0,
|
||||
orderCount: orderCount,
|
||||
bg: lastStage.bg,
|
||||
});
|
||||
if (lastStage.orderCount > 0) {
|
||||
stages.push(lastStage);
|
||||
}
|
||||
return {
|
||||
enabled: enabled,
|
||||
stages: stages,
|
||||
orderCount: orderCount,
|
||||
title: lastStage.title || "",
|
||||
stages: countInfo?.stages,
|
||||
};
|
||||
});
|
||||
|
||||
async function scrollOrderCount() {
|
||||
const stages = todayOrderCount.value.stages;
|
||||
if (stages.length === 0) {
|
||||
if (!stages.length) {
|
||||
return;
|
||||
}
|
||||
let index = 0;
|
||||
const doScroll = () => {
|
||||
for (const stage of stages) {
|
||||
TodayVipOrderCountRef.value.current = index;
|
||||
await utils.sleep(500);
|
||||
index++;
|
||||
if (index >= stages.length) {
|
||||
index = 0;
|
||||
}
|
||||
};
|
||||
doScroll();
|
||||
scrollOrderCountIntervalRef.value = setInterval(doScroll, 7000);
|
||||
}
|
||||
}
|
||||
|
||||
const scrollOrderCountIntervalRef: Ref = ref(null);
|
||||
onMounted(async () => {
|
||||
await getTodayVipOrderCount();
|
||||
await nextTick();
|
||||
await scrollOrderCount();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(scrollOrderCountIntervalRef.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
@@ -35,13 +35,7 @@ const menus = computed(() => [
|
||||
|
||||
const avatar = computed(() => {
|
||||
const avt = userStore.getUserInfo?.avatar;
|
||||
if (!avt) {
|
||||
return "";
|
||||
}
|
||||
if (avt.startsWith("http")) {
|
||||
return avt;
|
||||
}
|
||||
return `/api/basic/file/download?key=${avt}`;
|
||||
return avt ? `/api/basic/file/download?key=${avt}` : "";
|
||||
});
|
||||
|
||||
async function handleLogout() {
|
||||
|
||||
@@ -208,6 +208,10 @@ export default {
|
||||
orderManager: "Order Management",
|
||||
userSuites: "User Suites",
|
||||
netTest: "Network Test",
|
||||
|
||||
enterpriseSetting: "Enterprise Settings",
|
||||
projectManager: "Project Management",
|
||||
projectUserManager: "Project User Management",
|
||||
},
|
||||
certificateRepo: {
|
||||
title: "Certificate Repository",
|
||||
@@ -861,4 +865,8 @@ export default {
|
||||
select: "Select",
|
||||
placeholder: "select please",
|
||||
},
|
||||
adminMode: {
|
||||
enterpriseMode: "Enterprise Mode",
|
||||
saasMode: "SaaS Mode",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -214,6 +214,9 @@ export default {
|
||||
orderManager: "订单管理",
|
||||
userSuites: "用户套餐",
|
||||
netTest: "网络测试",
|
||||
enterpriseSetting: "企业管理设置",
|
||||
projectManager: "项目管理",
|
||||
projectUserManager: "项目用户管理",
|
||||
},
|
||||
certificateRepo: {
|
||||
title: "证书仓库",
|
||||
@@ -876,4 +879,11 @@ export default {
|
||||
select: "选择",
|
||||
placeholder: "请选择",
|
||||
},
|
||||
adminMode: {
|
||||
enterpriseMode: "企业模式",
|
||||
saasMode: "SaaS模式",
|
||||
},
|
||||
ent: {
|
||||
projectName: "项目名称",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -187,7 +187,59 @@ export const sysResources = [
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "certd.sysResources.enterpriseManager",
|
||||
name: "EnterpriseManager",
|
||||
path: "/sys/enterprise",
|
||||
redirect: "/sys/enterprise/project",
|
||||
meta: {
|
||||
icon: "ion:cart-outline",
|
||||
permission: "sys:settings:edit",
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isEnterprise;
|
||||
},
|
||||
keepAlive: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: "certd.sysResources.projectManager",
|
||||
name: "ProjectManager",
|
||||
path: "/sys/enterprise/project",
|
||||
component: "/sys/enterprise/project/index.vue",
|
||||
meta: {
|
||||
show: true,
|
||||
icon: "ion:cart",
|
||||
permission: "sys:settings:edit",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.projectMemberManager",
|
||||
name: "ProjectMemberManager",
|
||||
path: "/sys/enterprise/project/member",
|
||||
component: "/sys/enterprise/project/member/index.vue",
|
||||
meta: {
|
||||
isMenu: false,
|
||||
show: true,
|
||||
icon: "ion:cart",
|
||||
permission: "sys:settings:edit",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.enterpriseSetting",
|
||||
name: "EnterpriseSetting",
|
||||
path: "/sys/enterprise/setting",
|
||||
redirect: "/sys/settings?tab=enterprise",
|
||||
meta: {
|
||||
isMenu: true,
|
||||
show: true,
|
||||
icon: "ion:cart",
|
||||
permission: "sys:settings:edit",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.suiteManager",
|
||||
name: "SuiteManager",
|
||||
|
||||
@@ -86,6 +86,9 @@ export type SysPublicSetting = {
|
||||
>;
|
||||
// 系统通知
|
||||
notice?: string;
|
||||
|
||||
// 管理员模式
|
||||
adminMode?: "enterprise" | "saas";
|
||||
};
|
||||
export type SuiteSetting = {
|
||||
enabled?: boolean;
|
||||
|
||||
@@ -141,6 +141,9 @@ export const useSettingStore = defineStore({
|
||||
isComm(): boolean {
|
||||
return this.plusInfo?.isComm && (this.plusInfo?.expireTime === -1 || this.plusInfo?.expireTime > new Date().getTime());
|
||||
},
|
||||
isEnterprise(): boolean {
|
||||
return this.isPlus && this.sysPublic.adminMode === "enterprise";
|
||||
},
|
||||
isAgent(): boolean {
|
||||
return this.siteEnv?.agent?.enabled === true;
|
||||
},
|
||||
|
||||
@@ -476,10 +476,4 @@ h6 {
|
||||
.fs-icon{
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.hidden-important {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
<a-descriptions-item :label="t('authentication.username')">{{ userInfo.username }}</a-descriptions-item>
|
||||
<a-descriptions-item :label="t('authentication.nickName')">{{ userInfo.nickName }}</a-descriptions-item>
|
||||
<a-descriptions-item :label="t('authentication.avatar')">
|
||||
<a-avatar v-if="userInfo.avatar" size="large" :src="userAvatar" style="background-color: #eee"> </a-avatar>
|
||||
<a-avatar v-if="userInfo.avatar" size="large" :src="'api/basic/file/download?&key=' + userInfo.avatar" style="background-color: #eee"> </a-avatar>
|
||||
<a-avatar v-else size="large" style="background-color: #00b4f5">
|
||||
{{ userInfo.username }}
|
||||
</a-avatar>
|
||||
@@ -108,17 +108,6 @@ async function bind(type: string) {
|
||||
window.location.href = loginUrl;
|
||||
}
|
||||
|
||||
const userAvatar = computed(() => {
|
||||
if (isEmpty(userInfo.value.avatar)) {
|
||||
return "";
|
||||
}
|
||||
if (userInfo.value.avatar.startsWith("http")) {
|
||||
return userInfo.value.avatar;
|
||||
}
|
||||
|
||||
return "api/basic/file/download?&key=" + userInfo.value.avatar;
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await getUserInfo();
|
||||
await loadOauthBounds();
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { request } from "/src/api/service";
|
||||
|
||||
const apiPrefix = "/sys/project/provider";
|
||||
|
||||
export async function GetList(query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
|
||||
export async function AddObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
}
|
||||
|
||||
export async function UpdateObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
}
|
||||
|
||||
export async function DelObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetDetail(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/detail",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function DeleteBatch(ids: any[]) {
|
||||
return await request({
|
||||
url: apiPrefix + "/deleteByIds",
|
||||
method: "post",
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
||||
export async function SetDefault(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/setDefault",
|
||||
method: "post",
|
||||
data: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function SetDisabled(id: any, disabled: boolean) {
|
||||
return await request({
|
||||
url: apiPrefix + "/setDisabled",
|
||||
method: "post",
|
||||
data: { id, disabled },
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
import * as api from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
import { computed, Ref, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { Modal } from "ant-design-vue";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
const editRequest = async ({ form, row }: EditReq) => {
|
||||
form.id = row.id;
|
||||
const res = await api.UpdateObj(form);
|
||||
return res;
|
||||
};
|
||||
const delRequest = async ({ row }: DelReq) => {
|
||||
return await api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async ({ form }: AddReq) => {
|
||||
const res = await api.AddObj(form);
|
||||
return res;
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
const settingStore = useSettingStore();
|
||||
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||
context.selectedRowKeys = selectedRowKeys;
|
||||
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
plugins: {
|
||||
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||
rowSelection: {
|
||||
enabled: true,
|
||||
order: -2,
|
||||
before: true,
|
||||
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||
props: {
|
||||
multiple: true,
|
||||
crossPage: true,
|
||||
selectedRowKeys,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
request: {
|
||||
pageRequest,
|
||||
addRequest,
|
||||
editRequest,
|
||||
delRequest,
|
||||
},
|
||||
rowHandle: {
|
||||
minWidth: 200,
|
||||
fixed: "right",
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
title: "ID",
|
||||
key: "id",
|
||||
type: "number",
|
||||
column: {
|
||||
width: 100,
|
||||
},
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
domain: {
|
||||
title: t("certd.cnameDomain"),
|
||||
type: "text",
|
||||
editForm: {
|
||||
component: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
form: {
|
||||
component: {
|
||||
placeholder: t("certd.cnameDomainPlaceholder"),
|
||||
},
|
||||
helper: t("certd.cnameDomainHelper"),
|
||||
rules: [
|
||||
{ required: true, message: t("certd.requiredField") },
|
||||
{ pattern: /^[^*]+$/, message: t("certd.cnameDomainPattern") },
|
||||
],
|
||||
},
|
||||
column: {
|
||||
width: 200,
|
||||
},
|
||||
},
|
||||
dnsProviderType: {
|
||||
title: t("certd.dnsProvider"),
|
||||
type: "dict-select",
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
dict: dict({
|
||||
url: "pi/dnsProvider/list",
|
||||
value: "key",
|
||||
label: "title",
|
||||
}),
|
||||
form: {
|
||||
rules: [{ required: true, message: t("certd.requiredField") }],
|
||||
},
|
||||
column: {
|
||||
width: 150,
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
accessId: {
|
||||
title: t("certd.dnsProviderAuthorization"),
|
||||
type: "dict-select",
|
||||
dict: dict({
|
||||
url: "/pi/access/list",
|
||||
value: "id",
|
||||
label: "name",
|
||||
}),
|
||||
form: {
|
||||
component: {
|
||||
name: "access-selector",
|
||||
vModel: "modelValue",
|
||||
type: compute(({ form }) => {
|
||||
return form.dnsProviderType;
|
||||
}),
|
||||
},
|
||||
rules: [{ required: true, message: t("certd.requiredField") }],
|
||||
},
|
||||
column: {
|
||||
width: 150,
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
isDefault: {
|
||||
title: t("certd.isDefault"),
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: t("certd.yes"), value: true, color: "success" },
|
||||
{ label: t("certd.no"), value: false, color: "default" },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
value: false,
|
||||
rules: [{ required: true, message: t("certd.selectIsDefault") }],
|
||||
},
|
||||
column: {
|
||||
align: "center",
|
||||
width: 100,
|
||||
},
|
||||
},
|
||||
setDefault: {
|
||||
title: t("certd.setDefault"),
|
||||
type: "text",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
align: "center",
|
||||
conditionalRenderDisabled: true,
|
||||
cellRender: ({ row }) => {
|
||||
if (row.isDefault) {
|
||||
return;
|
||||
}
|
||||
const onClick = async () => {
|
||||
Modal.confirm({
|
||||
title: t("certd.prompt"),
|
||||
content: t("certd.confirmSetDefault"),
|
||||
onOk: async () => {
|
||||
await api.SetDefault(row.id);
|
||||
await crudExpose.doRefresh();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<a-button type={"link"} size={"small"} onClick={onClick}>
|
||||
{t("certd.setAsDefault")}
|
||||
</a-button>
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
title: t("certd.disabled"),
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: t("certd.enabled"), value: false, color: "success" },
|
||||
{ label: t("certd.disabledLabel"), value: true, color: "error" },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
value: false,
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
component: {
|
||||
title: t("certd.clickToToggle"),
|
||||
on: {
|
||||
async click({ value, row }) {
|
||||
Modal.confirm({
|
||||
title: t("certd.prompt"),
|
||||
content: t("certd.confirmToggleStatus", { action: !value ? t("certd.disable") : t("certd.enable") }),
|
||||
onOk: async () => {
|
||||
await api.SetDisabled(row.id, !value);
|
||||
await crudExpose.doRefresh();
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
createTime: {
|
||||
title: t("certd.createTime"),
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
width: 160,
|
||||
align: "center",
|
||||
},
|
||||
},
|
||||
updateTime: {
|
||||
title: t("certd.updateTime"),
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
show: true,
|
||||
width: 160,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<fs-page class="page-cert">
|
||||
<template #header>
|
||||
<div class="title">
|
||||
{{ t("certd.cnameTitle") }}
|
||||
<span class="sub">
|
||||
{{ t("certd.cnameDescription") }}
|
||||
<a href="https://certd.docmirror.cn/guide/feature/cname/" target="_blank">
|
||||
{{ t("certd.cnameLinkText") }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
<template #pagination-left>
|
||||
<a-tooltip :title="t('certd.batchDelete')">
|
||||
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import { DeleteBatch } from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
name: "CnameProvider",
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||
|
||||
const selectedRowKeys = context.selectedRowKeys;
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedRowKeys.value?.length > 0) {
|
||||
Modal.confirm({
|
||||
title: t("certd.confirmTitle"),
|
||||
content: t("certd.confirmDeleteBatch", { count: selectedRowKeys.value.length }),
|
||||
async onOk() {
|
||||
await DeleteBatch(selectedRowKeys.value);
|
||||
message.info(t("certd.deleteSuccess"));
|
||||
crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
},
|
||||
});
|
||||
} else {
|
||||
message.error(t("certd.selectRecordsFirst"));
|
||||
}
|
||||
};
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
onActivated(async () => {
|
||||
await crudExpose.doRefresh();
|
||||
});
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
@@ -0,0 +1,68 @@
|
||||
import { request } from "/src/api/service";
|
||||
|
||||
const apiPrefix = "/sys/enterprise/project";
|
||||
const userApiPrefix = "/sys/authority/user";
|
||||
|
||||
export async function GetList(query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
|
||||
export async function AddObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
}
|
||||
|
||||
export async function UpdateObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
}
|
||||
|
||||
export async function DelObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetDetail(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/detail",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function DeleteBatch(ids: any[]) {
|
||||
return await request({
|
||||
url: apiPrefix + "/deleteByIds",
|
||||
method: "post",
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
||||
export async function SetDisabled(id: any, disabled: boolean) {
|
||||
return await request({
|
||||
url: apiPrefix + "/setDisabled",
|
||||
method: "post",
|
||||
data: { id, disabled },
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
import * as api from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
import { computed, Ref, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { Modal } from "ant-design-vue";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
const editRequest = async ({ form, row }: EditReq) => {
|
||||
form.id = row.id;
|
||||
const res = await api.UpdateObj(form);
|
||||
return res;
|
||||
};
|
||||
const delRequest = async ({ row }: DelReq) => {
|
||||
return await api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async ({ form }: AddReq) => {
|
||||
const res = await api.AddObj(form);
|
||||
return res;
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
const settingStore = useSettingStore();
|
||||
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||
context.selectedRowKeys = selectedRowKeys;
|
||||
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
plugins: {
|
||||
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||
rowSelection: {
|
||||
enabled: true,
|
||||
order: -2,
|
||||
before: true,
|
||||
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||
props: {
|
||||
multiple: true,
|
||||
crossPage: true,
|
||||
selectedRowKeys,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
request: {
|
||||
pageRequest,
|
||||
addRequest,
|
||||
editRequest,
|
||||
delRequest,
|
||||
},
|
||||
rowHandle: {
|
||||
minWidth: 200,
|
||||
fixed: "right",
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
title: "ID",
|
||||
key: "id",
|
||||
type: "number",
|
||||
column: {
|
||||
width: 100,
|
||||
},
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
name: {
|
||||
title: t("certd.ent.projectName"),
|
||||
type: "text",
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
form: {
|
||||
component: {},
|
||||
helper: t("certd.ent.projectNameHelper"),
|
||||
rules: [{ required: true, message: t("certd.requiredField") }],
|
||||
},
|
||||
column: {
|
||||
width: 200,
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
title: t("certd.disabled"),
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: t("certd.enabled"), value: false, color: "success" },
|
||||
{ label: t("certd.disabledLabel"), value: true, color: "error" },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
value: false,
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
component: {
|
||||
title: t("certd.clickToToggle"),
|
||||
on: {
|
||||
async click({ value, row }) {
|
||||
Modal.confirm({
|
||||
title: t("certd.prompt"),
|
||||
content: t("certd.confirmToggleStatus", { action: !value ? t("certd.disable") : t("certd.enable") }),
|
||||
onOk: async () => {
|
||||
await api.SetDisabled(row.id, !value);
|
||||
await crudExpose.doRefresh();
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
createTime: {
|
||||
title: t("certd.createTime"),
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
width: 160,
|
||||
align: "center",
|
||||
},
|
||||
},
|
||||
updateTime: {
|
||||
title: t("certd.updateTime"),
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
show: true,
|
||||
width: 160,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<fs-page class="page-cert">
|
||||
<template #header>
|
||||
<div class="title">
|
||||
{{ t("certd.sysResources.projectManager") }}
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
<template #pagination-left>
|
||||
<a-tooltip :title="t('certd.batchDelete')">
|
||||
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import { DeleteBatch } from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
name: "ProjectManager",
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||
|
||||
const selectedRowKeys = context.selectedRowKeys;
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedRowKeys.value?.length > 0) {
|
||||
Modal.confirm({
|
||||
title: t("certd.confirmTitle"),
|
||||
content: t("certd.confirmDeleteBatch", { count: selectedRowKeys.value.length }),
|
||||
async onOk() {
|
||||
await DeleteBatch(selectedRowKeys.value);
|
||||
message.info(t("certd.deleteSuccess"));
|
||||
crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
},
|
||||
});
|
||||
} else {
|
||||
message.error(t("certd.selectRecordsFirst"));
|
||||
}
|
||||
};
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
onActivated(async () => {
|
||||
await crudExpose.doRefresh();
|
||||
});
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
@@ -0,0 +1,67 @@
|
||||
import { request } from "/src/api/service";
|
||||
|
||||
const apiPrefix = "/sys/enterprise/projectMember";
|
||||
const userApiPrefix = "/sys/authority/user";
|
||||
export async function GetList(query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
|
||||
export async function AddObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
}
|
||||
|
||||
export async function UpdateObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
}
|
||||
|
||||
export async function DelObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetDetail(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/detail",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function DeleteBatch(ids: any[]) {
|
||||
return await request({
|
||||
url: apiPrefix + "/deleteByIds",
|
||||
method: "post",
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetUserSimpleByIds(query: any) {
|
||||
return await request({
|
||||
url: userApiPrefix + "/getSimpleByIds",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { Modal } from "ant-design-vue";
|
||||
import { Ref, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import * as api from "./api";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useI18n } from "/src/locales";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
const editRequest = async ({ form, row }: EditReq) => {
|
||||
form.id = row.id;
|
||||
const res = await api.UpdateObj(form);
|
||||
return res;
|
||||
};
|
||||
const delRequest = async ({ row }: DelReq) => {
|
||||
return await api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async ({ form }: AddReq) => {
|
||||
const res = await api.AddObj(form);
|
||||
return res;
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
const settingStore = useSettingStore();
|
||||
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||
context.selectedRowKeys = selectedRowKeys;
|
||||
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
plugins: {
|
||||
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||
rowSelection: {
|
||||
enabled: true,
|
||||
order: -2,
|
||||
before: true,
|
||||
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||
props: {
|
||||
multiple: true,
|
||||
crossPage: true,
|
||||
selectedRowKeys,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
request: {
|
||||
pageRequest,
|
||||
addRequest,
|
||||
editRequest,
|
||||
delRequest,
|
||||
},
|
||||
rowHandle: {
|
||||
minWidth: 200,
|
||||
fixed: "right",
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
title: "ID",
|
||||
key: "id",
|
||||
type: "number",
|
||||
column: {
|
||||
width: 100,
|
||||
},
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
projectId: {
|
||||
title: "项目ID",
|
||||
type: "text",
|
||||
search: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
width: 200,
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
userId: {
|
||||
title: "用户ID",
|
||||
type: "dict-select",
|
||||
dict: dict({
|
||||
url: "/sys/authority/user/getSimpleUsers",
|
||||
value: "id",
|
||||
label: "nickName",
|
||||
labelBuilder: (item: any) => item.nickName || item.username || item.phoneCode + item.mobile,
|
||||
}),
|
||||
search: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
width: 200,
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
permission: {
|
||||
title: t("certd.ent.projectPermission"),
|
||||
type: "dict-select",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: t("certd.read"), value: "read", color: "cyan" },
|
||||
{ label: t("certd.write"), value: "write", color: "blue" },
|
||||
{ label: t("certd.admin"), value: "admin", color: "green" },
|
||||
],
|
||||
}),
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
form: {
|
||||
show: true,
|
||||
},
|
||||
column: {
|
||||
width: 200,
|
||||
},
|
||||
},
|
||||
createTime: {
|
||||
title: t("certd.createTime"),
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
width: 160,
|
||||
align: "center",
|
||||
},
|
||||
},
|
||||
updateTime: {
|
||||
title: t("certd.updateTime"),
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
show: true,
|
||||
width: 160,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<fs-page class="page-project-member">
|
||||
<template #header>
|
||||
<div class="title">
|
||||
{{ t("certd.projectMemberManager") }}
|
||||
<span class="sub">
|
||||
{{ t("certd.projectMemberDescription") }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
<template #pagination-left>
|
||||
<a-tooltip :title="t('certd.batchDelete')">
|
||||
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import { DeleteBatch } from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
name: "ProjectMemberManager",
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const projectIdStr = route.query.projectId as string;
|
||||
const projectId = Number(projectIdStr);
|
||||
|
||||
const context: any = {
|
||||
projectId,
|
||||
};
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
|
||||
|
||||
const selectedRowKeys = context.selectedRowKeys;
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedRowKeys.value?.length > 0) {
|
||||
Modal.confirm({
|
||||
title: t("certd.confirmTitle"),
|
||||
content: t("certd.confirmDeleteBatch", { count: selectedRowKeys.value.length }),
|
||||
async onOk() {
|
||||
await DeleteBatch(selectedRowKeys.value);
|
||||
message.info(t("certd.deleteSuccess"));
|
||||
crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
},
|
||||
});
|
||||
} else {
|
||||
message.error(t("certd.selectRecordsFirst"));
|
||||
}
|
||||
};
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
onActivated(async () => {
|
||||
await crudExpose.doRefresh();
|
||||
});
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
@@ -26,6 +26,9 @@
|
||||
<a-tab-pane key="pipeline" :tab="t('certd.sys.setting.pipelineSetting')">
|
||||
<SettingPipeline v-if="activeKey === 'pipeline'" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="mode" :tab="t('certd.adminMode')">
|
||||
<SettingMode v-if="activeKey === 'mode'" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</fs-page>
|
||||
@@ -39,6 +42,8 @@ import SettingSafe from "/@/views/sys/settings/tabs/safe.vue";
|
||||
import SettingCaptcha from "/@/views/sys/settings/tabs/captcha.vue";
|
||||
import SettingPipeline from "/@/views/sys/settings/tabs/pipeline.vue";
|
||||
import SettingOauth from "/@/views/sys/settings/tabs/oauth.vue";
|
||||
import SettingMode from "/@/views/sys/settings/tabs/mode.vue";
|
||||
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ref } from "vue";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
<a-select-option value="ipv4first">{{ t("certd.ipv4Priority") }}</a-select-option>
|
||||
<a-select-option value="ipv6first">{{ t("certd.ipv6Priority") }}</a-select-option>
|
||||
</a-select>
|
||||
<div class="helper">{{ t("certd.dualStackNetworkHelper") }}, <a href="https://certd.docmirror.cn/guide/use/setting/ipv6.html" target="_blank">{{ t("certd.helpDocLink") }}</a></div>
|
||||
<div class="helper">
|
||||
{{ t("certd.dualStackNetworkHelper") }}, <a href="https://certd.docmirror.cn/guide/use/setting/ipv6.html" target="_blank">{{ t("certd.helpDocLink") }}</a>
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :label="t('certd.sys.setting.showRunStrategy')" :name="['public', 'showRunStrategy']">
|
||||
@@ -68,8 +70,6 @@ import { useSettingStore } from "/@/store/settings";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { util } from "/@/utils";
|
||||
import { useI18n } from "/src/locales";
|
||||
import AddonSelector from "../../../certd/addon/addon-selector/index.vue";
|
||||
import CaptchaInput from "/@/components/captcha/captcha-input.vue";
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="sys-settings-form sys-settings-mode">
|
||||
<a-form :model="formState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish">
|
||||
<a-form-item :label="t('certd.adminMode')" :name="['public', 'adminMode']">
|
||||
<fs-dict-radio v-model:checked="formState.public.adminMode" :dict="adminModeDict" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label=" " :colon="false" :wrapper-col="{ span: 8 }">
|
||||
<a-button :loading="saveLoading" type="primary" html-type="submit">{{ t("certd.saveButton") }}</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { reactive, ref } from "vue";
|
||||
import { SysSettings } from "/@/views/sys/settings/api";
|
||||
import * as api from "/@/views/sys/settings/api";
|
||||
import { merge } from "lodash-es";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { useI18n } from "/src/locales";
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
name: "SettingMode",
|
||||
});
|
||||
|
||||
const adminModeDict = [
|
||||
{
|
||||
label: t("certd.adminMode.enterpriseMode"),
|
||||
value: "enterprise",
|
||||
},
|
||||
{
|
||||
label: t("certd.adminMode.saasMode"),
|
||||
value: "saas",
|
||||
},
|
||||
];
|
||||
|
||||
const formState = reactive<Partial<SysSettings>>({
|
||||
public: {},
|
||||
private: {},
|
||||
});
|
||||
|
||||
async function loadSysSettings() {
|
||||
const data: any = await api.SysSettingsGet();
|
||||
merge(formState, data);
|
||||
}
|
||||
|
||||
const saveLoading = ref(false);
|
||||
loadSysSettings();
|
||||
const settingsStore = useSettingStore();
|
||||
const onFinish = async (form: any) => {
|
||||
try {
|
||||
saveLoading.value = true;
|
||||
|
||||
await api.SysSettingsSave(form);
|
||||
await settingsStore.loadSysSettings();
|
||||
notification.success({
|
||||
message: t("certd.saveSuccess"),
|
||||
});
|
||||
} finally {
|
||||
saveLoading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
@@ -3,24 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* eab从更多参数中挪到外面 ([5ea4f46](https://github.com/certd/certd/commit/5ea4f46de7ae403a7a16e9488dc1d9c7523d019a))
|
||||
* 第三方登录支持Microsoft ([beb7a4c](https://github.com/certd/certd/commit/beb7a4c99277262bb9681c5594cfcd3e36c52074))
|
||||
* 优化zerossl申请证书稳定性 ([4d86fb3](https://github.com/certd/certd/commit/4d86fb319b81dbf6fa6485982105725b1b066593))
|
||||
|
||||
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复新网找错域名的bug ([bd511f9](https://github.com/certd/certd/commit/bd511f97cb7fbdcaeff7ac899f0460a5c7b41826))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* oauth支持github 和google, 修复头像显示问题 ([693a4a6](https://github.com/certd/certd/commit/693a4a663385ced3176286bf4b5f3566da83d90e))
|
||||
|
||||
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
CREATE TABLE "cd_project"
|
||||
(
|
||||
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
"user_id" integer NOT NULL,
|
||||
"name" varchar(512) NOT NULL,
|
||||
"disabled" boolean NOT NULL DEFAULT (false),
|
||||
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||
);
|
||||
|
||||
|
||||
CREATE INDEX "index_project_user_id" ON "cd_project" ("user_id");
|
||||
INSERT INTO cd_project (id, user_id, "name", "disabled") VALUES (1, 0, 'default', false);
|
||||
|
||||
|
||||
ALTER TABLE cd_cert_info ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_cert_project_id" ON "cd_cert_info" ("project_id");
|
||||
|
||||
ALTER TABLE cd_site_info ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_site_project_id" ON "cd_site_info" ("project_id");
|
||||
|
||||
ALTER TABLE cd_site_ip ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_site_ip_project_id" ON "cd_site_ip" ("project_id");
|
||||
|
||||
ALTER TABLE cd_open_key ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_open_key_project_id" ON "cd_open_key" ("project_id");
|
||||
|
||||
ALTER TABLE cd_access ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_access_project_id" ON "cd_access" ("project_id");
|
||||
|
||||
ALTER TABLE cd_addon ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_addon_project_id" ON "cd_addon" ("project_id");
|
||||
|
||||
ALTER TABLE pi_pipeline ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_pipeline_project_id" ON "cd_pipeline" ("project_id");
|
||||
|
||||
ALTER TABLE pi_pipeline_group ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_pipeline_group_project_id" ON "cd_pipeline_group" ("project_id");
|
||||
|
||||
ALTER TABLE pi_storage ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_storage_project_id" ON "cd_storage" ("project_id");
|
||||
|
||||
ALTER TABLE pi_notification ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_notification_project_id" ON "cd_notification" ("project_id");
|
||||
|
||||
ALTER TABLE pi_history ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_history_project_id" ON "cd_history" ("project_id");
|
||||
|
||||
ALTER TABLE pi_history_log ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_history_log_project_id" ON "cd_history_log" ("project_id");
|
||||
|
||||
|
||||
@@ -22,9 +22,7 @@ input:
|
||||
component:
|
||||
name: api-test
|
||||
action: TestRequest
|
||||
helper: |-
|
||||
测试前请务必先在新网后台关闭异地登录保护、关闭动态口令验证
|
||||
如果提示需要短信验证码,请等几个小时后再试
|
||||
helper: 点击测试接口是否正常
|
||||
pluginType: access
|
||||
type: builtIn
|
||||
scriptFilePath: /plugins/plugin-xinnet/access.js
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
addonType: oauth
|
||||
name: github
|
||||
title: GitHub认证
|
||||
desc: GitHub OAuth2登录
|
||||
icon: simple-icons:github
|
||||
showTest: false
|
||||
input:
|
||||
clientId:
|
||||
title: ClientId
|
||||
helper: '[GitHub Developer Settings](https://github.com/settings/developers)创建应用后获取'
|
||||
required: true
|
||||
clientSecretKey:
|
||||
title: ClientSecretKey
|
||||
component:
|
||||
placeholder: ClientSecretKey / appSecretKey
|
||||
required: true
|
||||
pluginType: addon
|
||||
type: builtIn
|
||||
scriptFilePath: /plugins/plugin-oauth/oauth2/plugin-github.js
|
||||
@@ -1,21 +0,0 @@
|
||||
addonType: oauth
|
||||
name: google
|
||||
title: Google认证
|
||||
desc: Google OAuth2登录
|
||||
icon: simple-icons:google
|
||||
showTest: false
|
||||
input:
|
||||
clientId:
|
||||
title: ClientId
|
||||
helper: >-
|
||||
[Google Cloud
|
||||
Console](https://console.cloud.google.com/apis/credentials)创建应用后获取
|
||||
required: true
|
||||
clientSecretKey:
|
||||
title: ClientSecretKey
|
||||
component:
|
||||
placeholder: ClientSecretKey / appSecretKey
|
||||
required: true
|
||||
pluginType: addon
|
||||
type: builtIn
|
||||
scriptFilePath: /plugins/plugin-oauth/oauth2/plugin-google.js
|
||||
@@ -1,26 +0,0 @@
|
||||
addonType: oauth
|
||||
name: microsoft
|
||||
title: Microsoft认证
|
||||
desc: Microsoft OAuth2登录
|
||||
icon: simple-icons:microsoft
|
||||
showTest: false
|
||||
input:
|
||||
clientId:
|
||||
title: ClientId
|
||||
helper: '[Azure Portal](https://portal.azure.com/)创建应用后获取'
|
||||
required: true
|
||||
clientSecretKey:
|
||||
title: ClientSecretKey
|
||||
component:
|
||||
placeholder: ClientSecretKey / appSecretKey
|
||||
required: true
|
||||
tenantId:
|
||||
title: TenantId
|
||||
helper: 租户ID,留空使用/common端点(需要应用配置为多租户)
|
||||
component:
|
||||
placeholder: common 或 租户ID
|
||||
value: common
|
||||
required: false
|
||||
pluginType: addon
|
||||
type: builtIn
|
||||
scriptFilePath: /plugins/plugin-oauth/oauth2/plugin-microsoft.js
|
||||
@@ -215,7 +215,7 @@ input:
|
||||
component:
|
||||
name: access-selector
|
||||
type: eab
|
||||
maybeNeed: false
|
||||
maybeNeed: true
|
||||
required: false
|
||||
helper: >-
|
||||
需要提供EAB授权
|
||||
@@ -246,7 +246,7 @@ input:
|
||||
component:
|
||||
name: access-selector
|
||||
type: google
|
||||
maybeNeed: false
|
||||
maybeNeed: true
|
||||
required: false
|
||||
helper: >-
|
||||
google服务账号授权与EAB授权选填其中一个,[服务账号授权获取方法](https://certd.docmirror.cn/guide/use/google/)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-server",
|
||||
"version": "1.38.7",
|
||||
"version": "1.38.5",
|
||||
"description": "fast-server base midway",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -48,20 +48,20 @@
|
||||
"@aws-sdk/client-iam": "^3.964.0",
|
||||
"@aws-sdk/client-route-53": "^3.964.0",
|
||||
"@aws-sdk/client-s3": "^3.964.0",
|
||||
"@certd/acme-client": "^1.38.7",
|
||||
"@certd/basic": "^1.38.7",
|
||||
"@certd/commercial-core": "^1.38.7",
|
||||
"@certd/acme-client": "^1.38.5",
|
||||
"@certd/basic": "^1.38.5",
|
||||
"@certd/commercial-core": "^1.38.5",
|
||||
"@certd/cv4pve-api-javascript": "^8.4.2",
|
||||
"@certd/jdcloud": "^1.38.7",
|
||||
"@certd/lib-huawei": "^1.38.7",
|
||||
"@certd/lib-k8s": "^1.38.7",
|
||||
"@certd/lib-server": "^1.38.7",
|
||||
"@certd/midway-flyway-js": "^1.38.7",
|
||||
"@certd/pipeline": "^1.38.7",
|
||||
"@certd/plugin-cert": "^1.38.7",
|
||||
"@certd/plugin-lib": "^1.38.7",
|
||||
"@certd/plugin-plus": "^1.38.7",
|
||||
"@certd/plus-core": "^1.38.7",
|
||||
"@certd/jdcloud": "^1.38.5",
|
||||
"@certd/lib-huawei": "^1.38.5",
|
||||
"@certd/lib-k8s": "^1.38.5",
|
||||
"@certd/lib-server": "^1.38.5",
|
||||
"@certd/midway-flyway-js": "^1.38.5",
|
||||
"@certd/pipeline": "^1.38.5",
|
||||
"@certd/plugin-cert": "^1.38.5",
|
||||
"@certd/plugin-lib": "^1.38.5",
|
||||
"@certd/plugin-plus": "^1.38.5",
|
||||
"@certd/plus-core": "^1.38.5",
|
||||
"@google-cloud/publicca": "^1.3.0",
|
||||
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185",
|
||||
"@huaweicloud/huaweicloud-sdk-core": "^3.1.185",
|
||||
|
||||
@@ -28,7 +28,7 @@ export class UserController extends CrudController<UserService> {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/getSimpleUserByIds', {summary: 'sys:auth:user:add'})
|
||||
@Post('/getSimpleUserByIds', {summary: 'sys:auth:user:view'})
|
||||
async getSimpleUserByIds(@Body('ids') ids: number[]) {
|
||||
const users = await this.service.find({
|
||||
select: {
|
||||
@@ -46,6 +46,21 @@ export class UserController extends CrudController<UserService> {
|
||||
return this.ok(users);
|
||||
}
|
||||
|
||||
|
||||
@Post('/getSimpleUsers', {summary: 'sys:auth:user:view'})
|
||||
async getSimpleUsers() {
|
||||
const users = await this.service.find({
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
nickName: true,
|
||||
mobile: true,
|
||||
phoneCode: true,
|
||||
},
|
||||
});
|
||||
return this.ok(users);
|
||||
}
|
||||
|
||||
@Post('/page', {summary: 'sys:auth:user:view'})
|
||||
async page(
|
||||
@Body(ALL)
|
||||
@@ -153,4 +168,6 @@ export class UserController extends CrudController<UserService> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { CrudController, SysSettingsService } from "@certd/lib-server";
|
||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core";
|
||||
import { ProjectService } from "../../../modules/sys/enterprise/service/project-service.js";
|
||||
import { ProjectEntity } from "../../../modules/sys/enterprise/entity/project.js";
|
||||
import { merge } from "lodash-es";
|
||||
|
||||
/**
|
||||
*/
|
||||
@Provide()
|
||||
@Controller("/api/sys/enterprise/project")
|
||||
export class SysProjectController extends CrudController<ProjectEntity> {
|
||||
@Inject()
|
||||
service: ProjectService;
|
||||
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
||||
getService<T>() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post("/page", { summary: "sys:settings:view" })
|
||||
async page(@Body(ALL) body: any) {
|
||||
body.query = body.query ?? {};
|
||||
return await super.page(body);
|
||||
}
|
||||
|
||||
@Post("/list", { summary: "sys:settings:view" })
|
||||
async list(@Body(ALL) body: any) {
|
||||
return super.list(body);
|
||||
}
|
||||
|
||||
@Post("/add", { summary: "sys:settings:edit" })
|
||||
async add(@Body(ALL) bean: any) {
|
||||
const def: any = {
|
||||
isDefault: false,
|
||||
disabled: false,
|
||||
};
|
||||
merge(bean, def);
|
||||
bean.userId = this.getUserId();
|
||||
return super.add(bean);
|
||||
}
|
||||
|
||||
@Post("/update", { summary: "sys:settings:edit" })
|
||||
async update(@Body(ALL) bean: any) {
|
||||
bean.userId = this.getUserId();
|
||||
return super.update(bean);
|
||||
}
|
||||
|
||||
@Post("/info", { summary: "sys:settings:view" })
|
||||
async info(@Query("id") id: number) {
|
||||
return super.info(id);
|
||||
}
|
||||
|
||||
@Post("/delete", { summary: "sys:settings:edit" })
|
||||
async delete(@Query("id") id: number) {
|
||||
return super.delete(id);
|
||||
}
|
||||
|
||||
@Post("/deleteByIds", { summary: "sys:settings:edit" })
|
||||
async deleteByIds(@Body("ids") ids: number[]) {
|
||||
const res = await this.service.delete(ids);
|
||||
return this.ok(res);
|
||||
}
|
||||
@Post("/setDisabled", { summary: "sys:settings:edit" })
|
||||
async setDisabled(@Body("id") id: number, @Body("disabled") disabled: boolean) {
|
||||
await this.service.setDisabled(id, disabled);
|
||||
return this.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { CrudController, SysSettingsService } from "@certd/lib-server";
|
||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core";
|
||||
import { ProjectMemberEntity } from "../../../modules/sys/enterprise/entity/project-member.js";
|
||||
import { ProjectMemberService } from "../../../modules/sys/enterprise/service/project-member-service.js";
|
||||
import { merge } from "lodash-es";
|
||||
|
||||
/**
|
||||
*/
|
||||
@Provide()
|
||||
@Controller("/api/sys/enterprise/projectMember")
|
||||
export class SysProjectMemberController extends CrudController<ProjectMemberEntity> {
|
||||
@Inject()
|
||||
service: ProjectMemberService;
|
||||
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
||||
getService<T>() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post("/page", { summary: "sys:settings:view" })
|
||||
async page(@Body(ALL) body: any) {
|
||||
body.query = body.query ?? {};
|
||||
return await super.page(body);
|
||||
}
|
||||
|
||||
@Post("/list", { summary: "sys:settings:view" })
|
||||
async list(@Body(ALL) body: any) {
|
||||
return super.list(body);
|
||||
}
|
||||
|
||||
@Post("/add", { summary: "sys:settings:edit" })
|
||||
async add(@Body(ALL) bean: any) {
|
||||
const def: any = {
|
||||
isDefault: false,
|
||||
disabled: false,
|
||||
};
|
||||
merge(bean, def);
|
||||
bean.userId = this.getUserId();
|
||||
return super.add(bean);
|
||||
}
|
||||
|
||||
@Post("/update", { summary: "sys:settings:edit" })
|
||||
async update(@Body(ALL) bean: any) {
|
||||
bean.userId = this.getUserId();
|
||||
return super.update(bean);
|
||||
}
|
||||
|
||||
@Post("/info", { summary: "sys:settings:view" })
|
||||
async info(@Query("id") id: number) {
|
||||
return super.info(id);
|
||||
}
|
||||
|
||||
@Post("/delete", { summary: "sys:settings:edit" })
|
||||
async delete(@Query("id") id: number) {
|
||||
return super.delete(id);
|
||||
}
|
||||
|
||||
@Post("/deleteByIds", { summary: "sys:settings:edit" })
|
||||
async deleteByIds(@Body("ids") ids: number[]) {
|
||||
const res = await this.service.delete(ids);
|
||||
return this.ok(res);
|
||||
}
|
||||
}
|
||||
@@ -84,9 +84,5 @@ export function startProxyServer(opts:{port:number}) {
|
||||
logger.info(`[proxy] 正向代理服务器运行在 http://0.0.0.0:${port}`);
|
||||
});
|
||||
|
||||
proxyServer.close(() => {
|
||||
logger.info('[proxy] 正向代理服务器已关闭');
|
||||
});
|
||||
|
||||
return proxyServer
|
||||
}
|
||||
@@ -42,6 +42,9 @@ export class CertInfoEntity {
|
||||
@Column({ name: 'cert_file', comment: '证书下载' })
|
||||
certFile: string;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -71,6 +71,9 @@ export class SiteInfoEntity {
|
||||
@Column({ name: 'group_id', comment: '分组id' })
|
||||
groupId: number;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' })
|
||||
createTime: Date;
|
||||
@Column({ name: 'update_time', comment: '修改时间', default: () => 'CURRENT_TIMESTAMP' })
|
||||
|
||||
@@ -33,6 +33,8 @@ export class SiteIpEntity {
|
||||
remark: string;
|
||||
@Column({ name: "disabled", comment: "禁用启用" })
|
||||
disabled: boolean;
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' })
|
||||
createTime: Date;
|
||||
|
||||
@@ -17,6 +17,9 @@ export class OpenKeyEntity {
|
||||
@Column({ name: 'scope', comment: '权限范围' })
|
||||
scope: string; // open 仅开放接口、 user 用户所有权限
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' })
|
||||
createTime: Date;
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ export class HistoryLogEntity {
|
||||
@Column({ comment: '日志内容', length: 40960, nullable: true })
|
||||
logs: string;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -26,6 +26,9 @@ export class HistoryEntity {
|
||||
})
|
||||
endTime: Date;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
@@ -38,6 +41,7 @@ export class HistoryEntity {
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
|
||||
|
||||
pipelineTitle: string;
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ export class NotificationEntity {
|
||||
@Column({ name: 'is_default', comment: '是否默认' })
|
||||
isDefault: boolean;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -17,6 +17,9 @@ export class PipelineGroupEntity {
|
||||
@Column({ name: 'favorite', comment: '收藏' })
|
||||
favorite: boolean;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -61,6 +61,9 @@ export class PipelineEntity {
|
||||
@Column({name: 'order', comment: '排序', nullable: true,})
|
||||
order: number;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({name: 'create_time',comment: '创建时间', default: () => 'CURRENT_TIMESTAMP',})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
|
||||
@@ -23,6 +23,9 @@ export class StorageEntity {
|
||||
@Column({ comment: 'value', length: 40960, nullable: true })
|
||||
value: string;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -39,6 +39,9 @@ export class TemplateEntity {
|
||||
})
|
||||
order: number;
|
||||
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -113,9 +113,6 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
|
||||
async add(bean: PipelineEntity) {
|
||||
bean.status = ResultType.none;
|
||||
if (bean.order == null) {
|
||||
bean.order = 0;
|
||||
}
|
||||
await this.save(bean);
|
||||
return bean;
|
||||
}
|
||||
@@ -246,9 +243,6 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
if (!bean.status) {
|
||||
bean.status = ResultType.none;
|
||||
}
|
||||
if (bean.order == null) {
|
||||
bean.order = 0;
|
||||
}
|
||||
if (!isUpdate) {
|
||||
//如果是添加,先保存一下,获取到id,更新pipeline.id
|
||||
await this.addOrUpdate(bean);
|
||||
|
||||
@@ -54,7 +54,6 @@ export class SubDomainService extends BaseService<SubDomainEntity> {
|
||||
throw new Error('域名已存在');
|
||||
}
|
||||
return await super.add(bean)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
*/
|
||||
@Entity('cd_audit_log')
|
||||
export class AuditLogEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id', comment: 'UserId' })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: 'user_name', comment: '用户名' })
|
||||
userName: string;
|
||||
|
||||
@Column({ name: 'project_id', comment: 'ProjectId' })
|
||||
projectId: number;
|
||||
|
||||
@Column({ name: 'project_name', comment: '项目名称' })
|
||||
projectName: string;
|
||||
|
||||
@Column({ name: 'action', comment: '操作' })
|
||||
action: string;
|
||||
|
||||
@Column({ name: 'content', comment: '内容' })
|
||||
content: string;
|
||||
|
||||
@Column({ name: 'ip_address', comment: 'IP地址' })
|
||||
ipAddress: string;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
*/
|
||||
@Entity('cd_project_member')
|
||||
export class ProjectMemberEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id', comment: 'UserId' })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: 'project_id', comment: 'ProjectId' })
|
||||
projectId: number;
|
||||
|
||||
@Column({ name: 'permission', comment: '权限' })
|
||||
permission: string; // read / write / admin
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
*/
|
||||
@Entity('cd_project')
|
||||
export class ProjectEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id', comment: 'UserId' })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: 'name', comment: '项目名称' })
|
||||
name: string;
|
||||
|
||||
@Column({ name: 'disabled', comment: '禁用' })
|
||||
disabled: boolean;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core';
|
||||
import {BaseService, SysSettingsService} from '@certd/lib-server';
|
||||
import {InjectEntityModel} from '@midwayjs/typeorm';
|
||||
import {Repository} from 'typeorm';
|
||||
import { ProjectMemberEntity } from '../entity/project-member.js';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class ProjectMemberService extends BaseService<ProjectMemberEntity> {
|
||||
@InjectEntityModel(ProjectMemberEntity)
|
||||
repository: Repository<ProjectMemberEntity>;
|
||||
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async add(bean: ProjectMemberEntity) {
|
||||
const {projectId, userId} = bean;
|
||||
if (!projectId) {
|
||||
throw new Error('项目ID不能为空');
|
||||
}
|
||||
if (!userId) {
|
||||
throw new Error('用户ID不能为空');
|
||||
}
|
||||
const exist = await this.repository.findOne({
|
||||
where: {
|
||||
projectId,
|
||||
userId,
|
||||
},
|
||||
});
|
||||
if (exist) {
|
||||
throw new Error('项目用户已存在');
|
||||
}
|
||||
return await super.add(bean)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core';
|
||||
import {BaseService, SysSettingsService} from '@certd/lib-server';
|
||||
import {InjectEntityModel} from '@midwayjs/typeorm';
|
||||
import {Repository} from 'typeorm';
|
||||
import { ProjectEntity } from '../entity/project.js';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class ProjectService extends BaseService<ProjectEntity> {
|
||||
@InjectEntityModel(ProjectEntity)
|
||||
repository: Repository<ProjectEntity>;
|
||||
|
||||
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async add(bean: ProjectEntity) {
|
||||
const {name} = bean;
|
||||
if (!name) {
|
||||
throw new Error('项目名称不能为空');
|
||||
}
|
||||
const exist = await this.repository.findOne({
|
||||
where: {
|
||||
name,
|
||||
userId:0,
|
||||
},
|
||||
});
|
||||
if (exist) {
|
||||
throw new Error('项目名称已存在');
|
||||
}
|
||||
bean.userId = 0
|
||||
bean.disabled = false
|
||||
return await super.add(bean)
|
||||
}
|
||||
|
||||
async setDisabled(id: number, disabled: boolean) {
|
||||
const project = await this.repository.findOne({
|
||||
where: {
|
||||
id,
|
||||
userId:0,
|
||||
},
|
||||
});
|
||||
if (!project) {
|
||||
throw new Error('项目不存在');
|
||||
}
|
||||
await this.repository.update({
|
||||
userId:0,
|
||||
}, {
|
||||
disabled,
|
||||
});
|
||||
project.disabled = disabled;
|
||||
await this.repository.save(project);
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ export class AcmeService {
|
||||
externalAccountBinding: this.eab,
|
||||
backoffAttempts: this.options.maxCheckRetryCount || 20,
|
||||
backoffMin: 5000,
|
||||
backoffMax: 1000*1000,
|
||||
backoffMax: 10000,
|
||||
urlMapping,
|
||||
signal: this.options.signal,
|
||||
logger: this.logger,
|
||||
|
||||
@@ -264,7 +264,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
name: "access-selector",
|
||||
type: "eab",
|
||||
},
|
||||
maybeNeed: false,
|
||||
maybeNeed: true,
|
||||
required: false,
|
||||
helper:
|
||||
"需要提供EAB授权" +
|
||||
@@ -291,7 +291,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
name: "access-selector",
|
||||
type: "google",
|
||||
},
|
||||
maybeNeed: false,
|
||||
maybeNeed: true,
|
||||
required: false,
|
||||
helper: "google服务账号授权与EAB授权选填其中一个,[服务账号授权获取方法](https://certd.docmirror.cn/guide/use/google/)\n服务账号授权需要配置代理或者服务器本身在海外",
|
||||
mergeScript: `
|
||||
|
||||
@@ -2,7 +2,4 @@ export * from './api.js'
|
||||
export * from './oidc/plugin-oidc.js'
|
||||
export * from './wx/plugin-wx.js'
|
||||
export * from './oauth2/plugin-gitee.js'
|
||||
export * from './oauth2/plugin-clogin.js'
|
||||
export * from './oauth2/plugin-github.js'
|
||||
export * from './oauth2/plugin-google.js'
|
||||
export * from './oauth2/plugin-microsoft.js'
|
||||
export * from './oauth2/plugin-clogin.js'
|
||||
@@ -1,103 +0,0 @@
|
||||
import { AddonInput, BaseAddon, IsAddon } from "@certd/lib-server";
|
||||
import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } from "../api.js";
|
||||
|
||||
@IsAddon({
|
||||
addonType: "oauth",
|
||||
name: 'github',
|
||||
title: 'GitHub认证',
|
||||
desc: 'GitHub OAuth2登录',
|
||||
icon:"simple-icons:github",
|
||||
showTest: false,
|
||||
})
|
||||
export class GithubOauthProvider extends BaseAddon implements IOauthProvider {
|
||||
|
||||
@AddonInput({
|
||||
title: "ClientId",
|
||||
helper: "[GitHub Developer Settings](https://github.com/settings/developers)创建应用后获取",
|
||||
required: true,
|
||||
})
|
||||
clientId = "";
|
||||
|
||||
@AddonInput({
|
||||
title: "ClientSecretKey",
|
||||
component: {
|
||||
placeholder: "ClientSecretKey / appSecretKey",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
clientSecretKey = "";
|
||||
|
||||
async buildLoginUrl(params: BuildLoginUrlReq) {
|
||||
|
||||
let scope = "user:email" // Scope of the access request
|
||||
let state:any = {
|
||||
forType: params.forType || 'login',
|
||||
}
|
||||
state = this.ctx.utils.hash.base64(JSON.stringify(state))
|
||||
|
||||
const authorizeEndpoint = "https://github.com/login/oauth/authorize"
|
||||
const redirectUrl = encodeURIComponent(params.redirectUri)
|
||||
const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}`
|
||||
return {
|
||||
loginUrl,
|
||||
ticketValue: {
|
||||
state,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async onCallback(req: OnCallbackReq) {
|
||||
|
||||
const code = req.code || ""
|
||||
|
||||
const tokenEndpoint = "https://github.com/login/oauth/access_token"
|
||||
|
||||
const uri = new URL(req.currentURL)
|
||||
const redirectUri = `${uri.origin}${uri.pathname}`
|
||||
const res = await this.ctx.utils.http.request( {
|
||||
url: tokenEndpoint,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Accept": "application/json"
|
||||
},
|
||||
data:{
|
||||
client_id: this.clientId,
|
||||
client_secret: this.clientSecretKey,
|
||||
code,
|
||||
redirect_uri: redirectUri
|
||||
}
|
||||
})
|
||||
|
||||
const tokens = res
|
||||
|
||||
const userInfoEndpoint = "https://api.github.com/user"
|
||||
|
||||
// 获取用户信息
|
||||
const userInfoRes = await this.ctx.utils.http.request( {
|
||||
url: userInfoEndpoint,
|
||||
method: "get",
|
||||
headers: {
|
||||
"Authorization": `Bearer ${tokens.access_token}`,
|
||||
"Accept": "application/json"
|
||||
}
|
||||
})
|
||||
const userInfo = userInfoRes
|
||||
|
||||
return {
|
||||
token:{
|
||||
accessToken: tokens.access_token,
|
||||
refreshToken: tokens.refresh_token,
|
||||
expiresIn: tokens.expires_in,
|
||||
},
|
||||
userInfo: {
|
||||
openId: userInfo.id,
|
||||
nickName: userInfo.login || userInfo.name || "",
|
||||
avatar: userInfo.avatar_url,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
async buildLogoutUrl(params: BuildLogoutUrlReq) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
import { AddonInput, BaseAddon, IsAddon } from "@certd/lib-server";
|
||||
import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } from "../api.js";
|
||||
|
||||
@IsAddon({
|
||||
addonType: "oauth",
|
||||
name: 'google',
|
||||
title: 'Google认证',
|
||||
desc: 'Google OAuth2登录',
|
||||
icon:"simple-icons:google",
|
||||
showTest: false,
|
||||
})
|
||||
export class GoogleOauthProvider extends BaseAddon implements IOauthProvider {
|
||||
|
||||
@AddonInput({
|
||||
title: "ClientId",
|
||||
helper: "[Google Cloud Console](https://console.cloud.google.com/apis/credentials)创建应用后获取",
|
||||
required: true,
|
||||
})
|
||||
clientId = "";
|
||||
|
||||
@AddonInput({
|
||||
title: "ClientSecretKey",
|
||||
component: {
|
||||
placeholder: "ClientSecretKey / appSecretKey",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
clientSecretKey = "";
|
||||
|
||||
async buildLoginUrl(params: BuildLoginUrlReq) {
|
||||
|
||||
let scope = "email profile" // Scope of the access request
|
||||
let state:any = {
|
||||
forType: params.forType || 'login',
|
||||
}
|
||||
state = this.ctx.utils.hash.base64(JSON.stringify(state))
|
||||
|
||||
const authorizeEndpoint = "https://accounts.google.com/o/oauth2/auth"
|
||||
const redirectUrl = encodeURIComponent(params.redirectUri)
|
||||
const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}`
|
||||
return {
|
||||
loginUrl,
|
||||
ticketValue: {
|
||||
state,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async onCallback(req: OnCallbackReq) {
|
||||
|
||||
const code = req.code || ""
|
||||
|
||||
const tokenEndpoint = "https://oauth2.googleapis.com/token"
|
||||
|
||||
const uri = new URL(req.currentURL)
|
||||
const redirectUri = `${uri.origin}${uri.pathname}`
|
||||
const res = await this.ctx.utils.http.request( {
|
||||
url: tokenEndpoint,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
data:{
|
||||
client_id: this.clientId,
|
||||
client_secret: this.clientSecretKey,
|
||||
code,
|
||||
redirect_uri: redirectUri,
|
||||
grant_type: "authorization_code"
|
||||
}
|
||||
})
|
||||
|
||||
const tokens = res
|
||||
|
||||
const userInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo"
|
||||
|
||||
// 获取用户信息
|
||||
const userInfoRes = await this.ctx.utils.http.request( {
|
||||
url: userInfoEndpoint,
|
||||
method: "get",
|
||||
headers: {
|
||||
"Authorization": `Bearer ${tokens.access_token}`
|
||||
}
|
||||
})
|
||||
const userInfo = userInfoRes
|
||||
|
||||
return {
|
||||
token:{
|
||||
accessToken: tokens.access_token,
|
||||
refreshToken: tokens.refresh_token,
|
||||
expiresIn: tokens.expires_in,
|
||||
},
|
||||
userInfo: {
|
||||
openId: userInfo.sub,
|
||||
nickName: userInfo.name || userInfo.email || "",
|
||||
avatar: userInfo.picture,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
async buildLogoutUrl(params: BuildLogoutUrlReq) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
import { AddonInput, BaseAddon, IsAddon } from "@certd/lib-server";
|
||||
import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } from "../api.js";
|
||||
|
||||
@IsAddon({
|
||||
addonType: "oauth",
|
||||
name: 'microsoft',
|
||||
title: 'Microsoft认证',
|
||||
desc: 'Microsoft OAuth2登录',
|
||||
icon:"simple-icons:microsoft",
|
||||
showTest: false,
|
||||
})
|
||||
export class MicrosoftOauthProvider extends BaseAddon implements IOauthProvider {
|
||||
|
||||
@AddonInput({
|
||||
title: "ClientId",
|
||||
helper: "[Azure Portal](https://portal.azure.com/)创建应用后获取",
|
||||
required: true,
|
||||
})
|
||||
clientId = "";
|
||||
|
||||
@AddonInput({
|
||||
title: "ClientSecretKey",
|
||||
component: {
|
||||
placeholder: "ClientSecretKey / appSecretKey",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
clientSecretKey = "";
|
||||
|
||||
@AddonInput({
|
||||
title: "TenantId",
|
||||
helper: "租户ID,留空使用/common端点(需要应用配置为多租户)",
|
||||
component: {
|
||||
placeholder: "common 或 租户ID",
|
||||
},
|
||||
value: "common",
|
||||
required: false,
|
||||
})
|
||||
tenantId = "common";
|
||||
|
||||
async buildLoginUrl(params: BuildLoginUrlReq) {
|
||||
|
||||
let scope = "openid profile email User.Read" // Scope of the access request
|
||||
let state:any = {
|
||||
forType: params.forType || 'login',
|
||||
}
|
||||
state = this.ctx.utils.hash.base64(JSON.stringify(state))
|
||||
|
||||
const authorizeEndpoint = `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/authorize`
|
||||
const redirectUrl = encodeURIComponent(params.redirectUri)
|
||||
const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}`
|
||||
return {
|
||||
loginUrl,
|
||||
ticketValue: {
|
||||
state,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async onCallback(req: OnCallbackReq) {
|
||||
|
||||
const code = req.code || ""
|
||||
if (!code) {
|
||||
throw new Error("Missing code parameter");
|
||||
}
|
||||
|
||||
const tokenEndpoint = `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/token`
|
||||
|
||||
const uri = new URL(req.currentURL)
|
||||
const redirectUri = `${uri.origin}${uri.pathname}`
|
||||
|
||||
// 构建 form-urlencoded 格式的数据
|
||||
const formData = new URLSearchParams();
|
||||
formData.append('client_id', this.clientId);
|
||||
formData.append('client_secret', this.clientSecretKey);
|
||||
formData.append('code', code);
|
||||
formData.append('redirect_uri', redirectUri);
|
||||
formData.append('grant_type', 'authorization_code');
|
||||
|
||||
const res = await this.ctx.utils.http.request( {
|
||||
url: tokenEndpoint,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Accept": "application/json"
|
||||
},
|
||||
data: formData.toString()
|
||||
})
|
||||
|
||||
const tokens = res
|
||||
|
||||
const userInfoEndpoint = "https://graph.microsoft.com/v1.0/me"
|
||||
|
||||
// 获取用户信息
|
||||
const userInfoRes = await this.ctx.utils.http.request( {
|
||||
url: userInfoEndpoint,
|
||||
method: "get",
|
||||
headers: {
|
||||
"Authorization": `Bearer ${tokens.access_token}`,
|
||||
"Accept": "application/json"
|
||||
}
|
||||
})
|
||||
const userInfo = userInfoRes
|
||||
|
||||
return {
|
||||
token:{
|
||||
accessToken: tokens.access_token,
|
||||
refreshToken: tokens.refresh_token,
|
||||
expiresIn: tokens.expires_in,
|
||||
},
|
||||
userInfo: {
|
||||
openId: userInfo.id,
|
||||
nickName: userInfo.displayName || userInfo.userPrincipalName || "",
|
||||
avatar: userInfo.avatar || "",
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
async buildLogoutUrl(params: BuildLogoutUrlReq) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
01:18
|
||||
00:04
|
||||
|
||||
@@ -1 +1 @@
|
||||
16
|
||||
11
|
||||
|
||||
@@ -1 +1 @@
|
||||
01:33
|
||||
00:18
|
||||
|
||||
Reference in New Issue
Block a user