This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package accounts
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *CreatePopupAction) RunGet(params struct {
ProviderCode string
}) {
this.Data["providerCode"] = params.ProviderCode
// 服务商列表
providersResp, err := this.RPC().ACMEProviderRPC().FindAllACMEProviders(this.AdminContext(), &pb.FindAllACMEProvidersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var providerMaps = []maps.Map{}
for _, provider := range providersResp.AcmeProviders {
providerMaps = append(providerMaps, maps.Map{
"name": provider.Name,
"code": provider.Code,
"description": provider.Description,
"requireEAB": provider.RequireEAB,
"eabDescription": provider.EabDescription,
})
}
this.Data["providers"] = providerMaps
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
Name string
ProviderCode string
EabKid string
EabKey string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var accountId int64
defer func() {
this.CreateLogInfo(codes.ACMEProviderAccount_LogCreateACMEProviderAccount, accountId)
}()
params.Must.
Field("name", params.Name).
Require("请输入账号名称").
Field("providerCode", params.ProviderCode).
Require("请选择服务商")
providerResp, err := this.RPC().ACMEProviderRPC().FindACMEProviderWithCode(this.AdminContext(), &pb.FindACMEProviderWithCodeRequest{AcmeProviderCode: params.ProviderCode})
if err != nil {
this.ErrorPage(err)
return
}
var provider = providerResp.AcmeProvider
if provider == nil {
this.Fail("请选择服务商")
}
if provider.RequireEAB {
params.Must.
Field("eabKid", params.EabKid).
Require("请输入EAB Kid").
Field("eabKey", params.EabKey).
Require("请输入EAB HMAC Key")
}
createResp, err := this.RPC().ACMEProviderAccountRPC().CreateACMEProviderAccount(this.AdminContext(), &pb.CreateACMEProviderAccountRequest{
Name: params.Name,
ProviderCode: params.ProviderCode,
EabKid: params.EabKid,
EabKey: params.EabKey,
})
if err != nil {
this.ErrorPage(err)
return
}
accountId = createResp.AcmeProviderAccountId
this.Success()
}

View File

@@ -0,0 +1,27 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package accounts
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
AccountId int64
}) {
defer this.CreateLogInfo(codes.ACMEProviderAccount_LogDeleteACMEProviderAccount, params.AccountId)
_, err := this.RPC().ACMEProviderAccountRPC().DeleteACMEProviderAccount(this.AdminContext(), &pb.DeleteACMEProviderAccountRequest{AcmeProviderAccountId: params.AccountId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,61 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package accounts
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "account")
}
func (this *IndexAction) RunGet(params struct{}) {
countResp, err := this.RPC().ACMEProviderAccountRPC().CountAllEnabledACMEProviderAccounts(this.AdminContext(), &pb.CountAllEnabledACMEProviderAccountsRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var count = countResp.Count
var page = this.NewPage(count)
this.Data["page"] = page.AsHTML()
accountsResp, err := this.RPC().ACMEProviderAccountRPC().ListEnabledACMEProviderAccounts(this.AdminContext(), &pb.ListEnabledACMEProviderAccountsRequest{
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
var accountMaps = []maps.Map{}
for _, account := range accountsResp.AcmeProviderAccounts {
var providerMap maps.Map
if account.AcmeProvider != nil {
providerMap = maps.Map{
"name": account.AcmeProvider.Name,
"code": account.AcmeProvider.Code,
"requireEAB": account.AcmeProvider.RequireEAB,
}
}
accountMaps = append(accountMaps, maps.Map{
"id": account.Id,
"isOn": account.IsOn,
"name": account.Name,
"eabKid": account.EabKid,
"eabKey": account.EabKey,
"provider": providerMap,
})
}
this.Data["accounts"] = accountMaps
this.Show()
}

View File

@@ -0,0 +1,109 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package accounts
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
AccountId int64
}) {
// 账号信息
accountResp, err := this.RPC().ACMEProviderAccountRPC().FindEnabledACMEProviderAccount(this.AdminContext(), &pb.FindEnabledACMEProviderAccountRequest{AcmeProviderAccountId: params.AccountId})
if err != nil {
this.ErrorPage(err)
return
}
var account = accountResp.AcmeProviderAccount
if account == nil {
this.NotFound("ACMEProviderAccount", params.AccountId)
return
}
var providerMap maps.Map
if account.AcmeProvider != nil {
providerMap = maps.Map{
"name": account.AcmeProvider.Name,
"code": account.AcmeProvider.Code,
"description": account.AcmeProvider.Description,
"eabDescription": account.AcmeProvider.EabDescription,
"requireEAB": account.AcmeProvider.RequireEAB,
}
}
this.Data["account"] = maps.Map{
"id": account.Id,
"name": account.Name,
"isOn": account.IsOn,
"providerCode": account.ProviderCode,
"eabKid": account.EabKid,
"eabKey": account.EabKey,
"provider": providerMap,
}
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
AccountId int64
Name string
ProviderCode string
EabKid string
EabKey string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.ACMEProviderAccount_LogUpdateACMEProviderAccount, params.AccountId)
params.Must.
Field("name", params.Name).
Require("请输入账号名称").
Field("providerCode", params.ProviderCode).
Require("请选择服务商")
providerResp, err := this.RPC().ACMEProviderRPC().FindACMEProviderWithCode(this.AdminContext(), &pb.FindACMEProviderWithCodeRequest{AcmeProviderCode: params.ProviderCode})
if err != nil {
this.ErrorPage(err)
return
}
var provider = providerResp.AcmeProvider
if provider == nil {
this.Fail("请选择服务商")
}
if provider.RequireEAB {
params.Must.
Field("eabKid", params.EabKid).
Require("请输入EAB Kid").
Field("eabKey", params.EabKey).
Require("请输入EAB HMAC Key")
}
_, err = this.RPC().ACMEProviderAccountRPC().UpdateACMEProviderAccount(this.AdminContext(), &pb.UpdateACMEProviderAccountRequest{
AcmeProviderAccountId: params.AccountId,
Name: params.Name,
EabKid: params.EabKid,
EabKey: params.EabKey,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,150 @@
package acme
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"strings"
)
type CreateAction struct {
actionutils.ParentAction
}
func (this *CreateAction) Init() {
this.Nav("", "", "create")
}
func (this *CreateAction) RunGet(params struct{}) {
// 证书服务商
providersResp, err := this.RPC().ACMEProviderRPC().FindAllACMEProviders(this.AdminContext(), &pb.FindAllACMEProvidersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var providerMaps = []maps.Map{}
for _, provider := range providersResp.AcmeProviders {
providerMaps = append(providerMaps, maps.Map{
"name": provider.Name,
"code": provider.Code,
})
}
this.Data["providers"] = providerMaps
// 域名解析服务商
dnsProvidersResp, err := this.RPC().DNSProviderRPC().FindAllEnabledDNSProviders(this.AdminContext(), &pb.FindAllEnabledDNSProvidersRequest{
AdminId: this.AdminId(),
UserId: 0,
})
if err != nil {
this.ErrorPage(err)
return
}
dnsProviderMaps := []maps.Map{}
for _, provider := range dnsProvidersResp.DnsProviders {
dnsProviderMaps = append(dnsProviderMaps, maps.Map{
"id": provider.Id,
"name": provider.Name,
"typeName": provider.TypeName,
})
}
this.Data["dnsProviders"] = dnsProviderMaps
this.Show()
}
func (this *CreateAction) RunPost(params struct {
PlatformUserId int64
TaskId int64
AuthType string
AcmeUserId int64
DnsProviderId int64
DnsDomain string
Domains []string
AutoRenew bool
AuthURL string
Must *actions.Must
}) {
if params.AuthType != "dns" && params.AuthType != "http" {
this.Fail("无法识别的认证方式'" + params.AuthType + "'")
}
if params.AcmeUserId <= 0 {
this.Fail("请选择一个申请证书的用户")
}
// 校验DNS相关信息
dnsDomain := strings.ToLower(params.DnsDomain)
if params.AuthType == "dns" {
if params.DnsProviderId <= 0 {
this.Fail("请选择DNS服务商")
}
if len(params.DnsDomain) == 0 {
this.Fail("请输入顶级域名")
}
if !domainutils.ValidateDomainFormat(dnsDomain) {
this.Fail("请输入正确的顶级域名")
}
}
if len(params.Domains) == 0 {
this.Fail("请输入证书域名列表")
}
var realDomains = []string{}
for _, domain := range params.Domains {
domain = strings.ToLower(domain)
if params.AuthType == "dns" { // DNS认证
if !strings.HasSuffix(domain, "."+dnsDomain) && domain != dnsDomain {
this.Fail("证书域名中的" + domain + "和顶级域名不一致")
}
} else if params.AuthType == "http" { // HTTP认证
if strings.Contains(domain, "*") {
this.Fail("在HTTP认证时域名" + domain + "不能包含通配符")
}
}
realDomains = append(realDomains, domain)
}
if params.TaskId == 0 {
createResp, err := this.RPC().ACMETaskRPC().CreateACMETask(this.AdminContext(), &pb.CreateACMETaskRequest{
UserId: params.PlatformUserId,
AuthType: params.AuthType,
AcmeUserId: params.AcmeUserId,
DnsProviderId: params.DnsProviderId,
DnsDomain: dnsDomain,
Domains: realDomains,
AutoRenew: params.AutoRenew,
AuthURL: params.AuthURL,
})
if err != nil {
this.ErrorPage(err)
return
}
params.TaskId = createResp.AcmeTaskId
defer this.CreateLogInfo(codes.ACMETask_LogCreateACMETask, createResp.AcmeTaskId)
} else {
_, err := this.RPC().ACMETaskRPC().UpdateACMETask(this.AdminContext(), &pb.UpdateACMETaskRequest{
AcmeTaskId: params.TaskId,
AcmeUserId: params.AcmeUserId,
DnsProviderId: params.DnsProviderId,
DnsDomain: dnsDomain,
Domains: realDomains,
AutoRenew: params.AutoRenew,
AuthURL: params.AuthURL,
})
if err != nil {
this.ErrorPage(err)
return
}
defer this.CreateLogInfo(codes.ACMETask_LogUpdateACMETask, params.TaskId)
}
this.Data["taskId"] = params.TaskId
this.Success()
}

View File

@@ -0,0 +1,25 @@
package acme
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteTaskAction struct {
actionutils.ParentAction
}
func (this *DeleteTaskAction) RunPost(params struct {
TaskId int64
}) {
defer this.CreateLogInfo(codes.ACMETask_LogDeleteACMETask, params.TaskId)
_, err := this.RPC().ACMETaskRPC().DeleteACMETask(this.AdminContext(), &pb.DeleteACMETaskRequest{AcmeTaskId: params.TaskId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,298 @@
package acme
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "task")
this.SecondMenu("list")
}
func (this *IndexAction) RunGet(params struct {
UserId int64
Type string
Keyword string
UserType string
}) {
this.Data["type"] = params.Type
this.Data["keyword"] = params.Keyword
this.Data["userType"] = params.UserType
var userOnly = params.UserId > 0 || params.UserType == "user"
// 当前用户
this.Data["searchingUserId"] = params.UserId
var userMap = maps.Map{
"id": 0,
"username": "",
"fullname": "",
}
if params.UserId > 0 {
userResp, err := this.RPC().UserRPC().FindEnabledUser(this.AdminContext(), &pb.FindEnabledUserRequest{UserId: params.UserId})
if err != nil {
this.ErrorPage(err)
return
}
var user = userResp.User
if user != nil {
userMap = maps.Map{
"id": user.Id,
"username": user.Username,
"fullname": user.Fullname,
}
}
}
this.Data["user"] = userMap
var countAll int64
var countAvailable int64
var countExpired int64
var count7Days int64
var count30Days int64
// 计算数量
{
// all
resp, err := this.RPC().ACMETaskRPC().CountAllEnabledACMETasks(this.AdminContext(), &pb.CountAllEnabledACMETasksRequest{
UserId: params.UserId,
Keyword: params.Keyword,
UserOnly: userOnly,
})
if err != nil {
this.ErrorPage(err)
return
}
countAll = resp.Count
// available
resp, err = this.RPC().ACMETaskRPC().CountAllEnabledACMETasks(this.AdminContext(), &pb.CountAllEnabledACMETasksRequest{
UserId: params.UserId,
IsAvailable: true,
Keyword: params.Keyword,
UserOnly: userOnly,
})
if err != nil {
this.ErrorPage(err)
return
}
countAvailable = resp.Count
// expired
resp, err = this.RPC().ACMETaskRPC().CountAllEnabledACMETasks(this.AdminContext(), &pb.CountAllEnabledACMETasksRequest{
UserId: params.UserId,
IsExpired: true,
Keyword: params.Keyword,
UserOnly: userOnly,
})
if err != nil {
this.ErrorPage(err)
return
}
countExpired = resp.Count
// expire in 7 days
resp, err = this.RPC().ACMETaskRPC().CountAllEnabledACMETasks(this.AdminContext(), &pb.CountAllEnabledACMETasksRequest{
UserId: params.UserId,
ExpiringDays: 7,
Keyword: params.Keyword,
UserOnly: userOnly,
})
if err != nil {
this.ErrorPage(err)
return
}
count7Days = resp.Count
// expire in 30 days
resp, err = this.RPC().ACMETaskRPC().CountAllEnabledACMETasks(this.AdminContext(), &pb.CountAllEnabledACMETasksRequest{
UserId: params.UserId,
ExpiringDays: 30,
Keyword: params.Keyword,
UserOnly: userOnly,
})
if err != nil {
this.ErrorPage(err)
return
}
count30Days = resp.Count
}
this.Data["countAll"] = countAll
this.Data["countAvailable"] = countAvailable
this.Data["countExpired"] = countExpired
this.Data["count7Days"] = count7Days
this.Data["count30Days"] = count30Days
// 分页
var page *actionutils.Page
var tasksResp *pb.ListEnabledACMETasksResponse
var err error
switch params.Type {
case "":
page = this.NewPage(countAll)
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
UserId: params.UserId,
Offset: page.Offset,
Size: page.Size,
Keyword: params.Keyword,
UserOnly: userOnly,
})
case "available":
page = this.NewPage(countAvailable)
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
UserId: params.UserId,
IsAvailable: true,
Offset: page.Offset,
Size: page.Size,
Keyword: params.Keyword,
UserOnly: userOnly,
})
case "expired":
page = this.NewPage(countExpired)
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
UserId: params.UserId,
IsExpired: true,
Offset: page.Offset,
Size: page.Size,
Keyword: params.Keyword,
UserOnly: userOnly,
})
case "7days":
page = this.NewPage(count7Days)
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
UserId: params.UserId,
ExpiringDays: 7,
Offset: page.Offset,
Size: page.Size,
Keyword: params.Keyword,
UserOnly: userOnly,
})
case "30days":
page = this.NewPage(count30Days)
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
UserId: params.UserId,
ExpiringDays: 30,
Offset: page.Offset,
Size: page.Size,
Keyword: params.Keyword,
UserOnly: userOnly,
})
default:
page = this.NewPage(countAll)
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
UserId: params.UserId,
Keyword: params.Keyword,
UserOnly: userOnly,
Offset: page.Offset,
Size: page.Size,
})
}
if err != nil {
this.ErrorPage(err)
return
}
this.Data["page"] = page.AsHTML()
var taskMaps = []maps.Map{}
for _, task := range tasksResp.AcmeTasks {
if task.AcmeUser == nil {
continue
}
// 服务商
var providerMap maps.Map
if task.AcmeUser.AcmeProvider != nil {
providerMap = maps.Map{
"name": task.AcmeUser.AcmeProvider.Name,
"code": task.AcmeUser.AcmeProvider.Code,
}
}
// 账号
var accountMap maps.Map
if task.AcmeUser.AcmeProviderAccount != nil {
accountMap = maps.Map{
"id": task.AcmeUser.AcmeProviderAccount.Id,
"name": task.AcmeUser.AcmeProviderAccount.Name,
}
}
// DNS服务商
dnsProviderMap := maps.Map{}
if task.AuthType == "dns" && task.DnsProvider != nil {
dnsProviderMap = maps.Map{
"id": task.DnsProvider.Id,
"name": task.DnsProvider.Name,
}
}
// 证书
var certMap maps.Map = nil
if task.SslCert != nil {
certMap = maps.Map{
"id": task.SslCert.Id,
"name": task.SslCert.Name,
"beginTime": timeutil.FormatTime("Y-m-d", task.SslCert.TimeBeginAt),
"endTime": timeutil.FormatTime("Y-m-d", task.SslCert.TimeEndAt),
}
}
// 日志
var logMap maps.Map = nil
if task.LatestACMETaskLog != nil {
logMap = maps.Map{
"id": task.LatestACMETaskLog.Id,
"isOk": task.LatestACMETaskLog.IsOk,
"error": task.LatestACMETaskLog.Error,
"createdTime": timeutil.FormatTime("m-d", task.CreatedAt),
}
}
// user
userResp, err := this.RPC().ACMETaskRPC().FindACMETaskUser(this.AdminContext(), &pb.FindACMETaskUserRequest{AcmeTaskId: task.Id})
if err != nil {
this.ErrorPage(err)
return
}
var taskUserMap = maps.Map{
"id": 0,
}
if userResp.User != nil {
taskUserMap = maps.Map{
"id": userResp.User.Id,
"username": userResp.User.Username,
"fullname": userResp.User.Fullname,
}
}
taskMaps = append(taskMaps, maps.Map{
"id": task.Id,
"authType": task.AuthType,
"acmeUser": maps.Map{
"id": task.AcmeUser.Id,
"email": task.AcmeUser.Email,
"provider": providerMap,
"account": accountMap,
},
"dnsProvider": dnsProviderMap,
"dnsDomain": task.DnsDomain,
"domains": task.Domains,
"autoRenew": task.AutoRenew,
"cert": certMap,
"log": logMap,
"user": taskUserMap,
})
}
this.Data["tasks"] = taskMaps
this.Show()
}

View File

@@ -0,0 +1,30 @@
package acme
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type RunAction struct {
actionutils.ParentAction
}
func (this *RunAction) RunPost(params struct {
TaskId int64
}) {
defer this.CreateLogInfo(codes.ACMETask_LogRunACMETask, params.TaskId)
runResp, err := this.RPC().ACMETaskRPC().RunACMETask(this.AdminContext(), &pb.RunACMETaskRequest{AcmeTaskId: params.TaskId})
if err != nil {
this.ErrorPage(err)
return
}
if runResp.IsOk {
this.Data["certId"] = runResp.SslCertId
this.Success()
} else {
this.Fail(runResp.Error)
}
}

View File

@@ -0,0 +1,170 @@
package acme
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"strings"
)
type UpdateTaskPopupAction struct {
actionutils.ParentAction
}
func (this *UpdateTaskPopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdateTaskPopupAction) RunGet(params struct {
TaskId int64
}) {
taskResp, err := this.RPC().ACMETaskRPC().FindEnabledACMETask(this.AdminContext(), &pb.FindEnabledACMETaskRequest{AcmeTaskId: params.TaskId})
if err != nil {
this.ErrorPage(err)
return
}
var task = taskResp.AcmeTask
if task == nil {
this.NotFound("acmeTask", params.TaskId)
return
}
var dnsProviderMap maps.Map
if task.DnsProvider != nil {
dnsProviderMap = maps.Map{
"id": task.DnsProvider.Id,
}
} else {
dnsProviderMap = maps.Map{
"id": 0,
}
}
var acmeUserMap maps.Map
if task.AcmeUser != nil {
acmeUserMap = maps.Map{
"id": task.AcmeUser.Id,
}
} else {
acmeUserMap = maps.Map{
"id": 0,
}
}
this.Data["task"] = maps.Map{
"id": task.Id,
"authType": task.AuthType,
"acmeUser": acmeUserMap,
"dnsDomain": task.DnsDomain,
"domains": task.Domains,
"autoRenew": task.AutoRenew,
"isOn": task.IsOn,
"authURL": task.AuthURL,
"dnsProvider": dnsProviderMap,
}
// 域名解析服务商
providersResp, err := this.RPC().DNSProviderRPC().FindAllEnabledDNSProviders(this.AdminContext(), &pb.FindAllEnabledDNSProvidersRequest{
AdminId: this.AdminId(),
UserId: 0,
})
if err != nil {
this.ErrorPage(err)
return
}
var providerMaps = []maps.Map{}
for _, provider := range providersResp.DnsProviders {
providerMaps = append(providerMaps, maps.Map{
"id": provider.Id,
"name": provider.Name,
"typeName": provider.TypeName,
})
}
this.Data["providers"] = providerMaps
this.Show()
}
func (this *UpdateTaskPopupAction) RunPost(params struct {
TaskId int64
AuthType string
AcmeUserId int64
DnsProviderId int64
DnsDomain string
DomainsJSON []byte
AutoRenew bool
AuthURL string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.ACMETask_LogUpdateACMETask, params.TaskId)
if params.AuthType != "dns" && params.AuthType != "http" {
this.Fail("无法识别的认证方式'" + params.AuthType + "'")
}
if params.AcmeUserId <= 0 {
this.Fail("请选择一个申请证书的用户")
}
dnsDomain := strings.ToLower(params.DnsDomain)
if params.AuthType == "dns" {
if params.DnsProviderId <= 0 {
this.Fail("请选择DNS服务商")
}
if len(params.DnsDomain) == 0 {
this.Fail("请输入顶级域名")
}
if !domainutils.ValidateDomainFormat(dnsDomain) {
this.Fail("请输入正确的顶级域名")
}
}
var domains = []string{}
if len(params.DomainsJSON) > 0 {
err := json.Unmarshal(params.DomainsJSON, &domains)
if err != nil {
this.Fail("解析域名数据失败:" + err.Error())
return
}
}
if len(domains) == 0 {
this.Fail("请输入证书域名列表")
}
var realDomains = []string{}
for _, domain := range domains {
domain = strings.ToLower(domain)
if params.AuthType == "dns" {
if !strings.HasSuffix(domain, "."+dnsDomain) && domain != dnsDomain {
this.Fail("证书域名中的" + domain + "和顶级域名不一致")
}
} else if params.AuthType == "http" { // HTTP认证
if strings.Contains(domain, "*") {
this.Fail("在HTTP认证时域名" + domain + "不能包含通配符")
}
}
realDomains = append(realDomains, domain)
}
_, err := this.RPC().ACMETaskRPC().UpdateACMETask(this.AdminContext(), &pb.UpdateACMETaskRequest{
AcmeTaskId: params.TaskId,
AcmeUserId: params.AcmeUserId,
DnsProviderId: params.DnsProviderId,
DnsDomain: dnsDomain,
Domains: realDomains,
AutoRenew: params.AutoRenew,
AuthURL: params.AuthURL,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,44 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package acme
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type UserOptionsAction struct {
actionutils.ParentAction
}
func (this *UserOptionsAction) RunPost(params struct {
PlatformUserId int64
}) {
// 获取所有可用的用户
usersResp, err := this.RPC().ACMEUserRPC().FindAllACMEUsers(this.AdminContext(), &pb.FindAllACMEUsersRequest{
AdminId: 0,
UserId: params.PlatformUserId,
})
if err != nil {
this.ErrorPage(err)
return
}
var userMaps = []maps.Map{}
for _, user := range usersResp.AcmeUsers {
description := user.Description
if len(description) > 0 {
description = "" + description + ""
}
userMaps = append(userMaps, maps.Map{
"id": user.Id,
"description": description,
"email": user.Email,
"providerCode": user.AcmeProviderCode,
})
}
this.Data["users"] = userMaps
this.Success()
}

View File

@@ -0,0 +1,33 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type AccountsWithCodeAction struct {
actionutils.ParentAction
}
func (this *AccountsWithCodeAction) RunPost(params struct {
Code string
}) {
accountsResp, err := this.RPC().ACMEProviderAccountRPC().FindAllACMEProviderAccountsWithProviderCode(this.AdminContext(), &pb.FindAllACMEProviderAccountsWithProviderCodeRequest{AcmeProviderCode: params.Code})
if err != nil {
this.ErrorPage(err)
return
}
var accountMaps = []maps.Map{}
for _, account := range accountsResp.AcmeProviderAccounts {
accountMaps = append(accountMaps, maps.Map{
"id": account.Id,
"name": account.Name,
})
}
this.Data["accounts"] = accountMaps
this.Success()
}

View File

@@ -0,0 +1,133 @@
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *CreatePopupAction) RunGet(params struct {
PlatformUserId int64
ProviderCode string
}) {
this.Data["platformUserId"] = params.PlatformUserId
this.Data["providerCode"] = params.ProviderCode
// 平台用户信息
this.Data["platformUser"] = nil
if params.PlatformUserId > 0 {
platformUserResp, err := this.RPC().UserRPC().FindEnabledUser(this.AdminContext(), &pb.FindEnabledUserRequest{UserId: params.PlatformUserId})
if err != nil {
this.ErrorPage(err)
return
}
var platformUser = platformUserResp.User
if platformUser != nil {
this.Data["platformUser"] = maps.Map{
"id": platformUser.Id,
"username": platformUser.Username,
"fullname": platformUser.Fullname,
}
}
}
// 服务商
providersResp, err := this.RPC().ACMEProviderRPC().FindAllACMEProviders(this.AdminContext(), &pb.FindAllACMEProvidersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var providerMaps = []maps.Map{}
for _, provider := range providersResp.AcmeProviders {
providerMaps = append(providerMaps, maps.Map{
"code": provider.Code,
"name": provider.Name,
"requireEAB": provider.RequireEAB,
})
}
this.Data["providers"] = providerMaps
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
PlatformUserId int64
Email string
ProviderCode string
AccountId int64
Description string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
params.Must.
Field("email", params.Email).
Require("请输入邮箱").
Email("请输入正确的邮箱格式").
Field("providerCode", params.ProviderCode).
Require("请选择所属服务商")
providerResp, err := this.RPC().ACMEProviderRPC().FindACMEProviderWithCode(this.AdminContext(), &pb.FindACMEProviderWithCodeRequest{
AcmeProviderCode: params.ProviderCode,
})
if err != nil {
this.ErrorPage(err)
return
}
if providerResp.AcmeProvider == nil {
this.Fail("找不到要选择的证书")
}
if providerResp.AcmeProvider.RequireEAB {
if params.AccountId <= 0 {
this.Fail("此服务商要求必须选择或创建服务商账号")
}
// 同一个账号只能有一个用户
countResp, err := this.RPC().ACMEUserRPC().
CountACMEUsers(this.AdminContext(), &pb.CountAcmeUsersRequest{
AcmeProviderAccountId: params.AccountId,
})
if err != nil {
this.ErrorPage(err)
return
}
if countResp.Count > 0 {
this.Fail("此服务商账号已被别的用户使用,请换成别的账号")
}
}
createResp, err := this.RPC().ACMEUserRPC().CreateACMEUser(this.AdminContext(), &pb.CreateACMEUserRequest{
UserId: params.PlatformUserId,
Email: params.Email,
Description: params.Description,
AcmeProviderCode: params.ProviderCode,
AcmeProviderAccountId: params.AccountId,
})
if err != nil {
this.ErrorPage(err)
return
}
// 返回数据
this.Data["acmeUser"] = maps.Map{
"id": createResp.AcmeUserId,
"description": params.Description,
"email": params.Email,
"providerCode": params.ProviderCode,
}
// 日志
defer this.CreateLogInfo(codes.ACMEUser_LogCreateACMEUser, createResp.AcmeUserId)
this.Success()
}

View File

@@ -0,0 +1,34 @@
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
UserId int64
}) {
defer this.CreateLogInfo(codes.ACMEUser_LogDeleteACMEUser, params.UserId)
countResp, err := this.RPC().ACMETaskRPC().CountAllEnabledACMETasksWithACMEUserId(this.AdminContext(), &pb.CountAllEnabledACMETasksWithACMEUserIdRequest{AcmeUserId: params.UserId})
if err != nil {
this.ErrorPage(err)
return
}
if countResp.Count > 0 {
this.Fail("有任务正在和这个用户关联,所以不能删除")
}
_, err = this.RPC().ACMEUserRPC().DeleteACMEUser(this.AdminContext(), &pb.DeleteACMEUserRequest{AcmeUserId: params.UserId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,73 @@
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "user")
}
func (this *IndexAction) RunGet(params struct{}) {
countResp, err := this.RPC().ACMEUserRPC().CountACMEUsers(this.AdminContext(), &pb.CountAcmeUsersRequest{
AdminId: this.AdminId(),
UserId: 0,
})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
usersResp, err := this.RPC().ACMEUserRPC().ListACMEUsers(this.AdminContext(), &pb.ListACMEUsersRequest{
AdminId: this.AdminId(),
UserId: 0,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
userMaps := []maps.Map{}
for _, user := range usersResp.AcmeUsers {
// 服务商
var providerMap maps.Map
if user.AcmeProvider != nil {
providerMap = maps.Map{
"name": user.AcmeProvider.Name,
"code": user.AcmeProvider.Code,
}
}
// 账号
var accountMap maps.Map
if user.AcmeProviderAccount != nil {
accountMap = maps.Map{
"id": user.AcmeProviderAccount.Id,
"name": user.AcmeProviderAccount.Name,
}
}
userMaps = append(userMaps, maps.Map{
"id": user.Id,
"email": user.Email,
"description": user.Description,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", user.CreatedAt),
"provider": providerMap,
"account": accountMap,
})
}
this.Data["users"] = userMaps
this.Show()
}

View File

@@ -0,0 +1,15 @@
package users
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
type SelectPopupAction struct {
actionutils.ParentAction
}
func (this *SelectPopupAction) Init() {
this.Nav("", "", "")
}
func (this *SelectPopupAction) RunGet(params struct{}) {
this.Show()
}

View File

@@ -0,0 +1,81 @@
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
UserId int64
}) {
userResp, err := this.RPC().ACMEUserRPC().FindEnabledACMEUser(this.AdminContext(), &pb.FindEnabledACMEUserRequest{AcmeUserId: params.UserId})
if err != nil {
this.ErrorPage(err)
return
}
user := userResp.AcmeUser
if user == nil {
this.NotFound("acmeUser", params.UserId)
return
}
// 服务商
var providerMap maps.Map
if user.AcmeProvider != nil {
providerMap = maps.Map{
"name": user.AcmeProvider.Name,
"code": user.AcmeProvider.Code,
}
}
// 账号
var accountMap maps.Map
if user.AcmeProviderAccount != nil {
accountMap = maps.Map{
"id": user.AcmeProviderAccount.Id,
"name": user.AcmeProviderAccount.Name,
}
}
this.Data["user"] = maps.Map{
"id": user.Id,
"email": user.Email,
"description": user.Description,
"provider": providerMap,
"account": accountMap,
}
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
UserId int64
Description string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.ACMEUser_LogUpdateACMEUser, params.UserId)
_, err := this.RPC().ACMEUserRPC().UpdateACMEUser(this.AdminContext(), &pb.UpdateACMEUserRequest{
AcmeUserId: params.UserId,
Description: params.Description,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}