handle logout

Seto Elkahfi committed Aug 1, 2024 at 12:58 UTC fcf585913a468528376471e77337afaba2176fce
6 files changed +99 -40
frontend/splitfire-desktop/app/_src/lib/tauriHandler.ts
+1
@@ -14,6 +14,7 @@ export const TAURI_PLAYER_RECORDING_LENGTH = 'player_recording_length' // in se
14
15 // Account
16 export const TAURI_ACCOUNT_LOGIN = 'account_login'
17 +export const TAURI_ACCOUNT_LOGOUT = 'account_logout'
18 export const TAURI_ACCOUNT_REGISTER = 'account_register'
19
20 export enum TauriResponse {
frontend/splitfire-desktop/app/_ui/global-nav.tsx
+2
@@ -9,7 +9,9 @@ import { useContext, useState } from 'react';
9 import Image from 'next/image';
10 import { UserContext } from '../_src/lib/CurrentUserContext';
11
12 +
13 export function GlobalNav() {
14 +
15 const [isOpen, setIsOpen] = useState(false);
16 const close = () => setIsOpen(false);
17 const user = useContext(UserContext);
frontend/splitfire-desktop/app/logout/page.tsx
+37 -12
@@ -1,20 +1,45 @@
1 -export async function generateStaticParams() {
2 - const posts = [
3 - { slug: "post-1" },
4 - { slug: "post-2" },
5 - { slug: "post-3" },
6 - ];
7 -
8 - return posts.map((post) => ({
9 - slug: post.slug,
10 - }))
1 +"use client";
2 +
3 +import { useContext, useEffect, useState } from "react";
4 +import { UserContext } from "../_src/lib/CurrentUserContext";
5 +import { useLogger } from "../_src/lib/logger";
6 +import { db } from "../_src/lib/db";
7 +import { invoke } from "@tauri-apps/api/tauri";
8 +import { TAURI_ACCOUNT_LOGOUT } from "../_src/lib/tauriHandler";
9 +import { useRouter } from "next/navigation";
10 +
11 +enum State {
12 + LOADING,
13 + LOADED,
14 + ERROR,
15 }
16
17 export default function Page() {
18 + const [state, setState] = useState(State.LOADING);
19 + const log = useLogger("Logout/Page");
20 + const currentUser = useContext(UserContext);
21 + const router = useRouter();
22 +
23 + useEffect(() => {
24 + async function logout() {
25 + log.debug(currentUser);
26 + db.currentUser.clear();
27 + if (currentUser.user?.accessToken) {
28 + const res = await invoke(TAURI_ACCOUNT_LOGOUT, {
29 + accessToken: currentUser.user?.accessToken,
30 + });
31 + log.debug(res);
32 + }
33 + setState(State.LOADED);
34 + router.push("/");
35 + }
36 + logout();
37 + // eslint-disable-next-line react-hooks/exhaustive-deps
38 + }, [state]);
39 + const text = state === State.LOADING ? "Logging out..." : "Logged out";
40 return (
41 <div className="prose prose-sm prose-invert max-w-none">
16 - <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
17 - </div>
42 + <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">{text}</div>
43 </div>
44 );
45 }
frontend/splitfire-desktop/src-tauri/src/main.rs
+9 -2
@@ -18,8 +18,14 @@ use app::{
18 player_unmount::{__cmd__player_unmount, player_unmount},
19 },
20 rest::{
21 - account::{__cmd__account_login, __cmd__account_register, account_login, account_register},
22 - content::{__cmd__content_carousel, __cmd__content_ready_to_play, content_carousel, content_ready_to_play},
21 + account::{
22 + __cmd__account_login, __cmd__account_logout, __cmd__account_register, account_login,
23 + account_logout, account_register,
24 + },
25 + content::{
26 + __cmd__content_carousel, __cmd__content_ready_to_play, content_carousel,
27 + content_ready_to_play,
28 + },
29 },
30 sfai_home_dir_path,
31 };
@@ -55,6 +61,7 @@ fn main() {
61 })
62 .invoke_handler(tauri::generate_handler![
63 account_login,
64 + account_logout,
65 account_register,
66 open_lyrics_editor,
67 open_player,
frontend/splitfire-desktop/src-tauri/src/models/player.rs
+1 -1
@@ -24,7 +24,7 @@ impl Display for ResultFile {
24
25 #[derive(Serialize, Deserialize)]
26 #[derive(Debug)]
27 -enum Status {
27 +pub enum Status {
28 #[serde(rename = "downloading")]
29 Downloading,
30 #[serde(rename = "splitting")]
frontend/splitfire-desktop/src-tauri/src/rest/account.rs
+49 -25
@@ -1,19 +1,30 @@
1 +use crate::{
2 + command::constants::{
3 + base_url_builder, PATH_ACCOUNT_LOGIN, PATH_ACCOUNT_LOGOUT, PATH_ACCOUNT_REGISTER,
4 + },
5 + models::{
6 + account::{AccountLoginResponse, LoginResponse},
7 + player::TauriResponse,
8 + },
9 +};
10 use log::debug;
11 use reqwest::Client;
12 use serde_json::json;
13 use tauri;
5 -use crate::{command::constants::{base_url_builder, PATH_ACCOUNT_LOGIN, PATH_ACCOUNT_REGISTER}, models::{account::{AccountLoginResponse, LoginResponse}, player::TauriResponse}};
14
15 #[tauri::command]
16 pub async fn account_login(username: String, password: String) -> AccountLoginResponse {
9 - debug!("Logging in with username {}, password {}", username, password);
17 + debug!(
18 + "Logging in with username {}, password {}",
19 + username, password
20 + );
21 // Login
22 let body = json!( {
23 "username": username,
24 "password": password
25 });
26 let response = Client::new()
16 - .post(login_url_builder())
27 + .post(account_url_builder(PATH_ACCOUNT_LOGIN))
28 .json(&body)
29 .send()
30 .await;
@@ -24,42 +35,38 @@ pub async fn account_login(username: String, password: String) -> AccountLoginRe
35 Some(token) => {
36 // Trim Bearer prefix
37 let token = match token.to_str() {
27 - Ok(token) => {
28 - token.trim_start_matches("Bearer ")
29 - },
38 + Ok(token) => token.trim_start_matches("Bearer "),
39 Err(e) => {
40 println!("Failed to get token: {:?}", e);
41 return AccountLoginResponse {
42 status: TauriResponse::Error,
43 message: "Failed to get token".to_string(),
44 access_token: None,
36 - user: None
45 + user: None,
46 };
47 }
48 };
49 Some(token.to_string())
41 - },
50 + }
51 None => {
52 println!("Failed to get token");
53 return AccountLoginResponse {
54 status: TauriResponse::Error,
55 message: "Failed to get token".to_string(),
56 access_token: None,
48 - user: None
57 + user: None,
58 };
59 }
60 };
61 let res: LoginResponse = match response.json().await {
53 - Ok(json) => {
54 - json
55 - },
62 + Ok(json) => json,
63 Err(e) => {
64 println!("Failed to parse response: {:?}", e);
65 return AccountLoginResponse {
66 status: TauriResponse::Error,
67 message: "Failed to parse response".to_string(),
68 access_token: None,
62 - user: None
69 + user: None,
70 };
71 }
72 };
@@ -69,7 +76,7 @@ pub async fn account_login(username: String, password: String) -> AccountLoginRe
76 status: TauriResponse::Success,
77 message: res.message,
78 access_token: token,
72 - user: res.user
79 + user: res.user,
80 }
81 }
82 Err(e) => {
@@ -78,15 +85,38 @@ pub async fn account_login(username: String, password: String) -> AccountLoginRe
85 status: TauriResponse::Error,
86 message: "Failed to get response".to_string(),
87 access_token: None,
81 - user: None
88 + user: None,
89 }
90 }
91 }
92 }
93
94 +#[tauri::command]
95 +pub async fn account_logout(access_token: String) {
96 + debug!("Logging out with access token {}", access_token);
97 + // Logout
98 + let response = Client::new()
99 + .post(account_url_builder(PATH_ACCOUNT_LOGOUT))
100 + .header("Authorization", format!("Bearer {}", access_token))
101 + .send()
102 + .await;
103 +
104 + match response {
105 + Ok(response) => {
106 + debug!("Got response: {:?}", response);
107 + }
108 + Err(e) => {
109 + println!("Failed to get response: {:?}", e);
110 + }
111 + }
112 +}
113 +
114 #[tauri::command]
115 pub async fn account_register(username: String, email: String, password: String) {
89 - debug!("Registering with username {} and email {}.", username, email);
116 + debug!(
117 + "Registering with username {} and email {}.",
118 + username, email
119 + );
120 // Register
121 let body = json!( {
122 "username": username,
@@ -94,7 +124,7 @@ pub async fn account_register(username: String, email: String, password: String)
124 "password": password
125 });
126 let response = Client::new()
97 - .post(register_url_builder())
127 + .post(account_url_builder(PATH_ACCOUNT_REGISTER))
128 .json(&body)
129 .send()
130 .await;
@@ -117,14 +147,8 @@ pub async fn account_register(username: String, email: String, password: String)
147 }
148 }
149
120 -fn login_url_builder() -> String {
150 +fn account_url_builder(path: &str) -> String {
151 let mut base_url = base_url_builder();
122 - base_url.add_route(PATH_ACCOUNT_LOGIN);
152 + base_url.add_route(path);
153 base_url.build()
154 }
125 -
126 -fn register_url_builder() -> String {
127 - let mut base_url = base_url_builder();
128 - base_url.add_route(PATH_ACCOUNT_REGISTER);
129 - base_url.build()
130 -}
\ No newline at end of file