fix(iam): write nullable inet fields correctly

This commit is contained in:
Your Name
2026-04-20 16:16:52 +08:00
parent a109a6836f
commit 79d9b872f6
2 changed files with 57 additions and 10 deletions

View File

@@ -83,6 +83,13 @@ func iamInt64OrZero(value *int64) int64 {
return *value
}
func iamNullableIP(value string) interface{} {
if value == "" {
return nil
}
return value
}
// Ensure interfaces
var _ IAMRepository = (*PostgresIAMRepository)(nil)
@@ -101,14 +108,6 @@ func (r *PostgresIAMRepository) CreateRole(ctx context.Context, role *model.Role
parentID = role.ParentRoleID
}
var createdIP, updatedIP interface{}
if role.CreatedIP != "" {
createdIP = role.CreatedIP
}
if role.UpdatedIP != "" {
updatedIP = role.UpdatedIP
}
now := time.Now()
if role.CreatedAt == nil {
role.CreatedAt = &now
@@ -119,7 +118,7 @@ func (r *PostgresIAMRepository) CreateRole(ctx context.Context, role *model.Role
_, err := r.pool.Exec(ctx, query,
role.Code, role.Name, role.Type, parentID, role.Level, role.Description, role.IsActive,
role.RequestID, createdIP, updatedIP, role.Version, role.CreatedAt, role.UpdatedAt,
role.RequestID, iamNullableIP(role.CreatedIP), iamNullableIP(role.UpdatedIP), role.Version, role.CreatedAt, role.UpdatedAt,
)
if err != nil {
if strings.Contains(err.Error(), "duplicate key") || strings.Contains(err.Error(), "unique constraint") {
@@ -170,7 +169,7 @@ func (r *PostgresIAMRepository) UpdateRole(ctx context.Context, role *model.Role
WHERE code = $1 AND is_active = true
`
result, err := r.pool.Exec(ctx, query, role.Code, role.Name, role.Description, role.IsActive, role.UpdatedIP)
result, err := r.pool.Exec(ctx, query, role.Code, role.Name, role.Description, role.IsActive, iamNullableIP(role.UpdatedIP))
if err != nil {
return fmt.Errorf("failed to update role: %w", err)
}

View File

@@ -281,3 +281,51 @@ func TestGetUserRolesWithCodeAcceptsNullableTenantAndGrantFields(t *testing.T) {
t.Fatalf("expected null request_id to map to empty string, got %q", roles[0].RequestID)
}
}
func TestUpdateRoleStoresEmptyUpdatedIPAsNil(t *testing.T) {
db := &stubIAMDB{
execTag: pgconn.NewCommandTag("UPDATE 1"),
}
repo := newPostgresIAMRepositoryWithDB(db)
err := repo.UpdateRole(context.Background(), &model.Role{
Code: "viewer",
Name: "Viewer",
Description: "readonly",
IsActive: true,
UpdatedIP: "",
})
if err != nil {
t.Fatalf("UpdateRole() error = %v", err)
}
if len(db.execArgs) != 5 {
t.Fatalf("unexpected exec args length: got=%d want=5", len(db.execArgs))
}
if db.execArgs[4] != nil {
t.Fatalf("expected empty updated_ip to be stored as nil, got %#v", db.execArgs[4])
}
}
func TestUpdateRolePreservesExplicitUpdatedIP(t *testing.T) {
db := &stubIAMDB{
execTag: pgconn.NewCommandTag("UPDATE 1"),
}
repo := newPostgresIAMRepositoryWithDB(db)
err := repo.UpdateRole(context.Background(), &model.Role{
Code: "viewer",
Name: "Viewer",
Description: "readonly",
IsActive: true,
UpdatedIP: "10.0.0.8",
})
if err != nil {
t.Fatalf("UpdateRole() error = %v", err)
}
if len(db.execArgs) != 5 {
t.Fatalf("unexpected exec args length: got=%d want=5", len(db.execArgs))
}
if db.execArgs[4] != "10.0.0.8" {
t.Fatalf("expected explicit updated_ip to be preserved, got %#v", db.execArgs[4])
}
}