+
diff --git a/front/src/store/auth.ts b/front/src/store/auth.ts
index d2a3f1530..a4a9d364b 100644
--- a/front/src/store/auth.ts
+++ b/front/src/store/auth.ts
@@ -2,6 +2,7 @@ import type { BackendError, User } from '~/types'
import type { Module } from 'vuex'
import type { RootState } from '~/store/index'
import type { RouteLocationRaw } from 'vue-router'
+import type { WebviewWindow } from '@tauri-apps/api/webview'
import axios from 'axios'
import useLogger from '~/composables/useLogger'
@@ -9,6 +10,7 @@ import useFormData from '~/composables/useFormData'
import { clear as clearIDB } from 'idb-keyval'
import { useQueue } from '~/composables/audio/queue'
+import { isTauri } from '~/composables/tauri'
export type Permission = 'settings' | 'library' | 'moderation'
export interface State {
@@ -21,6 +23,8 @@ export interface State {
scopedTokens: ScopedTokens
applicationSecret: string | undefined
+
+ oauthWindow: WebviewWindow | undefined
}
interface ScopedTokens {
@@ -55,7 +59,7 @@ function getDefaultOauth (): OAuthTokens {
async function createOauthApp () {
const payload = {
- name: `Funkwhale web client at ${window.location.hostname}`,
+ name: `Funkwhale web client at ${location.hostname}`,
website: location.origin,
scopes: NEEDED_SCOPES,
redirect_uris: `${location.origin}/auth/callback`
@@ -78,7 +82,9 @@ const store: Module
= {
oauth: getDefaultOauth(),
scopedTokens: getDefaultScopedTokens(),
- applicationSecret: undefined
+ applicationSecret: undefined,
+
+ oauthWindow: undefined
},
getters: {
header: state => {
@@ -243,14 +249,41 @@ const store: Module = {
commit('permission', { key: permission, status: hasPermission })
}
},
- async oauthLogin ({ state, rootState, commit }, next: RouteLocationRaw) {
+ async tryFinishOAuthFlow ({ state }) {
+ if (isTauri()) {
+ return state.oauthWindow?.close().catch(() => {
+ // Ignore the error in case of window being already closed
+ })
+ }
+ },
+ async oauthLogin ({ state, rootState, commit, dispatch }, next: RouteLocationRaw) {
const app = await createOauthApp()
commit('oauthApp', app)
- const redirectUri = encodeURIComponent(`${location.origin}/auth/callback`)
- const params = `response_type=code&scope=${encodeURIComponent(NEEDED_SCOPES)}&redirect_uri=${redirectUri}&state=${next}&client_id=${state.oauth.clientId}`
+ const redirectUrl = encodeURIComponent(`${location.origin}/auth/callback`)
+ const params = `response_type=code&scope=${encodeURIComponent(NEEDED_SCOPES)}&redirect_uri=${redirectUrl}&state=${next}&client_id=${state.oauth.clientId}`
const authorizeUrl = `${rootState.instance.instanceUrl}authorize?${params}`
- logger.log('Redirecting user...', authorizeUrl)
- window.location.href = authorizeUrl
+
+ if (isTauri()) {
+ const { WebviewWindow } = await import('@tauri-apps/api/webview')
+
+ state.oauthWindow = new WebviewWindow('oauth', {
+ title: `Login to ${rootState.instance.settings.instance.name}`,
+ parent: 'main',
+ url: authorizeUrl
+ })
+
+ const token = await new Promise((resolve, reject) => {
+ state.oauthWindow?.once('tauri://error', reject)
+ state.oauthWindow?.once('tauri://destroyed', () => reject(new Error('Aborted by user')))
+ state.oauthWindow?.once('oauthToken', async (event) => resolve(event.payload))
+ }).finally(() => dispatch('tryFinishOAuthFlow'))
+
+ commit('oauthToken', token)
+ await dispatch('fetchUser')
+ } else {
+ logger.log('Redirecting user...', authorizeUrl)
+ location.href = authorizeUrl
+ }
},
async handleOauthCallback ({ state, commit, dispatch }, authorizationCode) {
logger.log('Fetching token...')
@@ -266,6 +299,18 @@ const store: Module = {
useFormData(payload),
{ headers: { 'Content-Type': 'multipart/form-data' } }
)
+
+ if (isTauri()) {
+ const { getCurrent } = await import('@tauri-apps/api/window')
+ const currentWindow = getCurrent()
+
+ // If the current window is the oauth window, pass the event to the main window
+ if (currentWindow.label === 'oauth') {
+ await currentWindow.emit('oauthToken', response.data)
+ return
+ }
+ }
+
commit('oauthToken', response.data)
await dispatch('fetchUser')
},
diff --git a/front/tauri/Cargo.lock b/front/tauri/Cargo.lock
index 2e7413a6f..75c258109 100644
--- a/front/tauri/Cargo.lock
+++ b/front/tauri/Cargo.lock
@@ -567,6 +567,33 @@ dependencies = [
"objc",
]
+[[package]]
+name = "color-eyre"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
+dependencies = [
+ "backtrace",
+ "color-spantrace",
+ "eyre",
+ "indenter",
+ "once_cell",
+ "owo-colors",
+ "tracing-error",
+]
+
+[[package]]
+name = "color-spantrace"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2"
+dependencies = [
+ "once_cell",
+ "owo-colors",
+ "tracing-core",
+ "tracing-error",
+]
+
[[package]]
name = "color_quant"
version = "1.1.0"
@@ -1009,6 +1036,16 @@ dependencies = [
"pin-project-lite",
]
+[[package]]
+name = "eyre"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
+dependencies = [
+ "indenter",
+ "once_cell",
+]
+
[[package]]
name = "fastrand"
version = "1.9.0"
@@ -1099,6 +1136,7 @@ dependencies = [
name = "funkwhale"
version = "0.1.0"
dependencies = [
+ "color-eyre",
"serde",
"serde_json",
"tauri",
@@ -1714,6 +1752,12 @@ dependencies = [
"num-traits",
]
+[[package]]
+name = "indenter"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
+
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -2288,6 +2332,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+[[package]]
+name = "owo-colors"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+
[[package]]
name = "pango"
version = "0.18.3"
@@ -3908,6 +3958,16 @@ dependencies = [
"valuable",
]
+[[package]]
+name = "tracing-error"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
+dependencies = [
+ "tracing",
+ "tracing-subscriber",
+]
+
[[package]]
name = "tracing-log"
version = "0.2.0"
diff --git a/front/tauri/Cargo.toml b/front/tauri/Cargo.toml
index f90ecf30a..163ac6a59 100644
--- a/front/tauri/Cargo.toml
+++ b/front/tauri/Cargo.toml
@@ -22,9 +22,10 @@ tauri-build = { version = "2.0.0-beta", features = [] }
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "2.0.0-beta", features = [] }
+color-eyre = "0.6.2"
[features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
# DO NOT REMOVE!!
-custom-protocol = [ "tauri/custom-protocol" ]
+custom-protocol = ["tauri/custom-protocol"]
diff --git a/front/tauri/capabilities/migrated.json b/front/tauri/capabilities/migrated.json
index 0fff22326..4abe92575 100644
--- a/front/tauri/capabilities/migrated.json
+++ b/front/tauri/capabilities/migrated.json
@@ -2,7 +2,7 @@
"identifier": "migrated",
"description": "permissions that were migrated from v1",
"context": "local",
- "windows": ["main"],
+ "windows": ["main", "oauth"],
"permissions": [
"path:default",
"event:default",
diff --git a/front/tauri/capabilities/oauth.json b/front/tauri/capabilities/oauth.json
new file mode 100644
index 000000000..ac8ea9e66
--- /dev/null
+++ b/front/tauri/capabilities/oauth.json
@@ -0,0 +1,8 @@
+{
+ "identifier": "oauth2",
+ "description": "permissions that required for OAuth2 login window",
+ "context": "local",
+ "windows": ["main"],
+ "permissions": ["webview:allow-create-webview-window", "window:allow-close"],
+ "platforms": ["linux", "macOS", "windows", "android", "iOS"]
+}
diff --git a/front/tauri/rust-toolchain.toml b/front/tauri/rust-toolchain.toml
new file mode 100644
index 000000000..92ebe6655
--- /dev/null
+++ b/front/tauri/rust-toolchain.toml
@@ -0,0 +1,4 @@
+[toolchain]
+profile = "minimal"
+channel = "1.71.0"
+components = ["rust-src", "rust-analyzer", "clippy"]
diff --git a/front/tauri/src/main.rs b/front/tauri/src/main.rs
index a406808a5..41ef8437d 100644
--- a/front/tauri/src/main.rs
+++ b/front/tauri/src/main.rs
@@ -1,6 +1,12 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
-fn main() {
+use color_eyre::Result;
+
+fn main() -> Result<()> {
+ color_eyre::install()?;
+
funkwhale_lib::run();
+
+ Ok(())
}
diff --git a/front/tauri/tauri.conf.json b/front/tauri/tauri.conf.json
index ef3861aa1..a999007af 100644
--- a/front/tauri/tauri.conf.json
+++ b/front/tauri/tauri.conf.json
@@ -10,11 +10,12 @@
},
"windows": [
{
+ "label": "main",
"fullscreen": false,
"height": 600,
+ "width": 800,
"resizable": true,
- "title": "Funkwhale",
- "width": 800
+ "title": "Funkwhale"
}
]
},