发布 0.1.0:通知渠道、告警规则、令牌版本与安全加固
This commit is contained in:
@@ -1,9 +1,16 @@
|
||||
package oci
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/oracle/oci-go-sdk/v65/common"
|
||||
|
||||
"oci-portal/internal/model"
|
||||
)
|
||||
|
||||
@@ -19,6 +26,89 @@ type AccountProfile struct {
|
||||
PromotionExpires *time.Time
|
||||
}
|
||||
|
||||
// AccountCapabilities 是账户能力接口的关键字段。来源为 Limits 服务
|
||||
// 20230301 版 `/compartments/{tenancy}/capabilities?accountInfoOnly=true`
|
||||
// (与控制台同源;oci-go-sdk v65 未收录,自签名裸调)。
|
||||
// 该接口对暂停/已终止租户仍可访问,借此把「暂停」从「失联」中区分出来。
|
||||
type AccountCapabilities struct {
|
||||
Suspended bool `json:"suspended"`
|
||||
AccountStatus string `json:"accountStatus"`
|
||||
FreeTierEnabled bool `json:"freeTierEnabled"`
|
||||
FreeTierOnly bool `json:"freeTierOnly"`
|
||||
PromotionStatus string `json:"promotionStatus"`
|
||||
ProgramType string `json:"programType"`
|
||||
HasSaasSubscription bool `json:"hasSaasSubscription"`
|
||||
Deletable bool `json:"deletable"`
|
||||
}
|
||||
|
||||
// capabilitiesEnvelope 对应接口原始响应:顶层与 accountInfo 各有一个
|
||||
// suspended,任一为 true 即视为暂停。
|
||||
type capabilitiesEnvelope struct {
|
||||
Capabilities struct {
|
||||
Suspended bool `json:"suspended"`
|
||||
AccountInfo struct {
|
||||
FreeTierEnabled bool `json:"freeTierEnabled"`
|
||||
FreeTierOnly bool `json:"freeTierOnly"`
|
||||
PromotionStatus string `json:"promotionStatus"`
|
||||
Suspended bool `json:"suspended"`
|
||||
ProgramType string `json:"programType"`
|
||||
HasSaasSubscription bool `json:"hasSaasSubscription"`
|
||||
AccountStatus string `json:"accountStatus"`
|
||||
Deletable bool `json:"deletable"`
|
||||
} `json:"accountInfo"`
|
||||
} `json:"capabilities"`
|
||||
}
|
||||
|
||||
// parseAccountCapabilities 把原始响应体压平为关键字段视图。
|
||||
func parseAccountCapabilities(body []byte) (AccountCapabilities, error) {
|
||||
var env capabilitiesEnvelope
|
||||
if err := json.Unmarshal(body, &env); err != nil {
|
||||
return AccountCapabilities{}, fmt.Errorf("decode account capabilities: %w", err)
|
||||
}
|
||||
info := env.Capabilities.AccountInfo
|
||||
return AccountCapabilities{
|
||||
Suspended: env.Capabilities.Suspended || info.Suspended,
|
||||
AccountStatus: info.AccountStatus,
|
||||
FreeTierEnabled: info.FreeTierEnabled,
|
||||
FreeTierOnly: info.FreeTierOnly,
|
||||
PromotionStatus: info.PromotionStatus,
|
||||
ProgramType: info.ProgramType,
|
||||
HasSaasSubscription: info.HasSaasSubscription,
|
||||
Deletable: info.Deletable,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAccountCapabilities 实现 Client:查询账户能力(暂停/账户状态/免费层)。
|
||||
// region 应传 home region;请求带 API Key 签名,并沿用租户出站代理。
|
||||
func (c *RealClient) GetAccountCapabilities(ctx context.Context, cred Credentials, region string) (AccountCapabilities, error) {
|
||||
url := fmt.Sprintf("https://limits.%s.oci.oraclecloud.com/20230301/compartments/%s/capabilities?accountInfoOnly=true",
|
||||
normalizeRegion(region), cred.TenancyOCID)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return AccountCapabilities{}, fmt.Errorf("new capabilities request: %w", err)
|
||||
}
|
||||
if err := common.DefaultRequestSigner(provider(cred)).Sign(req); err != nil {
|
||||
return AccountCapabilities{}, fmt.Errorf("sign capabilities request: %w", err)
|
||||
}
|
||||
hc := proxyHTTPClient(cred.Proxy)
|
||||
if hc == nil {
|
||||
hc = &http.Client{Timeout: proxyClientTimeout}
|
||||
}
|
||||
resp, err := hc.Do(req)
|
||||
if err != nil {
|
||||
return AccountCapabilities{}, fmt.Errorf("get account capabilities: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
|
||||
if err != nil {
|
||||
return AccountCapabilities{}, fmt.Errorf("read account capabilities: %w", err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return AccountCapabilities{}, fmt.Errorf("get account capabilities: status %d", resp.StatusCode)
|
||||
}
|
||||
return parseAccountCapabilities(body)
|
||||
}
|
||||
|
||||
// ClassifyAccount 按订阅字段判定账户类别:
|
||||
// - paymentModel 非空且不是 FREE_TRIAL:付费;
|
||||
// - paymentModel 为 FREE_TRIAL 时,promotion ACTIVE 或 tier FREE_AND_TRIAL
|
||||
|
||||
Reference in New Issue
Block a user