Skip to content

Commit

Permalink
Merge pull request #408 from Zagrios/feature/admin-confirm-modal
Browse files Browse the repository at this point in the history
[feature] Added admin launch information modal
  • Loading branch information
Zagrios authored Jan 24, 2024
2 parents 16b9ca7 + 63d35f6 commit 0b7cad8
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 14 deletions.
10 changes: 10 additions & 0 deletions assets/jsons/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,16 @@
"enter-oculus-token": "Ein Oculus-Token eingeben"
},
"valid-btn": "Validieren"
},
"launch-as-admin": {
"title": "Administratorberechtigungen",
"body": {
"info": "Es wurde festgestellt, dass Steam mit Administratorrechten ausgeführt wird. Um mit Steam zu kommunizieren, muss auch Beat Saber als Administrator gestartet werden. Andernfalls könnte Beat Saber Probleme haben und nach dem Starten schließen.",
"info-2": "Das Starten von Beat Saber im Administratormodus gibt auch den installierten Mods Administratorrechte. Daher wird empfohlen, Steam ohne Administratorrechte neu zu starten.",
"info-3": "Beachten Sie, dass es nicht ratsam ist, Steam Administratorrechte zu geben, da dies auch die installierten Spiele und Mods betrifft und ein Sicherheitsrisiko darstellt."
},
"launch-as-admin": "Als Administrator starten",
"not-remind-me": "Nicht mehr erinnern"
}
},
"maps": {
Expand Down
10 changes: 10 additions & 0 deletions assets/jsons/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,16 @@
"enter-oculus-token": "Enter an Oculus token"
},
"valid-btn": "Validate"
},
"launch-as-admin": {
"title": "Administrator Permissions",
"body": {
"info": "Steam has been detected as running with administrator permissions. To communicate with Steam, Beat Saber must also be launched as an administrator. Otherwise, Beat Saber might experience problems and close after launching.",
"info-2": "Launching Beat Saber in administrator mode will also give administrator rights to the installed mods. Therefore, it is recommended to restart Steam without administrator permissions.",
"info-3": "Note that it is advised against giving administrator rights to Steam, as this affects the installed games and mods, presenting a security risk."
},
"launch-as-admin": "Launch as Administrator",
"not-remind-me": "Do not remind me"
}
},
"maps": {
Expand Down
10 changes: 10 additions & 0 deletions assets/jsons/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,16 @@
"enter-oculus-token": "Introducir un token de Oculus"
},
"valid-btn": "Validar"
},
"launch-as-admin": {
"title": "Permisos Administrador",
"body": {
"info": "Se ha detectado que Steam está funcionando con permisos de administrador. Para comunicarse con Steam, Beat Saber también debe iniciarse como administrador. De lo contrario, Beat Saber podría experimentar problemas y cerrarse después de iniciar.",
"info-2": "Iniciar Beat Saber en modo administrador también otorgará derechos de administrador a los mods instalados. Por lo tanto, se recomienda reiniciar Steam sin permisos de administrador.",
"info-3": "Tenga en cuenta que se desaconseja otorgar derechos de administrador a Steam, ya que esto afecta a los juegos y mods instalados, presentando un riesgo de seguridad."
},
"launch-as-admin": "Iniciar como Administrador",
"not-remind-me": "No volver a recordármelo"
}
},
"maps": {
Expand Down
10 changes: 10 additions & 0 deletions assets/jsons/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,16 @@
"enter-oculus-token": "Entrer un token Oculus"
},
"valid-btn": "Valider"
},
"launch-as-admin": {
"title": "Permissions Administrateur",
"body": {
"info": "Steam a été détecté comme fonctionnant avec des permissions administrateur. Afin communiquer avec Steam, Beat Saber doit également être lancé en tant qu'administrateur. Dans le cas contraire, Beat Saber pourrait rencontrer des problèmes et se fermer après son lancement.",
"info-2": "Lancer Beat Saber en mode administrateur donnera également les droits administrateur aux mods installés. Il est donc plutôt recommandé de redémarrer Steam sans permissions administrateur.",
"info-3": "Notez qu'il est déconseillé de donner des droits d'administrateur à Steam, car cela affecte également les jeux et mods installés, présentant un risque pour la sécurité."
},
"launch-as-admin": "Lancer en administateur",
"not-remind-me": "Ne plus me rappeler"
}
},
"maps": {
Expand Down
10 changes: 10 additions & 0 deletions assets/jsons/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,16 @@
"enter-oculus-token": "オキュラストークンを入力する"
},
"valid-btn": "確認"
},
"launch-as-admin": {
"title": "管理者権限",
"body": {
"info": "Steamが管理者権限で動作していることが検出されました。Steamと通信するためには、Beat Saberも管理者として起動する必要があります。そうでない場合、Beat Saberは問題が発生し、起動後に終了する可能性があります。",
"info-2": "管理者モードでBeat Saberを起動すると、インストールされたMODにも管理者権限が与えられます。そのため、管理者権限なしでSteamを再起動することをお勧めします。",
"info-3": "Steamに管理者権限を与えることはお勧めできません。これはインストールされたゲームやMODにも影響を与え、セキュリティリスクをもたらすからです。"
},
"launch-as-admin": "管理者として起動",
"not-remind-me": "Больше не напоминать"
}
},
"maps": {
Expand Down
9 changes: 9 additions & 0 deletions assets/jsons/translations/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,15 @@
"enter-oculus-token": "Введите токен Oculus"
},
"valid-btn": "Подтвердить"
},
"launch-as-admin": {
"title": "Права Администратора",
"body": {
"info": "Обнаружено, что Steam работает с правами администратора. Чтобы связаться со Steam, Beat Saber также должен быть запущен от имени администратора. В противном случае Beat Saber может столкнуться с проблемами и закрыться после запуска.",
"info-2": "Запуск Beat Saber в режиме администратора также даст права администратора установленным модам. Поэтому рекомендуется перезапустить Steam без прав администратора.",
"info-3": "Обратите внимание, что не рекомендуется предоставлять права администратора Steam, так как это также влияет на установленные игры и моды, представляя угрозу безопасности."
},
"launch-as-admin": "Запустить от имени администратора"
}
},
"maps": {
Expand Down
10 changes: 10 additions & 0 deletions assets/jsons/translations/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,16 @@
"enter-oculus-token": "輸入Oculus令牌"
},
"valid-btn": "驗證"
},
"launch-as-admin": {
"title": "管理員權限",
"body": {
"info": "檢測到Steam正在以管理員權限運行。為了與Steam通信,Beat Saber也必須以管理員身份啟動。否則,Beat Saber可能會遇到問題並在啟動後關閉。",
"info-2": "以管理員模式啟動Beat Saber還會將管理員權限賦予已安裝的模組。因此,建議重啟Steam,不使用管理員權限。",
"info-3": "請注意,不建議給Steam管理員權限,因為這也會影響已安裝的遊戲和模組,帶來安全風險。"
},
"launch-as-admin": "以管理員身份啟動",
"not-remind-me": "不再提醒我"
}
},
"maps": {
Expand Down
10 changes: 10 additions & 0 deletions assets/jsons/translations/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,16 @@
"enter-oculus-token": "输入Oculus令牌"
},
"valid-btn": "验证"
},
"launch-as-admin": {
"title": "管理员权限",
"body": {
"info": "检测到Steam正在以管理员权限运行。为了与Steam通信,Beat Saber也必须以管理员身份启动。否则,Beat Saber可能会遇到问题并在启动后关闭。",
"info-2": "以管理员模式启动Beat Saber还会将管理员权限赋予已安装的模组。因此,建议重启Steam,不使用管理员权限。",
"info-3": "请注意,不建议给Steam管理员权限,因为这也会影响已安装的游戏和模组,带来安全风险。"
},
"launch-as-admin": "以管理员身份启动",
"not-remind-me": "不再提醒我"
}
},
"maps": {
Expand Down
12 changes: 11 additions & 1 deletion src/main/ipcs/bs-launcher-ipcs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { IpcService } from '../services/ipc.service';
import { from } from "rxjs";
import { SteamLauncherService } from "../services/bs-launcher/steam-launcher.service";
import { OculusLauncherService } from "../services/bs-launcher/oculus-launcher.service";
import { SteamService } from "../services/steam.service";
import isElevated from "is-elevated";

const ipc = IpcService.getInstance();

Expand All @@ -13,6 +15,14 @@ ipc.on<LaunchOption>('bs-launch.launch', (req, reply) => {
reply(bsLauncher.launch(req.args));
});

ipc.on<boolean>("bs-launch.need-start-as-admin", (_, reply) => {
const steam = SteamService.getInstance();
reply(from(isElevated().then(elevated => {
if(elevated){ return false; }
return steam.isElevated();
})));
})

ipc.on<LaunchOption>("create-launch-shortcut", (req, reply) => {
const bsLauncher = BSLauncherService.getInstance();
reply(from(bsLauncher.createLaunchShortcut(req.args)));
Expand All @@ -29,4 +39,4 @@ ipc.on<void>("restore-original-oculus-folder", (_, reply) => {
reply(from(
oculusLauncher.deleteBsSymlinks().then(() => oculusLauncher.restoreOriginalBeatSaber())
));
})
})
12 changes: 5 additions & 7 deletions src/main/services/bs-launcher/steam-launcher.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,15 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto

obs.next({type: BSLaunchEvent.BS_LAUNCHING});

const needToStartAsAdmin = await this.needStartBsAsAdmin().catch(err => {
log.error("Error while checking if need to start BS as Admin", err);
return false;
});

const launchPromise = !needToStartAsAdmin ? (
const launchPromise = !launchOptions.admin ? (
this.launchBs(exePath, launchArgs, { env: {...process.env, "SteamAppId": BS_APP_ID} })
) : (
new Promise<number>(resolve => {
const adminProcess = exec(`"${this.getStartBsAsAdminExePath()}" "${exePath}" ${launchArgs.join(" ")}`, { env: {...process.env, "SteamAppId": BS_APP_ID} });
adminProcess.on("error", err => {log.error("Error while starting BS as Admin", err); resolve(-1)});
adminProcess.on("error", err => {
log.error("Error while starting BS as Admin", err);
resolve(-1)
});

setTimeout(() => {
adminProcess.removeAllListeners("error");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { BsmButton } from "renderer/components/shared/bsm-button.component"
import { BsmImage } from "renderer/components/shared/bsm-image.component"
import { ModalComponent, ModalExitCode } from "renderer/services/modale.service"
import BeatConflict from "../../../../../assets/images/apngs/beat-conflict.png";
import { useTranslation } from "renderer/hooks/use-translation.hook";
import { BsmCheckbox } from "renderer/components/shared/bsm-checkbox.component";
import { useState } from "react";

export const NeedLaunchAdminModal: ModalComponent<boolean, void> = ({resolver}) => {

const t = useTranslation();

const [dontShowAgain, setDontShowAgain] = useState(false);

return (
<form className="text-gray-800 dark:text-gray-200 flex flex-col min-w-[350px]">
<h1 className="text-3xl uppercase tracking-wide w-full text-center">{t("modals.launch-as-admin.title")}</h1>
<BsmImage className="mx-auto h-24" image={BeatConflict} />
<div className="flex flex-col gap-3">
<p className="w-0 min-w-full">{t("modals.launch-as-admin.body.info")}</p>
<p className="w-0 min-w-full">{t("modals.launch-as-admin.body.info-2")}</p>
<p className="w-0 min-w-full text-sm italic">{t("modals.launch-as-admin.body.info-3")}</p>
</div>
<div className="flex flex-row justify-start items-center gap-1.5 my-4">
<BsmCheckbox className="relative z-[1] w-6 aspect-square" checked={dontShowAgain} onChange={setDontShowAgain} />
<span>{t("modals.launch-as-admin.not-remind-me")}</span>
</div>
<div className="grid grid-flow-col grid-cols-2 gap-4">
<BsmButton typeColor="cancel" className="rounded-md text-center flex items-center justify-center transition-all h-8" onClick={() => resolver({ exitCode: ModalExitCode.CANCELED })} withBar={false} text="misc.cancel" />
<BsmButton typeColor="primary" className="rounded-md text-center flex items-center justify-center transition-all h-8" onClick={() => resolver({ exitCode: ModalExitCode.COMPLETED, data: dontShowAgain })} withBar={false} text="modals.launch-as-admin.launch-as-admin" />
</div>
</form>
)
}
25 changes: 20 additions & 5 deletions src/renderer/services/bs-launcher.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ModalExitCode, ModalService } from "./modale.service";
import { OriginalOculusVersionBackupModal } from "renderer/components/modal/modal-types/original-oculus-version-backup.modal";
import { CustomError } from "shared/models/exceptions/custom-error.class";
import { sToMs } from "shared/helpers/time.helpers";
import { NeedLaunchAdminModal } from "renderer/components/modal/modal-types/need-launch-admin-modal.component";

export class BSLauncherService {
private static instance: BSLauncherService;
Expand All @@ -21,7 +22,7 @@ export class BSLauncherService {
private readonly modals: ModalService;

public readonly versionRunning$: BehaviorSubject<BSVersion> = new BehaviorSubject(null);

public static getInstance(){
if(!BSLauncherService.instance){ BSLauncherService.instance = new BSLauncherService(); }
return BSLauncherService.instance;
Expand Down Expand Up @@ -70,7 +71,17 @@ export class BSLauncherService {
}
}))
}


private async doMustStartAsAdmin(): Promise<boolean> {
const needAdmin = await lastValueFrom(this.ipcService.sendV2<boolean, void>("bs-launch.need-start-as-admin"));
if(!needAdmin){ return false; }
if(this.config.get("dont-remind-admin")){ return true; }
const modalRes = await this.modals.openModal(NeedLaunchAdminModal);
if(modalRes.exitCode !== ModalExitCode.COMPLETED){ throw new Error("Admin launch canceled"); }
this.config.set("dont-remind-admin", modalRes.data);
return true;
}

public doLaunch(launchOptions: LaunchOption): Observable<BSLaunchEventData>{
return this.ipcService.sendV2<BSLaunchEventData, LaunchOption>("bs-launch.launch", {args: launchOptions});
}
Expand All @@ -79,17 +90,21 @@ export class BSLauncherService {

return new Observable<BSLaunchEventData>(obs => {
(async () => {

if(launchOptions.version.metadata?.store === BsStore.OCULUS && !this.notRewindBackupOculus()){
const { exitCode, data: notRewind } = await this.modals.openModal(OriginalOculusVersionBackupModal);
if(exitCode !== ModalExitCode.COMPLETED){ return; }
this.setNotRewindBackupOculus(notRewind);
}


if(launchOptions.version.metadata?.store !== BsStore.OCULUS){
launchOptions.admin = await this.doMustStartAsAdmin();
}

const launch$ = this.handleLaunchEvents(this.doLaunch(launchOptions));

await lastValueFrom(launch$);

})().then(() => {
obs.complete();
}).catch(err => {
Expand Down
3 changes: 2 additions & 1 deletion src/shared/models/bs-launch/launch-option.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export interface LaunchOption {
oculus?: boolean,
desktop?: boolean,
debug?: boolean,
additionalArgs?: string[]
additionalArgs?: string[],
admin?: boolean,
}

0 comments on commit 0b7cad8

Please sign in to comment.