summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-01-04 18:17:36 +0500
committerilotterytea <iltsu@alright.party>2025-01-04 18:17:36 +0500
commit6053418526536a932f9e6ad51e648b7098eeb2da (patch)
treeef8aebbdb5514b6dd5a4e7e9d42150f0cfe60069 /core
parent7d5dc081c71d209778ad7fd05d41c9d909643af0 (diff)
feat: authentication system
Diffstat (limited to 'core')
-rw-r--r--core/src/kz/ilotterytea/maxon/MaxonConstants.java9
-rw-r--r--core/src/kz/ilotterytea/maxon/MaxonGame.java179
-rw-r--r--core/src/kz/ilotterytea/maxon/localization/LineId.java9
-rw-r--r--core/src/kz/ilotterytea/maxon/screens/MenuScreen.java206
-rw-r--r--core/src/kz/ilotterytea/maxon/session/SessionClient.java323
5 files changed, 632 insertions, 94 deletions
diff --git a/core/src/kz/ilotterytea/maxon/MaxonConstants.java b/core/src/kz/ilotterytea/maxon/MaxonConstants.java
index 5139ccc..cab66f4 100644
--- a/core/src/kz/ilotterytea/maxon/MaxonConstants.java
+++ b/core/src/kz/ilotterytea/maxon/MaxonConstants.java
@@ -18,6 +18,7 @@ public class MaxonConstants {
public static final String GAME_APP_PACKAGE = "kz.ilotterytea." + GAME_APP_ID;
public static final String GAME_APP_URL;
public static final String GAME_VERSION = "1.0.1";
+ public static final Integer GAME_PROTOCOL = 1;
public static final String GAME_MAIN_DEVELOPER = "ilotterytea";
public static final List<Triple<String, String, Integer>> GAME_DEVELOPERS = Arrays.asList(
@@ -55,6 +56,12 @@ public class MaxonConstants {
public static final DecimalFormat DECIMAL_FORMAT2 = new DecimalFormat("###,###");
public static final String GAME_VERSIONS_FILE_URL = "https://assets.ilotterytea.kz/maxon/versions.json";
+ public static final String IDENTITY_BASE_URL = "https://id.ilotterytea.kz";
+ public static final String IDENTITY_INVALIDATE_URL = IDENTITY_BASE_URL + "/invalidate";
+ public static final String IDENTITY_VALIDATE_URL = IDENTITY_BASE_URL + "/validate";
+ public static final String IDENTITY_REFRESH_URL = IDENTITY_BASE_URL + "/refresh";
+ public static final String IDENTITY_AUTHENTICATION_URL = IDENTITY_BASE_URL + "/authenticate";
+ public static final String IDENTITY_REGISTRATION_URL = IDENTITY_BASE_URL;
public static final long DISCORD_APPLICATION_ID = 1051092609659052062L;
@@ -68,7 +75,7 @@ public class MaxonConstants {
for (int y = 0; y < checkers; y++) {
for (int x = 0; x < checkers; x++) {
- if ((x + y) % 2 == 0){
+ if ((x + y) % 2 == 0) {
pixmap.setColor(Color.MAGENTA);
} else {
pixmap.setColor(Color.BLACK);
diff --git a/core/src/kz/ilotterytea/maxon/MaxonGame.java b/core/src/kz/ilotterytea/maxon/MaxonGame.java
index 63de3e8..b53c510 100644
--- a/core/src/kz/ilotterytea/maxon/MaxonGame.java
+++ b/core/src/kz/ilotterytea/maxon/MaxonGame.java
@@ -8,93 +8,100 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import kz.ilotterytea.maxon.localization.LocalizationManager;
import kz.ilotterytea.maxon.pets.PetManager;
import kz.ilotterytea.maxon.screens.SplashScreen;
+import kz.ilotterytea.maxon.session.SessionClient;
import kz.ilotterytea.maxon.utils.GameUpdater;
public class MaxonGame extends Game {
- public SpriteBatch batch;
- public AssetManager assetManager;
- public Preferences prefs;
-
- private LocalizationManager locale;
- private PetManager petManager;
-
- private DiscordActivityClient discordActivityClient;
-
- private static MaxonGame instance;
-
- public static MaxonGame getInstance() {
- if (instance == null) {
- instance = new MaxonGame();
- }
- return instance;
- }
-
- public PetManager getPetManager() {
- return petManager;
- }
-
- public DiscordActivityClient getDiscordActivityClient() {
- return discordActivityClient;
- }
-
- public LocalizationManager getLocale() {
- return locale;
- }
-
- public void setLocale(LocalizationManager locale) {
- this.locale = locale;
- }
-
- @Override
- public void create () {
- // Check the latest version
- new GameUpdater().checkLatestUpdate();
-
- batch = new SpriteBatch();
- prefs = Gdx.app.getPreferences(MaxonConstants.GAME_APP_PACKAGE);
- locale = new LocalizationManager(Gdx.files.internal("i18n/" + prefs.getString("lang", "en_us") + ".json"));
-
- Gdx.graphics.setVSync(prefs.getBoolean("vsync", true));
-
- if (prefs.getBoolean("fullscreen", false)) {
- Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
- } else if (
- prefs.contains("width") ||
- prefs.contains("height")
- ) {
- int width = prefs.getInteger("width", 800);
-
- if (width < 800) {
- width = 800;
- prefs.putInteger("width", width);
- }
-
- int height = prefs.getInteger("height", 600);
-
- if (height < 600) {
- height = 600;
- prefs.putInteger("height", height);
- }
-
- prefs.flush();
- Gdx.graphics.setWindowedMode(width, height);
- }
-
- assetManager = new AssetManager();
- petManager = new PetManager(assetManager);
-
- discordActivityClient = new DiscordActivityClient();
-
- this.setScreen(new SplashScreen());
- }
-
- @Override
- public void dispose () {
- batch.dispose();
- for (String name : assetManager.getAssetNames()) {
- assetManager.unload(name);
- }
- assetManager.dispose();
- discordActivityClient.dispose();
- }
+ public SpriteBatch batch;
+ public AssetManager assetManager;
+ public Preferences prefs;
+
+ private LocalizationManager locale;
+ private PetManager petManager;
+
+ private DiscordActivityClient discordActivityClient;
+ private SessionClient sessionClient;
+
+ private static MaxonGame instance;
+
+ public static MaxonGame getInstance() {
+ if (instance == null) {
+ instance = new MaxonGame();
+ }
+ return instance;
+ }
+
+ public PetManager getPetManager() {
+ return petManager;
+ }
+
+ public DiscordActivityClient getDiscordActivityClient() {
+ return discordActivityClient;
+ }
+
+ public SessionClient getSessionClient() {
+ return sessionClient;
+ }
+
+ public LocalizationManager getLocale() {
+ return locale;
+ }
+
+ public void setLocale(LocalizationManager locale) {
+ this.locale = locale;
+ }
+
+ @Override
+ public void create() {
+ // Check the latest version
+ new GameUpdater().checkLatestUpdate();
+
+ sessionClient = new SessionClient(Gdx.app.getPreferences("kz.ilotterytea.SigninSession"));
+ batch = new SpriteBatch();
+ prefs = Gdx.app.getPreferences(MaxonConstants.GAME_APP_PACKAGE);
+ locale = new LocalizationManager(Gdx.files.internal("i18n/" + prefs.getString("lang", "en_us") + ".json"));
+
+ Gdx.graphics.setVSync(prefs.getBoolean("vsync", true));
+
+ if (prefs.getBoolean("fullscreen", false)) {
+ Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
+ } else if (
+ prefs.contains("width") ||
+ prefs.contains("height")
+ ) {
+ int width = prefs.getInteger("width", 800);
+
+ if (width < 800) {
+ width = 800;
+ prefs.putInteger("width", width);
+ }
+
+ int height = prefs.getInteger("height", 600);
+
+ if (height < 600) {
+ height = 600;
+ prefs.putInteger("height", height);
+ }
+
+ prefs.flush();
+ Gdx.graphics.setWindowedMode(width, height);
+ }
+
+ assetManager = new AssetManager();
+ petManager = new PetManager(assetManager);
+
+ discordActivityClient = new DiscordActivityClient();
+
+ this.setScreen(new SplashScreen());
+ }
+
+ @Override
+ public void dispose() {
+ batch.dispose();
+ for (String name : assetManager.getAssetNames()) {
+ assetManager.unload(name);
+ }
+ assetManager.dispose();
+ discordActivityClient.dispose();
+ }
}
diff --git a/core/src/kz/ilotterytea/maxon/localization/LineId.java b/core/src/kz/ilotterytea/maxon/localization/LineId.java
index 2ef671a..23eedc1 100644
--- a/core/src/kz/ilotterytea/maxon/localization/LineId.java
+++ b/core/src/kz/ilotterytea/maxon/localization/LineId.java
@@ -24,6 +24,15 @@ public enum LineId {
CreditsTester,
CreditsMoral,
+ LoginTitle,
+ LoginUsername,
+ LoginPassword,
+ LoginRegister,
+ LoginSend,
+ LoginProcessing,
+ LoginButton,
+ LoginAuthorised,
+
GiftboxOpen,
MinigameSlotsSpinbutton,
diff --git a/core/src/kz/ilotterytea/maxon/screens/MenuScreen.java b/core/src/kz/ilotterytea/maxon/screens/MenuScreen.java
index 43dfbca..ec60b33 100644
--- a/core/src/kz/ilotterytea/maxon/screens/MenuScreen.java
+++ b/core/src/kz/ilotterytea/maxon/screens/MenuScreen.java
@@ -1,6 +1,7 @@
package kz.ilotterytea.maxon.screens;
-import com.badlogic.gdx.*;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Screen;
import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
@@ -27,7 +28,10 @@ import kz.ilotterytea.maxon.constants.SettingsConstants;
import kz.ilotterytea.maxon.localization.LineId;
import kz.ilotterytea.maxon.localization.LocalizationManager;
import kz.ilotterytea.maxon.player.Savegame;
-import kz.ilotterytea.maxon.ui.*;
+import kz.ilotterytea.maxon.session.SessionClient;
+import kz.ilotterytea.maxon.ui.DebugWidget;
+import kz.ilotterytea.maxon.ui.SavegameWidget;
+import kz.ilotterytea.maxon.ui.ShakingImageButton;
import kz.ilotterytea.maxon.utils.GameUpdater;
import kz.ilotterytea.maxon.utils.OsUtils;
import net.mgsx.gltf.scene3d.attributes.PBRCubemapAttribute;
@@ -38,14 +42,19 @@ import net.mgsx.gltf.scene3d.scene.SceneManager;
import net.mgsx.gltf.scene3d.scene.SceneSkybox;
import net.mgsx.gltf.scene3d.utils.EnvironmentUtil;
import net.mgsx.gltf.scene3d.utils.IBLBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
public class MenuScreen implements Screen {
+ private static final Logger log = LoggerFactory.getLogger(MenuScreen.class);
private MaxonGame game;
private Stage stage;
private Skin uiSkin;
+ private TextButton loginButton;
+
private Music menuMusic;
private final Savegame savegame = Savegame.getInstance();
@@ -57,7 +66,8 @@ public class MenuScreen implements Screen {
private Sound clickSound;
private float soundVolume;
- @Override public void show() {
+ @Override
+ public void show() {
this.game = MaxonGame.getInstance();
game.getDiscordActivityClient().runThread();
@@ -317,7 +327,18 @@ public class MenuScreen implements Screen {
}
});
+ // Login button
+ loginButton = new TextButton(game.getLocale().getLine(LineId.LoginButton), uiSkin);
+ loginButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+ showLoginWindow();
+ }
+ });
+
if (!OsUtils.isMobile) {
+ rightGameControlTable.add(loginButton).padRight(16f);
rightGameControlTable.add(localeButton).size(iconSize).padRight(16f);
rightGameControlTable.add(musicButton).size(iconSize).padRight(16f);
rightGameControlTable.add(resolutionButton).size(iconSize);
@@ -384,6 +405,57 @@ public class MenuScreen implements Screen {
stage.act(delta);
stage.draw();
+
+ // Login button logic
+ SessionClient session = game.getSessionClient();
+ if (!session.isProcessing() && !session.isAuthorised() && !loginButton.getText().equals(game.getLocale().getLine(LineId.LoginButton))) {
+ loginButton.setText(game.getLocale().getLine(LineId.LoginButton));
+ loginButton.clearListeners();
+ loginButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+ showLoginWindow();
+ }
+
+ @Override
+ public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
+ super.enter(event, x, y, pointer, fromActor);
+ loginButton.setColor(new Color(0xffffffff));
+ }
+
+ @Override
+ public void exit(InputEvent event, float x, float y, int pointer, Actor fromActor) {
+ super.exit(event, x, y, pointer, fromActor);
+ loginButton.setColor(new Color(0xeeeeeeff));
+ }
+ });
+ loginButton.setStyle(uiSkin.get("default", TextButton.TextButtonStyle.class));
+ loginButton.setDisabled(false);
+ } else if (session.isAuthorised() && !loginButton.getText().equals(game.getLocale().getFormattedLine(LineId.LoginAuthorised, session.getUsername()))) {
+ loginButton.setText(game.getLocale().getFormattedLine(LineId.LoginAuthorised, session.getUsername()));
+ loginButton.clearListeners();
+ loginButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+ session.invalidateToken();
+ }
+
+ @Override
+ public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
+ super.enter(event, x, y, pointer, fromActor);
+ loginButton.setColor(new Color(0xffaaaaff));
+ }
+
+ @Override
+ public void exit(InputEvent event, float x, float y, int pointer, Actor fromActor) {
+ super.exit(event, x, y, pointer, fromActor);
+ loginButton.setColor(Color.WHITE);
+ }
+ });
+ loginButton.setDisabled(true);
+ }
}
@Override
@@ -392,9 +464,16 @@ public class MenuScreen implements Screen {
sceneManager.updateViewport(width, height);
}
- @Override public void pause() {}
- @Override public void resume() {}
- @Override public void hide() {
+ @Override
+ public void pause() {
+ }
+
+ @Override
+ public void resume() {
+ }
+
+ @Override
+ public void hide() {
for (Timer.Task task : tasks) {
task.cancel();
}
@@ -403,7 +482,9 @@ public class MenuScreen implements Screen {
menuMusic.stop();
dispose();
}
- @Override public void dispose() {
+
+ @Override
+ public void dispose() {
stage.dispose();
sceneManager.dispose();
}
@@ -669,4 +750,115 @@ public class MenuScreen implements Screen {
});
engineCredits.add(engineImage).height(OsUtils.isMobile ? 64f : 32f).width(OsUtils.isMobile ? 360f : 180f);
}
+
+ private void showLoginWindow() {
+ Image bgTint = new Image(uiSkin, "halftransparentblack");
+ bgTint.setFillParent(true);
+ stage.addActor(bgTint);
+
+ // Table
+ Table table = new Table();
+ table.setFillParent(true);
+ table.align(Align.center);
+
+ stage.addActor(table);
+
+ // Window
+ Table window = new Table(uiSkin);
+ window.setBackground("bg");
+ window.align(Align.center);
+ table.add(window).size(460f, 400f);
+
+ // Table for title and close button
+ Table titleTable = new Table(uiSkin);
+ titleTable.setBackground("bg2");
+ window.add(titleTable).growX().row();
+
+ // Title
+ Label titleLabel = new Label(game.getLocale().getLine(LineId.LoginTitle), uiSkin);
+ titleTable.add(titleLabel).pad(8f, 16f, 8f, 16f).growX();
+
+ // Close button
+ TextButton closeButton = new TextButton(" X ", uiSkin);
+ closeButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+ table.remove();
+ bgTint.remove();
+ clickSound.play(soundVolume);
+ }
+ });
+ titleTable.add(closeButton).pad(8f, 16f, 8f, 16f);
+
+ // Table for fields
+ Table contentTable = new Table();
+ window.add(contentTable).pad(16f).grow().row();
+
+ // Username
+ Label usernameLabel = new Label(game.getLocale().getLine(LineId.LoginUsername), uiSkin);
+ contentTable.add(usernameLabel).grow().row();
+
+ TextField usernameField = new TextField("", uiSkin);
+ usernameField.setMessageText("...");
+ usernameField.setTextFieldFilter((textField, c) -> Character.toString(c).matches("^[a-zA-Z0-9]"));
+ usernameField.setMaxLength(25);
+ contentTable.add(usernameField).padBottom(15f).grow().row();
+
+ // Password
+ Label passwordLabel = new Label(game.getLocale().getLine(LineId.LoginPassword), uiSkin);
+ contentTable.add(passwordLabel).grow().row();
+
+ TextField passwordField = new TextField("", uiSkin);
+ passwordField.setMessageText("...");
+
+ String[] passwords = {"", ""};
+
+ passwordField.setTextFieldListener((textField, c) -> {
+ String hiddenText = passwords[0];
+ String fieldText = passwords[1];
+
+ if (c == 8 && !fieldText.isEmpty() && !hiddenText.isEmpty()) {
+ fieldText = fieldText.substring(0, fieldText.length() - 1);
+ hiddenText = hiddenText.substring(0, hiddenText.length() - 1);
+ } else if (c != 8) {
+ fieldText += '*';
+ hiddenText += c;
+ }
+
+ textField.setText(fieldText);
+ passwords[0] = hiddenText;
+ passwords[1] = fieldText;
+ });
+
+ contentTable.add(passwordField).grow().row();
+
+ // Register button
+ TextButton registerButton = new TextButton(game.getLocale().getLine(LineId.LoginRegister), uiSkin, "link");
+ registerButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+ Gdx.net.openURI(MaxonConstants.IDENTITY_REGISTRATION_URL);
+ }
+ });
+ contentTable.add(registerButton).padTop(15f).padBottom(15f).grow().row();
+
+ // Login button
+ TextButton sendButton = new TextButton(game.getLocale().getLine(LineId.LoginSend), uiSkin);
+ sendButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+ MaxonGame.getInstance().getSessionClient().authorize(usernameField.getText(), passwords[0]);
+ loginButton.setText(game.getLocale().getLine(LineId.LoginProcessing));
+ loginButton.setDisabled(true);
+ // maybe we could somehow fire the close button instead of cv pasting
+ table.remove();
+ bgTint.remove();
+ clickSound.play(soundVolume);
+ }
+ });
+ contentTable.add(sendButton).grow().row();
+ }
}
diff --git a/core/src/kz/ilotterytea/maxon/session/SessionClient.java b/core/src/kz/ilotterytea/maxon/session/SessionClient.java
new file mode 100644
index 0000000..31edd6e
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/session/SessionClient.java
@@ -0,0 +1,323 @@
+package kz.ilotterytea.maxon.session;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Net;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.net.HttpRequestBuilder;
+import com.badlogic.gdx.net.HttpStatus;
+import com.badlogic.gdx.utils.JsonReader;
+import com.badlogic.gdx.utils.JsonValue;
+import com.badlogic.gdx.utils.JsonWriter;
+import com.badlogic.gdx.utils.Timer;
+import kz.ilotterytea.maxon.MaxonConstants;
+import kz.ilotterytea.maxon.utils.RandomUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SessionClient {
+ private final Logger log;
+
+ private final Preferences sessionPreferences;
+ private final String clientToken;
+ private String accessToken;
+ private String userId, username, password;
+ private boolean isProcessing, isAuthorised;
+
+ public SessionClient(Preferences sessionPreferences) {
+ startValidationThread();
+ this.log = LoggerFactory.getLogger(SessionClient.class);
+
+ this.clientToken = RandomUtils.generateRandomString();
+ this.sessionPreferences = sessionPreferences;
+ this.isProcessing = false;
+ this.isAuthorised = false;
+
+ if (sessionPreferences.contains("username") && sessionPreferences.contains("password")) {
+ this.authorize(sessionPreferences.getString("username"), sessionPreferences.getString("password"));
+ }
+ }
+
+ public void authorize(String username, String password) {
+ log.info("Authorising...");
+ this.isProcessing = true;
+ sessionPreferences.putString("username", username);
+ sessionPreferences.putString("password", password);
+ sessionPreferences.flush();
+
+ JsonValue agent = new JsonValue(JsonValue.ValueType.object);
+ agent.addChild("name", new JsonValue(String.valueOf(MaxonConstants.GAME_APP_ID.charAt(0)).toUpperCase() + MaxonConstants.GAME_APP_ID.substring(1)));
+ agent.addChild("version", new JsonValue(MaxonConstants.GAME_PROTOCOL));
+
+ JsonValue json = new JsonValue(JsonValue.ValueType.object);
+ json.addChild("agent", agent);
+ json.addChild("username", new JsonValue(username));
+ json.addChild("password", new JsonValue(password));
+ json.addChild("clientToken", new JsonValue(clientToken));
+
+ Net.HttpRequest request =
+ new HttpRequestBuilder()
+ .newRequest()
+ .method(Net.HttpMethods.POST)
+ .url(MaxonConstants.IDENTITY_AUTHENTICATION_URL)
+ .timeout(20000)
+ .header("Content-Type", "application/json")
+ .content(json.toJson(JsonWriter.OutputType.json))
+ .build();
+
+ Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
+ @Override
+ public void handleHttpResponse(Net.HttpResponse httpResponse) {
+ SessionClient.this.isProcessing = false;
+
+ try {
+ JsonValue json = new JsonReader().parse(httpResponse.getResultAsString());
+
+ if (httpResponse.getStatus().getStatusCode() != HttpStatus.SC_OK) {
+ String type = json.get("error").getString("type");
+ String error = json.get("error").getString("message");
+ log.error("Failed to authorise: {} ({})", error, type);
+
+ sessionPreferences.remove("username");
+ sessionPreferences.remove("password");
+ sessionPreferences.flush();
+
+ return;
+ }
+
+ SessionClient.this.username = username;
+ SessionClient.this.password = password;
+ SessionClient.this.accessToken = json.get("data").getString("accessToken");
+ SessionClient.this.userId = String.valueOf(json.get("data").get("user").getInt("id"));
+ SessionClient.this.isAuthorised = true;
+ log.info("Successfully authorised! Welcome back, {}!", SessionClient.this.username);
+ } catch (Exception e) {
+ log.error("An exception was thrown while authorising", e);
+ }
+ }
+
+ @Override
+ public void failed(Throwable t) {
+ log.error("Failed to send an authorisation request", t);
+ }
+
+ @Override
+ public void cancelled() {
+ log.info("Authorisation request was cancelled!");
+ }
+ });
+ }
+
+ public void validateToken() {
+ if (clientToken == null || accessToken == null) {
+ return;
+ }
+
+ log.info("Validating token...");
+
+ JsonValue json = new JsonValue(JsonValue.ValueType.object);
+ json.addChild("clientToken", new JsonValue(clientToken));
+ json.addChild("accessToken", new JsonValue(accessToken));
+
+ Net.HttpRequest request =
+ new HttpRequestBuilder()
+ .newRequest()
+ .method(Net.HttpMethods.POST)
+ .url(MaxonConstants.IDENTITY_VALIDATE_URL)
+ .timeout(20000)
+ .header("Content-Type", "application/json")
+ .content(json.toJson(JsonWriter.OutputType.json))
+ .build();
+
+ Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
+ @Override
+ public void handleHttpResponse(Net.HttpResponse httpResponse) {
+ try {
+ JsonValue json = new JsonReader().parse(httpResponse.getResultAsString());
+
+ if (httpResponse.getStatus().getStatusCode() != HttpStatus.SC_OK) {
+ String type = json.get("error").getString("type");
+ String error = json.get("error").getString("message");
+ log.error("Failed to validate: {} ({})", error, type);
+ accessToken = null;
+ userId = null;
+ isAuthorised = false;
+ authorize(username, password);
+ return;
+ }
+
+ int expiresInSeconds = json.get("data").getInt("expiresInSeconds");
+
+ if (expiresInSeconds < 1000) {
+ refreshToken();
+ }
+
+ log.info("Token validated!");
+ } catch (Exception e) {
+ log.error("An exception was thrown while validating", e);
+ }
+ }
+
+ @Override
+ public void failed(Throwable t) {
+ log.error("Failed to send a validation request", t);
+ }
+
+ @Override
+ public void cancelled() {
+ log.info("Validation request was cancelled!");
+ }
+ });
+ }
+
+ public void invalidateToken() {
+ if (clientToken == null || accessToken == null) {
+ return;
+ }
+
+ log.info("Invalidating token...");
+
+ JsonValue json = new JsonValue(JsonValue.ValueType.object);
+ json.addChild("clientToken", new JsonValue(clientToken));
+ json.addChild("accessToken", new JsonValue(accessToken));
+
+ Net.HttpRequest request =
+ new HttpRequestBuilder()
+ .newRequest()
+ .method(Net.HttpMethods.POST)
+ .url(MaxonConstants.IDENTITY_INVALIDATE_URL)
+ .timeout(20000)
+ .header("Content-Type", "application/json")
+ .content(json.toJson(JsonWriter.OutputType.json))
+ .build();
+
+ Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
+ @Override
+ public void handleHttpResponse(Net.HttpResponse httpResponse) {
+ try {
+ JsonValue json = new JsonReader().parse(httpResponse.getResultAsString());
+
+ if (httpResponse.getStatus().getStatusCode() != HttpStatus.SC_OK) {
+ String type = json.get("error").getString("type");
+ String error = json.get("error").getString("message");
+ log.error("Failed to invalidate: {} ({})", error, type);
+ return;
+ }
+
+ log.info("Invalidated! Bye, {}", username);
+
+ accessToken = null;
+ userId = null;
+ username = null;
+ password = null;
+ isAuthorised = false;
+ sessionPreferences.remove("username");
+ sessionPreferences.remove("password");
+ sessionPreferences.flush();
+ } catch (Exception ignored) {
+ }
+ }
+
+ @Override
+ public void failed(Throwable t) {
+ }
+
+ @Override
+ public void cancelled() {
+ }
+ });
+ }
+
+ public void refreshToken() {
+ if (clientToken == null || accessToken == null) {
+ return;
+ }
+
+ log.info("Refreshing token...");
+
+ JsonValue json = new JsonValue(JsonValue.ValueType.object);
+ json.addChild("clientToken", new JsonValue(clientToken));
+ json.addChild("accessToken", new JsonValue(accessToken));
+
+ Net.HttpRequest request =
+ new HttpRequestBuilder()
+ .newRequest()
+ .method(Net.HttpMethods.POST)
+ .url(MaxonConstants.IDENTITY_REFRESH_URL)
+ .timeout(20000)
+ .header("Content-Type", "application/json")
+ .content(json.toJson(JsonWriter.OutputType.json))
+ .build();
+
+ Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
+ @Override
+ public void handleHttpResponse(Net.HttpResponse httpResponse) {
+ try {
+ JsonValue json = new JsonReader().parse(httpResponse.getResultAsString());
+
+ if (httpResponse.getStatus().getStatusCode() != HttpStatus.SC_OK) {
+ String type = json.get("error").getString("type");
+ String error = json.get("error").getString("message");
+ log.error("Failed to refresh: {} ({})", error, type);
+ accessToken = null;
+ userId = null;
+ isAuthorised = false;
+ log.warn(error);
+ return;
+ }
+
+ accessToken = json.get("data").get("accessToken").asString();
+ log.info("Token has been refreshed!");
+ } catch (Exception e) {
+ log.error("An exception was thrown while refreshing", e);
+ }
+ }
+
+ @Override
+ public void failed(Throwable t) {
+ log.error("Failed to send a refresh request", t);
+ }
+
+ @Override
+ public void cancelled() {
+ log.info("Refresh request was cancelled!");
+ }
+ });
+ }
+
+ public boolean isAuthorised() {
+ return this.isAuthorised;
+ }
+
+ public boolean isProcessing() {
+ return isProcessing;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public String getClientToken() {
+ return clientToken;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ private void startValidationThread() {
+ Timer.schedule(new Timer.Task() {
+ @Override
+ public void run() {
+ validateToken();
+ }
+ }, 60000, 60000);
+ }
+}