Merge pull request #277 from ltctceplrm/api-key-popup
Add legacy api key popup so users can copy old keys
This commit is contained in:
commit
63e8359895
4 changed files with 199 additions and 56 deletions
|
|
@ -16,6 +16,8 @@ import { TMDBSeasonAPI } from 'packages/obsidian/src/api/apis/TMDBSeasonAPI';
|
||||||
import { TMDBSeriesAPI } from 'packages/obsidian/src/api/apis/TMDBSeriesAPI';
|
import { TMDBSeriesAPI } from 'packages/obsidian/src/api/apis/TMDBSeriesAPI';
|
||||||
import { VNDBAPI } from 'packages/obsidian/src/api/apis/VNDBAPI';
|
import { VNDBAPI } from 'packages/obsidian/src/api/apis/VNDBAPI';
|
||||||
import { WikipediaAPI } from 'packages/obsidian/src/api/apis/WikipediaAPI';
|
import { WikipediaAPI } from 'packages/obsidian/src/api/apis/WikipediaAPI';
|
||||||
|
import type { LegacyApiKeyEntry } from 'packages/obsidian/src/modals/LegacyApiKeysModal';
|
||||||
|
import { LegacyApiKeysModal } from 'packages/obsidian/src/modals/LegacyApiKeysModal';
|
||||||
import { PropertyMapper } from 'packages/obsidian/src/settings/PropertyMapper';
|
import { PropertyMapper } from 'packages/obsidian/src/settings/PropertyMapper';
|
||||||
import { PropertyMappingModel } from 'packages/obsidian/src/settings/PropertyMapping';
|
import { PropertyMappingModel } from 'packages/obsidian/src/settings/PropertyMapping';
|
||||||
import type { MediaDbPluginSettings } from 'packages/obsidian/src/settings/Settings';
|
import type { MediaDbPluginSettings } from 'packages/obsidian/src/settings/Settings';
|
||||||
|
|
@ -168,35 +170,42 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadSettings(): Promise<void> {
|
private getLegacyApiKeyEntries(diskSettings: Record<string, unknown>): LegacyApiKeyEntry[] {
|
||||||
const diskSettings: MediaDbPluginSettings = (await this.loadData()) as MediaDbPluginSettings;
|
return this.settings.LegacyApiKeys.filter(key => typeof diskSettings[key] === 'string' && diskSettings[key].length > 0).map(key => ({
|
||||||
const defaultSettings: MediaDbPluginSettings = getDefaultSettings(this);
|
key,
|
||||||
const loadedSettings: MediaDbPluginSettings = Object.assign({}, defaultSettings, diskSettings);
|
value: diskSettings[key] as string,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
// delete old api keys
|
private removeLegacyApiKeys(settings: Record<string, unknown>): void {
|
||||||
// @ts-ignore
|
for (const key of this.settings.LegacyApiKeys) {
|
||||||
delete loadedSettings.BoardgameGeekKey;
|
delete settings[key];
|
||||||
// @ts-ignore
|
}
|
||||||
delete loadedSettings.ComicVineKey;
|
}
|
||||||
// @ts-ignore
|
|
||||||
delete loadedSettings.GiantBombKey;
|
async loadSettings(): Promise<void> {
|
||||||
// @ts-ignore
|
const diskSettings = (await this.loadData()) as Record<string, unknown>;
|
||||||
delete loadedSettings.MobyGamesKey;
|
const defaultSettings: MediaDbPluginSettings = getDefaultSettings(this);
|
||||||
// @ts-ignore
|
const loadedSettings = Object.assign({}, defaultSettings, diskSettings) as MediaDbPluginSettings;
|
||||||
delete loadedSettings.OMDbKey;
|
|
||||||
// @ts-ignore
|
|
||||||
delete loadedSettings.TMDBKey;
|
|
||||||
|
|
||||||
const migratedModels = PropertyMappingModel.migrateModels(
|
const migratedModels = PropertyMappingModel.migrateModels(
|
||||||
loadedSettings.propertyMappingModels || [],
|
loadedSettings.propertyMappingModels || [],
|
||||||
defaultSettings.propertyMappingModels.map(m => PropertyMappingModel.fromJSON(m)),
|
defaultSettings.propertyMappingModels.map(m => PropertyMappingModel.fromJSON(m)),
|
||||||
);
|
);
|
||||||
|
|
||||||
loadedSettings.propertyMappingModels = migratedModels.map(m => m.toJSON());
|
loadedSettings.propertyMappingModels = migratedModels.map(m => m.toJSON());
|
||||||
|
|
||||||
this.settings = loadedSettings;
|
this.settings = loadedSettings;
|
||||||
|
|
||||||
await this.saveSettings();
|
const legacyEntries = this.getLegacyApiKeyEntries(diskSettings);
|
||||||
|
if (legacyEntries.length > 0) {
|
||||||
|
this.app.workspace.onLayoutReady((): void => {
|
||||||
|
window.setTimeout((): void => {
|
||||||
|
new LegacyApiKeysModal(this.app, legacyEntries, (): void => {
|
||||||
|
this.removeLegacyApiKeys(this.settings as unknown as Record<string, unknown>);
|
||||||
|
void this.saveSettings();
|
||||||
|
}).open();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveSettings(): Promise<void> {
|
async saveSettings(): Promise<void> {
|
||||||
|
|
|
||||||
93
packages/obsidian/src/modals/LegacyApiKeysModal.ts
Normal file
93
packages/obsidian/src/modals/LegacyApiKeysModal.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
import type { App } from 'obsidian';
|
||||||
|
import { Modal, Setting, Notice } from 'obsidian';
|
||||||
|
|
||||||
|
export interface LegacyApiKeyEntry {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LegacyApiKeysModal extends Modal {
|
||||||
|
private entries: LegacyApiKeyEntry[];
|
||||||
|
private onConfirm: () => void;
|
||||||
|
|
||||||
|
constructor(app: App, entries: LegacyApiKeyEntry[], onConfirm: () => void) {
|
||||||
|
super(app);
|
||||||
|
this.entries = entries;
|
||||||
|
this.onConfirm = onConfirm;
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpen(): void {
|
||||||
|
const { contentEl } = this;
|
||||||
|
contentEl.addClass('media-db-plugin-legacy-keys-modal');
|
||||||
|
|
||||||
|
contentEl.createEl('h2', { text: 'Media DB plugin: Legacy API keys found' });
|
||||||
|
|
||||||
|
const wrapper = contentEl.createDiv({ cls: 'media-db-plugin-legacy-keys-wrapper' });
|
||||||
|
|
||||||
|
const intro = wrapper.createDiv({ cls: 'media-db-plugin-legacy-keys-intro' });
|
||||||
|
intro.createEl('p', {
|
||||||
|
text: 'Media DB plugin has found old plaintext API keys in your settings. Copy them now if needed, they should be removed for safety.',
|
||||||
|
});
|
||||||
|
|
||||||
|
intro.createEl('p', {
|
||||||
|
text: 'The new keychain-backed system will be used instead. The plugin will not be usable until the old plaintext keys have been deleted.',
|
||||||
|
});
|
||||||
|
|
||||||
|
const textarea = wrapper.createEl('textarea', {
|
||||||
|
cls: 'media-db-plugin-legacy-keys-textarea',
|
||||||
|
attr: {
|
||||||
|
readonly: 'true',
|
||||||
|
spellcheck: 'false',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
textarea.value = this.entries.map(e => `${e.key}: ${e.value}`).join('\n');
|
||||||
|
textarea.addClass('media-db-plugin-hidden');
|
||||||
|
|
||||||
|
contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
|
||||||
|
|
||||||
|
const bottomSettingRow = new Setting(contentEl);
|
||||||
|
|
||||||
|
bottomSettingRow.addButton(btn => {
|
||||||
|
btn.setButtonText('Copy');
|
||||||
|
btn.onClick(async () => {
|
||||||
|
await navigator.clipboard.writeText(textarea.value);
|
||||||
|
new Notice('Legacy API keys copied to clipboard.');
|
||||||
|
});
|
||||||
|
btn.buttonEl.addClass('media-db-plugin-button');
|
||||||
|
});
|
||||||
|
|
||||||
|
bottomSettingRow.addButton(btn => {
|
||||||
|
btn.setButtonText('Show keys');
|
||||||
|
|
||||||
|
btn.onClick(() => {
|
||||||
|
const isHidden = textarea.hasClass('media-db-plugin-hidden');
|
||||||
|
if (isHidden) {
|
||||||
|
textarea.removeClass('media-db-plugin-hidden');
|
||||||
|
btn.setButtonText('Hide keys');
|
||||||
|
} else {
|
||||||
|
textarea.addClass('media-db-plugin-hidden');
|
||||||
|
btn.setButtonText('Show keys');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btn.buttonEl.addClass('media-db-plugin-button');
|
||||||
|
});
|
||||||
|
|
||||||
|
bottomSettingRow.addButton(btn => {
|
||||||
|
btn.setButtonText('Delete plaintext keys');
|
||||||
|
btn.setCta();
|
||||||
|
btn.onClick(() => {
|
||||||
|
this.close();
|
||||||
|
this.onConfirm();
|
||||||
|
});
|
||||||
|
btn.buttonEl.addClass('media-db-plugin-button');
|
||||||
|
btn.buttonEl.addClass('mod-warning');
|
||||||
|
btn.buttonEl.addClass('mod-danger');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose(): void {
|
||||||
|
this.contentEl.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,14 +50,16 @@ function createPropertyMappingsDescription(): DocumentFragment {
|
||||||
export interface MediaDbPluginSettings {
|
export interface MediaDbPluginSettings {
|
||||||
OMDbKeyId: string;
|
OMDbKeyId: string;
|
||||||
TMDBKeyId: string;
|
TMDBKeyId: string;
|
||||||
MobyGamesKeyId: string;
|
//MobyGamesKeyId: string;
|
||||||
GiantBombKeyId: string;
|
//GiantBombKeyId: string;
|
||||||
IGDBClientId: string;
|
IGDBClientId: string;
|
||||||
IGDBClientSecret: string;
|
IGDBClientSecret: string;
|
||||||
RAWGAPIKeyId: string;
|
RAWGAPIKeyId: string;
|
||||||
ComicVineKeyId: string;
|
ComicVineKeyId: string;
|
||||||
BoardgameGeekKeyId: string;
|
BoardgameGeekKeyId: string;
|
||||||
|
|
||||||
|
LegacyApiKeys: readonly ['OMDbKey', 'TMDBKey', 'MobyGamesKey', 'GiantBombKey', 'ComicVineKey', 'BoardgameGeekKey'];
|
||||||
|
|
||||||
sfwFilter: boolean;
|
sfwFilter: boolean;
|
||||||
templates: boolean;
|
templates: boolean;
|
||||||
customDateFormat: string;
|
customDateFormat: string;
|
||||||
|
|
@ -69,12 +71,12 @@ export interface MediaDbPluginSettings {
|
||||||
|
|
||||||
BoardgameGeekAPI_disabledMediaTypes: MediaType[];
|
BoardgameGeekAPI_disabledMediaTypes: MediaType[];
|
||||||
ComicVineAPI_disabledMediaTypes: MediaType[];
|
ComicVineAPI_disabledMediaTypes: MediaType[];
|
||||||
GiantBombAPI_disabledMediaTypes: MediaType[];
|
//GiantBombAPI_disabledMediaTypes: MediaType[];
|
||||||
IGDBAPI_disabledMediaTypes: MediaType[];
|
IGDBAPI_disabledMediaTypes: MediaType[];
|
||||||
RAWGAPI_disabledMediaTypes: MediaType[];
|
RAWGAPI_disabledMediaTypes: MediaType[];
|
||||||
MALAPI_disabledMediaTypes: MediaType[];
|
MALAPI_disabledMediaTypes: MediaType[];
|
||||||
MALAPIManga_disabledMediaTypes: MediaType[];
|
MALAPIManga_disabledMediaTypes: MediaType[];
|
||||||
MobyGamesAPI_disabledMediaTypes: MediaType[];
|
//MobyGamesAPI_disabledMediaTypes: MediaType[];
|
||||||
MusicBrainzAPI_disabledMediaTypes: MediaType[];
|
MusicBrainzAPI_disabledMediaTypes: MediaType[];
|
||||||
OMDbAPI_disabledMediaTypes: MediaType[];
|
OMDbAPI_disabledMediaTypes: MediaType[];
|
||||||
OpenLibraryAPI_disabledMediaTypes: MediaType[];
|
OpenLibraryAPI_disabledMediaTypes: MediaType[];
|
||||||
|
|
@ -309,14 +311,16 @@ class MediaTypeMappedSettings {
|
||||||
const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
||||||
OMDbKeyId: '',
|
OMDbKeyId: '',
|
||||||
TMDBKeyId: '',
|
TMDBKeyId: '',
|
||||||
MobyGamesKeyId: '',
|
//MobyGamesKeyId: '',
|
||||||
GiantBombKeyId: '',
|
//GiantBombKeyId: '',
|
||||||
IGDBClientId: '',
|
IGDBClientId: '',
|
||||||
IGDBClientSecret: '',
|
IGDBClientSecret: '',
|
||||||
RAWGAPIKeyId: '',
|
RAWGAPIKeyId: '',
|
||||||
ComicVineKeyId: '',
|
ComicVineKeyId: '',
|
||||||
BoardgameGeekKeyId: '',
|
BoardgameGeekKeyId: '',
|
||||||
|
|
||||||
|
LegacyApiKeys: ['OMDbKey', 'TMDBKey', 'MobyGamesKey', 'GiantBombKey', 'ComicVineKey', 'BoardgameGeekKey'],
|
||||||
|
|
||||||
sfwFilter: true,
|
sfwFilter: true,
|
||||||
templates: true,
|
templates: true,
|
||||||
customDateFormat: 'L',
|
customDateFormat: 'L',
|
||||||
|
|
@ -328,12 +332,12 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
||||||
|
|
||||||
BoardgameGeekAPI_disabledMediaTypes: [],
|
BoardgameGeekAPI_disabledMediaTypes: [],
|
||||||
ComicVineAPI_disabledMediaTypes: [],
|
ComicVineAPI_disabledMediaTypes: [],
|
||||||
GiantBombAPI_disabledMediaTypes: [],
|
//GiantBombAPI_disabledMediaTypes: [],
|
||||||
IGDBAPI_disabledMediaTypes: [],
|
IGDBAPI_disabledMediaTypes: [],
|
||||||
RAWGAPI_disabledMediaTypes: [],
|
RAWGAPI_disabledMediaTypes: [],
|
||||||
MALAPI_disabledMediaTypes: [],
|
MALAPI_disabledMediaTypes: [],
|
||||||
MALAPIManga_disabledMediaTypes: [],
|
MALAPIManga_disabledMediaTypes: [],
|
||||||
MobyGamesAPI_disabledMediaTypes: [],
|
//MobyGamesAPI_disabledMediaTypes: [],
|
||||||
MusicBrainzAPI_disabledMediaTypes: [],
|
MusicBrainzAPI_disabledMediaTypes: [],
|
||||||
OMDbAPI_disabledMediaTypes: [],
|
OMDbAPI_disabledMediaTypes: [],
|
||||||
OpenLibraryAPI_disabledMediaTypes: [],
|
OpenLibraryAPI_disabledMediaTypes: [],
|
||||||
|
|
@ -610,38 +614,38 @@ export class MediaDbSettingTab extends PluginSettingTab {
|
||||||
return component;
|
return component;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
apiKeyGroup.addSetting(
|
// apiKeyGroup.addSetting(
|
||||||
setting =>
|
// setting =>
|
||||||
void setting
|
// void setting
|
||||||
.setName('Moby Games key')
|
// .setName('Moby Games key')
|
||||||
.setDesc('API key for "www.mobygames.com".')
|
// .setDesc('API key for "www.mobygames.com".')
|
||||||
.addComponent(el => {
|
// .addComponent(el => {
|
||||||
const component = new SecretComponent(this.app, el);
|
// const component = new SecretComponent(this.app, el);
|
||||||
|
|
||||||
component.setValue(this.plugin.settings.MobyGamesKeyId).onChange(data => {
|
// component.setValue(this.plugin.settings.MobyGamesKeyId).onChange(data => {
|
||||||
this.plugin.settings.MobyGamesKeyId = data;
|
// this.plugin.settings.MobyGamesKeyId = data;
|
||||||
void this.plugin.saveSettings();
|
// void this.plugin.saveSettings();
|
||||||
});
|
// });
|
||||||
|
|
||||||
return component;
|
// return component;
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
apiKeyGroup.addSetting(
|
// apiKeyGroup.addSetting(
|
||||||
setting =>
|
// setting =>
|
||||||
void setting
|
// void setting
|
||||||
.setName('Giant Bomb Key')
|
// .setName('Giant Bomb Key')
|
||||||
.setDesc('API key for "www.giantbomb.com".')
|
// .setDesc('API key for "www.giantbomb.com".')
|
||||||
.addComponent(el => {
|
// .addComponent(el => {
|
||||||
const component = new SecretComponent(this.app, el);
|
// const component = new SecretComponent(this.app, el);
|
||||||
|
|
||||||
component.setValue(this.plugin.settings.GiantBombKeyId).onChange(data => {
|
// component.setValue(this.plugin.settings.GiantBombKeyId).onChange(data => {
|
||||||
this.plugin.settings.GiantBombKeyId = data;
|
// this.plugin.settings.GiantBombKeyId = data;
|
||||||
void this.plugin.saveSettings();
|
// void this.plugin.saveSettings();
|
||||||
});
|
// });
|
||||||
|
|
||||||
return component;
|
// return component;
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
apiKeyGroup.addSetting(
|
apiKeyGroup.addSetting(
|
||||||
setting =>
|
setting =>
|
||||||
void setting
|
void setting
|
||||||
|
|
|
||||||
|
|
@ -295,3 +295,40 @@ small.media-db-plugin-list-text {
|
||||||
width: var(--checkbox-size);
|
width: var(--checkbox-size);
|
||||||
height: var(--checkbox-size);
|
height: var(--checkbox-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-legacy-keys-modal {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-legacy-keys-intro {
|
||||||
|
color: var(--text-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-legacy-keys-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--size-4-3);
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-legacy-keys-textarea {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
min-height: var(--size-4-5);
|
||||||
|
min-width: var(--size-4-7);
|
||||||
|
box-sizing: border-box;
|
||||||
|
resize: vertical;
|
||||||
|
padding: var(--size-4-3);
|
||||||
|
border-radius: var(--radius-s);
|
||||||
|
border: 1px solid var(--background-modifier-border);
|
||||||
|
background: var(--background-primary);
|
||||||
|
color: var(--text-normal);
|
||||||
|
font-family: var(--font-monospace);
|
||||||
|
font-size: var(--font-ui-smaller);
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
.media-db-plugin-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue