diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/account/AccountProfileManager.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/account/AccountProfileManager.kt index b0f10765b..10338ba91 100644 --- a/src/main/java/de/bixilon/minosoft/config/profile/profiles/account/AccountProfileManager.kt +++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/account/AccountProfileManager.kt @@ -17,6 +17,8 @@ import com.fasterxml.jackson.databind.JavaType import de.bixilon.kutil.cast.CastUtil.unsafeCast import de.bixilon.kutil.collections.CollectionUtil.synchronizedBiMapOf import de.bixilon.kutil.collections.map.bi.AbstractMutableBiMap +import de.bixilon.kutil.json.JsonUtil.toJsonObject +import de.bixilon.kutil.json.JsonUtil.toMutableJsonObject import de.bixilon.kutil.watcher.map.bi.BiMapDataWatcher.Companion.watchedBiMap import de.bixilon.minosoft.config.profile.GlobalProfileManager import de.bixilon.minosoft.config.profile.ProfileManager @@ -28,7 +30,7 @@ import java.util.concurrent.locks.ReentrantLock object AccountProfileManager : ProfileManager { override val namespace = "minosoft:account".toResourceLocation() - override val latestVersion = 1 + override val latestVersion = 2 override val saveLock = ReentrantLock() override val profileClass = AccountProfile::class.java override val jacksonProfileType: JavaType = Jackson.MAPPER.typeFactory.constructType(profileClass) @@ -53,4 +55,22 @@ object AccountProfileManager : ProfileManager { return profile } + + private fun removeMojangAccounts(data: MutableMap) { + val entries = data["entries"]?.toMutableJsonObject() ?: return + val toRemove: MutableSet = mutableSetOf() + for ((id, entry) in entries) { + if (entry.toJsonObject()?.get("type") != "minosoft:mojang_account") { + continue + } + toRemove += id + } + entries -= toRemove + } + + override fun migrate(from: Int, data: MutableMap) { + when (from) { + 1 -> removeMojangAccounts(data) + } + } } diff --git a/src/main/java/de/bixilon/minosoft/data/accounts/Account.kt b/src/main/java/de/bixilon/minosoft/data/accounts/Account.kt index 0f23e32fc..3e1d7b14e 100644 --- a/src/main/java/de/bixilon/minosoft/data/accounts/Account.kt +++ b/src/main/java/de/bixilon/minosoft/data/accounts/Account.kt @@ -22,7 +22,6 @@ import de.bixilon.kutil.watcher.DataWatcher.Companion.watched import de.bixilon.minosoft.config.profile.profiles.account.AccountProfileManager import de.bixilon.minosoft.config.profile.profiles.eros.server.entries.Server import de.bixilon.minosoft.data.accounts.types.microsoft.MicrosoftAccount -import de.bixilon.minosoft.data.accounts.types.mojang.MojangAccount import de.bixilon.minosoft.data.accounts.types.offline.OfflineAccount import de.bixilon.minosoft.data.player.properties.PlayerProperties import de.bixilon.minosoft.data.registries.ResourceLocation @@ -31,7 +30,6 @@ import java.util.* @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes( - JsonSubTypes.Type(value = MojangAccount::class, name = "minosoft:mojang_account"), JsonSubTypes.Type(value = OfflineAccount::class, name = "minosoft:offline_account"), JsonSubTypes.Type(value = MicrosoftAccount::class, name = "minosoft:microsoft_account"), ) diff --git a/src/main/java/de/bixilon/minosoft/data/accounts/types/mojang/MojangAccount.kt b/src/main/java/de/bixilon/minosoft/data/accounts/types/mojang/MojangAccount.kt deleted file mode 100644 index a0a228908..000000000 --- a/src/main/java/de/bixilon/minosoft/data/accounts/types/mojang/MojangAccount.kt +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.data.accounts.types.mojang - -import com.fasterxml.jackson.annotation.JsonProperty -import de.bixilon.kutil.cast.CastUtil.nullCast -import de.bixilon.kutil.cast.CastUtil.unsafeCast -import de.bixilon.kutil.json.JsonUtil.asJsonObject -import de.bixilon.kutil.latch.CountUpAndDownLatch -import de.bixilon.kutil.uuid.UUIDUtil.toUUID -import de.bixilon.minosoft.data.accounts.Account -import de.bixilon.minosoft.data.accounts.AccountStates -import de.bixilon.minosoft.data.player.properties.PlayerProperties -import de.bixilon.minosoft.data.registries.CompanionResourceLocation -import de.bixilon.minosoft.data.registries.ResourceLocation -import de.bixilon.minosoft.util.KUtil.toResourceLocation -import de.bixilon.minosoft.util.account.AccountUtil -import de.bixilon.minosoft.util.http.HTTP2.postJson -import de.bixilon.minosoft.util.http.exceptions.AuthenticationException -import de.bixilon.minosoft.util.logging.Log -import de.bixilon.minosoft.util.logging.LogLevels -import de.bixilon.minosoft.util.logging.LogMessageType -import java.net.ConnectException -import java.util.* - -@Deprecated("Mojang authentication is legacy. Will be removed in the future!") -class MojangAccount( - override val id: String, - username: String, - override val uuid: UUID, - val email: String, - @field:JsonProperty private var accessToken: String, - override val properties: PlayerProperties?, -) : Account(username) { - @Transient - private var refreshed: Boolean = false - override val type: ResourceLocation = RESOURCE_LOCATION - - override fun join(serverId: String) { - AccountUtil.joinMojangServer(username, accessToken, uuid, serverId) - } - - override fun logout(clientToken: String) { - val response = mutableMapOf( - "accessToken" to accessToken, - "clientToken" to clientToken, - ).postJson(MOJANG_URL_INVALIDATE) - - - if (response.statusCode != 200) { - throw AuthenticationException(response.statusCode) - } - state = AccountStates.EXPIRED - Log.log(LogMessageType.AUTHENTICATION, LogLevels.VERBOSE) { "Mojang account login successful (username=$username)" } - } - - override fun check(latch: CountUpAndDownLatch?, clientToken: String) { - if (refreshed) { - return - } - try { - latch?.inc() - refresh(clientToken) - } catch (exception: ConnectException) { - exception.printStackTrace() - state = AccountStates.OFFLINE - } catch (exception: Throwable) { - this.error = exception - state = AccountStates.ERRORED - throw exception - } - latch?.dec() - } - - @Synchronized - fun refresh(clientToken: String) { - state = AccountStates.REFRESHING - val response = mutableMapOf( - "accessToken" to accessToken, - "clientToken" to clientToken, - ).postJson(MOJANG_URL_REFRESH) - - response.body!! - - if (response.statusCode != 200) { - throw AuthenticationException(response.statusCode, response.body["errorMessage"].nullCast()) - } - - this.accessToken = response.body["accessToken"].unsafeCast() - - refreshed = true - state = AccountStates.WORKING - save() - Log.log(LogMessageType.AUTHENTICATION, LogLevels.VERBOSE) { "Mojang account refresh successful (username=$username)" } - } - - override fun toString(): String { - return "MojangAccount{$username}" - } - - companion object : CompanionResourceLocation { - private const val MOJANG_URL_LOGIN = "https://authserver.mojang.com/authenticate" - private const val MOJANG_URL_REFRESH = "https://authserver.mojang.com/refresh" - private const val MOJANG_URL_INVALIDATE = "https://authserver.mojang.com/invalidate" - override val RESOURCE_LOCATION: ResourceLocation = "minosoft:mojang_account".toResourceLocation() - - fun login(clientToken: String, email: String, password: String): MojangAccount { - val response = mutableMapOf( - "agent" to mutableMapOf( - "name" to "Minecraft", - "version" to 1, - ), - "username" to email, - "password" to password, - "clientToken" to clientToken, - "requestUser" to true, - ).postJson(MOJANG_URL_LOGIN) - - response.body!! - - if (response.statusCode != 200) { - throw AuthenticationException(response.statusCode, response.body["errorMessage"]?.nullCast()) - } - - Log.log(LogMessageType.AUTHENTICATION, LogLevels.VERBOSE) { "Mojang login successful (email=$email)" } - - val uuid = response.body["selectedProfile"].asJsonObject()["id"].toString().toUUID() - val account = MojangAccount( - id = response.body["user"].asJsonObject()["id"].unsafeCast(), - username = response.body["selectedProfile"].asJsonObject()["name"].unsafeCast(), - uuid = uuid, - email = email, - accessToken = response.body["accessToken"].unsafeCast(), - properties = PlayerProperties.fetch(uuid), - ) - account.state = AccountStates.WORKING - return account - } - } -} diff --git a/src/main/java/de/bixilon/minosoft/gui/eros/main/account/AccountController.kt b/src/main/java/de/bixilon/minosoft/gui/eros/main/account/AccountController.kt index 33b44b7c3..ecf176b68 100644 --- a/src/main/java/de/bixilon/minosoft/gui/eros/main/account/AccountController.kt +++ b/src/main/java/de/bixilon/minosoft/gui/eros/main/account/AccountController.kt @@ -24,7 +24,6 @@ import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager import de.bixilon.minosoft.data.accounts.Account import de.bixilon.minosoft.data.accounts.AccountStates import de.bixilon.minosoft.data.accounts.types.microsoft.MicrosoftAccount -import de.bixilon.minosoft.data.accounts.types.mojang.MojangAccount import de.bixilon.minosoft.data.accounts.types.offline.OfflineAccount import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.text.ChatComponent @@ -33,7 +32,6 @@ import de.bixilon.minosoft.gui.eros.controller.EmbeddedJavaFXController import de.bixilon.minosoft.gui.eros.dialog.ErosErrorReport.Companion.report import de.bixilon.minosoft.gui.eros.dialog.SimpleErosConfirmationDialog import de.bixilon.minosoft.gui.eros.main.account.add.MicrosoftAddController -import de.bixilon.minosoft.gui.eros.main.account.add.MojangAddController import de.bixilon.minosoft.gui.eros.main.account.add.OfflineAddController import de.bixilon.minosoft.gui.eros.util.JavaFXUtil import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.ctext @@ -272,16 +270,6 @@ class AccountController : EmbeddedJavaFXController() { icon = FontAwesomeSolid.MAP, addHandler = { OfflineAddController(it).show() }, ), - ErosAccountType( - resourceLocation = MojangAccount.RESOURCE_LOCATION, - translationKey = "minosoft:main.account.type.mojang".toResourceLocation(), - additionalDetails = listOf( - "minosoft:main.account.account_info.email".toResourceLocation() to { it.email }, - "minosoft:main.account.account_info.uuid".toResourceLocation() to { it.uuid }, - ), - icon = FontAwesomeSolid.BUILDING, - addHandler = { MojangAddController(it).show() }, - ), ) val T.erosType: ErosAccountType? diff --git a/src/main/java/de/bixilon/minosoft/gui/eros/main/account/add/MojangAddController.kt b/src/main/java/de/bixilon/minosoft/gui/eros/main/account/add/MojangAddController.kt deleted file mode 100644 index a7fc3c364..000000000 --- a/src/main/java/de/bixilon/minosoft/gui/eros/main/account/add/MojangAddController.kt +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.gui.eros.main.account.add - -import de.bixilon.kutil.concurrent.pool.DefaultThreadPool -import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager -import de.bixilon.minosoft.data.accounts.types.mojang.MojangAccount -import de.bixilon.minosoft.gui.eros.controller.JavaFXWindowController -import de.bixilon.minosoft.gui.eros.main.account.AccountController -import de.bixilon.minosoft.gui.eros.util.JavaFXUtil -import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.ctext -import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.placeholder -import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.text -import de.bixilon.minosoft.util.KUtil.text -import de.bixilon.minosoft.util.KUtil.toResourceLocation -import javafx.fxml.FXML -import javafx.scene.control.Button -import javafx.scene.control.PasswordField -import javafx.scene.control.TextField -import javafx.scene.input.KeyCode -import javafx.scene.input.KeyEvent -import javafx.scene.text.TextFlow -import javafx.stage.Modality - -class MojangAddController( - private val accountController: AccountController, -) : JavaFXWindowController() { - @FXML private lateinit var headerFX: TextFlow - @FXML private lateinit var descriptionFX: TextFlow - - @FXML private lateinit var emailLabelFX: TextFlow - @FXML private lateinit var emailFX: TextField - - @FXML private lateinit var passwordLabelFX: TextFlow - @FXML private lateinit var passwordFX: PasswordField - - @FXML private lateinit var errorFX: TextFlow - - @FXML private lateinit var loginButtonFX: Button - @FXML private lateinit var cancelButtonFX: Button - - - public override fun show() { - JavaFXUtil.openModalAsync(TITLE, LAYOUT, this, modality = Modality.APPLICATION_MODAL) { super.show() } - } - - override fun init() { - super.init() - - - headerFX.text = HEADER - descriptionFX.text = DESCRIPTION - - emailLabelFX.text = EMAIL_LABEL - emailFX.placeholder = EMAIL_PLACEHOLDER - passwordLabelFX.text = PASSWORD_LABEL - passwordFX.placeholder = PASSWORD_PLACEHOLDER - - loginButtonFX.ctext = ADD_BUTTON - cancelButtonFX.ctext = CANCEL_BUTTON - - errorFX.isVisible = false - emailFX.textProperty().addListener { _, _, _ -> - validate() - } - passwordFX.textProperty().addListener { _, _, _ -> - validate() - } - } - - override fun postInit() { - super.postInit() - - stage.scene.root.addEventFilter(KeyEvent.KEY_PRESSED) { - if (it.code == KeyCode.ESCAPE) { - cancel() - } - } - } - - private fun validate() { - if (emailFX.text.isBlank()) { - loginButtonFX.isDisable = true - return - } - if (passwordFX.text.isEmpty()) { - loginButtonFX.isDisable = true - return - } - loginButtonFX.isDisable = false - } - - @FXML - fun login() { - val profile = ErosProfileManager.selected.general.accountProfile - if (loginButtonFX.isDisable) { - return - } - loginButtonFX.isDisable = true - errorFX.isVisible = false - DefaultThreadPool += { - try { - val account = MojangAccount.login(email = emailFX.text, password = passwordFX.text, clientToken = profile.clientToken) - profile.entries[account.id] = account - profile.selected = account - JavaFXUtil.runLater { - accountController.refreshList() - close() - } - } catch (exception: Exception) { - JavaFXUtil.runLater { - exception.printStackTrace() - errorFX.text = exception.text - errorFX.isVisible = true - loginButtonFX.isDisable = false - } - } - } - } - - @FXML - fun cancel() { - close() - } - - companion object { - private val LAYOUT = "minosoft:eros/main/account/add/mojang.fxml".toResourceLocation() - - private val TITLE = "minosoft:main.account.add.mojang.title".toResourceLocation() - private val HEADER = "minosoft:main.account.add.mojang.header".toResourceLocation() - private val DESCRIPTION = "minosoft:main.account.add.mojang.description".toResourceLocation() - private val EMAIL_LABEL = "minosoft:main.account.add.mojang.email.label".toResourceLocation() - private val EMAIL_PLACEHOLDER = "minosoft:main.account.add.mojang.email.placeholder".toResourceLocation() - private val PASSWORD_LABEL = "minosoft:main.account.add.mojang.password.label".toResourceLocation() - private val PASSWORD_PLACEHOLDER = "minosoft:main.account.add.mojang.password.placeholder".toResourceLocation() - private val ADD_BUTTON = "minosoft:main.account.add.mojang.add_button".toResourceLocation() - private val CANCEL_BUTTON = "minosoft:main.account.add.mojang.cancel_button".toResourceLocation() - } -} diff --git a/src/main/resources/assets/minosoft/eros/main/account/add/mojang.fxml b/src/main/resources/assets/minosoft/eros/main/account/add/mojang.fxml deleted file mode 100644 index 216ba2aab..000000000 --- a/src/main/resources/assets/minosoft/eros/main/account/add/mojang.fxml +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/resources/assets/minosoft/language/en_us.lang b/src/main/resources/assets/minosoft/language/en_us.lang index ae8ef86c9..d299f864b 100644 --- a/src/main/resources/assets/minosoft/language/en_us.lang +++ b/src/main/resources/assets/minosoft/language/en_us.lang @@ -89,7 +89,6 @@ minosoft:main.account.list.info.button.check=Check minosoft:main.account.list.info.button.use=Use minosoft:main.account.list.info.button.add=Add account minosoft:main.account.no_account_selected=No account selected -minosoft:main.account.type.mojang=Mojang minosoft:main.account.type.microsoft=Microsoft minosoft:main.account.type.offline=Offline @@ -120,16 +119,6 @@ minosoft:main.account.add.offline.username.placeholder=Test user minosoft:main.account.add.offline.add_button=Add minosoft:main.account.add.offline.cancel_button=Cancel -minosoft:main.account.add.mojang.title=Add mojang account -minosoft:main.account.add.mojang.header=Add mojang account -minosoft:main.account.add.mojang.description=Please enter your mojang email (or for legacy accounts their username) and your password to continue -minosoft:main.account.add.mojang.email.label=E-mail -minosoft:main.account.add.mojang.email.placeholder=user@example.org -minosoft:main.account.add.mojang.password.label=Password -minosoft:main.account.add.mojang.password.placeholder=******** -minosoft:main.account.add.mojang.add_button=Add -minosoft:main.account.add.mojang.cancel_button=Cancel - minosoft:main.account.add.microsoft.please_wait.device_code=Obtaining device code...Please wait! minosoft:main.account.add.microsoft.title=Add microsoft account - Minosoft diff --git a/src/main/resources/assets/minosoft/language/es_es.lang b/src/main/resources/assets/minosoft/language/es_es.lang index fd8006f03..519461d7d 100644 --- a/src/main/resources/assets/minosoft/language/es_es.lang +++ b/src/main/resources/assets/minosoft/language/es_es.lang @@ -63,7 +63,6 @@ minosoft:server_list.refresh.text2=información minosoft:main.account.no_account_selected=Sin cuenta seleccionada -minosoft:main.account.type.mojang=Mojang minosoft:main.account.type.microsoft=Microsoft minosoft:main.account.type.offline=Offline @@ -82,16 +81,6 @@ minosoft:main.account.add.offline.username.placeholder=Usuario ejemplo minosoft:main.account.add.offline.add_button=Añadir minosoft:main.account.add.offline.cancel_button=Cancelar -minosoft:main.account.add.mojang.title=Añadir cuenta de Mojang -minosoft:main.account.add.mojang.header=Añadir cuenta de Mojang -minosoft:main.account.add.mojang.description=Introduze tu email (o nombre de usuario para cuentas antiguas) y tu contraseña -minosoft:main.account.add.mojang.email.label=E-mail -minosoft:main.account.add.mojang.email.placeholder=user@ejemplo.es -minosoft:main.account.add.mojang.password.label=Contraseña -minosoft:main.account.add.mojang.password.placeholder=**** -minosoft:main.account.add.mojang.add_button=Añadir -minosoft:main.account.add.mojang.cancel_button=Cancelar - minosoft:main.account.add.microsoft.title=Añadir cuenta de Microsoft