From 20c4bbcee2dc452fd329e9329db5dc3ddca4e533 Mon Sep 17 00:00:00 2001 From: Zhihe Li Date: Thu, 13 Feb 2025 11:00:19 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20migration=20check?= =?UTF-8?q?=20to=20delete=20index=20DB=20when=20updating=20(#2241)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 Add migration check to delete index DB when updating ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13223 --- .../addon-test-support/helpers/indexed-db.js | 4 +-- addons/api/addon/services/indexed-db.js | 25 ++++++++++++++++--- .../scopes/scope/authenticate/method/index.js | 1 - ui/admin/app/routes/application.js | 2 +- ui/admin/app/services/session.js | 12 +++++---- .../scope/authenticate/method/index-test.js | 8 +----- 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/addons/api/addon-test-support/helpers/indexed-db.js b/addons/api/addon-test-support/helpers/indexed-db.js index 6adc6002e..01c927cf0 100644 --- a/addons/api/addon-test-support/helpers/indexed-db.js +++ b/addons/api/addon-test-support/helpers/indexed-db.js @@ -20,9 +20,9 @@ * @param hooks */ export function setupIndexedDb(hooks) { - hooks.beforeEach(function () { + hooks.beforeEach(async function () { const indexedDb = this.owner.lookup('service:indexed-db'); - indexedDb.setup(`test-indexed-db-${Date.now()}`); + await indexedDb.setup(`test-indexed-db-${Date.now()}`); }); hooks.afterEach(async function () { diff --git a/addons/api/addon/services/indexed-db.js b/addons/api/addon/services/indexed-db.js index 898cda3b6..0bd833bad 100644 --- a/addons/api/addon/services/indexed-db.js +++ b/addons/api/addon/services/indexed-db.js @@ -97,23 +97,42 @@ const unconvertFields = (result, object, schema, serializer) => { /** * Service to encapsulate the IndexedDB implementation. To use this service, call - * `setup` from the application root and + * `setup` from the application root. This will create the database and the necessary indexes. + * + * Make sure to increment the version number of the database whenever the indexes change. + * This will delete the old database and create a new one with the new indexes. */ export default class IndexedDbService extends Service { // =attributes #db; + #version = 2; + get db() { return this.#db; } - setup(dbName) { + async setup(dbName) { // Don't run setup again if we already have one or if we didn't get a name if (this.#db || !dbName) { return; } + const doesDbExist = await Dexie.exists(dbName); + + // If the database already exists, open the database and + // check if the version is a lower version than the current one + if (doesDbExist) { + const dbVerifier = new Dexie(dbName); + await dbVerifier.open(); + if (dbVerifier.verno < this.#version) { + await dbVerifier.delete(); + } else { + dbVerifier.close(); + } + } + this.#db = new Dexie(dbName); - this.#db.version(2).stores(modelIndexes); + this.#db.version(this.#version).stores(modelIndexes); } /** diff --git a/ui/admin/app/controllers/scopes/scope/authenticate/method/index.js b/ui/admin/app/controllers/scopes/scope/authenticate/method/index.js index 9c739ffca..162121c96 100644 --- a/ui/admin/app/controllers/scopes/scope/authenticate/method/index.js +++ b/ui/admin/app/controllers/scopes/scope/authenticate/method/index.js @@ -47,7 +47,6 @@ export default class ScopesScopeAuthenticateMethodIndexController extends Contro requestCookies, { scope, authMethod }, ); - this.router.transitionTo('index'); break; case TYPE_AUTH_METHOD_OIDC: await this.startOIDCAuthentication(authenticatorName, { diff --git a/ui/admin/app/routes/application.js b/ui/admin/app/routes/application.js index e91d193c0..a5933254c 100644 --- a/ui/admin/app/routes/application.js +++ b/ui/admin/app/routes/application.js @@ -73,7 +73,7 @@ export default class ApplicationRoute extends Route { const userId = this.session.data?.authenticated?.user_id; const hostUrl = this.window.location.host; if (userId && hostUrl) { - this.indexedDb.setup(formatDbName(userId, hostUrl)); + await this.indexedDb.setup(formatDbName(userId, hostUrl)); } } } diff --git a/ui/admin/app/services/session.js b/ui/admin/app/services/session.js index 174f92622..b2d5f251b 100644 --- a/ui/admin/app/services/session.js +++ b/ui/admin/app/services/session.js @@ -15,13 +15,15 @@ export default class SessionService extends BaseSessionService { * Extend ember simple auth's handleAuthentication method * so we can hook in and setup the DB after a successful authentication */ - handleAuthentication() { - super.handleAuthentication(...arguments); - + async handleAuthentication() { const userId = this.data?.authenticated?.user_id; - const hostUrl = this.window.location.host; + const hostUrl = this.window.location?.host; if (userId && hostUrl) { - this.indexedDb.setup(formatDbName(userId, hostUrl)); + await this.indexedDb.setup(formatDbName(userId, hostUrl)); } + + // We let ember-simple-auth handle transitioning back to the index after authentication. + // This route can be configured in our environment config. + super.handleAuthentication(...arguments); } } diff --git a/ui/admin/tests/unit/controllers/scopes/scope/authenticate/method/index-test.js b/ui/admin/tests/unit/controllers/scopes/scope/authenticate/method/index-test.js index d2b849aa1..d52fb33e6 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/authenticate/method/index-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/authenticate/method/index-test.js @@ -5,7 +5,7 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -import { currentURL, visit, waitUntil } from '@ember/test-helpers'; +import { visit } from '@ember/test-helpers'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import { setupIndexedDb } from 'api/test-support/helpers/indexed-db'; import { authenticateSession } from 'ember-simple-auth/test-support'; @@ -55,10 +55,6 @@ module( urls.authenticate = `scopes/global/authenticate/${instances.authMethod}`; }); - test('it exists', function (assert) { - assert.ok(controller); - }); - test('authenticate action saves login information and redirects to correct page', async function (assert) { await visit(urls.authenticate); const identification = 'admin123'; @@ -76,11 +72,9 @@ module( identification, password: 'password', }); - await waitUntil(() => currentURL() === urls.globalScope); const { authenticator: authAfter, username: usernameAfter } = session.data.authenticated; - assert.strictEqual(currentURL(), urls.globalScope); assert.strictEqual( authAfter, `authenticator:${instances.authMethod.type}`,