- Fix race condition where permission prompts failed on first request due to Buffer polyfill not being initialized during module evaluation - Replace Buffer.from() with native browser APIs (atob + TextDecoder) in prompt.ts for reliable base64 decoding - Add debug logging to reckless mode approval checks - Update permission encryption to support v2 vault key format - Enhance LoggerService with warn/error/debug methods and log storage - Add logs component for viewing extension activity - Simplify deriving modal component - Rename icon files from gooti to plebian-signer - Update permissions component with improved styling Files modified: - projects/chrome/src/prompt.ts - projects/firefox/src/prompt.ts - projects/*/src/background-common.ts - projects/common/src/lib/services/logger/logger.service.ts - projects/*/src/app/components/home/logs/ (new) - projects/*/public/*.svg, *.png (renamed) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
90 lines
2.3 KiB
TypeScript
90 lines
2.3 KiB
TypeScript
import { Component, inject, OnInit } from '@angular/core';
|
|
import {
|
|
IconButtonComponent,
|
|
Identity_DECRYPTED,
|
|
NavComponent,
|
|
Permission_DECRYPTED,
|
|
StorageService,
|
|
} from '@common';
|
|
import { ActivatedRoute } from '@angular/router';
|
|
|
|
interface HostPermissions {
|
|
host: string;
|
|
permissions: Permission_DECRYPTED[];
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-permissions',
|
|
imports: [IconButtonComponent],
|
|
templateUrl: './permissions.component.html',
|
|
styleUrl: './permissions.component.scss',
|
|
})
|
|
export class PermissionsComponent extends NavComponent implements OnInit {
|
|
identity?: Identity_DECRYPTED;
|
|
hostsPermissions: HostPermissions[] = [];
|
|
|
|
readonly #activatedRoute = inject(ActivatedRoute);
|
|
readonly #storage = inject(StorageService);
|
|
|
|
ngOnInit(): void {
|
|
const selectedIdentityId =
|
|
this.#activatedRoute.parent?.snapshot.params['id'];
|
|
if (!selectedIdentityId) {
|
|
return;
|
|
}
|
|
|
|
this.#initialize(selectedIdentityId);
|
|
}
|
|
|
|
async onClickRevokePermission(permission: Permission_DECRYPTED) {
|
|
await this.#storage.deletePermission(permission.id);
|
|
this.#buildHostsPermissions(this.identity?.id);
|
|
}
|
|
|
|
async onClickRemoveAllPermissions() {
|
|
const allPermissions = this.hostsPermissions.flatMap(hp => hp.permissions);
|
|
for (const permission of allPermissions) {
|
|
await this.#storage.deletePermission(permission.id);
|
|
}
|
|
this.#buildHostsPermissions(this.identity?.id);
|
|
}
|
|
|
|
#initialize(identityId: string) {
|
|
this.identity = this.#storage
|
|
.getBrowserSessionHandler()
|
|
.browserSessionData?.identities.find((x) => x.id === identityId);
|
|
|
|
if (!this.identity) {
|
|
return;
|
|
}
|
|
|
|
this.#buildHostsPermissions(identityId);
|
|
}
|
|
|
|
#buildHostsPermissions(identityId: string | undefined) {
|
|
if (!identityId) {
|
|
return;
|
|
}
|
|
|
|
this.hostsPermissions = [];
|
|
|
|
const hostPermissions = (
|
|
this.#storage.getBrowserSessionHandler().browserSessionData
|
|
?.permissions ?? []
|
|
)
|
|
.filter((x) => x.identityId === identityId)
|
|
.sortBy((x) => x.host)
|
|
.groupBy(
|
|
(x) => x.host,
|
|
(y) => y
|
|
);
|
|
|
|
hostPermissions.forEach((permissions, host) => {
|
|
this.hostsPermissions.push({
|
|
host: host,
|
|
permissions: permissions.sortBy((x) => x.method),
|
|
});
|
|
});
|
|
}
|
|
}
|