发布 0.1.0:通知渠道、告警规则、令牌版本与安全加固
CI / test (push) Successful in 30s
Release / release (push) Successful in 49s

This commit is contained in:
Wang Defa
2026-07-10 17:38:34 +08:00
parent 4af6a0ca92
commit dbba1f4905
78 changed files with 6898 additions and 551 deletions
+53 -22
View File
@@ -67,12 +67,14 @@ func (h *ociConfigHandler) costs(c *gin.Context) {
// ---- 租户审计日志 ----
// getAuditEvents 实时查询租户 OCI 审计事件:hours 首查(缺省 24);
// start/end/page 为截断后的同窗续查;窗口越界或非法返回 400
// getAuditEvents 批式懒加载查询审计事件:cursor 为空自当前时刻首查,
// 非空从上次响应游标继续向更早回溯;limit 单批目标条数(缺省 100,上限 200)
//
// @Summary 实时查询租户 OCI 审计事件:hours 首查
// @Summary 批式懒加载查询租户 OCI 审计事件
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param cursor query string false "续查游标(上次响应原样带回)"
// @Param limit query int false "单批目标条数,缺省 100,上限 200"
// @Success 200 {object} map[string]any
// @Security BearerAuth
// @Router /api/v1/oci-configs/{id}/audit-events [get]
@@ -81,13 +83,10 @@ func (h *ociConfigHandler) getAuditEvents(c *gin.Context) {
if !ok {
return
}
hours, _ := strconv.Atoi(c.DefaultQuery("hours", "24"))
q := service.AuditQuery{
Region: c.Query("region"), Hours: hours,
Start: c.Query("start"), End: c.Query("end"), Page: c.Query("page"),
}
limit, _ := strconv.Atoi(c.Query("limit"))
q := service.AuditQuery{Region: c.Query("region"), Cursor: c.Query("cursor"), Limit: limit}
result, err := h.svc.AuditEvents(c.Request.Context(), id, q)
if errors.Is(err, service.ErrInvalidAuditHours) || errors.Is(err, service.ErrInvalidAuditWindow) {
if errors.Is(err, service.ErrInvalidAuditCursor) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
@@ -143,9 +142,29 @@ type createTenantUserRequest struct {
AddToAdminGroup bool `json:"addToAdminGroup"`
}
// @Summary 租户身份域列表
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Success 200 {object} map[string]any
// @Security BearerAuth
// @Router /api/v1/oci-configs/{id}/domains [get]
func (h *ociConfigHandler) listIdentityDomains(c *gin.Context) {
id, ok := pathID(c)
if !ok {
return
}
domains, err := h.svc.IdentityDomains(c.Request.Context(), id)
if err != nil {
respondError(c, err)
return
}
c.JSON(http.StatusOK, domains)
}
// @Summary 租户 IAM 用户列表
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Success 200 {object} map[string]any
// @Security BearerAuth
// @Router /api/v1/oci-configs/{id}/users [get]
@@ -154,7 +173,7 @@ func (h *ociConfigHandler) listTenantUsers(c *gin.Context) {
if !ok {
return
}
users, err := h.svc.TenantUsers(c.Request.Context(), id)
users, err := h.svc.TenantUsers(c.Request.Context(), id, c.Query("domainId"))
if err != nil {
respondError(c, err)
return
@@ -165,6 +184,7 @@ func (h *ociConfigHandler) listTenantUsers(c *gin.Context) {
// @Summary 租户用户详情
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param userId path string true "userId"
// @Success 200 {object} map[string]any
// @Security BearerAuth
@@ -174,7 +194,7 @@ func (h *ociConfigHandler) getTenantUserDetail(c *gin.Context) {
if !ok {
return
}
detail, err := h.svc.TenantUserDetail(c.Request.Context(), id, c.Param("userId"))
detail, err := h.svc.TenantUserDetail(c.Request.Context(), id, c.Query("domainId"), c.Param("userId"))
if err != nil {
respondError(c, err)
return
@@ -185,6 +205,7 @@ func (h *ociConfigHandler) getTenantUserDetail(c *gin.Context) {
// @Summary 创建租户 IAM 用户
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param body body createTenantUserRequest true "请求体"
// @Success 201 {object} map[string]any
// @Security BearerAuth
@@ -199,7 +220,7 @@ func (h *ociConfigHandler) createTenantUser(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user, err := h.svc.CreateTenantUser(c.Request.Context(), id, oci.CreateTenantUserInput{
user, err := h.svc.CreateTenantUser(c.Request.Context(), id, c.Query("domainId"), oci.CreateTenantUserInput{
Name: req.Name,
Description: req.Description,
Email: req.Email,
@@ -229,6 +250,7 @@ type updateTenantUserRequest struct {
// @Summary 更新租户 IAM 用户
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param userId path string true "userId"
// @Param body body updateTenantUserRequest true "请求体"
// @Success 200 {object} map[string]any
@@ -244,7 +266,7 @@ func (h *ociConfigHandler) updateTenantUser(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user, err := h.svc.UpdateTenantUser(c.Request.Context(), id, c.Param("userId"), oci.UpdateTenantUserInput{
user, err := h.svc.UpdateTenantUser(c.Request.Context(), id, c.Query("domainId"), c.Param("userId"), oci.UpdateTenantUserInput{
Description: req.Description,
Email: req.Email,
GivenName: req.GivenName,
@@ -262,6 +284,7 @@ func (h *ociConfigHandler) updateTenantUser(c *gin.Context) {
// @Summary 删除租户 IAM 用户
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param userId path string true "userId"
// @Success 204 "无内容"
// @Security BearerAuth
@@ -271,7 +294,7 @@ func (h *ociConfigHandler) deleteTenantUser(c *gin.Context) {
if !ok {
return
}
if err := h.svc.DeleteTenantUser(c.Request.Context(), id, c.Param("userId")); err != nil {
if err := h.svc.DeleteTenantUser(c.Request.Context(), id, c.Query("domainId"), c.Param("userId")); err != nil {
respondError(c, err)
return
}
@@ -281,6 +304,7 @@ func (h *ociConfigHandler) deleteTenantUser(c *gin.Context) {
// @Summary 重置租户用户密码
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param userId path string true "userId"
// @Success 200 {object} map[string]any
// @Security BearerAuth
@@ -290,7 +314,7 @@ func (h *ociConfigHandler) resetTenantUserPassword(c *gin.Context) {
if !ok {
return
}
password, err := h.svc.ResetTenantUserPassword(c.Request.Context(), id, c.Param("userId"))
password, err := h.svc.ResetTenantUserPassword(c.Request.Context(), id, c.Query("domainId"), c.Param("userId"))
if err != nil {
respondError(c, err)
return
@@ -301,6 +325,7 @@ func (h *ociConfigHandler) resetTenantUserPassword(c *gin.Context) {
// @Summary 清除用户 MFA 设备
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param userId path string true "userId"
// @Success 200 {object} map[string]any
// @Security BearerAuth
@@ -310,7 +335,7 @@ func (h *ociConfigHandler) deleteTenantUserMfa(c *gin.Context) {
if !ok {
return
}
deleted, err := h.svc.DeleteTenantUserMfa(c.Request.Context(), id, c.Param("userId"))
deleted, err := h.svc.DeleteTenantUserMfa(c.Request.Context(), id, c.Query("domainId"), c.Param("userId"))
if err != nil {
respondError(c, err)
return
@@ -344,6 +369,7 @@ func (h *ociConfigHandler) deleteTenantUserApiKeys(c *gin.Context) {
// @Summary ---- 域通知收件人与密码策略 ----
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Success 200 {object} map[string]any
// @Security BearerAuth
// @Router /api/v1/oci-configs/{id}/notification-recipients [get]
@@ -352,7 +378,7 @@ func (h *ociConfigHandler) getNotificationRecipients(c *gin.Context) {
if !ok {
return
}
recipients, err := h.svc.NotificationRecipients(c.Request.Context(), id)
recipients, err := h.svc.NotificationRecipients(c.Request.Context(), id, c.Query("domainId"))
if err != nil {
respondError(c, err)
return
@@ -363,6 +389,7 @@ func (h *ociConfigHandler) getNotificationRecipients(c *gin.Context) {
// @Summary 更新通知收件人
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param body body object true "请求体(见接口说明)"
// @Success 200 {object} map[string]any
// @Security BearerAuth
@@ -379,7 +406,7 @@ func (h *ociConfigHandler) updateNotificationRecipients(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
recipients, err := h.svc.UpdateNotificationRecipients(c.Request.Context(), id, req.Recipients)
recipients, err := h.svc.UpdateNotificationRecipients(c.Request.Context(), id, c.Query("domainId"), req.Recipients)
if err != nil {
respondError(c, err)
return
@@ -390,6 +417,7 @@ func (h *ociConfigHandler) updateNotificationRecipients(c *gin.Context) {
// @Summary 密码策略列表
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Success 200 {object} map[string]any
// @Security BearerAuth
// @Router /api/v1/oci-configs/{id}/password-policies [get]
@@ -398,7 +426,7 @@ func (h *ociConfigHandler) listPasswordPolicies(c *gin.Context) {
if !ok {
return
}
policies, err := h.svc.PasswordPolicies(c.Request.Context(), id)
policies, err := h.svc.PasswordPolicies(c.Request.Context(), id, c.Query("domainId"))
if err != nil {
respondError(c, err)
return
@@ -409,6 +437,7 @@ func (h *ociConfigHandler) listPasswordPolicies(c *gin.Context) {
// @Summary 更新密码策略
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param policyId path string true "policyId"
// @Param body body object true "请求体(见接口说明)"
// @Success 200 {object} map[string]any
@@ -428,7 +457,7 @@ func (h *ociConfigHandler) updatePasswordPolicy(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
policy, err := h.svc.UpdatePasswordPolicy(c.Request.Context(), id, c.Param("policyId"), oci.UpdatePasswordPolicyInput{
policy, err := h.svc.UpdatePasswordPolicy(c.Request.Context(), id, c.Query("domainId"), c.Param("policyId"), oci.UpdatePasswordPolicyInput{
PasswordExpiresAfter: req.PasswordExpiresAfter,
MinLength: req.MinLength,
NumPasswordsInHistory: req.NumPasswordsInHistory,
@@ -443,6 +472,7 @@ func (h *ociConfigHandler) updatePasswordPolicy(c *gin.Context) {
// @Summary 身份域设置
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Success 200 {object} map[string]any
// @Security BearerAuth
// @Router /api/v1/oci-configs/{id}/identity-settings [get]
@@ -451,7 +481,7 @@ func (h *ociConfigHandler) getIdentitySetting(c *gin.Context) {
if !ok {
return
}
setting, err := h.svc.IdentitySetting(c.Request.Context(), id)
setting, err := h.svc.IdentitySetting(c.Request.Context(), id, c.Query("domainId"))
if err != nil {
respondError(c, err)
return
@@ -462,6 +492,7 @@ func (h *ociConfigHandler) getIdentitySetting(c *gin.Context) {
// @Summary 更新身份域设置
// @Tags 租户 IAM
// @Param id path int true "配置 ID"
// @Param domainId query string false "身份域 OCID(缺省 Default 域)"
// @Param body body object true "请求体(见接口说明)"
// @Success 200 {object} map[string]any
// @Security BearerAuth
@@ -478,7 +509,7 @@ func (h *ociConfigHandler) updateIdentitySetting(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
setting, err := h.svc.UpdateIdentitySetting(c.Request.Context(), id, *req.PrimaryEmailRequired)
setting, err := h.svc.UpdateIdentitySetting(c.Request.Context(), id, c.Query("domainId"), *req.PrimaryEmailRequired)
if err != nil {
respondError(c, err)
return