Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update subscribed accounts when connected site authorizations are modified #1412

Merged
merged 3 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ export default class Extension {
}

private updateCurrentTabs ({ urls }: RequestActiveTabsUrlUpdate) {
this.#state.udateCurrentTabsUrl(urls);
this.#state.updateCurrentTabsUrl(urls);
}

private getConnectedTabsUrl () {
Expand Down
35 changes: 27 additions & 8 deletions packages/extension-base/src/background/handlers/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ export default class State {

public readonly signSubject: BehaviorSubject<SigningRequest[]> = new BehaviorSubject<SigningRequest[]>([]);

public readonly authUrlSubjects: Record<string, BehaviorSubject<AuthUrlInfo>> = {};

public defaultAuthAccountSelection: string[] = [];

constructor (providers: Providers = {}) {
Expand All @@ -169,6 +171,11 @@ export default class State {

this.#authUrls = previousAuth;

// Initialize authUrlSubjects for each URL
Object.entries(previousAuth).forEach(([url, authInfo]) => {
this.authUrlSubjects[url] = new BehaviorSubject<AuthUrlInfo>(authInfo);
});

// retrieve previously set default auth accounts
const storageDefaultAuthAccounts: Record<string, string> = await chrome.storage.local.get(DEFAULT_AUTH_ACCOUNTS);
const defaultAuthString: string = storageDefaultAuthAccounts?.[DEFAULT_AUTH_ACCOUNTS] || '[]';
Expand Down Expand Up @@ -215,10 +222,6 @@ export default class State {
return this.#authUrls;
}

private set authUrls (urls: AuthUrls) {
this.#authUrls = urls;
}

private popupClose (): void {
this.#windows.forEach((id: number) =>
withErrorLog(() => chrome.windows.remove(id))
Expand All @@ -243,14 +246,24 @@ export default class State {
const complete = async (authorizedAccounts: string[] = []) => {
const { idStr, request: { origin }, url } = this.#authRequests[id];

this.#authUrls[this.stripUrl(url)] = {
const strippedUrl = this.stripUrl(url);

const authInfo: AuthUrlInfo = {
authorizedAccounts,
count: 0,
id: idStr,
origin,
url
};

this.#authUrls[strippedUrl] = authInfo;

if (!this.authUrlSubjects[strippedUrl]) {
this.authUrlSubjects[strippedUrl] = new BehaviorSubject<AuthUrlInfo>(authInfo);
} else {
this.authUrlSubjects[strippedUrl].next(authInfo);
}

await this.saveCurrentAuthList();
await this.updateDefaultAuthAccounts(authorizedAccounts);
delete this.#authRequests[id];
Expand All @@ -271,7 +284,7 @@ export default class State {
};
};

public udateCurrentTabsUrl (urls: string[]) {
public updateCurrentTabsUrl (urls: string[]) {
Copy link
Member

@TarikGul TarikGul Jul 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be more specific to @bee344 mention above: When we release this - this specific name change in the api should be mentioned as a BREAKING CHANGE - it's quite minor but nonetheless will be nice to have in the CHANGELOG and release message. I do like this though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should preserve the original method and just mark it as deprecated and add the new one with the fixed name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reintroduced udateCurrentTabsUrl and marked as deprecated.

const connectedTabs = urls.map((url) => {
let strippedUrl = '';

Expand Down Expand Up @@ -385,6 +398,11 @@ export default class State {
delete this.#authUrls[url];
await this.saveCurrentAuthList();

if (this.authUrlSubjects[url]) {
entry.authorizedAccounts = [];
this.authUrlSubjects[url].next(entry);
}

return this.#authUrls;
}

Expand All @@ -403,9 +421,10 @@ export default class State {
this.updateIcon(shouldClose);
}

public async updateAuthorizedAccounts (authorizedAccountDiff: AuthorizedAccountsDiff): Promise<void> {
authorizedAccountDiff.forEach(([url, authorizedAccountDiff]) => {
public async updateAuthorizedAccounts (authorizedAccountsDiff: AuthorizedAccountsDiff): Promise<void> {
authorizedAccountsDiff.forEach(([url, authorizedAccountDiff]) => {
this.#authUrls[url].authorizedAccounts = authorizedAccountDiff;
this.authUrlSubjects[url].next(this.#authUrls[url]);
});

await this.saveCurrentAuthList();
Expand Down
21 changes: 18 additions & 3 deletions packages/extension-base/src/background/handlers/Tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@

/* global chrome */

import type { Subscription } from 'rxjs';
import type { InjectedAccount, InjectedMetadataKnown, MetadataDef, ProviderMeta } from '@polkadot/extension-inject/types';
import type { KeyringPair } from '@polkadot/keyring/types';
import type { JsonRpcResponse } from '@polkadot/rpc-provider/types';
import type { SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types';
import type { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
import type { MessageTypes, RequestAccountList, RequestAccountUnsubscribe, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestTypes, ResponseRpcListProviders, ResponseSigning, ResponseTypes, SubscriptionMessageTypes } from '../types.js';
import type { AuthUrlInfo, MessageTypes, RequestAccountList, RequestAccountUnsubscribe, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestTypes, ResponseRpcListProviders, ResponseSigning, ResponseTypes, SubscriptionMessageTypes } from '../types.js';
import type { AuthResponse } from './State.js';
import type State from './State.js';

import { combineLatest, type Subscription } from 'rxjs';

import { checkIfDenied } from '@polkadot/phishing';
import { keyring } from '@polkadot/ui-keyring';
import { accounts as accountsObservable } from '@polkadot/ui-keyring/observable/accounts';
Expand Down Expand Up @@ -56,6 +57,10 @@ export default class Tabs {
private filterForAuthorizedAccounts (accounts: InjectedAccount[], url: string): InjectedAccount[] {
const auth = this.#state.authUrls[this.#state.stripUrl(url)];

if (!auth) {
return [];
}

return accounts.filter(
(allAcc) =>
auth.authorizedAccounts
Expand All @@ -79,8 +84,18 @@ export default class Tabs {
private accountsSubscribeAuthorized (url: string, id: string, port: chrome.runtime.Port): string {
const cb = createSubscription<'pub(accounts.subscribe)'>(id, port);

const strippedUrl = this.#state.stripUrl(url);

const authUrlObservable = this.#state.authUrlSubjects[strippedUrl]?.asObservable();

if (!authUrlObservable) {
console.error(`No authUrlSubject found for ${strippedUrl}`);

return id;
}

this.#accountSubs[id] = {
subscription: accountsObservable.subject.subscribe((accounts: SubjectInfo): void => {
subscription: combineLatest([accountsObservable.subject, authUrlObservable]).subscribe(([accounts, _authUrlInfo]: [SubjectInfo, AuthUrlInfo]): void => {
const transformedAccounts = transformAccounts(accounts);

cb(this.filterForAuthorizedAccounts(transformedAccounts, url));
Expand Down