(ctx context.Context, params database.UpdateExternalAuthLinkRefreshTokenParams)
| 263 | } |
| 264 | |
| 265 | func (db *dbCrypt) UpdateExternalAuthLinkRefreshToken(ctx context.Context, params database.UpdateExternalAuthLinkRefreshTokenParams) error { |
| 266 | // The SQL query uses an optimistic lock: |
| 267 | // WHERE oauth_refresh_token = @old_oauth_refresh_token |
| 268 | // The caller supplies the plaintext old token (since dbcrypt |
| 269 | // decrypts on read), but the DB stores the encrypted value. |
| 270 | // Because AES-GCM is non-deterministic, we cannot simply |
| 271 | // re-encrypt the old token — the ciphertext would differ. |
| 272 | // Instead, read the current row from the inner (raw) store |
| 273 | // and use the actual encrypted value for the WHERE clause. |
| 274 | if params.OldOauthRefreshToken != "" && db.ciphers != nil && db.primaryCipherDigest != "" { |
| 275 | raw, err := db.Store.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ |
| 276 | ProviderID: params.ProviderID, |
| 277 | UserID: params.UserID, |
| 278 | }) |
| 279 | if err != nil { |
| 280 | return err |
| 281 | } |
| 282 | // Decrypt the stored token so we can compare with the |
| 283 | // caller-supplied plaintext. |
| 284 | decrypted := raw.OAuthRefreshToken |
| 285 | if err := db.decryptField(&decrypted, raw.OAuthRefreshTokenKeyID); err != nil { |
| 286 | return err |
| 287 | } |
| 288 | if decrypted != params.OldOauthRefreshToken { |
| 289 | // The token has changed since the caller read it; |
| 290 | // the optimistic lock should fail (no rows updated). |
| 291 | // Return nil to match the :exec semantics of the SQL |
| 292 | // query, which silently updates zero rows. |
| 293 | return nil |
| 294 | } |
| 295 | // Use the raw encrypted value so the WHERE clause matches. |
| 296 | params.OldOauthRefreshToken = raw.OAuthRefreshToken |
| 297 | } |
| 298 | |
| 299 | // We would normally use a sql.NullString here, but sqlc does not want to make |
| 300 | // a params struct with a nullable string. |
| 301 | var digest sql.NullString |
| 302 | if params.OAuthRefreshTokenKeyID != "" { |
| 303 | digest.String = params.OAuthRefreshTokenKeyID |
| 304 | digest.Valid = true |
| 305 | } |
| 306 | if err := db.encryptField(¶ms.OAuthRefreshToken, &digest); err != nil { |
| 307 | return err |
| 308 | } |
| 309 | |
| 310 | return db.Store.UpdateExternalAuthLinkRefreshToken(ctx, params) |
| 311 | } |
| 312 | |
| 313 | func (db *dbCrypt) GetCryptoKeys(ctx context.Context) ([]database.CryptoKey, error) { |
| 314 | keys, err := db.Store.GetCryptoKeys(ctx) |
nothing calls this directly
no test coverage detected