Decrypt decrypts all user tokens and revokes all ciphers.
(ctx context.Context, log slog.Logger, sqlDB *sql.DB, ciphers []Cipher)
| 193 | |
| 194 | // Decrypt decrypts all user tokens and revokes all ciphers. |
| 195 | func Decrypt(ctx context.Context, log slog.Logger, sqlDB *sql.DB, ciphers []Cipher) error { |
| 196 | db := database.New(sqlDB) |
| 197 | cdb, err := New(ctx, db, ciphers...) |
| 198 | if err != nil { |
| 199 | return xerrors.Errorf("create cryptdb: %w", err) |
| 200 | } |
| 201 | |
| 202 | // HACK: instead of adding logic to configure the primary cipher, we just |
| 203 | // set it to the empty string so that it will not encrypt anything. |
| 204 | cryptDB, ok := cdb.(*dbCrypt) |
| 205 | if !ok { |
| 206 | return xerrors.Errorf("developer error: dbcrypt.New did not return *dbCrypt") |
| 207 | } |
| 208 | cryptDB.primaryCipherDigest = "" |
| 209 | |
| 210 | userIDs, err := db.AllUserIDs(ctx, false) |
| 211 | if err != nil { |
| 212 | return xerrors.Errorf("get users: %w", err) |
| 213 | } |
| 214 | log.Info(ctx, "decrypting user tokens", slog.F("user_count", len(userIDs))) |
| 215 | for idx, uid := range userIDs { |
| 216 | err := cryptDB.InTx(func(tx database.Store) error { |
| 217 | userLinks, err := tx.GetUserLinksByUserID(ctx, uid) |
| 218 | if err != nil { |
| 219 | return xerrors.Errorf("get user links for user: %w", err) |
| 220 | } |
| 221 | for _, userLink := range userLinks { |
| 222 | if !userLink.OAuthAccessTokenKeyID.Valid && !userLink.OAuthRefreshTokenKeyID.Valid { |
| 223 | log.Debug(ctx, "skipping user link", slog.F("user_id", uid), slog.F("current", idx+1)) |
| 224 | continue |
| 225 | } |
| 226 | if _, err := tx.UpdateUserLink(ctx, database.UpdateUserLinkParams{ |
| 227 | OAuthAccessToken: userLink.OAuthAccessToken, |
| 228 | OAuthAccessTokenKeyID: sql.NullString{}, // we explicitly want to clear the key id |
| 229 | OAuthRefreshToken: userLink.OAuthRefreshToken, |
| 230 | OAuthRefreshTokenKeyID: sql.NullString{}, // we explicitly want to clear the key id |
| 231 | OAuthExpiry: userLink.OAuthExpiry, |
| 232 | UserID: uid, |
| 233 | LoginType: userLink.LoginType, |
| 234 | Claims: userLink.Claims, |
| 235 | }); err != nil { |
| 236 | return xerrors.Errorf("update user link user_id=%s linked_id=%s: %w", userLink.UserID, userLink.LinkedID, err) |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | externalAuthLinks, err := tx.GetExternalAuthLinksByUserID(ctx, uid) |
| 241 | if err != nil { |
| 242 | return xerrors.Errorf("get git auth links for user: %w", err) |
| 243 | } |
| 244 | for _, externalAuthLink := range externalAuthLinks { |
| 245 | if !externalAuthLink.OAuthAccessTokenKeyID.Valid && !externalAuthLink.OAuthRefreshTokenKeyID.Valid { |
| 246 | log.Debug(ctx, "skipping external auth link", slog.F("user_id", uid), slog.F("current", idx+1)) |
| 247 | continue |
| 248 | } |
| 249 | if _, err := tx.UpdateExternalAuthLink(ctx, database.UpdateExternalAuthLinkParams{ |
| 250 | ProviderID: externalAuthLink.ProviderID, |
| 251 | UserID: uid, |
| 252 | UpdatedAt: externalAuthLink.UpdatedAt, |
no test coverage detected