Skip to content
This repository was archived by the owner on Aug 30, 2025. It is now read-only.
7 changes: 5 additions & 2 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: "2"
run:
tests: false
linters:
default: none
default: standard
enable:
- bodyclose
- dogsled
Expand Down Expand Up @@ -47,7 +47,7 @@ linters:
- performance
- style
gocyclo:
min-complexity: 20
min-complexity: 10
lll:
line-length: 140
misspell:
Expand Down Expand Up @@ -105,11 +105,14 @@ formatters:
enable:
- gofmt
- goimports
- golines
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

many of the changes are from this.

settings:
gofmt:
rewrite-rules:
- pattern: interface{}
replacement: any
golines:
max-len: 140
exclusions:
generated: lax
paths:
Expand Down
33 changes: 24 additions & 9 deletions backend/internal/auth/apikey/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ type TokenContextData struct {
}

var (
InvalidApiKeyErr = errors.New("token is not a valid neosync api key")
ApiKeyExpiredErr = nucleuserrors.NewUnauthenticated("token is expired")
ErrInvalidApiKey = errors.New("token is not a valid neosync api key")
ErrApiKeyExpired = nucleuserrors.NewUnauthenticated("token is expired")
)

type Queries interface {
GetAccountApiKeyByKeyValue(ctx context.Context, db db_queries.DBTX, apiKey string) (db_queries.NeosyncApiAccountApiKey, error)
GetAccountApiKeyByKeyValue(
ctx context.Context,
db db_queries.DBTX,
apiKey string,
) (db_queries.NeosyncApiAccountApiKey, error)
}

type Client struct {
Expand All @@ -49,10 +53,19 @@ func New(
for _, procedure := range allowedWorkerProcedures {
allowedWorkerProcedureSet[procedure] = struct{}{}
}
return &Client{q: queries, db: db, allowedWorkerApiKeys: allowedWorkerApiKeys, allowedWorkerProcedures: allowedWorkerProcedureSet}
return &Client{
q: queries,
db: db,
allowedWorkerApiKeys: allowedWorkerApiKeys,
allowedWorkerProcedures: allowedWorkerProcedureSet,
}
}

func (c *Client) InjectTokenCtx(ctx context.Context, header http.Header, spec connect.Spec) (context.Context, error) {
func (c *Client) InjectTokenCtx(
ctx context.Context,
header http.Header,
spec connect.Spec,
) (context.Context, error) {
token, err := utils.GetBearerTokenFromHeader(header, "Authorization")
if err != nil {
return nil, err
Expand All @@ -66,11 +79,11 @@ func (c *Client) InjectTokenCtx(ctx context.Context, header http.Header, spec co
if err != nil && !neosyncdb.IsNoRows(err) {
return nil, err
} else if err != nil && neosyncdb.IsNoRows(err) {
return nil, InvalidApiKeyErr
return nil, ErrInvalidApiKey
}

if time.Now().After(apiKey.ExpiresAt.Time) {
return nil, ApiKeyExpiredErr
return nil, ErrApiKeyExpired
}

return SetTokenData(ctx, &TokenContextData{
Expand All @@ -87,13 +100,15 @@ func (c *Client) InjectTokenCtx(ctx context.Context, header http.Header, spec co
ApiKeyType: apikey.WorkerApiKey,
}), nil
}
return nil, InvalidApiKeyErr
return nil, ErrInvalidApiKey
}

func GetTokenDataFromCtx(ctx context.Context) (*TokenContextData, error) {
data, ok := ctx.Value(TokenContextKey{}).(*TokenContextData)
if !ok {
return nil, nucleuserrors.NewUnauthenticated("ctx does not contain TokenContextData or unable to cast struct")
return nil, nucleuserrors.NewUnauthenticated(
"ctx does not contain TokenContextData or unable to cast struct",
)
}
return data, nil
}
Expand Down
2 changes: 1 addition & 1 deletion backend/internal/auth/apikey/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func Test_Client_InjectTokenCtx_Account_Expired(t *testing.T) {
"Authorization": []string{fmt.Sprintf("Bearer %s", fakeToken)},
}, connect.Spec{})
assert.Error(t, err)
assert.True(t, errors.Is(err, ApiKeyExpiredErr))
assert.True(t, errors.Is(err, ErrApiKeyExpired))
assert.Nil(t, newctx)
}

Expand Down
16 changes: 12 additions & 4 deletions backend/internal/auth/authmw/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import (
)

type AuthClient interface {
InjectTokenCtx(ctx context.Context, header http.Header, spec connect.Spec) (context.Context, error)
InjectTokenCtx(
ctx context.Context,
header http.Header,
spec connect.Spec,
) (context.Context, error)
}

type AuthMiddleware struct {
Expand All @@ -25,11 +29,15 @@ func New(
return &AuthMiddleware{jwtClient: jwtClient, apiKeyClient: apiKeyClient}
}

func (n *AuthMiddleware) InjectTokenCtx(ctx context.Context, header http.Header, spec connect.Spec) (context.Context, error) {
func (n *AuthMiddleware) InjectTokenCtx(
ctx context.Context,
header http.Header,
spec connect.Spec,
) (context.Context, error) {
apiKeyCtx, err := n.apiKeyClient.InjectTokenCtx(ctx, header, spec)
if err != nil && !errors.Is(err, auth_apikey.InvalidApiKeyErr) {
if err != nil && !errors.Is(err, auth_apikey.ErrInvalidApiKey) {
return nil, err
} else if err != nil && errors.Is(err, auth_apikey.InvalidApiKeyErr) {
} else if err != nil && errors.Is(err, auth_apikey.ErrInvalidApiKey) {
return n.jwtClient.InjectTokenCtx(ctx, header, spec)
}
return apiKeyCtx, nil
Expand Down
2 changes: 1 addition & 1 deletion backend/internal/auth/authmw/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func Test_AuthMiddleware_InjectTokenCtx_ApiKey_JwtFallback(t *testing.T) {

ctx := context.Background()
mockApiKey.On("InjectTokenCtx", ctx, mock.Anything, mock.Anything).
Return(nil, auth_apikey.InvalidApiKeyErr)
Return(nil, auth_apikey.ErrInvalidApiKey)
mockJwt.On("InjectTokenCtx", ctx, mock.Anything, mock.Anything).
Return(context.Background(), nil)

Expand Down
33 changes: 27 additions & 6 deletions backend/internal/auth/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,17 @@ import (
)

type Interface interface {
GetTokenResponse(ctx context.Context, clientId string, code string, redirecturi string) (*AuthTokenResponse, error)
GetRefreshedAccessToken(ctx context.Context, clientId string, refreshToken string) (*AuthTokenResponse, error)
GetTokenResponse(
ctx context.Context,
clientId string,
code string,
redirecturi string,
) (*AuthTokenResponse, error)
GetRefreshedAccessToken(
ctx context.Context,
clientId string,
refreshToken string,
) (*AuthTokenResponse, error)
GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)
GetTokenEndpoint(ctx context.Context) (string, error)
GetAuthorizationEndpoint(ctx context.Context) (string, error)
Expand Down Expand Up @@ -147,7 +156,10 @@ func (c *Client) GetRefreshedAccessToken(
clientSecret := c.clientIdSecretMap[clientId]
payload := strings.NewReader(
fmt.Sprintf(
"grant_type=refresh_token&client_id=%s&client_secret=%s&refresh_token=%s", clientId, clientSecret, refreshToken,
"grant_type=refresh_token&client_id=%s&client_secret=%s&refresh_token=%s",
clientId,
clientSecret,
refreshToken,
),
)
tokenurl, err := c.GetTokenEndpoint(ctx)
Expand Down Expand Up @@ -179,14 +191,20 @@ func (c *Client) GetRefreshedAccessToken(
err = json.Unmarshal(body, &tokenResponse)

if err != nil {
return nil, fmt.Errorf("unable to unmarshal token response from refresh token request: %w", err)
return nil, fmt.Errorf(
"unable to unmarshal token response from refresh token request: %w",
err,
)
}

if tokenResponse.AccessToken == "" {
var errorResponse AuthTokenErrorData
err = json.Unmarshal(body, &errorResponse)
if err != nil {
return nil, fmt.Errorf("unable to unmarshal error response from refresh token request: %w", err)
return nil, fmt.Errorf(
"unable to unmarshal error response from refresh token request: %w",
err,
)
}
return &AuthTokenResponse{
Result: nil,
Expand Down Expand Up @@ -274,7 +292,10 @@ type openIdConfiguration struct {
}

func (c *Client) getOpenIdConfiguration(ctx context.Context) (*openIdConfiguration, error) {
configUrl := fmt.Sprintf("%s/.well-known/openid-configuration", strings.TrimSuffix(c.authBaseUrl, "/"))
configUrl := fmt.Sprintf(
"%s/.well-known/openid-configuration",
strings.TrimSuffix(c.authBaseUrl, "/"),
)

req, err := http.NewRequestWithContext(ctx, http.MethodGet, configUrl, http.NoBody)
if err != nil {
Expand Down
16 changes: 13 additions & 3 deletions backend/internal/auth/clientcred_token_provider/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ type tokenProviderClient struct {
clientSecret string
}

func (c *tokenProviderClient) GetToken(ctx context.Context) (*auth_client.AuthTokenResponse, error) {
func (c *tokenProviderClient) GetToken(
ctx context.Context,
) (*auth_client.AuthTokenResponse, error) {
values := url.Values{
"grant_type": []string{"client_credentials"},
"client_id": []string{c.clientId},
Expand Down Expand Up @@ -87,9 +89,17 @@ type ClientCredentialsTokenProvider struct {
expiresAt *time.Time
}

func New(tokenurl, clientId, clientSecret string, tokenExpirationBuffer time.Duration, logger *slog.Logger) *ClientCredentialsTokenProvider {
func New(
tokenurl, clientId, clientSecret string,
tokenExpirationBuffer time.Duration,
logger *slog.Logger,
) *ClientCredentialsTokenProvider {
return &ClientCredentialsTokenProvider{
tokenprovider: &tokenProviderClient{tokenurl: tokenurl, clientId: clientId, clientSecret: clientSecret},
tokenprovider: &tokenProviderClient{
tokenurl: tokenurl,
clientId: clientId,
clientSecret: clientSecret,
},
tokenExpBuffer: tokenExpirationBuffer,
logger: logger,
}
Expand Down
23 changes: 18 additions & 5 deletions backend/internal/auth/jwt/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,19 @@ func New(
}

// Validates and returns a parsed access token (if available)
func (j *Client) validateToken(ctx context.Context, accessToken string) (*validator.ValidatedClaims, error) {
func (j *Client) validateToken(
ctx context.Context,
accessToken string,
) (*validator.ValidatedClaims, error) {
rawParsedToken, err := j.jwtValidator.ValidateToken(ctx, accessToken)
if err != nil {
return nil, nucleuserrors.NewUnauthenticated(err.Error())
}
validatedClaims, ok := rawParsedToken.(*validator.ValidatedClaims)
if !ok {
return nil, nucleuserrors.NewInternalError("unable to convert token claims what was expected")
return nil, nucleuserrors.NewInternalError(
"unable to convert token claims what was expected",
)
}
return validatedClaims, nil
}
Expand Down Expand Up @@ -111,7 +116,11 @@ func hasScope(scopes []string, expectedScope string) bool {
}

// Validates the ctx is authenticated. Stuffs the parsed token onto the context
func (j *Client) InjectTokenCtx(ctx context.Context, header http.Header, spec connect.Spec) (context.Context, error) {
func (j *Client) InjectTokenCtx(
ctx context.Context,
header http.Header,
spec connect.Spec,
) (context.Context, error) {
token, err := utils.GetBearerTokenFromHeader(header, "Authorization")
if err != nil {
return nil, err
Expand All @@ -124,7 +133,9 @@ func (j *Client) InjectTokenCtx(ctx context.Context, header http.Header, spec co

claims, ok := parsedToken.CustomClaims.(*CustomClaims)
if !ok {
return nil, nucleuserrors.NewInternalError("unable to cast custom token claims to CustomClaims struct")
return nil, nucleuserrors.NewInternalError(
"unable to cast custom token claims to CustomClaims struct",
)
}

scopes := getCombinedScopesAndPermissions(claims.Scope, claims.Permissions)
Expand Down Expand Up @@ -161,7 +172,9 @@ func GetTokenDataFromCtx(ctx context.Context) (*TokenContextData, error) {
val := ctx.Value(TokenContextKey{})
data, ok := val.(*TokenContextData)
if !ok {
return nil, nucleuserrors.NewUnauthenticated(fmt.Sprintf("ctx does not contain TokenContextData or unable to cast struct: %T", val))
return nil, nucleuserrors.NewUnauthenticated(
fmt.Sprintf("ctx does not contain TokenContextData or unable to cast struct: %T", val),
)
}
return data, nil
}
Expand Down
6 changes: 4 additions & 2 deletions backend/internal/cmds/mgmt/migrate/down/down.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ func NewCmd() *cobra.Command {
)
},
}
cmd.Flags().StringP("database", "d", "", "optionally set the database url, otherwise it will pull from the environment")
cmd.Flags().StringP("source", "s", "", "optionally set the migrations dir, otherwise pull from DB_SCHEMA_DIR env")
cmd.Flags().
StringP("database", "d", "", "optionally set the database url, otherwise it will pull from the environment")
cmd.Flags().
StringP("source", "s", "", "optionally set the migrations dir, otherwise pull from DB_SCHEMA_DIR env")
return cmd
}

Expand Down
6 changes: 4 additions & 2 deletions backend/internal/cmds/mgmt/migrate/up/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ func NewCmd() *cobra.Command {
)
},
}
cmd.Flags().StringP("database", "d", "", "optionally set the database url, otherwise it will pull from the environment")
cmd.Flags().StringP("source", "s", "", "optionally set the migrations dir, otherwise pull from DB_SCHEMA_DIR env")
cmd.Flags().
StringP("database", "d", "", "optionally set the database url, otherwise it will pull from the environment")
cmd.Flags().
StringP("source", "s", "", "optionally set the migrations dir, otherwise pull from DB_SCHEMA_DIR env")
return cmd
}

Expand Down
Loading