Skip to content

Commit b7cb412

Browse files
Raderpulltheflower
andauthored
Add namespace exists check before create namespace mapping (#1249)
Co-authored-by: Zhang ZeHua <pulltheflower@163.com>
1 parent 9823cb8 commit b7cb412

8 files changed

Lines changed: 117 additions & 3 deletions

File tree

api/handler/mirror_namespace_mapping.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package handler
22

33
import (
4+
"errors"
45
"fmt"
56
"log/slog"
67
"strconv"
78

89
"github.com/gin-gonic/gin"
910
"opencsg.com/csghub-server/api/httpbase"
1011
"opencsg.com/csghub-server/common/config"
12+
"opencsg.com/csghub-server/common/errorx"
1113
"opencsg.com/csghub-server/common/types"
1214
"opencsg.com/csghub-server/component"
1315
)
@@ -48,7 +50,11 @@ func (h *MirrorNamespaceMappingHandler) Create(ctx *gin.Context) {
4850
ms, err := h.mirrorNamespaceMapping.Create(ctx.Request.Context(), msReq)
4951
if err != nil {
5052
slog.ErrorContext(ctx.Request.Context(), "Failed to create mirror namespace mapping", "error", err)
51-
httpbase.ServerError(ctx, err)
53+
if errors.Is(err, errorx.ErrTargetNamespaceNotFound) {
54+
httpbase.BadRequestWithExt(ctx, err)
55+
} else {
56+
httpbase.ServerError(ctx, err)
57+
}
5258
return
5359
}
5460
httpbase.OK(ctx, ms)
@@ -110,8 +116,12 @@ func (h *MirrorNamespaceMappingHandler) Update(ctx *gin.Context) {
110116
msReq.ID = msId
111117
ms, err := h.mirrorNamespaceMapping.Update(ctx.Request.Context(), msReq)
112118
if err != nil {
113-
slog.ErrorContext(ctx.Request.Context(), "Failed to get mirror namespace mappings", "error", err)
114-
httpbase.ServerError(ctx, err)
119+
slog.ErrorContext(ctx.Request.Context(), "Failed to update mirror namespace mapping", "error", err)
120+
if errors.Is(err, errorx.ErrTargetNamespaceNotFound) {
121+
httpbase.BadRequestWithExt(ctx, err)
122+
} else {
123+
httpbase.ServerError(ctx, err)
124+
}
115125
return
116126
}
117127
httpbase.OK(ctx, ms)

common/errorx/error_req.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package errorx
22

3+
import "fmt"
4+
35
const errReqPrefix = "REQ-ERR"
46

57
const (
@@ -17,6 +19,9 @@ const (
1719

1820
errReqContentTypeUnsupported
1921
errRateLimitExceeded
22+
errLimitedIPLocation
23+
errCaptchaIncorrect
24+
errTargetNamespaceNotFound
2025
)
2126

2227
var (
@@ -118,6 +123,45 @@ var (
118123
//
119124
// zh-HK: 請求過於頻繁,需要驗證碼
120125
ErrRateLimitExceeded = CustomError{prefix: errReqPrefix, code: errRateLimitExceeded}
126+
127+
// requests from this IP location are restricted, captcha is required
128+
//
129+
// Description: Requests originating from this IP location are restricted. To proceed, please complete a captcha verification.
130+
//
131+
// Description_ZH: 来自此IP位置的请求受到限制。要继续操作,请完成验证码验证。
132+
//
133+
// en-US: Requests from this IP location are restricted, captcha is required
134+
//
135+
// zh-CN: 来自该IP位置的请求受限,需要验证码
136+
//
137+
// zh-HK: 來自該IP位置的請求受限,需要驗證碼
138+
ErrLimitedIPLocation = CustomError{prefix: errReqPrefix, code: errLimitedIPLocation}
139+
140+
// captcha verification failed
141+
//
142+
// Description: The provided captcha verification failed. Please try again with a valid captcha.
143+
//
144+
// Description_ZH: 提供的验证码验证失败。请使用有效的验证码重试。
145+
//
146+
// en-US: Captcha verification failed
147+
//
148+
// zh-CN: 验证码验证失败
149+
//
150+
// zh-HK: 驗證碼驗證失敗
151+
ErrCaptchaIncorrect = CustomError{prefix: errReqPrefix, code: errCaptchaIncorrect}
152+
153+
// the target namespace does not exist
154+
//
155+
// Description: The specified target namespace was not found in the system. Please verify the namespace exists before creating or updating the mapping.
156+
//
157+
// Description_ZH: 指定的目标命名空间在系统中不存在。请在创建或更新映射之前确认命名空间存在。
158+
//
159+
// en-US: Target namespace not found
160+
//
161+
// zh-CN: 目标命名空间不存在
162+
//
163+
// zh-HK: 目標命名空間不存在
164+
ErrTargetNamespaceNotFound = CustomError{prefix: errReqPrefix, code: errTargetNamespaceNotFound}
121165
)
122166

123167
func BadRequest(originErr error, ext context) error {
@@ -146,3 +190,12 @@ func ReqParamInvalid(err error, ext context) error {
146190
context: ext,
147191
}
148192
}
193+
194+
func TargetNamespaceNotFound(namespace string) error {
195+
return CustomError{
196+
prefix: errReqPrefix,
197+
code: errTargetNamespaceNotFound,
198+
err: fmt.Errorf("target namespace not found: %s", namespace),
199+
context: Ctx().Set("target_namespace", namespace),
200+
}
201+
}

common/i18n/en-US/err_req.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88
"error.REQ-ERR-10": {
99
"other": "Too many requests, captcha is required"
1010
},
11+
"error.REQ-ERR-11": {
12+
"other": "Requests from this IP location are restricted, captcha is required"
13+
},
14+
"error.REQ-ERR-12": {
15+
"other": "Captcha verification failed"
16+
},
17+
"error.REQ-ERR-13": {
18+
"other": "Target namespace not found"
19+
},
1120
"error.REQ-ERR-2": {
1221
"other": "Request body cannot be empty"
1322
},

common/i18n/zh-CN/err_req.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88
"error.REQ-ERR-10": {
99
"other": "请求过于频繁,需要验证码"
1010
},
11+
"error.REQ-ERR-11": {
12+
"other": "来自该IP位置的请求受限,需要验证码"
13+
},
14+
"error.REQ-ERR-12": {
15+
"other": "验证码验证失败"
16+
},
17+
"error.REQ-ERR-13": {
18+
"other": "目标命名空间不存在"
19+
},
1120
"error.REQ-ERR-2": {
1221
"other": "请求体不能为空"
1322
},

common/i18n/zh-HK/err_req.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88
"error.REQ-ERR-10": {
99
"other": "請求過於頻繁,需要驗證碼"
1010
},
11+
"error.REQ-ERR-11": {
12+
"other": "來自該IP位置的請求受限,需要驗證碼"
13+
},
14+
"error.REQ-ERR-12": {
15+
"other": "驗證碼驗證失敗"
16+
},
17+
"error.REQ-ERR-13": {
18+
"other": "目標命名空間不存在"
19+
},
1120
"error.REQ-ERR-2": {
1221
"other": "請求體不能為空"
1322
},

component/mirror_namespace_mapping.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import (
66

77
"opencsg.com/csghub-server/builder/store/database"
88
"opencsg.com/csghub-server/common/config"
9+
"opencsg.com/csghub-server/common/errorx"
910
"opencsg.com/csghub-server/common/types"
1011
)
1112

1213
type mirrorNamespaceMappingComponentImpl struct {
1314
mirrorNamespaceMappingStore database.MirrorNamespaceMappingStore
1415
userStore database.UserStore
16+
namespaceStore database.NamespaceStore
1517
}
1618

1719
type MirrorNamespaceMappingComponent interface {
@@ -26,10 +28,19 @@ func NewMirrorNamespaceMappingComponent(config *config.Config) (MirrorNamespaceM
2628
return &mirrorNamespaceMappingComponentImpl{
2729
mirrorNamespaceMappingStore: database.NewMirrorNamespaceMappingStore(),
2830
userStore: database.NewUserStore(),
31+
namespaceStore: database.NewNamespaceStore(),
2932
}, nil
3033
}
3134

3235
func (c *mirrorNamespaceMappingComponentImpl) Create(ctx context.Context, req types.CreateMirrorNamespaceMappingReq) (*database.MirrorNamespaceMapping, error) {
36+
exists, err := c.namespaceStore.Exists(ctx, req.TargetNamespace)
37+
if err != nil {
38+
return nil, fmt.Errorf("failed to check target namespace existence, error: %w", err)
39+
}
40+
if !exists {
41+
return nil, errorx.TargetNamespaceNotFound(req.TargetNamespace)
42+
}
43+
3344
var mnm database.MirrorNamespaceMapping
3445
mnm.SourceNamespace = req.SourceNamespace
3546
mnm.TargetNamespace = req.TargetNamespace
@@ -59,6 +70,16 @@ func (c *mirrorNamespaceMappingComponentImpl) Index(ctx context.Context) ([]data
5970
return mnm, nil
6071
}
6172
func (c *mirrorNamespaceMappingComponentImpl) Update(ctx context.Context, req types.UpdateMirrorNamespaceMappingReq) (*database.MirrorNamespaceMapping, error) {
73+
if req.TargetNamespace != nil {
74+
exists, err := c.namespaceStore.Exists(ctx, *req.TargetNamespace)
75+
if err != nil {
76+
return nil, fmt.Errorf("failed to check target namespace existence, error: %w", err)
77+
}
78+
if !exists {
79+
return nil, errorx.TargetNamespaceNotFound(*req.TargetNamespace)
80+
}
81+
}
82+
6283
var mnm database.MirrorNamespaceMapping
6384
mnm.ID = req.ID
6485
if req.SourceNamespace != nil {

component/mirror_namespace_mapping_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
func TestMirrorNamespaceMappingComponent_Create(t *testing.T) {
1313
ctx := context.TODO()
1414
mc := initializeTestMirrorNamespaceMappingComponent(ctx, t)
15+
mc.mocks.stores.NamespaceMock().EXPECT().Exists(ctx, "u").Return(true, nil)
1516
mc.mocks.stores.MirrorNamespaceMappingMock().EXPECT().Create(ctx, &database.MirrorNamespaceMapping{
1617
SourceNamespace: "sn",
1718
TargetNamespace: "u",
@@ -52,6 +53,7 @@ func TestMirrorNamespaceMappingComponent_Index(t *testing.T) {
5253
func TestMirrorNamespaceMappingComponent_Update(t *testing.T) {
5354
ctx := context.TODO()
5455
mc := initializeTestMirrorNamespaceMappingComponent(ctx, t)
56+
mc.mocks.stores.NamespaceMock().EXPECT().Exists(ctx, "u").Return(true, nil)
5557
mc.mocks.stores.MirrorNamespaceMappingMock().EXPECT().Update(ctx, &database.MirrorNamespaceMapping{
5658
ID: 1,
5759
SourceNamespace: "sn",

component/wireset_ce.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ func NewTestSpaceResourceComponent(config *config.Config, stores *tests.MockStor
102102
func NewTestMirrorNamespaceMappingComponent(config *config.Config, stores *tests.MockStores) *mirrorNamespaceMappingComponentImpl {
103103
return &mirrorNamespaceMappingComponentImpl{
104104
mirrorNamespaceMappingStore: stores.MirrorNamespaceMapping,
105+
namespaceStore: stores.Namespace,
105106
}
106107
}
107108

0 commit comments

Comments
 (0)