174 lines
4.4 KiB
Go
174 lines
4.4 KiB
Go
package api
|
||
|
||
import (
|
||
"net/http"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
|
||
"oci-portal/internal/oci"
|
||
)
|
||
|
||
// ---- Federation:SAML IdP 与 sign-on 免 MFA ----
|
||
|
||
// createIdpRequest 的映射 / JIT 字段全部可缺省:布尔用指针区分「未传」,
|
||
// 缺省即控制台默认(JIT 开启建用户不更新、分配 Administrators 组、
|
||
// 名称 ID 格式无、NameID 映射用户名)。
|
||
type createIdpRequest struct {
|
||
Name string `json:"name" binding:"required"`
|
||
Metadata string `json:"metadata" binding:"required"`
|
||
Description string `json:"description"`
|
||
IconURL string `json:"iconUrl"`
|
||
|
||
NameIDFormat string `json:"nameIdFormat"`
|
||
AssertionAttribute string `json:"assertionAttribute"`
|
||
UserStoreAttribute string `json:"userStoreAttribute"`
|
||
|
||
JitEnabled *bool `json:"jitEnabled"`
|
||
JitCreate *bool `json:"jitCreate"`
|
||
JitUpdate *bool `json:"jitUpdate"`
|
||
JitAssignAdminGroup *bool `json:"jitAssignAdminGroup"`
|
||
JitMapEmail bool `json:"jitMapEmail"`
|
||
}
|
||
|
||
func boolOr(v *bool, def bool) bool {
|
||
if v == nil {
|
||
return def
|
||
}
|
||
return *v
|
||
}
|
||
|
||
func (h *ociConfigHandler) listIdentityProviders(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
idps, err := h.svc.IdentityProviders(c.Request.Context(), id)
|
||
if err != nil {
|
||
respondError(c, err)
|
||
return
|
||
}
|
||
c.JSON(http.StatusOK, idps)
|
||
}
|
||
|
||
func (h *ociConfigHandler) createIdentityProvider(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var req createIdpRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
idp, err := h.svc.CreateIdentityProvider(c.Request.Context(), id, oci.CreateIdpInput{
|
||
Name: req.Name,
|
||
Metadata: req.Metadata,
|
||
Description: req.Description,
|
||
IconURL: req.IconURL,
|
||
NameIDFormat: req.NameIDFormat,
|
||
AssertionAttribute: req.AssertionAttribute,
|
||
UserStoreAttribute: req.UserStoreAttribute,
|
||
JitEnabled: boolOr(req.JitEnabled, true),
|
||
JitCreate: boolOr(req.JitCreate, true),
|
||
JitUpdate: boolOr(req.JitUpdate, false),
|
||
JitAssignAdminGroup: boolOr(req.JitAssignAdminGroup, true),
|
||
JitMapEmail: req.JitMapEmail,
|
||
})
|
||
if err != nil {
|
||
respondError(c, err)
|
||
return
|
||
}
|
||
c.JSON(http.StatusCreated, idp)
|
||
}
|
||
|
||
func (h *ociConfigHandler) activateIdentityProvider(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var req struct {
|
||
Enabled *bool `json:"enabled" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
idp, err := h.svc.SetIdentityProviderEnabled(c.Request.Context(), id, c.Param("idpId"), *req.Enabled)
|
||
if err != nil {
|
||
respondError(c, err)
|
||
return
|
||
}
|
||
c.JSON(http.StatusOK, idp)
|
||
}
|
||
|
||
func (h *ociConfigHandler) deleteIdentityProvider(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
if err := h.svc.DeleteIdentityProvider(c.Request.Context(), id, c.Param("idpId")); err != nil {
|
||
respondError(c, err)
|
||
return
|
||
}
|
||
c.Status(http.StatusNoContent)
|
||
}
|
||
|
||
func (h *ociConfigHandler) downloadSamlMetadata(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
metadata, err := h.svc.DomainSamlMetadata(c.Request.Context(), id)
|
||
if err != nil {
|
||
respondError(c, err)
|
||
return
|
||
}
|
||
c.Header("Content-Disposition", `attachment; filename="oci-domain-saml-metadata.xml"`)
|
||
c.Data(http.StatusOK, "application/xml", metadata)
|
||
}
|
||
|
||
func (h *ociConfigHandler) listSignOnRules(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
rules, err := h.svc.ConsoleSignOnRules(c.Request.Context(), id)
|
||
if err != nil {
|
||
respondError(c, err)
|
||
return
|
||
}
|
||
c.JSON(http.StatusOK, rules)
|
||
}
|
||
|
||
func (h *ociConfigHandler) createMfaExemption(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var req struct {
|
||
IdentityProviderID string `json:"identityProviderId" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
rule, err := h.svc.CreateMfaExemption(c.Request.Context(), id, req.IdentityProviderID)
|
||
if err != nil {
|
||
respondError(c, err)
|
||
return
|
||
}
|
||
c.JSON(http.StatusCreated, rule)
|
||
}
|
||
|
||
func (h *ociConfigHandler) deleteMfaExemption(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
if err := h.svc.DeleteMfaExemption(c.Request.Context(), id, c.Param("ruleId")); err != nil {
|
||
respondError(c, err)
|
||
return
|
||
}
|
||
c.Status(http.StatusNoContent)
|
||
}
|