diff --git a/auth/middleware.go b/auth/middleware.go index 4334ea3339e7467fb3f0729b55f807e755015812..0483e6ca61948b9d25f8327a6e32b90f43028534 100644 --- a/auth/middleware.go +++ b/auth/middleware.go @@ -49,11 +49,11 @@ USER_SUSPENDED = "suspended" ) const ( - AUTH_OAUTH_LEGACY = iota - AUTH_OAUTH2 = iota - AUTH_COOKIE = iota - AUTH_INTERNAL = iota - AUTH_WEBHOOK = iota + AUTH_OAUTH_LEGACY = "OAUTH_LEGACY" + AUTH_OAUTH2 = "OAUTH2" + AUTH_COOKIE = "COOKIE" + AUTH_INTERNAL = "INTERNAL" + AUTH_WEBHOOK = "WEBHOOK" ) type AuthContext struct { @@ -67,7 +67,7 @@ URL *string Location *string Bio *string SuspensionNotice *string - AuthMethod int + AuthMethod string // Only set for meta.sr.ht-api PGPKey *string diff --git a/webhooks/config.go b/webhooks/config.go index a381eb4cad356eebeb2f6776956a696f1edcc69d..f93f4465dd7fc5874f280622215cba7cd1e16ea1 100644 --- a/webhooks/config.go +++ b/webhooks/config.go @@ -9,11 +9,19 @@ "git.sr.ht/~sircmpwn/core-go/auth" ) +// The following invariants apply to AuthConfig: +// 1. AuthMethod will be either OAUTH2 or INTERNAL +// 2. If OAUTH2, TokenHash, Grants, and Expires will be non-nil, and ClientID +// may be non-nil, and NodeID will be nil. +// 3. If INTERNAL, TokenHash, Grants, Expires, and ClientID will be nil, and +// NodeID will be non-nil. type AuthConfig struct { - TokenHash string - Grants string - ClientID *string - Expires time.Time + AuthMethod string + TokenHash *string + Grants *string + ClientID *string + Expires *time.Time + NodeID *string } // Pulls auth details out of the config context and returns a structure of all @@ -25,16 +33,21 @@ switch user.AuthMethod { case auth.AUTH_OAUTH_LEGACY: return AuthConfig{}, fmt.Errorf("Native webhooks are not supported with legacy OAuth") case auth.AUTH_OAUTH2: - ac := AuthConfig{ - TokenHash: hex.EncodeToString(user.TokenHash[:]), - Grants: user.BearerToken.Grants, - Expires: user.BearerToken.Expires.Time(), - } + tokenHash := hex.EncodeToString(user.TokenHash[:]) + grants := user.BearerToken.Grants + expires := user.BearerToken.Expires.Time() + var clientID *string if user.BearerToken.ClientID != "" { - clientID := user.BearerToken.ClientID - ac.ClientID = &clientID + _clientID := user.BearerToken.ClientID + clientID = &_clientID } - return ac, nil + return AuthConfig { + AuthMethod: user.AuthMethod, + TokenHash: &tokenHash, + Grants: &grants, + Expires: &expires, + ClientID: clientID, + }, nil case auth.AUTH_COOKIE: // TODO: Should this work? return AuthConfig{}, fmt.Errorf("Native webhooks are not supported with web authentication") diff --git a/webhooks/context.go b/webhooks/context.go index 082f7d2da8efca92934bd638939e7f1c339c0592..0ebc794484a9e2fa3bd2a4e8e340191b1eb6a19d 100644 --- a/webhooks/context.go +++ b/webhooks/context.go @@ -50,7 +50,10 @@ // the configuration of a secondary authentication and GraphQL context. func (webhook *WebhookContext) Exec(ctx context.Context, schema graphql.ExecutableSchema) ([]byte, error) { sub := webhook.Subscription - tslice, err := hex.DecodeString(sub.TokenHash) + if sub.AuthMethod != auth.AUTH_OAUTH2 { + panic("TODO") + } + tslice, err := hex.DecodeString(*sub.TokenHash) if err != nil { panic(err) } @@ -58,7 +61,7 @@ var tokenHash [64]byte copy(tokenHash[:], tslice) ctx, err = auth.WebhookAuth(ctx, webhook.User, - tokenHash, sub.Grants, sub.ClientID, sub.Expires) + tokenHash, *sub.Grants, sub.ClientID, *sub.Expires) if err != nil { // TODO: This codepath can occur when the token has expired, and we may // want to communicate this to the user. diff --git a/webhooks/queue.go b/webhooks/queue.go index fc6b8cf6d9df735f669b62d1b07a6a580627c71d..7c660ee2152f2b0266ef99a967772a7dbe700cb1 100644 --- a/webhooks/queue.go +++ b/webhooks/queue.go @@ -28,13 +28,15 @@ Schema graphql.ExecutableSchema } type WebhookSubscription struct { - ID int - URL string - Query string - TokenHash string - Grants string - ClientID *string - Expires time.Time + ID int + URL string + Query string + AuthMethod string + TokenHash *string + Grants *string + ClientID *string + NodeID *string + Expires *time.Time } // Creates a new worker for delivering webhooks. The caller must start the @@ -125,8 +127,9 @@ rows *sql.Rows ) if rows, err = q. Columns("sub.id", "sub.url", "sub.query", - "sub.token_hash", "sub.grants", "sub.client_id", - "sub.expires"). + "sub.auth_method", + "sub.token_hash", "sub.grants", "sub.client_id", "sub.expires", + "sub.node_id"). Where("? = ANY(sub.events)", event). PlaceholderFormat(sq.Dollar). RunWith(tx). @@ -138,8 +141,9 @@ for rows.Next() { var sub WebhookSubscription if err := rows.Scan(&sub.ID, &sub.URL, &sub.Query, - &sub.TokenHash, &sub.Grants, &sub.ClientID, - &sub.Expires); err != nil { + &sub.AuthMethod, + &sub.TokenHash, &sub.Grants, &sub.ClientID, &sub.Expires, + &sub.NodeID); err != nil { panic(err) } subs = append(subs, &sub)