Add StateVersion.Three to fix premium migration (#666)
* Add StateVersion.Three to fix premium migration
This commit is contained in:
parent
52f77c0277
commit
5fad7c666f
|
@ -1,5 +1,6 @@
|
|||
export enum StateVersion {
|
||||
One = 1, // Original flat key/value pair store
|
||||
Two = 2, // Move to a typed State object
|
||||
Latest = Two,
|
||||
Three = 3, // Fix migration of users' premium status
|
||||
Latest = Three,
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import { GlobalStateFactory } from "../factories/globalStateFactory";
|
|||
import { StateFactory } from "../factories/stateFactory";
|
||||
import { Account, AccountSettings } from "../models/domain/account";
|
||||
|
||||
import { TokenService } from "./token.service";
|
||||
|
||||
// Originally (before January 2022) storage was handled as a flat key/value pair store.
|
||||
// With the move to a typed object for state storage these keys should no longer be in use anywhere outside of this migration.
|
||||
const v1Keys: { [key: string]: string } = {
|
||||
|
@ -153,6 +155,9 @@ export class StateMigrationService<
|
|||
case StateVersion.One:
|
||||
await this.migrateStateFrom1To2();
|
||||
break;
|
||||
case StateVersion.Two:
|
||||
await this.migrateStateFrom2To3();
|
||||
break;
|
||||
}
|
||||
|
||||
currentStateVersion += 1;
|
||||
|
@ -448,6 +453,27 @@ export class StateMigrationService<
|
|||
}
|
||||
}
|
||||
|
||||
protected async migrateStateFrom2To3(): Promise<void> {
|
||||
const authenticatedUserIds = await this.get<string[]>(keys.authenticatedAccounts);
|
||||
await Promise.all(
|
||||
authenticatedUserIds.map(async (userId) => {
|
||||
const account = await this.get<TAccount>(userId);
|
||||
if (
|
||||
account?.profile?.hasPremiumPersonally === null &&
|
||||
account.tokens?.accessToken != null
|
||||
) {
|
||||
const decodedToken = await TokenService.decodeToken(account.tokens.accessToken);
|
||||
account.profile.hasPremiumPersonally = decodedToken.premium;
|
||||
await this.set(userId, account);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const globals = await this.getGlobals();
|
||||
globals.stateVersion = StateVersion.Three;
|
||||
await this.set(keys.global, globals);
|
||||
}
|
||||
|
||||
protected get options(): StorageOptions {
|
||||
return { htmlStorageLocation: HtmlStorageLocation.Local };
|
||||
}
|
||||
|
|
|
@ -6,6 +6,25 @@ import { Utils } from "../misc/utils";
|
|||
import { IdentityTokenResponse } from "../models/response/identityTokenResponse";
|
||||
|
||||
export class TokenService implements TokenServiceAbstraction {
|
||||
static decodeToken(token: string): Promise<any> {
|
||||
if (token == null) {
|
||||
throw new Error("Token not provided.");
|
||||
}
|
||||
|
||||
const parts = token.split(".");
|
||||
if (parts.length !== 3) {
|
||||
throw new Error("JWT must have 3 parts");
|
||||
}
|
||||
|
||||
const decoded = Utils.fromUrlB64ToUtf8(parts[1]);
|
||||
if (decoded == null) {
|
||||
throw new Error("Cannot decode the token");
|
||||
}
|
||||
|
||||
const decodedToken = JSON.parse(decoded);
|
||||
return decodedToken;
|
||||
}
|
||||
|
||||
constructor(private stateService: StateService) {}
|
||||
|
||||
async setTokens(
|
||||
|
@ -87,18 +106,7 @@ export class TokenService implements TokenServiceAbstraction {
|
|||
throw new Error("Token not found.");
|
||||
}
|
||||
|
||||
const parts = token.split(".");
|
||||
if (parts.length !== 3) {
|
||||
throw new Error("JWT must have 3 parts");
|
||||
}
|
||||
|
||||
const decoded = Utils.fromUrlB64ToUtf8(parts[1]);
|
||||
if (decoded == null) {
|
||||
throw new Error("Cannot decode the token");
|
||||
}
|
||||
|
||||
const decodedToken = JSON.parse(decoded);
|
||||
return decodedToken;
|
||||
return TokenService.decodeToken(token);
|
||||
}
|
||||
|
||||
async getTokenExpirationDate(): Promise<Date> {
|
||||
|
|
Loading…
Reference in New Issue