Skip to content

Commit b0ca1e7

Browse files
committed
wip: checking in
1 parent 553c6cd commit b0ca1e7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1122
-3585
lines changed

services/api/internal/api/handlers/auth/credentials.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
basehttp "github.com/catalystgo/catalyst-forge/lib/foundry/httpkit"
99
"github.com/gin-gonic/gin"
1010
apimodels "github.com/input-output-hk/catalyst-forge/services/api/internal/api/models/auth"
11-
akauth "github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/authkit"
11+
akauth "github.com/input-output-hk/catalyst-forge/services/api/internal/authkit"
1212
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/store"
1313
)
1414

services/api/internal/api/handlers/auth/credentials_add.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
basehttp "github.com/catalystgo/catalyst-forge/lib/foundry/httpkit"
99
"github.com/gin-gonic/gin"
1010
apimodels "github.com/input-output-hk/catalyst-forge/services/api/internal/api/models/auth"
11-
akauth "github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/authkit"
11+
akauth "github.com/input-output-hk/catalyst-forge/services/api/internal/authkit"
1212
akservice "github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/service"
1313
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/store"
1414
)

services/api/internal/api/handlers/auth/devicelink.go

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
"github.com/catalystgo/catalyst-forge/lib/foundry/httpkit"
99
"github.com/gin-gonic/gin"
10-
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/authkit"
10+
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit"
1111
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/rate"
1212
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/service"
1313
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/store"
@@ -23,7 +23,7 @@ type DeviceLinkDeps struct {
2323
// RegisterDeviceLink registers all device-link endpoints.
2424
func RegisterDeviceLink(r *gin.Engine, deps DeviceLinkDeps) {
2525
api := r.Group("/api/v1/auth/device-link")
26-
26+
2727
// @Summary Begin device link flow
2828
// @Description Initiates a device authorization flow for CLI/device authentication
2929
// @Tags auth
@@ -35,7 +35,7 @@ func RegisterDeviceLink(r *gin.Engine, deps DeviceLinkDeps) {
3535
// @Failure 500 {object} httpkit.ErrorResponse "Internal server error"
3636
// @Router /api/v1/auth/device-link/begin [post]
3737
api.POST("/begin", beginDeviceLinkHandler(deps.DeviceLinkService, deps.RateLimiter))
38-
38+
3939
// @Summary Authorize device link
4040
// @Description Authorizes a pending device link request (requires authentication and step-up)
4141
// @Tags auth
@@ -49,7 +49,7 @@ func RegisterDeviceLink(r *gin.Engine, deps DeviceLinkDeps) {
4949
// @Failure 428 {object} httpkit.ErrorResponse "Step-up authentication required"
5050
// @Router /api/v1/auth/device-link/authorize [post]
5151
api.POST("/authorize", authorizeDeviceLinkHandler(deps.DeviceLinkService))
52-
52+
5353
// @Summary Exchange device code for tokens
5454
// @Description Exchanges a device code for access and refresh tokens (polling endpoint)
5555
// @Tags auth
@@ -90,7 +90,7 @@ func beginDeviceLinkHandler(linkService service.DeviceLinkService, limiter rate.
9090
return func(c *gin.Context) {
9191
// Get client IP for rate limiting
9292
clientIP := getClientIP(c)
93-
93+
9494
// Check rate limit
9595
if limiter != nil {
9696
allowed, err := limiter.AllowBegin(c.Request.Context(), clientIP)
@@ -99,33 +99,33 @@ func beginDeviceLinkHandler(linkService service.DeviceLinkService, limiter rate.
9999
return
100100
}
101101
}
102-
102+
103103
var req struct {
104104
DeviceName string `json:"device_name"`
105105
Purpose string `json:"purpose"` // "login" or "step_up"
106106
}
107-
107+
108108
if err := httpkit.ParseJSON(c.Writer, c.Request, &req); err != nil {
109109
return
110110
}
111-
111+
112112
// Default device name if not provided
113113
if req.DeviceName == "" {
114114
req.DeviceName = "CLI Device"
115115
}
116-
116+
117117
// Default purpose to login
118118
if req.Purpose == "" {
119119
req.Purpose = "login"
120120
}
121-
121+
122122
// Begin the device link flow
123123
resp, err := linkService.BeginDeviceLink(c.Request.Context(), req.DeviceName, req.Purpose)
124124
if err != nil {
125125
_ = httpkit.NewInternalError().Write(c.Writer)
126126
return
127127
}
128-
128+
129129
_ = httpkit.WriteJSON(c.Writer, http.StatusOK, resp)
130130
}
131131
}
@@ -139,33 +139,33 @@ func authorizeDeviceLinkHandler(linkService service.DeviceLinkService) gin.Handl
139139
_ = httpkit.NewUnauthorizedError("authentication required").Write(c.Writer)
140140
return
141141
}
142-
142+
143143
// Check for fresh step-up
144144
if ctx.RequiresStepUp(time.Now().UTC()) {
145145
httpkit.ErrorResponse(c.Writer, http.StatusPreconditionRequired, "step_up_required", "Fresh authentication required")
146146
return
147147
}
148-
148+
149149
var req struct {
150150
UserCode string `json:"user_code"`
151151
}
152-
152+
153153
if err := httpkit.ParseJSON(c.Writer, c.Request, &req); err != nil {
154154
return
155155
}
156-
156+
157157
if req.UserCode == "" {
158158
_ = httpkit.NewBadRequestError("user_code is required").Write(c.Writer)
159159
return
160160
}
161-
161+
162162
// Authorize the device link
163163
err := linkService.AuthorizeDeviceLink(c.Request.Context(), req.UserCode, ctx.UserID)
164164
if err != nil {
165165
_ = httpkit.NewBadRequestError("invalid or expired code").Write(c.Writer)
166166
return
167167
}
168-
168+
169169
c.Status(http.StatusNoContent)
170170
}
171171
}
@@ -176,24 +176,24 @@ func exchangeDeviceCodeHandler(linkService service.DeviceLinkService, limiter ra
176176
var req struct {
177177
DeviceCode string `json:"device_code"`
178178
}
179-
179+
180180
if err := httpkit.ParseJSON(c.Writer, c.Request, &req); err != nil {
181181
return
182182
}
183-
183+
184184
if req.DeviceCode == "" {
185185
_ = httpkit.NewBadRequestError("device_code is required").Write(c.Writer)
186186
return
187187
}
188-
188+
189189
// Check rate limit
190190
if limiter != nil {
191191
allowed, err := limiter.AllowExchange(c.Request.Context(), req.DeviceCode)
192192
if err != nil {
193193
// Check if it's a slow_down error
194194
if err.Error() == "slow_down" {
195195
_ = httpkit.WriteJSON(c.Writer, http.StatusBadRequest, map[string]string{
196-
"error": "slow_down",
196+
"error": "slow_down",
197197
"error_description": "You are polling too frequently",
198198
})
199199
return
@@ -202,45 +202,45 @@ func exchangeDeviceCodeHandler(linkService service.DeviceLinkService, limiter ra
202202
if !allowed {
203203
_ = limiter.RecordSlowDown(c.Request.Context(), req.DeviceCode)
204204
_ = httpkit.WriteJSON(c.Writer, http.StatusBadRequest, map[string]string{
205-
"error": "slow_down",
205+
"error": "slow_down",
206206
"error_description": "You are polling too frequently",
207207
})
208208
return
209209
}
210210
}
211-
211+
212212
// Exchange the device code
213213
resp, err := linkService.ExchangeDeviceCode(c.Request.Context(), req.DeviceCode)
214214
if err != nil {
215215
_ = httpkit.NewInternalError().Write(c.Writer)
216216
return
217217
}
218-
218+
219219
// Check status for pending/expired responses
220220
if resp.Status != "" {
221221
// Return status codes for polling clients
222222
switch resp.Status {
223223
case "authorization_pending":
224224
_ = httpkit.WriteJSON(c.Writer, http.StatusBadRequest, map[string]string{
225-
"error": "authorization_pending",
225+
"error": "authorization_pending",
226226
"error_description": "The authorization request is still pending",
227227
})
228228
case "slow_down":
229229
_ = httpkit.WriteJSON(c.Writer, http.StatusBadRequest, map[string]string{
230-
"error": "slow_down",
230+
"error": "slow_down",
231231
"error_description": "You are polling too frequently",
232232
})
233233
case "expired_token":
234234
_ = httpkit.WriteJSON(c.Writer, http.StatusBadRequest, map[string]string{
235-
"error": "expired_token",
235+
"error": "expired_token",
236236
"error_description": "The device code has expired",
237237
})
238238
default:
239239
_ = httpkit.NewInternalError().Write(c.Writer)
240240
}
241241
return
242242
}
243-
243+
244244
// Success - reset rate limit and return tokens
245245
if limiter != nil {
246246
_ = limiter.ResetExchange(c.Request.Context(), req.DeviceCode)
@@ -267,13 +267,13 @@ func RegisterDeviceLinkVerify(r *gin.Engine, linkStore store.DeviceLinkStore) {
267267
_ = httpkit.NewBadRequestError("code parameter is required").Write(c.Writer)
268268
return
269269
}
270-
270+
271271
link, err := service.VerifyDeviceCode(c.Request.Context(), linkStore, userCode)
272272
if err != nil {
273273
_ = httpkit.NewBadRequestError("invalid or expired code").Write(c.Writer)
274274
return
275275
}
276-
276+
277277
_ = httpkit.WriteJSON(c.Writer, http.StatusOK, map[string]interface{}{
278278
"device_name": link.DeviceName,
279279
"purpose": link.Purpose,
@@ -301,12 +301,12 @@ func getClientIP(c *gin.Context) string {
301301
}
302302
return strings.TrimSpace(xff)
303303
}
304-
304+
305305
// Try X-Real-IP header
306306
if xri := c.GetHeader("X-Real-IP"); xri != "" {
307307
return xri
308308
}
309-
309+
310310
// Fall back to remote address
311311
return c.ClientIP()
312-
}
312+
}

services/api/internal/api/handlers/auth/devicelink_test.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
"github.com/gin-gonic/gin"
1414
"github.com/google/uuid"
15-
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/authkit"
15+
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit"
1616
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/domain"
1717
"github.com/input-output-hk/catalyst-forge/services/api/internal/authkit/service"
1818
"github.com/stretchr/testify/assert"
@@ -99,14 +99,14 @@ func TestBeginDeviceLinkHandler(t *testing.T) {
9999
gin.SetMode(gin.TestMode)
100100

101101
tests := []struct {
102-
name string
103-
requestBody string
104-
rateLimitAllowed bool
105-
serviceError error
106-
wantStatus int
107-
wantDeviceCode string
108-
wantUserCode string
109-
wantErrorKey string
102+
name string
103+
requestBody string
104+
rateLimitAllowed bool
105+
serviceError error
106+
wantStatus int
107+
wantDeviceCode string
108+
wantUserCode string
109+
wantErrorKey string
110110
}{
111111
{
112112
name: "ok/successful_begin",
@@ -144,7 +144,7 @@ func TestBeginDeviceLinkHandler(t *testing.T) {
144144
tc := tc // capture range variable
145145
t.Run(tc.name, func(t *testing.T) {
146146
r := gin.New()
147-
147+
148148
linkService := &mockDeviceLinkService{
149149
beginFunc: func(ctx context.Context, deviceName string, purpose string) (*service.DeviceLinkResponse, error) {
150150
if tc.serviceError != nil {
@@ -160,13 +160,13 @@ func TestBeginDeviceLinkHandler(t *testing.T) {
160160
}, nil
161161
},
162162
}
163-
163+
164164
limiter := &mockDeviceLinkLimiter{
165165
allowBeginFunc: func(ctx context.Context, ip string) (bool, error) {
166166
return tc.rateLimitAllowed, nil
167167
},
168168
}
169-
169+
170170
handler := beginDeviceLinkHandler(linkService, limiter)
171171
r.POST("/begin", handler)
172172

@@ -206,7 +206,7 @@ func TestAuthorizeDeviceLinkHandler(t *testing.T) {
206206

207207
t.Run("ok/successful_authorize", func(t *testing.T) {
208208
r := gin.New()
209-
209+
210210
// Add authenticated context with valid step-up
211211
r.Use(func(c *gin.Context) {
212212
authCtx := authkit.AuthContext{
@@ -250,7 +250,7 @@ func TestAuthorizeDeviceLinkHandler(t *testing.T) {
250250

251251
t.Run("error/requires_step_up", func(t *testing.T) {
252252
r := gin.New()
253-
253+
254254
// Add authenticated context without step-up
255255
r.Use(func(c *gin.Context) {
256256
authCtx := authkit.AuthContext{
@@ -278,7 +278,7 @@ func TestAuthorizeDeviceLinkHandler(t *testing.T) {
278278

279279
t.Run("error/missing_user_code", func(t *testing.T) {
280280
r := gin.New()
281-
281+
282282
// Add authenticated context with valid step-up
283283
r.Use(func(c *gin.Context) {
284284
authCtx := authkit.AuthContext{
@@ -306,7 +306,7 @@ func TestAuthorizeDeviceLinkHandler(t *testing.T) {
306306

307307
t.Run("error/invalid_code", func(t *testing.T) {
308308
r := gin.New()
309-
309+
310310
// Add authenticated context with valid step-up
311311
r.Use(func(c *gin.Context) {
312312
authCtx := authkit.AuthContext{
@@ -485,7 +485,7 @@ func TestRegisterDeviceLinkVerify(t *testing.T) {
485485

486486
t.Run("ok/valid_code", func(t *testing.T) {
487487
r := gin.New()
488-
488+
489489
// Mock store
490490
linkStore := &mockDeviceLinkStore{
491491
getByUserCodeFunc: func(ctx context.Context, userCode string) (*domain.DeviceLink, error) {
@@ -498,7 +498,7 @@ func TestRegisterDeviceLinkVerify(t *testing.T) {
498498
}, nil
499499
},
500500
}
501-
501+
502502
RegisterDeviceLinkVerify(r, linkStore)
503503

504504
req := httptest.NewRequest("GET", "/api/v1/auth/device-link/verify?code=TEST-123", nil)
@@ -577,4 +577,4 @@ func (m *mockDeviceLinkStore) Delete(ctx context.Context, id uuid.UUID) error {
577577

578578
func (m *mockDeviceLinkStore) DeleteExpired(ctx context.Context, before time.Time) (int64, error) {
579579
return 0, nil
580-
}
580+
}

0 commit comments

Comments
 (0)