From 722802c0013d18a36e10c34d060c4c5064c452dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ana=C3=AFs=20Saraiva?=
<53227802+Kisakay@users.noreply.github.com>
Date: Mon, 19 Oct 2026 18:57:41 +0200
Subject: [PATCH] launcher: purge auth Mojang (depreciee), Microsoft uniquement
- bootstrap: validateSelected() ne tente plus de sign-in Mojang
- suppression formulaire login.ejs / login.js et de la vue login
- authmanager: retrait addMojangAccount/removeMojangAccount/mojangErrorDisplayable
- configmanager: retrait clientToken et helpers comptes Mojang
- settings/processbuilder: flux Microsoft uniquement (user_type=msa)
- landing: retrait du refresh de statut Mojang (fonction + UI + CSS)
---
launcher/app/app.ejs | 1 -
launcher/app/assets/css/launcher.css | 103 ---------
launcher/app/assets/js/authmanager.js | 198 ++---------------
launcher/app/assets/js/configmanager.js | 63 +-----
launcher/app/assets/js/processbuilder.js | 4 +-
launcher/app/assets/js/scripts/landing.js | 63 ------
launcher/app/assets/js/scripts/login.js | 234 ---------------------
launcher/app/assets/js/scripts/settings.js | 30 +--
launcher/app/assets/js/scripts/uibinder.js | 34 +--
launcher/app/landing.ejs | 19 --
launcher/app/login.ejs | 65 ------
11 files changed, 31 insertions(+), 783 deletions(-)
delete mode 100644 launcher/app/assets/js/scripts/login.js
delete mode 100644 launcher/app/login.ejs
diff --git a/launcher/app/app.ejs b/launcher/app/app.ejs
index bfef51a..c41ff90 100644
--- a/launcher/app/app.ejs
+++ b/launcher/app/app.ejs
@@ -30,7 +30,6 @@
<%- include('frame') %>
<%- include('welcome') %>
- <%- include('login') %>
<%- include('waiting') %>
<%- include('loginOptions') %>
<%- include('settings') %>
diff --git a/launcher/app/assets/css/launcher.css b/launcher/app/assets/css/launcher.css
index 02e129a..16b325e 100644
--- a/launcher/app/assets/css/launcher.css
+++ b/launcher/app/assets/css/launcher.css
@@ -3208,109 +3208,6 @@ input:checked + .toggleSwitchSlider:before {
margin-left: 10px;
}
-/* Wrapper container for the mojang status bar. */
-#mojangStatusWrapper {
- position: relative;
- display: flex;
- cursor: pointer;
-}
-
-/* Icon which displays the status of the mojang services. */
-#mojang_status_icon {
- font-size: 30px;
- color: #848484;
- margin-left: 15px;
- font-family: 'sans-serif';
-}
-
-/* Tooltip which displays more details about the mojang statuses. */
-#mojangStatusTooltip {
- position: absolute;
- visibility: hidden;
- opacity: 0;
- width: 145px;
- min-height: 150px;
- background-color: rgba(0, 0, 0, 0.75);
- color: #fff;
- border-radius: 4px;
- padding: 5px 10px;
- z-index: 1;
- font-family: 'Avenir Medium';
- font-size: 12px;
- transition: visibility 0s linear 0.25s, opacity 0.25s ease;
- bottom: calc(100% + 15px);
- transform: translateX(-50%);
- margin-left: 50%;
- box-shadow: 0px 0px 20px rgb(0, 0, 0);
- cursor: default;
-}
-#mojangStatusTooltip:after {
- content: " ";
- position: absolute;
- left: 50%;
- top: 100%;
- margin-left: -5px;
- border-width: 5px;
- border-style: solid;
- border-color: rgba(0, 0, 0, 0.75) transparent transparent transparent;
-}
-#mojangStatusWrapper:hover #mojangStatusTooltip {
- visibility: visible;
- opacity: 1;
- transition-delay: 0s;
-}
-
-/* Tooltip title for the mojang statuses. */
-#mojangStatusTooltipTitle {
- width: 100%;
- text-align: center;
- margin-bottom: 5px;
- letter-spacing: 1px;
-}
-
-/* Wrapper container for the non essential services title. */
-#mojangStatusNEContainer {
- display: flex;
- align-items: center;
- margin: 10px 0px;
-}
-
-/* White bar which surrounds the non essential service title. */
-.mojangStatusNEBar {
- height: 1px;
- width: 100%;
- background: white;
-}
-
-/* Non essential service title text. */
-#mojangStatusNETitle {
- font-size: 10px;
- padding: 0px 3px;
- text-align: center;
- letter-spacing: 1px;
-}
-
-/* Wrapper container for mojang service information. */
-.mojangStatusContainer {
- display: flex;
-}
-
-/* Displays the name of the mojang service. */
-.mojangStatusName {
- width: 100%;
- font-size: 10px;
- letter-spacing: 1px;
- line-height: 12px;
- padding: 6px 0px;
-}
-
-/* Displays the status of the mojang service. */
-.mojangStatusIcon {
- margin-right: 10px;
- font-size: 18.5px;
- color: #848484;
-}
-
/* * *
* Landing View (Bottom Styles) | Center Content
* * */
diff --git a/launcher/app/assets/js/authmanager.js b/launcher/app/assets/js/authmanager.js
index 5d67bbb..e7985b6 100644
--- a/launcher/app/assets/js/authmanager.js
+++ b/launcher/app/assets/js/authmanager.js
@@ -1,10 +1,10 @@
/**
* AuthManager
*
- * This module aims to abstract login procedures. Results from Mojang's REST api
- * are retrieved through our Mojang module. These results are processed and stored,
- * if applicable, in the config using the ConfigManager. All login procedures should
- * be made through this module.
+ * This module aims to abstract login procedures. Microsoft auth results
+ * are retrieved through our Microsoft module. These results are processed and
+ * stored, if applicable, in the config using the ConfigManager. All login
+ * procedures should be made through this module.
*
* @module authmanager
*/
@@ -12,7 +12,6 @@
const ConfigManager = require('./configmanager')
const { LoggerUtil } = require('helios-core')
const { RestResponseStatus } = require('helios-core/common')
-const { MojangRestAPI, MojangErrorCode } = require('helios-core/mojang')
const { MicrosoftAuth, MicrosoftErrorCode } = require('helios-core/microsoft')
const { AZURE_CLIENT_ID } = require('./ipcconstants')
const Lang = require('./langloader')
@@ -51,122 +50,8 @@ function microsoftErrorDisplayable(errorCode) {
}
}
-function mojangErrorDisplayable(errorCode) {
- switch(errorCode) {
- case MojangErrorCode.ERROR_METHOD_NOT_ALLOWED:
- return {
- title: Lang.queryJS('auth.mojang.error.methodNotAllowedTitle'),
- desc: Lang.queryJS('auth.mojang.error.methodNotAllowedDesc')
- }
- case MojangErrorCode.ERROR_NOT_FOUND:
- return {
- title: Lang.queryJS('auth.mojang.error.notFoundTitle'),
- desc: Lang.queryJS('auth.mojang.error.notFoundDesc')
- }
- case MojangErrorCode.ERROR_USER_MIGRATED:
- return {
- title: Lang.queryJS('auth.mojang.error.accountMigratedTitle'),
- desc: Lang.queryJS('auth.mojang.error.accountMigratedDesc')
- }
- case MojangErrorCode.ERROR_INVALID_CREDENTIALS:
- return {
- title: Lang.queryJS('auth.mojang.error.invalidCredentialsTitle'),
- desc: Lang.queryJS('auth.mojang.error.invalidCredentialsDesc')
- }
- case MojangErrorCode.ERROR_RATELIMIT:
- return {
- title: Lang.queryJS('auth.mojang.error.tooManyAttemptsTitle'),
- desc: Lang.queryJS('auth.mojang.error.tooManyAttemptsDesc')
- }
- case MojangErrorCode.ERROR_INVALID_TOKEN:
- return {
- title: Lang.queryJS('auth.mojang.error.invalidTokenTitle'),
- desc: Lang.queryJS('auth.mojang.error.invalidTokenDesc')
- }
- case MojangErrorCode.ERROR_ACCESS_TOKEN_HAS_PROFILE:
- return {
- title: Lang.queryJS('auth.mojang.error.tokenHasProfileTitle'),
- desc: Lang.queryJS('auth.mojang.error.tokenHasProfileDesc')
- }
- case MojangErrorCode.ERROR_CREDENTIALS_MISSING:
- return {
- title: Lang.queryJS('auth.mojang.error.credentialsMissingTitle'),
- desc: Lang.queryJS('auth.mojang.error.credentialsMissingDesc')
- }
- case MojangErrorCode.ERROR_INVALID_SALT_VERSION:
- return {
- title: Lang.queryJS('auth.mojang.error.invalidSaltVersionTitle'),
- desc: Lang.queryJS('auth.mojang.error.invalidSaltVersionDesc')
- }
- case MojangErrorCode.ERROR_UNSUPPORTED_MEDIA_TYPE:
- return {
- title: Lang.queryJS('auth.mojang.error.unsupportedMediaTypeTitle'),
- desc: Lang.queryJS('auth.mojang.error.unsupportedMediaTypeDesc')
- }
- case MojangErrorCode.ERROR_GONE:
- return {
- title: Lang.queryJS('auth.mojang.error.accountGoneTitle'),
- desc: Lang.queryJS('auth.mojang.error.accountGoneDesc')
- }
- case MojangErrorCode.ERROR_UNREACHABLE:
- return {
- title: Lang.queryJS('auth.mojang.error.unreachableTitle'),
- desc: Lang.queryJS('auth.mojang.error.unreachableDesc')
- }
- case MojangErrorCode.ERROR_NOT_PAID:
- return {
- title: Lang.queryJS('auth.mojang.error.gameNotPurchasedTitle'),
- desc: Lang.queryJS('auth.mojang.error.gameNotPurchasedDesc')
- }
- case MojangErrorCode.UNKNOWN:
- return {
- title: Lang.queryJS('auth.mojang.error.unknownErrorTitle'),
- desc: Lang.queryJS('auth.mojang.error.unknownErrorDesc')
- }
- default:
- throw new Error(`Unknown error code: ${errorCode}`)
- }
-}
-
// Functions
-/**
- * Add a Mojang account. This will authenticate the given credentials with Mojang's
- * authserver. The resultant data will be stored as an auth account in the
- * configuration database.
- *
- * @param {string} username The account username (email if migrated).
- * @param {string} password The account password.
- * @returns {Promise.
`
- if(service.essential){
- tooltipEssentialHTML += tooltipHTML
- } else {
- tooltipNonEssentialHTML += tooltipHTML
- }
-
- if(service.status === 'yellow' && status !== 'red'){
- status = 'yellow'
- } else if(service.status === 'red'){
- status = 'red'
- } else {
- if(service.status === 'grey'){
- ++greyCount
- }
- ++greenCount
- }
-
- }
-
- if(greenCount === statuses.length){
- if(greyCount === statuses.length){
- status = 'grey'
- } else {
- status = 'green'
- }
- }
-
- document.getElementById('mojangStatusEssentialContainer').innerHTML = tooltipEssentialHTML
- document.getElementById('mojangStatusNonEssentialContainer').innerHTML = tooltipNonEssentialHTML
- document.getElementById('mojang_status_icon').style.color = MojangRestAPI.statusToHex(status)
-}
-
const refreshServerStatus = async (fade = false) => {
loggerLanding.info('Refreshing Server Status')
const serv = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer())
@@ -266,11 +206,8 @@ const refreshServerStatus = async (fade = false) => {
}
-refreshMojangStatuses()
// Server Status is refreshed in uibinder.js on distributionIndexDone.
-// Refresh statuses every hour. The status page itself refreshes every day so...
-let mojangStatusListener = setInterval(() => refreshMojangStatuses(true), 60*60*1000)
// Set refresh rate to once every 5 minutes.
let serverStatusListener = setInterval(() => refreshServerStatus(true), 300000)
diff --git a/launcher/app/assets/js/scripts/login.js b/launcher/app/assets/js/scripts/login.js
deleted file mode 100644
index 30ff893..0000000
--- a/launcher/app/assets/js/scripts/login.js
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- * Script for login.ejs
- */
-// Validation Regexes.
-const validUsername = /^[a-zA-Z0-9_]{1,16}$/
-const basicEmail = /^\S+@\S+\.\S+$/
-//const validEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i
-
-// Login Elements
-const loginCancelContainer = document.getElementById('loginCancelContainer')
-const loginCancelButton = document.getElementById('loginCancelButton')
-const loginEmailError = document.getElementById('loginEmailError')
-const loginUsername = document.getElementById('loginUsername')
-const loginPasswordError = document.getElementById('loginPasswordError')
-const loginPassword = document.getElementById('loginPassword')
-const checkmarkContainer = document.getElementById('checkmarkContainer')
-const loginRememberOption = document.getElementById('loginRememberOption')
-const loginButton = document.getElementById('loginButton')
-const loginForm = document.getElementById('loginForm')
-
-// Control variables.
-let lu = false, lp = false
-
-
-/**
- * Show a login error.
- *
- * @param {HTMLElement} element The element on which to display the error.
- * @param {string} value The error text.
- */
-function showError(element, value){
- element.innerHTML = value
- element.style.opacity = 1
-}
-
-/**
- * Shake a login error to add emphasis.
- *
- * @param {HTMLElement} element The element to shake.
- */
-function shakeError(element){
- if(element.style.opacity == 1){
- element.classList.remove('shake')
- void element.offsetWidth
- element.classList.add('shake')
- }
-}
-
-/**
- * Validate that an email field is neither empty nor invalid.
- *
- * @param {string} value The email value.
- */
-function validateEmail(value){
- if(value){
- if(!basicEmail.test(value) && !validUsername.test(value)){
- showError(loginEmailError, Lang.queryJS('login.error.invalidValue'))
- loginDisabled(true)
- lu = false
- } else {
- loginEmailError.style.opacity = 0
- lu = true
- if(lp){
- loginDisabled(false)
- }
- }
- } else {
- lu = false
- showError(loginEmailError, Lang.queryJS('login.error.requiredValue'))
- loginDisabled(true)
- }
-}
-
-/**
- * Validate that the password field is not empty.
- *
- * @param {string} value The password value.
- */
-function validatePassword(value){
- if(value){
- loginPasswordError.style.opacity = 0
- lp = true
- if(lu){
- loginDisabled(false)
- }
- } else {
- lp = false
- showError(loginPasswordError, Lang.queryJS('login.error.invalidValue'))
- loginDisabled(true)
- }
-}
-
-// Emphasize errors with shake when focus is lost.
-loginUsername.addEventListener('focusout', (e) => {
- validateEmail(e.target.value)
- shakeError(loginEmailError)
-})
-loginPassword.addEventListener('focusout', (e) => {
- validatePassword(e.target.value)
- shakeError(loginPasswordError)
-})
-
-// Validate input for each field.
-loginUsername.addEventListener('input', (e) => {
- validateEmail(e.target.value)
-})
-loginPassword.addEventListener('input', (e) => {
- validatePassword(e.target.value)
-})
-
-/**
- * Enable or disable the login button.
- *
- * @param {boolean} v True to enable, false to disable.
- */
-function loginDisabled(v){
- if(loginButton.disabled !== v){
- loginButton.disabled = v
- }
-}
-
-/**
- * Enable or disable loading elements.
- *
- * @param {boolean} v True to enable, false to disable.
- */
-function loginLoading(v){
- if(v){
- loginButton.setAttribute('loading', v)
- loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.login'), Lang.queryJS('login.loggingIn'))
- } else {
- loginButton.removeAttribute('loading')
- loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.loggingIn'), Lang.queryJS('login.login'))
- }
-}
-
-/**
- * Enable or disable login form.
- *
- * @param {boolean} v True to enable, false to disable.
- */
-function formDisabled(v){
- loginDisabled(v)
- loginCancelButton.disabled = v
- loginUsername.disabled = v
- loginPassword.disabled = v
- if(v){
- checkmarkContainer.setAttribute('disabled', v)
- } else {
- checkmarkContainer.removeAttribute('disabled')
- }
- loginRememberOption.disabled = v
-}
-
-let loginViewOnSuccess = VIEWS.landing
-let loginViewOnCancel = VIEWS.settings
-let loginViewCancelHandler
-
-function loginCancelEnabled(val){
- if(val){
- $(loginCancelContainer).show()
- } else {
- $(loginCancelContainer).hide()
- }
-}
-
-loginCancelButton.onclick = (e) => {
- switchView(getCurrentView(), loginViewOnCancel, 500, 500, () => {
- loginUsername.value = ''
- loginPassword.value = ''
- loginCancelEnabled(false)
- if(loginViewCancelHandler != null){
- loginViewCancelHandler()
- loginViewCancelHandler = null
- }
- })
-}
-
-// Disable default form behavior.
-loginForm.onsubmit = () => { return false }
-
-// Bind login button behavior.
-loginButton.addEventListener('click', () => {
- // Disable form.
- formDisabled(true)
-
- // Show loading stuff.
- loginLoading(true)
-
- AuthManager.addMojangAccount(loginUsername.value, loginPassword.value).then((value) => {
- updateSelectedAccount(value)
- loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.loggingIn'), Lang.queryJS('login.success'))
- $('.circle-loader').toggleClass('load-complete')
- $('.checkmark').toggle()
- setTimeout(() => {
- switchView(VIEWS.login, loginViewOnSuccess, 500, 500, async () => {
- // Temporary workaround
- if(loginViewOnSuccess === VIEWS.settings){
- await prepareSettings()
- }
- loginViewOnSuccess = VIEWS.landing // Reset this for good measure.
- loginCancelEnabled(false) // Reset this for good measure.
- loginViewCancelHandler = null // Reset this for good measure.
- loginUsername.value = ''
- loginPassword.value = ''
- $('.circle-loader').toggleClass('load-complete')
- $('.checkmark').toggle()
- loginLoading(false)
- loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.success'), Lang.queryJS('login.login'))
- formDisabled(false)
- })
- }, 1000)
- }).catch((displayableError) => {
- loginLoading(false)
-
- let actualDisplayableError
- if(isDisplayableError(displayableError)) {
- msftLoginLogger.error('Error while logging in.', displayableError)
- actualDisplayableError = displayableError
- } else {
- // Uh oh.
- msftLoginLogger.error('Unhandled error during login.', displayableError)
- actualDisplayableError = Lang.queryJS('login.error.unknown')
- }
-
- setOverlayContent(actualDisplayableError.title, actualDisplayableError.desc, Lang.queryJS('login.tryAgain'))
- setOverlayHandler(() => {
- formDisabled(false)
- toggleOverlay(false)
- })
- toggleOverlay(true)
- })
-
-})
\ No newline at end of file
diff --git a/launcher/app/assets/js/scripts/settings.js b/launcher/app/assets/js/scripts/settings.js
index 0cd8351..fb73ce6 100644
--- a/launcher/app/assets/js/scripts/settings.js
+++ b/launcher/app/assets/js/scripts/settings.js
@@ -502,32 +502,10 @@ let msAccDomElementCache
function processLogOut(val, isLastAccount){
const parent = val.closest('.settingsAuthAccount')
const uuid = parent.getAttribute('uuid')
- const prevSelAcc = ConfigManager.getSelectedAccount()
- const targetAcc = ConfigManager.getAuthAccount(uuid)
- if(targetAcc.type === 'microsoft') {
- msAccDomElementCache = parent
- switchView(getCurrentView(), VIEWS.waiting, 500, 500, () => {
- ipcRenderer.send(MSFT_OPCODE.OPEN_LOGOUT, uuid, isLastAccount)
- })
- } else {
- AuthManager.removeMojangAccount(uuid).then(() => {
- if(!isLastAccount && uuid === prevSelAcc.uuid){
- const selAcc = ConfigManager.getSelectedAccount()
- refreshAuthAccountSelected(selAcc.uuid)
- updateSelectedAccount(selAcc)
- validateSelectedAccount()
- }
- if(isLastAccount) {
- loginOptionsCancelEnabled(false)
- loginOptionsViewOnLoginSuccess = VIEWS.settings
- loginOptionsViewOnLoginCancel = VIEWS.loginOptions
- switchView(getCurrentView(), VIEWS.loginOptions)
- }
- })
- $(parent).fadeOut(250, () => {
- parent.remove()
- })
- }
+ msAccDomElementCache = parent
+ switchView(getCurrentView(), VIEWS.waiting, 500, 500, () => {
+ ipcRenderer.send(MSFT_OPCODE.OPEN_LOGOUT, uuid, isLastAccount)
+ })
}
// Bind reply for Microsoft Logout.
diff --git a/launcher/app/assets/js/scripts/uibinder.js b/launcher/app/assets/js/scripts/uibinder.js
index 0cc158c..5ad96a6 100644
--- a/launcher/app/assets/js/scripts/uibinder.js
+++ b/launcher/app/assets/js/scripts/uibinder.js
@@ -17,7 +17,6 @@ let fatalStartupError = false
const VIEWS = {
landing: '#landingContainer',
loginOptions: '#loginOptionsContainer',
- login: '#loginContainer',
settings: '#settingsContainer',
welcome: '#welcomeContainer',
waiting: '#waitingContainer'
@@ -336,36 +335,21 @@ async function validateSelectedAccount(){
)
setOverlayHandler(() => {
- const isMicrosoft = selectedAcc.type === 'microsoft'
-
- if(isMicrosoft) {
- // Empty for now
- } else {
- // Mojang
- // For convenience, pre-populate the username of the account.
- document.getElementById('loginUsername').value = selectedAcc.username
- validateEmail(selectedAcc.username)
- }
-
loginOptionsViewOnLoginSuccess = getCurrentView()
loginOptionsViewOnLoginCancel = VIEWS.loginOptions
if(accLen > 0) {
loginOptionsViewOnCancel = getCurrentView()
loginOptionsViewCancelHandler = () => {
- if(isMicrosoft) {
- ConfigManager.addMicrosoftAuthAccount(
- selectedAcc.uuid,
- selectedAcc.accessToken,
- selectedAcc.username,
- selectedAcc.expiresAt,
- selectedAcc.microsoft.access_token,
- selectedAcc.microsoft.refresh_token,
- selectedAcc.microsoft.expires_at
- )
- } else {
- ConfigManager.addMojangAuthAccount(selectedAcc.uuid, selectedAcc.accessToken, selectedAcc.username, selectedAcc.displayName)
- }
+ ConfigManager.addMicrosoftAuthAccount(
+ selectedAcc.uuid,
+ selectedAcc.accessToken,
+ selectedAcc.username,
+ selectedAcc.expiresAt,
+ selectedAcc.microsoft.access_token,
+ selectedAcc.microsoft.refresh_token,
+ selectedAcc.microsoft.expires_at
+ )
ConfigManager.save()
validateSelectedAccount()
}
diff --git a/launcher/app/landing.ejs b/launcher/app/landing.ejs
index b9e0aab..8c3b486 100644
--- a/launcher/app/landing.ejs
+++ b/launcher/app/landing.ejs
@@ -39,25 +39,6 @@
<%- lang('landing.serverStatus') %>
<%- lang('landing.serverStatusPlaceholder') %>
-
-
-
<%- lang('landing.mojangStatus') %>
-
•
-
-
diff --git a/launcher/app/login.ejs b/launcher/app/login.ejs
deleted file mode 100644
index 2da8072..0000000
--- a/launcher/app/login.ejs
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file