Skip to content

Commit

Permalink
wip: show login link
Browse files Browse the repository at this point in the history
  • Loading branch information
dtkav committed Aug 7, 2024
1 parent 0ae83a6 commit e1683d9
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 45 deletions.
11 changes: 8 additions & 3 deletions src/LiveTokenStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ async function refresh(
if (entity instanceof S3RemoteDocument) {
payload = JSON.stringify({
docId: entity.documentId,
folder: entity.folderId,
relay: entity.relayId,
});
} else if (entity instanceof S3RemoteFolder) {
payload = JSON.stringify({
docId: entity.folderId,
folder: entity.folderId,
relay: entity.relayId,
});
} else {
Expand Down Expand Up @@ -75,9 +77,12 @@ async function refresh(
const clientToken = response.json as ClientToken;
onSuccess(clientToken);
})
.catch((reason) => {
error(reason, payload);
onError(reason);
.catch((e) => {
error(e, payload);
if (e.status === 401) {
loginManager.pb.authStore.isValid;
}
onError(e);
});
}

Expand Down
98 changes: 80 additions & 18 deletions src/LoginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
import { requestUrl } from "obsidian";
import { ObservableSet } from "./observable/ObservableSet";
import { User } from "./User";
import PocketBase, { BaseAuthStore } from "pocketbase";
import PocketBase, {
BaseAuthStore,
ClientResponseError,
type RecordAuthResponse,
type RecordModel,
} from "pocketbase";
import { curryLog } from "./debug";
import { Observable } from "./observable/Observable";

Expand Down Expand Up @@ -93,9 +98,13 @@ export class OAuth2Url extends Observable<OAuth2Url> {
delay: number = 0;
_age: number = 0;

set(value: string) {
set(value: string | undefined) {
this.url = value;
this._age = Date.now();
if (value) {
this._age = Date.now();
} else {
this._age = 0;
}
this.notifyListeners();
}

Expand All @@ -104,6 +113,45 @@ export class OAuth2Url extends Observable<OAuth2Url> {
}
}

function openBrowserPopup(url?: string): Window | null {
if (typeof window === "undefined" || !window?.open) {
throw new ClientResponseError(
new Error(
`Not in a browser context - please pass a custom urlCallback function.`
)
);
}

let width = 1024;
let height = 768;

let windowWidth = window.innerWidth;
let windowHeight = window.innerHeight;

// normalize window size
width = width > windowWidth ? windowWidth : width;
height = height > windowHeight ? windowHeight : height;

let left = windowWidth / 2 - width / 2;
let top = windowHeight / 2 - height / 2;

// note: we don't use the noopener and noreferrer attributes since
// for some reason browser blocks such windows then url is undefined/blank
return window.open(
url,
"popup_window",
"width=" +
width +
",height=" +
height +
",top=" +
top +
",left=" +
left +
",resizable,menubar=no"
);
}

export class LoginManager extends Observable<LoginManager> {
pb: PocketBase;
sm?: SubscriptionManager;
Expand All @@ -115,9 +163,10 @@ export class LoginManager extends Observable<LoginManager> {
constructor(openSettings: () => Promise<void>) {
super();
this._log = curryLog("[LoginManager]");
const pbLog = curryLog("[Pocketbase]");
this.pb = new PocketBase(AUTH_URL);
this.pb.beforeSend = (url, options) => {
this._log(url, options);
pbLog(url, options);
options.fetch = customFetch;
return { url, options };
};
Expand All @@ -132,7 +181,7 @@ export class LoginManager extends Observable<LoginManager> {
this._log(message, ...args);
}

setup(): boolean {
setup(authData?: RecordAuthResponse<RecordModel> | undefined): boolean {
if (!this.pb.authStore.isValid) {
this.notifyListeners(); // notify anyway
return false;
Expand All @@ -141,7 +190,17 @@ export class LoginManager extends Observable<LoginManager> {
this.user = this.makeUser(this.pb.authStore);
//this.sm = new SubscriptionManager(user);
this.notifyListeners();
//this.whoami();
if (authData) {
this.pb
.collection("oauth2_response")
.create({
user: authData.record.id,
oauth_response: authData.meta?.rawUser,
})
.catch((reason) => {
this.log(reason);
});
}
return true;
}

Expand Down Expand Up @@ -183,29 +242,32 @@ export class LoginManager extends Observable<LoginManager> {
}

logout() {
this.pb.cancelAllRequests();
this.pb.authStore.clear();
this.user = undefined;
this.notifyListeners();
}

async login(): Promise<boolean> {
await this.pb
login(): Promise<boolean> {
let eagerDefaultPopup = openBrowserPopup();
return this.pb
.collection("users")
.authWithOAuth2({
provider: "google",
fetch: fetch,
urlCallback: (url) => {
this.url.set(url);
if (eagerDefaultPopup) {
eagerDefaultPopup.location.href = url;
} else {
eagerDefaultPopup = openBrowserPopup(url);
}
},
})
.then((authData) => {
this.pb
.collection("oauth2_response")
.create({
user: authData.record.id,
oauth_response: authData.meta?.rawUser,
})
.catch((e) => {
// OAuth2 data already exists
});
this.url.set(undefined);
return this.setup(authData);
});
return this.setup();
}

async openLoginPage() {
Expand Down
19 changes: 9 additions & 10 deletions src/RelayManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import {
type Role,
type RemoteSharedFolder as RemoteFolder,
} from "./Relay";
import PocketBase, { type ListResult, type RecordModel } from "pocketbase";
import PocketBase, {
type AuthModel,
type ListResult,
type RecordModel,
type RecordSubscription,
} from "pocketbase";
import { ObservableMap } from "./observable/ObservableMap";
import { curryLog } from "./debug";
import { customFetch } from "./customFetch";
Expand Down Expand Up @@ -724,13 +729,8 @@ export class RelayManager {
constructor() {
this.log = curryLog("[RelayManager]", "log");
this.warn = curryLog("[RelayManager]", "warn");

this.pb = new PocketBase(AUTH_URL);
this.pb.beforeSend = (url, options) => {
this.log(url, options);
options.fetch = customFetch;
return { url, options };
};
this.pb = this.loginManager.pb;

Check failure on line 732 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Property 'loginManager' does not exist on type 'RelayManager'.

Check failure on line 732 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Property 'loginManager' does not exist on type 'RelayManager'.
this.sm = new SubscriptionManager(this.loginManager);

Check failure on line 733 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Property 'sm' does not exist on type 'RelayManager'.

Check failure on line 733 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Cannot find name 'SubscriptionManager'.

Check failure on line 733 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Property 'loginManager' does not exist on type 'RelayManager'.

Check failure on line 733 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Property 'sm' does not exist on type 'RelayManager'.

Check failure on line 733 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Cannot find name 'SubscriptionManager'.

Check failure on line 733 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Property 'loginManager' does not exist on type 'RelayManager'.

// Build the NodeLists
this.users = new ObservableMap<string, UserDAO>();
Expand Down Expand Up @@ -1095,7 +1095,6 @@ export class RelayManager {
}

destroy(): void {
this.unsubscribe();
this.pb.cancelAllRequests();
this.sm.destroy();

Check failure on line 1098 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Property 'sm' does not exist on type 'RelayManager'.

Check failure on line 1098 in src/RelayManager.ts

View workflow job for this annotation

GitHub Actions / build

Property 'sm' does not exist on type 'RelayManager'.
}
}
52 changes: 39 additions & 13 deletions src/components/LoggedIn.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { debounce } from "obsidian";
import type Live from "../main";
import SettingItem from "./SettingItem.svelte";
import SettingItemHeading from "./SettingItemHeading.svelte";
Expand All @@ -7,13 +8,14 @@
export let plugin: Live;
let lm: LoginManager;
lm = plugin.loginManager;
let url = lm.url;
async function logout() {
function logout() {
plugin.loginManager.logout();
}
async function login() {
await plugin.loginManager.login();
function login() {
plugin.loginManager.login();
}
</script>

Expand All @@ -23,21 +25,45 @@
name="Your account"
description="You are currently logged in as: {$lm.user?.name}."
>
<button on:click={logout}>Logout</button>
<button
on:click={debounce(() => {
logout();
})}>Logout</button
>
</SettingItem>
<slot></slot>
{:else}
<SettingItemHeading name="Account" />
<SettingItem
name="Login"
description="You need to login to use this plugin."
>
<button
on:click={async () => {
await login();
}}>Login with Google</button
{#if $url.url === undefined}
<SettingItem
name="Login"
description="You need to login to use this plugin."
>
</SettingItem>
<button
on:click={debounce(async () => {
await login();
})}>Login with Google</button
>
</SettingItem>
{:else}
<SettingItem
name="Login"
description="Please complete the login flow in your browser and wait a few seconds."
>
<button
class="mod-destructive"
on:click={debounce(() => {
url.set(undefined);
})}>Cancel</button
>
</SettingItem>
<SettingItem
name=""
description="If the login button does not work, you can try to login manually by
visiting this URL in your browser."
></SettingItem>
<input type="text" value={$url.url} readonly style="width: 100%" />
{/if}
{/if}

<style>
Expand Down
1 change: 0 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ export default class Live extends Plugin {

private _onLogout() {
this.tokenStore?.clear();
this.relayManager?.logout();
this._liveViews.refresh("logout");
}

Expand Down

0 comments on commit e1683d9

Please sign in to comment.