fix(tree-wide): re-apply yuzu specific changes

This commit is contained in:
liushuyu 2021-10-14 21:13:31 -06:00
parent a816cbe767
commit dde96db57c
No known key found for this signature in database
GPG key ID: 23D1CE4534419437
16 changed files with 133 additions and 127 deletions

View file

@ -2,7 +2,6 @@
//! //!
//! Provides mechanisms to authenticate users using JWT. //! Provides mechanisms to authenticate users using JWT.
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use futures::{Future, Stream}; use futures::{Future, Stream};
@ -13,16 +12,14 @@ use jwt::{decode, Algorithm, Validation};
use reqwest::header::USER_AGENT; use reqwest::header::USER_AGENT;
use url::form_urlencoded; use crate::frontend::rest::services::Future as InternalFuture;
use crate::frontend::rest::services::{default_future, Request, Response, WebService};
use frontend::rest::services::Future as InternalFuture; use crate::http::{build_async_client, build_client};
use frontend::rest::services::{default_future, Request, Response, WebService};
use http::{build_async_client, build_client}; use crate::config::JWTValidation;
use config::JWTValidation; use crate::logging::LoggingErrors;
use logging::LoggingErrors;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct Auth { struct Auth {
@ -48,6 +45,12 @@ pub struct JWTClaims {
pub is_subscribed: bool, pub is_subscribed: bool,
} }
#[derive(Debug, Serialize, Deserialize, Clone)]
struct AuthRequest {
username: String,
token: String
}
/// Calls the given server to obtain a JWT token and returns a Future<String> with the response /// Calls the given server to obtain a JWT token and returns a Future<String> with the response
pub fn authenticate_async( pub fn authenticate_async(
url: String, url: String,
@ -163,6 +166,7 @@ pub fn validate_token(
} }
pub fn handle(service: &WebService, _req: Request) -> InternalFuture { pub fn handle(service: &WebService, _req: Request) -> InternalFuture {
info!("Handling authentication");
let framework = service let framework = service
.framework .framework
.read() .read()
@ -185,14 +189,12 @@ pub fn handle(service: &WebService, _req: Request) -> InternalFuture {
_req.body() _req.body()
.concat2() .concat2()
.map(move |body| { .map(move |body| {
let req = form_urlencoded::parse(body.as_ref()) let req: AuthRequest = serde_json::from_slice(&body).log_expect("Malformed request");
.into_owned()
.collect::<HashMap<String, String>>();
// Determine which credentials we should use // Determine which credentials we should use
let (username, token) = { let (username, token) = {
let req_username = req.get("username").log_expect("No username in request"); let req_username = req.username;
let req_token = req.get("token").log_expect("No token in request"); let req_token = req.token;
// if the user didn't provide credentials, and theres nothing stored in the // if the user didn't provide credentials, and theres nothing stored in the
// database, return an early error // database, return an early error

View file

@ -2,20 +2,21 @@
//! //!
//! Launches the user's web browser on request from the frontend. //! Launches the user's web browser on request from the frontend.
use frontend::rest::services::Future as InternalFuture; use crate::frontend::rest::services::Future as InternalFuture;
use frontend::rest::services::{Request, Response, WebService}; use crate::frontend::rest::services::{Request, Response, WebService};
use crate::logging::LoggingErrors;
use futures::{Future, Stream}; use futures::{Future, Stream};
use hyper::header::ContentType; use hyper::header::ContentType;
use logging::LoggingErrors;
use std::collections::HashMap; #[derive(Debug, Serialize, Deserialize, Clone)]
use url::form_urlencoded; struct OpenRequest {
url: String,
}
pub fn handle(_service: &WebService, req: Request) -> InternalFuture { pub fn handle(_service: &WebService, req: Request) -> InternalFuture {
Box::new(req.body().concat2().map(move |body| { Box::new(req.body().concat2().map(move |body| {
let req = form_urlencoded::parse(body.as_ref()) let req: OpenRequest = serde_json::from_slice(&body).log_expect("Malformed request");
.into_owned() if webbrowser::open(&req.url).is_ok() {
.collect::<HashMap<String, String>>();
if webbrowser::open(req.get("url").log_expect("No URL to launch")).is_ok() {
Response::new() Response::new()
.with_status(hyper::Ok) .with_status(hyper::Ok)
.with_header(ContentType::json()) .with_header(ContentType::json())

View file

@ -39,6 +39,7 @@ pub fn handle(service: &WebService, req: Request) -> Future {
} else if key == "installDesktopShortcut" { } else if key == "installDesktopShortcut" {
info!("Found installDesktopShortcut {:?}", value); info!("Found installDesktopShortcut {:?}", value);
install_desktop_shortcut = value == "true"; install_desktop_shortcut = value == "true";
continue;
} }
if key == "mode" && value == "force" { if key == "mode" && value == "force" {

View file

@ -17,7 +17,7 @@ enum CallbackType {
/// Starts the main web UI. Will return when UI is closed. /// Starts the main web UI. Will return when UI is closed.
pub fn start_ui(app_name: &str, http_address: &str, is_launcher: bool) { pub fn start_ui(app_name: &str, http_address: &str, is_launcher: bool) {
let size = if is_launcher { (600, 300) } else { (1024, 500) }; let size = if is_launcher { (600, 300) } else { (1024, 600) };
info!("Spawning web view instance"); info!("Spawning web view instance");

View file

@ -333,7 +333,7 @@ mod natives {
}; };
path.push(format!("{}.desktop", slugify(name))); // file name path.push(format!("{}.desktop", slugify(name))); // file name
let desktop_file = format!( let desktop_file = format!(
"[Desktop Entry]\nName={}\nExec=\"{}\" {}\nComment={}\nPath={}\n", "[Desktop Entry]\nName={}\nExec=\"{}\" {}\nComment={}\nType=Application\nPath={}\n",
name, target, args, description, working_dir name, target, args, description, working_dir
); );
let desktop_f = File::create(path); let desktop_f = File::create(path);

View file

@ -2,10 +2,10 @@
//! //!
//! Contains the yuzu-emu core API implementation of a release source. //! Contains the yuzu-emu core API implementation of a release source.
use http::build_client; use crate::http::build_client;
use crate::sources::types::*;
use reqwest::header::USER_AGENT; use reqwest::header::USER_AGENT;
use reqwest::StatusCode; use reqwest::StatusCode;
use sources::types::*;
pub struct PatreonReleases {} pub struct PatreonReleases {}

View file

@ -1,13 +1,13 @@
//! Validates that users have correct authorization to download packages. //! Validates that users have correct authorization to download packages.
use frontend::rest::services::authentication; use crate::frontend::rest::services::authentication;
use installer::InstallerFramework; use crate::installer::InstallerFramework;
use logging::LoggingErrors; use crate::logging::LoggingErrors;
use tasks::resolver::ResolvePackageTask; use crate::tasks::resolver::ResolvePackageTask;
use tasks::{Task, TaskDependency, TaskMessage, TaskOrdering, TaskParamType}; use crate::tasks::{Task, TaskDependency, TaskMessage, TaskOrdering, TaskParamType};
pub struct CheckAuthorizationTask { pub struct CheckAuthorizationTask {
pub name: String, pub name: String,

View file

@ -9,8 +9,6 @@ use crate::tasks::TaskMessage;
use crate::tasks::TaskOrdering; use crate::tasks::TaskOrdering;
use crate::tasks::TaskParamType; use crate::tasks::TaskParamType;
use crate::tasks::resolver::ResolvePackageTask;
use crate::http::stream_file; use crate::http::stream_file;
use number_prefix::NumberPrefix::{self, Prefixed, Standalone}; use number_prefix::NumberPrefix::{self, Prefixed, Standalone};

View file

@ -1,17 +1,17 @@
//! Generates shortcuts for a specified file. //! Generates shortcuts for a specified file.
use installer::InstallerFramework; use crate::installer::InstallerFramework;
use tasks::Task; use crate::tasks::Task;
use tasks::TaskDependency; use crate::tasks::TaskDependency;
use tasks::TaskMessage; use crate::tasks::TaskMessage;
use tasks::TaskParamType; use crate::tasks::TaskParamType;
use config::PackageDescription; use crate::config::PackageDescription;
use logging::LoggingErrors; use crate::logging::LoggingErrors;
use native::create_desktop_shortcut; use crate::native::create_shortcut;
pub struct InstallDesktopShortcutTask { pub struct InstallDesktopShortcutTask {
pub name: String, pub name: String,
@ -81,7 +81,7 @@ impl Task for InstallDesktopShortcutTask {
.to_str() .to_str()
.log_expect("Unable to build shortcut metadata (exe)"); .log_expect("Unable to build shortcut metadata (exe)");
installed_files.push(create_desktop_shortcut( installed_files.push(create_shortcut(
&shortcut.name, &shortcut.name,
&shortcut.description, &shortcut.description,
tool_path, tool_path,

View file

@ -22,9 +22,9 @@ use crate::logging::LoggingErrors;
use crate::archives; use crate::archives;
use crate::tasks::install_desktop_shortcut::InstallDesktopShortcutTask;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::path::Path; use std::path::Path;
use tasks::install_desktop_shortcut::InstallDesktopShortcutTask;
pub struct InstallPackageTask { pub struct InstallPackageTask {
pub name: String, pub name: String,
@ -70,13 +70,18 @@ impl Task for InstallPackageTask {
// Ignore input from the uninstaller - no useful information passed // Ignore input from the uninstaller - no useful information passed
// If a previous task Breaks, then just early exit // If a previous task Breaks, then just early exit
match input.pop().log_expect("Install Package Task should have guaranteed output!") { match input
.pop()
.log_expect("Install Package Task should have guaranteed output!")
{
TaskParamType::Break => return Ok(TaskParamType::None), TaskParamType::Break => return Ok(TaskParamType::None),
_ => (), _ => (),
}; };
// Grab data from the resolver // Grab data from the resolver
let data = input.pop().log_expect("Install Package Task should have input from resolver!"); let data = input
.pop()
.log_expect("Install Package Task should have input from resolver!");
let (version, file, data) = match data { let (version, file, data) = match data {
TaskParamType::FileContents(version, file, data) => (version, file, data), TaskParamType::FileContents(version, file, data) => (version, file, data),
_ => return Err("Unexpected file contents param type to install package".to_string()), _ => return Err("Unexpected file contents param type to install package".to_string()),
@ -201,7 +206,7 @@ impl Task for InstallPackageTask {
TaskOrdering::Post, TaskOrdering::Post,
Box::new(InstallDesktopShortcutTask { Box::new(InstallDesktopShortcutTask {
name: self.name.clone(), name: self.name.clone(),
should_run: self.create_desktop_shortcuts should_run: self.create_desktop_shortcuts,
}), }),
), ),
TaskDependency::build(TaskOrdering::Post, Box::new(SaveDatabaseTask {})), TaskDependency::build(TaskOrdering::Post, Box::new(SaveDatabaseTask {})),

View file

@ -2,16 +2,16 @@
//! If theres multiple launchable packages, then choose the first listed in config //! If theres multiple launchable packages, then choose the first listed in config
//! If there are multiple shortcuts for the first package, then launch the first. //! If there are multiple shortcuts for the first package, then launch the first.
use installer::InstallerFramework; use crate::installer::InstallerFramework;
use tasks::Task; use crate::tasks::Task;
use tasks::TaskDependency; use crate::tasks::TaskDependency;
use tasks::TaskMessage; use crate::tasks::TaskMessage;
use tasks::TaskParamType; use crate::tasks::TaskParamType;
use config::PackageDescription; use crate::config::PackageDescription;
use logging::LoggingErrors; use crate::logging::LoggingErrors;
pub struct LaunchOnExitTask {} pub struct LaunchOnExitTask {}

View file

@ -100,7 +100,8 @@ app.get('/api/config', (req, res) => {
}) })
app.post('/api/start-install', (req, res) => { app.post('/api/start-install', (req, res) => {
console.log(`-- Install: ${req}`) console.log('-- Install:')
console.log(req.body)
progressSimulation(res) progressSimulation(res)
}) })

View file

@ -152,10 +152,13 @@ const app = new Vue({
const that = this const that = this
const app = this.$root const app = this.$root
app.ajax('/api/check-auth', function (auth) { axios.post('/api/check-auth', {
app.$data.username = auth.username username: app.$data.username,
app.$data.token = auth.token token: app.$data.token
that.jwt_token = auth.jwt_token }).then(function (resp) {
app.$data.username = resp.data.username
app.$data.token = resp.data.token
that.jwt_token = resp.data.jwt_token
that.is_authenticated = Object.keys(that.jwt_token).length !== 0 && that.jwt_token.constructor === Object that.is_authenticated = Object.keys(that.jwt_token).length !== 0 && that.jwt_token.constructor === Object
if (that.is_authenticated) { if (that.is_authenticated) {
// Give all permissions to vip roles // Give all permissions to vip roles
@ -166,13 +169,10 @@ const app = new Vue({
if (success) { if (success) {
success() success()
} }
}, function (e) { }).catch(function () {
if (error) { if (error) {
error() error()
} }
}, {
username: app.$data.username,
token: app.$data.token
}) })
}, },
stream_ajax: streamAjax stream_ajax: streamAjax

View file

@ -75,56 +75,55 @@
<script> <script>
export default { export default {
name: 'AuthenticationView', name: 'AuthenticationView',
created: function() { created: function () {
// If they are already authenticated when this page is loaded, // If they are already authenticated when this page is loaded,
// then we can asssume they are "clicking here for more details" and should show the appropriate error message // then we can asssume they are "clicking here for more details" and should show the appropriate error message
if (this.$root.is_authenticated) { if (this.$root.is_authenticated) {
this.verification_opened = true; this.verification_opened = true
} }
}, },
data: function() { data: function () {
return { return {
browser_opened: false, browser_opened: false,
verification_opened: false, verification_opened: false,
invalid_token: false, invalid_token: false
} }
}, },
computed: { computed: {
show_header: function() { show_header: function () {
return !this.browser_opened && !this.verification_opened && !this.invalid_token; return !this.browser_opened && !this.verification_opened && !this.invalid_token
}, },
invalid_login: function() { invalid_login: function () {
return this.verification_opened && !this.$root.is_authenticated; return this.verification_opened && !this.$root.is_authenticated
}, },
unlinked_patreon: function() { unlinked_patreon: function () {
return this.verification_opened && this.$root.is_authenticated && !this.$root.is_linked; return this.verification_opened && this.$root.is_authenticated && !this.$root.is_linked
}, },
no_subscription: function() { no_subscription: function () {
return this.verification_opened && this.$root.is_linked && !this.$root.is_subscribed; return this.verification_opened && this.$root.is_linked && !this.$root.is_subscribed
}, },
tier_not_selected: function() { tier_not_selected: function () {
return this.verification_opened && this.$root.is_linked && this.$root.is_subscribed && !this.$root.has_reward_tier; return this.verification_opened && this.$root.is_linked && this.$root.is_subscribed && !this.$root.has_reward_tier
}, },
combined_token: { combined_token: {
// getter // getter
get: function () { get: function () {
if (this.$root.$data.username && this.$root.$data.token) { if (this.$root.$data.username && this.$root.$data.token) {
return btoa(this.$root.$data.username + ":" + this.$root.$data.token) return btoa(this.$root.$data.username + ':' + this.$root.$data.token)
} }
return ""; return ''
}, },
// setter // setter
set: function (newValue) { set: function (newValue) {
try { try {
var split = atob(newValue).split(':') const split = atob(newValue).split(':')
this.$root.$data.username = split[0]; this.$root.$data.username = split[0]
this.$root.$data.token = split[1]; this.$root.$data.token = split[1]
this.invalid_token = false; this.invalid_token = false
} catch (e) { } catch (e) {
this.invalid_token = true; this.invalid_token = true
} }
} }
} }
@ -134,37 +133,35 @@ export default {
this.$router.go(-1) this.$router.go(-1)
}, },
paste: function () { paste: function () {
document.getElementById("token").focus(); document.getElementById('token').focus()
document.execCommand("paste"); document.execCommand('paste')
}, },
launch_browser: function(url) { launch_browser: function (url) {
const that = this; const that = this
let app = this.$root; this.$http.post('/api/open-browser', {
app.ajax('/api/open-browser', function (e) { url: url
}).then(function () {
// only open the browser opened message if there isn't an error message currently // only open the browser opened message if there isn't an error message currently
if (!that.verification_opened) { if (!that.verification_opened) {
that.browser_opened = true; that.browser_opened = true
} }
}, function (e) {}, { }).catch(function () {})
"url": url,
});
}, },
verify_token: function() { verify_token: function () {
this.browser_opened = false; this.browser_opened = false
this.$root.check_authentication(this.success, this.error); this.$root.check_authentication(this.success, this.error)
}, },
success: function() { success: function () {
// if they are eligible, go back to the select package page // if they are eligible, go back to the select package page
if (this.$root.has_reward_tier) { if (this.$root.has_reward_tier) {
this.$router.go(-1); this.$router.go(-1)
return; return
} }
// They aren't currently eligible for the release, so display the error message // They aren't currently eligible for the release, so display the error message
this.verification_opened = true; this.verification_opened = true
}, },
error: function() { error: function () {
this.verification_opened = true; this.verification_opened = true
} }
} }
} }

View file

@ -26,22 +26,22 @@
</template> </template>
<script> <script>
export default { export default {
name: "ReAuthenticationView", name: 'ReAuthenticationView',
methods: { methods: {
go_authenticate: function() { go_authenticate: function () {
this.$router.replace('/authentication') this.$router.replace('/authentication')
}, },
launch_old_version: function () { launch_old_version: function () {
this.$root.exit() this.$root.exit()
}, },
go_packages: function () { go_packages: function () {
this.$router.push('/packages') this.$router.push('/packages')
}
} }
} }
}
</script> </script>
<style scoped> <style scoped>
</style> </style>

View file

@ -26,14 +26,14 @@
</div> </div>
</div> </div>
</div> </div>
<div class="tile is-child is-6 box clickable-box" v-if="!$root.$data.metadata.preexisting_install" v-on:click.capture.stop="installDesktopShortcut = !installDesktopShortcut">
<h4>Install Options</h4>
<b-checkbox v-model="installDesktopShortcut">
Create Desktop Shortcut
</b-checkbox>
</div>
</div> </div>
</div> </div>
<div class="tile is-child is-6 box clickable-box" v-if="!$root.$data.metadata.preexisting_install" v-on:click.capture.stop="installDesktopShortcut = !installDesktopShortcut">
<h4>Install Options</h4>
<b-checkbox v-model="installDesktopShortcut">
Create Desktop Shortcut
</b-checkbox>
</div>
<div class="subtitle is-6" v-if="!$root.$data.metadata.preexisting_install && advanced">{{ $t('select_packages.location') }}</div> <div class="subtitle is-6" v-if="!$root.$data.metadata.preexisting_install && advanced">{{ $t('select_packages.location') }}</div>
<div class="field has-addons" v-if="!$root.$data.metadata.preexisting_install && advanced"> <div class="field has-addons" v-if="!$root.$data.metadata.preexisting_install && advanced">
@ -79,6 +79,7 @@ export default {
name: 'SelectPackages', name: 'SelectPackages',
data: function () { data: function () {
return { return {
publicPath: process.env.BASE_URL,
advanced: false, advanced: false,
repair: false, repair: false,
installDesktopShortcut: true installDesktopShortcut: true
@ -131,22 +132,22 @@ export default {
} }
// maintenance + repair // maintenance + repair
if (this.repair) { if (this.repair) {
this.$router.push('/install/repair') this.$router.push('/install/repair/' + this.installDesktopShortcut.toString())
return return
} }
// maintenance + modify // maintenance + modify
if (this.$root.$data.metadata.preexisting_install) { if (this.$root.$data.metadata.preexisting_install) {
this.$router.push('/install/regular') this.$router.push('/install/regular/' + this.installDesktopShortcut.toString())
return return
} }
const my = this const my = this
this.$http.post('/api/verify-path', `path=${this.$root.$data.install_location}`).then(function (resp) { this.$http.post('/api/verify-path', `path=${this.$root.$data.install_location}`).then(function (resp) {
const data = resp.data || {} const data = resp.data || {}
if (!data.exists) { if (!data.exists) {
my.$router.push('/install/regular') my.$router.push('/install/regular/' + my.installDesktopShortcut.toString())
} else { } else {
my.show_overwrite_dialog(function () { my.show_overwrite_dialog(function () {
my.$router.push('/install/repair') my.$router.push('/install/repair/' + my.installDesktopShortcut.toString())
}) })
} }
}) })