Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
28 changes: 20 additions & 8 deletions apps/app/src/routes/auth.sign-in.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SignedOut, useSignIn } from "@clerk/clerk-react";
import { SignedIn, SignedOut, useSignIn } from "@clerk/clerk-react";
import type { OAuthStrategy } from "@clerk/types";
import { createFileRoute, LinkProps } from "@tanstack/react-router";
import { createFileRoute, LinkProps, useNavigate } from "@tanstack/react-router";
import { zodValidator } from "@tanstack/zod-adapter";
import { createURL } from "../utils";
import { schema as connectSchema } from "./auth.connect";
Expand All @@ -20,11 +20,12 @@ function Component() {
return null;
}

const navigate = useNavigate();
const search = Route.useSearch();

const redirectUrl = createURL("/auth/sso-callback", search).toString();

const redirectUrlComplete = search
const redirectUrlComplete = search?.c
? createURL("/auth/connect", search).toString()
: ("/" satisfies LinkProps["to"]);

Expand All @@ -47,14 +48,13 @@ function Component() {
<div className="z-10 flex w-full flex-col items-center justify-center">
<div className="flex flex-col items-center">
<h1 className="mb-4 text-5xl font-bold md:text-6xl lg:text-7xl">
Welcome Back
Welcome
</h1>

<p className="mb-12 text-center text-base font-medium text-neutral-600 md:text-lg lg:text-xl">
Sign in to continue to Hyprnote
</p>

<SignedOut>
<p className="mb-12 text-center text-base font-medium text-neutral-600 md:text-lg lg:text-xl">
Sign in to continue to Hyprnote
</p>
<div className="mb-4 w-full">
<Button
size="lg"
Expand All @@ -68,6 +68,18 @@ function Component() {
</div>
<TOS />
</SignedOut>
<SignedIn>
<div className="mb-4 w-full">
<Button
size="lg"
variant="outline"
className="w-full min-h-11 text-lg"
onClick={() => navigate({ to: "/auth/sign-out" })}
>
Sign out
</Button>
</div>
</SignedIn>
</div>
</div>

Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/routes/auth.sso-callback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const Route = createFileRoute("/auth/sso-callback")({
function Component() {
const search = Route.useSearch();

const redirectUrl = search
const redirectUrl = search?.c
? createURL("/auth/connect", search).toString()
: ("/" satisfies LinkProps["to"]);

Expand Down
48 changes: 26 additions & 22 deletions apps/desktop/src/routes/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import { commands } from "@/types";
import { Trans } from "@lingui/react/macro";
import { useQuery } from "@tanstack/react-query";
import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { Channel } from "@tauri-apps/api/core";
import { message } from "@tauri-apps/plugin-dialog";
import { open } from "@tauri-apps/plugin-shell";
import { Pause, Play } from "lucide-react";
import { useEffect, useState } from "react";

import { type AuthEvent, commands as authCommands, type RequestParams } from "@hypr/plugin-auth";
import { commands as authCommands, events, type RequestParams } from "@hypr/plugin-auth";
import { commands as miscCommands } from "@hypr/plugin-misc";
import { commands as sfxCommands } from "@hypr/plugin-sfx";
import { Button } from "@hypr/ui/components/ui/button";
Expand All @@ -33,38 +32,39 @@ function Component() {
const navigate = useNavigate();

const [port, setPort] = useState<number | null>(null);
const [status, setStatus] = useState<AuthEvent | "Idle">("Idle");

useEffect(() => {
let cleanup: (() => void) | undefined;
let unlisten: (() => void) | undefined;

const channel = new Channel<AuthEvent>();
channel.onmessage = setStatus;

authCommands.startOauthServer(channel).then((port) => {
authCommands.startOauthServer().then((port) => {
setPort(port);

events.authEvent.listen(({ payload }) => {
if (payload === "success") {
commands.setupDb().then(() => {
navigate({ to: "/onboarding", replace: true });
});
return;
}

if (payload.error) {
message("Error occurred while authenticating!");
return;
}
}).then((fn) => {
unlisten = fn;
});

cleanup = () => {
unlisten?.();
authCommands.stopOauthServer(port);
};
});

return () => cleanup?.();
}, []);

useEffect(() => {
if (status === "Success") {
commands.setupDb().then(() => {
navigate({ to: "/onboarding", replace: true });
});
return;
}

if (status === "Error") {
message("Error occurred while authenticating!");
return;
}
}, [status]);

const url = useQuery({
queryKey: ["oauth-url", port],
enabled: !!port,
Expand Down Expand Up @@ -124,7 +124,11 @@ function Component() {
AI notepad for meetings
</TextAnimate>

<PushableButton onClick={handleSignIn} className="mb-4 w-full">
<PushableButton
disabled={port === null}
onClick={handleSignIn}
className="mb-4 w-full"
>
<Trans>Get Started</Trans>
</PushableButton>
</div>
Expand Down
12 changes: 8 additions & 4 deletions plugins/auth/js/bindings.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@


export const commands = {
async startOauthServer(channel: TAURI_CHANNEL<AuthEvent>) : Promise<number> {
return await TAURI_INVOKE("plugin:auth|start_oauth_server", { channel });
async startOauthServer() : Promise<number> {
return await TAURI_INVOKE("plugin:auth|start_oauth_server");
},
async stopOauthServer(port: number) : Promise<null> {
return await TAURI_INVOKE("plugin:auth|stop_oauth_server", { port });
Expand All @@ -27,18 +27,22 @@ async getFromStore(key: StoreKey) : Promise<string | null> {
/** user-defined events **/


export const events = __makeEvents__<{
authEvent: AuthEvent
}>({
authEvent: "plugin:auth:auth-event"
})

/** user-defined constants **/



/** user-defined types **/

export type AuthEvent = "Success" | "Error"
export type AuthEvent = "success" | { error: string }
export type RequestParams = { c: string; f: string; p: number }
export type ResponseParams = { ui: string; ai: string; st: string; dt: string }
export type StoreKey = "auth-user-id" | "auth-account-id"
export type TAURI_CHANNEL<TSend> = null
export type VaultKey = "remote-database" | "remote-server"

/** tauri-specta globals **/
Expand Down
9 changes: 3 additions & 6 deletions plugins/auth/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use crate::{store::StoreKey, vault::VaultKey, AuthEvent, AuthPluginExt};
use crate::{store::StoreKey, vault::VaultKey, AuthPluginExt};

#[tauri::command]
#[specta::specta]
pub fn start_oauth_server<R: tauri::Runtime>(
app: tauri::AppHandle<R>,
channel: tauri::ipc::Channel<AuthEvent>,
) -> Result<u16, String> {
app.start_oauth_server(channel)
pub fn start_oauth_server<R: tauri::Runtime>(app: tauri::AppHandle<R>) -> Result<u16, String> {
app.start_oauth_server()
}

#[tauri::command]
Expand Down
7 changes: 7 additions & 0 deletions plugins/auth/src/events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[derive(serde::Serialize, Clone, specta::Type, tauri_specta::Event)]
pub enum AuthEvent {
#[serde(rename = "success")]
Success,
#[serde(rename = "error")]
Error(String),
}
22 changes: 8 additions & 14 deletions plugins/auth/src/ext.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
use tauri::ipc::Channel;
use tauri_specta::Event;

use crate::{
store,
store::StoreKey,
events::AuthEvent,
store::{self, StoreKey},
vault::{Vault, VaultKey},
ResponseParams, CALLBACK_TEMPLATE_KEY,
};

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum AuthEvent {
Success,
Error,
}

pub trait AuthPluginExt<R: tauri::Runtime> {
fn start_oauth_server(&self, channel: Channel<AuthEvent>) -> Result<u16, String>;
fn start_oauth_server(&self) -> Result<u16, String>;
fn stop_oauth_server(&self, port: u16) -> Result<(), String>;
fn init_vault(&self, account_id: impl AsRef<str>) -> Result<(), String>;
fn reset_vault(&self) -> Result<(), String>;
Expand All @@ -23,7 +17,8 @@ pub trait AuthPluginExt<R: tauri::Runtime> {
}

impl<R: tauri::Runtime, T: tauri::Manager<R>> AuthPluginExt<R> for T {
fn start_oauth_server(&self, channel: Channel<AuthEvent>) -> Result<u16, String> {
fn start_oauth_server(&self) -> Result<u16, String> {
let app = self.app_handle().clone();
let store = store::get_store(self);

let env = self.state::<minijinja::Environment>().inner().clone();
Expand Down Expand Up @@ -70,11 +65,11 @@ impl<R: tauri::Runtime, T: tauri::Manager<R>> AuthPluginExt<R> for T {
}
store.save().unwrap();

channel.send(AuthEvent::Success).unwrap();
AuthEvent::Success.emit(&app).unwrap();
}
Err(err) => {
tracing::error!(error = ?err, url = ?u, "failed_to_parse_callback_params");
channel.send(AuthEvent::Error).unwrap();
AuthEvent::Error(err.to_string()).emit(&app).unwrap();
}
}
},
Expand Down Expand Up @@ -120,7 +115,6 @@ impl<R: tauri::Runtime, T: tauri::Manager<R>> AuthPluginExt<R> for T {

#[cfg(test)]
mod tests {
use super::*;
use crate::RequestParams;

#[test]
Expand Down
7 changes: 6 additions & 1 deletion plugins/auth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ use tauri::Manager;

mod commands;
mod error;
mod events;
mod ext;
mod store;
mod vault;

pub use error::*;
pub use events::*;
pub use ext::*;
pub use store::*;
pub use vault::*;
Expand All @@ -21,6 +23,7 @@ const CALLBACK_TEMPLATE_VALUE: &str = include_str!("../templates/callback.jinja"
fn make_specta_builder<R: tauri::Runtime>() -> tauri_specta::Builder<R> {
tauri_specta::Builder::<R>::new()
.plugin_name(PLUGIN_NAME)
.events(tauri_specta::collect_events![events::AuthEvent])
.commands(tauri_specta::collect_commands![
commands::start_oauth_server::<tauri::Wry>,
commands::stop_oauth_server::<tauri::Wry>,
Expand All @@ -38,7 +41,9 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {

tauri::plugin::Builder::new(PLUGIN_NAME)
.invoke_handler(specta_builder.invoke_handler())
.setup(|app, _api| {
.setup(move |app, _api| {
specta_builder.mount_events(app);

let mut env = minijinja::Environment::new();
env.add_template(CALLBACK_TEMPLATE_KEY, CALLBACK_TEMPLATE_VALUE)
.unwrap();
Expand Down
Loading