mirror of
https://github.com/Melledy/Nebula.git
synced 2025-12-25 18:54:36 +01:00
Initial Commit
This commit is contained in:
212
src/main/java/emu/nebula/server/routes/AgentZoneHandler.java
Normal file
212
src/main/java/emu/nebula/server/routes/AgentZoneHandler.java
Normal file
@@ -0,0 +1,212 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.GameContext;
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgIdUtils;
|
||||
import emu.nebula.net.GameSession;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.util.AeadHelper;
|
||||
import emu.nebula.util.Utils;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class AgentZoneHandler implements Handler {
|
||||
private final Int2ObjectMap<NetHandler> handlers;
|
||||
private final static byte[] EMPTY_BYTES = new byte[0];
|
||||
|
||||
public AgentZoneHandler() {
|
||||
this.handlers = new Int2ObjectOpenHashMap<>();
|
||||
this.registerHandlers();
|
||||
}
|
||||
|
||||
protected GameContext getGameContext() {
|
||||
return Nebula.getGameContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Context ctx) throws Exception {
|
||||
// Setup session
|
||||
GameSession session = null;
|
||||
|
||||
byte[] sessionKey = AeadHelper.serverGarbleKey;
|
||||
boolean hasKey3 = false;
|
||||
|
||||
// Get token
|
||||
String token = ctx.header("X-Token");
|
||||
|
||||
// Set headers
|
||||
ctx.res().setHeader("Server", "agent");
|
||||
|
||||
// Check if we have a token
|
||||
if (token != null) {
|
||||
// Get session
|
||||
session = getGameContext().getSessionByToken(token);
|
||||
|
||||
// Uh oh - session not found
|
||||
if (session == null || session.getKey() == null) {
|
||||
ctx.status(500);
|
||||
ctx.result("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set key
|
||||
sessionKey = session.getKey();
|
||||
hasKey3 = true;
|
||||
}
|
||||
|
||||
// Parse request
|
||||
byte[] data = null;
|
||||
int msgId = 0;
|
||||
|
||||
try {
|
||||
// Get message
|
||||
byte[] message = ctx.bodyAsBytes();
|
||||
int offset = 0;
|
||||
|
||||
// Sanity for malformed packets
|
||||
if (message.length <= 12) {
|
||||
ctx.status(500);
|
||||
ctx.result("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrypt message
|
||||
if (hasKey3) {
|
||||
message = AeadHelper.decryptChaCha(message, sessionKey);
|
||||
offset = 10;
|
||||
} else {
|
||||
message = AeadHelper.decryptBasic(message, sessionKey);
|
||||
message = AeadHelper.decryptGCM(message, sessionKey);
|
||||
}
|
||||
|
||||
// Get message id
|
||||
msgId = (message[offset++] << 8) | (message[offset++] & 0xff);
|
||||
|
||||
// Set data
|
||||
data = new byte[message.length - offset];
|
||||
System.arraycopy(message, offset, data, 0, data.length);
|
||||
|
||||
// Log
|
||||
if (Nebula.getConfig().getLogOptions().packets) {
|
||||
this.logRecv(msgId, data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Decrypt error
|
||||
e.printStackTrace();
|
||||
ctx.status(500);
|
||||
ctx.result("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update last active time for session
|
||||
if (session != null) {
|
||||
session.updateLastActiveTime();
|
||||
}
|
||||
|
||||
// Handle packet
|
||||
NetHandler handler = this.handlers.get(msgId);
|
||||
byte[] result = null;
|
||||
|
||||
try {
|
||||
if (handler == null) {
|
||||
Nebula.getLogger().warn("Unhandled request: " + msgId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check handler requirements
|
||||
if (session == null) {
|
||||
if (handler.requireSession()) {
|
||||
return;
|
||||
}
|
||||
} else if (session.getPlayer() == null && handler.requirePlayer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle data
|
||||
result = handler.handle(session, data);
|
||||
} catch (Exception e) {
|
||||
// Handler error
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
// Send result
|
||||
if (result == null) {
|
||||
ctx.status(500);
|
||||
ctx.result(EMPTY_BYTES);
|
||||
return;
|
||||
}
|
||||
|
||||
// Log
|
||||
if (Nebula.getConfig().getLogOptions().packets) {
|
||||
this.logSend(result);
|
||||
}
|
||||
|
||||
// Encrypt
|
||||
if (hasKey3) {
|
||||
result = AeadHelper.encryptChaCha(result, sessionKey);
|
||||
} else {
|
||||
result = AeadHelper.encryptGCM(result, sessionKey);
|
||||
result = AeadHelper.encryptBasic(result, sessionKey);
|
||||
}
|
||||
|
||||
// Send to client
|
||||
ctx.status(200);
|
||||
ctx.result(result);
|
||||
|
||||
ctx.res().setHeader("Content-Type", null);
|
||||
}
|
||||
}
|
||||
|
||||
// Loggers
|
||||
|
||||
private void logRecv(int msgId, byte[] data) {
|
||||
Nebula.getLogger().info("RECV: " + NetMsgIdUtils.getMsgIdName(msgId) + " (" + msgId + ")");
|
||||
System.out.println(Utils.bytesToHex(data));
|
||||
}
|
||||
|
||||
private void logSend(byte[] data) {
|
||||
int sendMsgId = (data[0] << 8) | (data[1] & 0xff);
|
||||
Nebula.getLogger().info("SEND: " + NetMsgIdUtils.getMsgIdName(sendMsgId) + " (" + sendMsgId + ")");
|
||||
System.out.println(Utils.bytesToHex(data, 2));
|
||||
}
|
||||
|
||||
// Register handlers
|
||||
|
||||
private void registerHandlers() {
|
||||
// Setup handlers
|
||||
Reflections reflections = new Reflections(Nebula.class.getPackageName());
|
||||
Set<Class<?>> handlers = reflections.getTypesAnnotatedWith(HandlerId.class);
|
||||
|
||||
for (Class<?> cls : handlers) {
|
||||
// Make sure class is a handler
|
||||
if (!NetHandler.class.isAssignableFrom(cls)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
NetHandler handler = (NetHandler) cls.getConstructor().newInstance();
|
||||
HandlerId def = cls.getAnnotation(HandlerId.class);
|
||||
|
||||
int opcode = def.value();
|
||||
if (opcode != 0) {
|
||||
// Put in handler map
|
||||
this.handlers.put(opcode, handler);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Log registration
|
||||
Nebula.getLogger().info("Registered " + handlers.size() + " handlers");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.server.HttpServer;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class CommonConfigHandler implements Handler {
|
||||
private HttpServer server;
|
||||
private String json;
|
||||
|
||||
public CommonConfigHandler(HttpServer server) {
|
||||
this.server = server;
|
||||
this.json = "{\"Code\":200,\"Data\":{\"AppConfig\":{\"ACCOUNT_RETRIEVAL\":{\"FIRST_LOGIN_POPUP\":false,\"LOGIN_POPUP\":false,\"PAGE_URL\":\"\"},\"AGREEMENT_POPUP_TYPE\":\"Browser\",\"APPLE_CURRENCY_BLOCK_LIST\":null,\"APPLE_TYPE_KEY\":\"apple_hk\",\"APP_CLIENT_LANG\":[\"en\"],\"APP_DEBUG\":0,\"APP_GL\":\"en\",\"BIND_METHOD\":[\"google\",\"apple_hk\",\"facebook\"],\"CAPTCHA_ENABLED\":false,\"CLIENT_LOG_REPORTING\":{\"ENABLE\":true},\"CREDIT_INVESTIGATION\":\"0.0\",\"DESTROY_USER_DAYS\":15,\"DESTROY_USER_ENABLE\":1,\"DETECTION_ADDRESS\":{\"AUTO\":{\"DNS\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"HTTP\":[\"${url}\",\"${url}\",\"${url}\"],\"MTR\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"PING\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"TCP\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"]},\"ENABLE\":true,\"ENABLE_MANUAL\":true,\"INTERNET\":\"https://www.google.com\",\"INTERNET_ADDRESS\":\"https://www.google.com\",\"NETWORK_ENDPORINT\":\"\",\"NETWORK_PROJECT\":\"\",\"NETWORK_SECRET_KEY\":\"\"},\"ENABLE_AGREEMENT\":true,\"ENABLE_MULTI_LANG_AGREEMENT\":false,\"ENABLE_TEXT_REVIEW\":true,\"ERROR_CODE\":\"4.4\",\"FILE_DOMAIN\":\"\",\"GEETEST_ENABLE\":false,\"GEETEST_ID\":\"\",\"GOOGLE_ANALYTICS_MEASUREMENT_ID\":\"\",\"MIGRATE_POPUP\":true,\"NICKNAME_REG\":\"^[A-Za-z0-9]{2,20}$\",\"POPUP\":{\"Data\":[{\"Lang\":\"ja\",\"Text\":\"YostarIDを作成\"},{\"Lang\":\"en\",\"Text\":\"CreateaYostaraccount\"},{\"Lang\":\"kr\",\"Text\":\"YOSTAR계정가입하기\"},{\"Lang\":\"fr\",\"Text\":\"CréezvotrecompteYostar\"},{\"Lang\":\"de\",\"Text\":\"EinenYostar-Accounterstellen\"}],\"Enable\":true},\"PRIVACY_AGREEMENT\":\"0.1\",\"RECHARGE_LIMIT\":{\"Enable\":false,\"IsOneLimit\":false,\"Items\":[],\"OneLimitAmount\":0},\"SHARE\":{\"CaptureScreen\":{\"AutoCloseDelay\":0,\"Enabled\":false},\"Facebook\":{\"AppID\":\"\",\"Enabled\":false},\"Instagram\":{\"Enabled\":false},\"Kakao\":{\"AppKey\":\"\",\"Enabled\":false},\"Naver\":{\"Enabled\":false},\"Twitter\":{\"Enabled\":false}},\"SLS\":{\"ACCESS_KEY_ID\":\"7b5d0ffd0943f26704fc547a871c68b1b5d56b5c9caeb354205b81f445d7af59\",\"ACCESS_KEY_SECRET\":\"4a5e9cc8a50819290c9bfa1fedc79da7c50e85189a05eb462a3d28a7688eabb0\",\"ENABLE\":false},\"SURVEY_POPUP_TYPE\":\"Browser\",\"UDATA\":{\"Enable\":false,\"URL\":\"${url}\"},\"USER_AGREEMENT\":\"0.1\",\"YOSTAR_PREFIX\":\"yoyo\"},\"EuropeUnion\":false,\"StoreConfig\":{\"ADJUST_APPID\":\"\",\"ADJUST_CHARGEEVENTTOKEN\":\"\",\"ADJUST_ENABLED\":0,\"ADJUST_EVENTTOKENS\":null,\"ADJUST_ISDEBUG\":0,\"AIRWALLEX_ENABLED\":false,\"AI_HELP\":{\"AihelpAppID\":\"yostar1_platform_2db52a57068b1ee3fe3652c8b53d581b\",\"AihelpAppKey\":\"YOSTAR1_app_bc226f4419a7447c9de95711f8a2d3d9\",\"AihelpDomain\":\"yostar1.aihelp.net\",\"CustomerServiceURL\":\"\",\"CustomerWay\":1,\"DisplayType\":\"Browser\",\"Enable\":1,\"Mode\":\"robot\"},\"APPLEID\":\"\",\"CODA_ENABLED\":false,\"ENABLED_PAY\":{\"AIRWALLEX_ENABLED\":false,\"CODA_ENABLED\":false,\"GMOAlipay\":false,\"GMOAu\":false,\"GMOCreditcard\":false,\"GMOCvs\":false,\"GMODocomo\":false,\"GMOPaypal\":false,\"GMOPaypay\":false,\"GMOSoftbank\":false,\"MYCARD_ENABLED\":false,\"PAYPAL_ENABLED\":true,\"RAZER_ENABLED\":false,\"STEAM_ENABLED\":false,\"STRIPE_ENABLED\":true,\"TOSS_ENABLED\":false,\"WEBMONEY_ENABLED\":false},\"FACEBOOK_APPID\":\"\",\"FACEBOOK_CLIENT_TOKEN\":\"\",\"FACEBOOK_SECRET\":\"\",\"FIREBASE_ENABLED\":0,\"GMO_CC_JS\":\"https://\",\"GMO_CC_KEY\":\"\",\"GMO_CC_SHOPID\":\"\",\"GMO_PAY_CHANNEL\":{\"GMOAlipay\":false,\"GMOAu\":false,\"GMOCreditcard\":false,\"GMOCvs\":false,\"GMODocomo\":false,\"GMOPaypal\":false,\"GMOPaypay\":false,\"GMOSoftbank\":false},\"GMO_PAY_ENABLED\":false,\"GOOGLE_CLIENT_ID\":\"\",\"GOOGLE_CLIENT_SECRET\":\"\",\"GUEST_CREATE_METHOD\":0,\"GUIDE_POPUP\":{\"DATA\":null,\"ENABLE\":0},\"LOGIN\":{\"DEFAULT\":\"yostar\",\"ICON_SIZE\":\"big\",\"SORT\":[\"google\",\"apple\",\"device\"]},\"MYCARD_ENABLED\":false,\"ONE_STORE_LICENSE_KEY\":\"\",\"PAYPAL_ENABLED\":false,\"RAZER_ENABLED\":false,\"REMOTE_CONFIG\":[],\"SAMSUNG_SANDBOX_MODE\":false,\"STEAM_APPID\":\"\",\"STEAM_ENABLED\":false,\"STEAM_PAY_APPID\":\"\",\"STRIPE_ENABLED\":false,\"TOSS_ENABLED\":false,\"TWITTER_KEY\":\"\",\"TWITTER_SECRET\":\"\",\"WEBMONEY_ENABLED\":false}},\"Msg\":\"OK\"}";
|
||||
|
||||
String address = server.getServerConfig().getDisplayAddress();
|
||||
this.json = this.json.replaceAll("\\$\\{url}", address);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result(this.json);
|
||||
}
|
||||
|
||||
}
|
||||
83
src/main/java/emu/nebula/server/routes/GetAuthHandler.java
Normal file
83
src/main/java/emu/nebula/server/routes/GetAuthHandler.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.account.Account;
|
||||
import emu.nebula.game.account.AccountHelper;
|
||||
import emu.nebula.util.JsonUtils;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class GetAuthHandler implements Handler {
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Parse request
|
||||
var req = JsonUtils.decode(ctx.body(), GetAuthRequestJson.class);
|
||||
|
||||
if (req == null || req.Account == null || req.Account.isEmpty() || req.Code == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100600,\"Data\":{},\"Msg\":\"Error\"}"); // PARAM_IS_EMPTY
|
||||
return;
|
||||
}
|
||||
|
||||
// Get account
|
||||
Account account = AccountHelper.getAccountByEmail(req.Account);
|
||||
|
||||
if (account == null) {
|
||||
// Create an account if were allowed to
|
||||
if (Nebula.getConfig().getServerOptions().isAutoCreateAccount()) {
|
||||
account = AccountHelper.createAccount(req.Account, null, 0);
|
||||
}
|
||||
} else {
|
||||
// Check passcode sent by email
|
||||
if (!account.verifyCode(req.Code)) {
|
||||
account = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity
|
||||
if (account == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100403,\"Data\":{},\"Msg\":\"Error\"}"); // TOKEN_AUTH_FAILED
|
||||
return;
|
||||
}
|
||||
|
||||
// Build request
|
||||
var response = new GetAuthResponseJson();
|
||||
|
||||
response.Code = 200;
|
||||
response.Msg = "OK";
|
||||
response.Data = new GetAuthResponseJson.GetAuthDataJson();
|
||||
response.Data.UID = account.getEmail();
|
||||
response.Data.Token = account.generateLoginToken();
|
||||
response.Data.Account = account.getEmail();
|
||||
|
||||
// Result
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result(JsonUtils.encode(response));
|
||||
}
|
||||
|
||||
private static class GetAuthRequestJson {
|
||||
public String Account;
|
||||
public String Code;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class GetAuthResponseJson {
|
||||
public int Code;
|
||||
public GetAuthDataJson Data;
|
||||
public String Msg;
|
||||
|
||||
private static class GetAuthDataJson {
|
||||
public String UID;
|
||||
public String Token;
|
||||
public String Account;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
22
src/main/java/emu/nebula/server/routes/HttpJsonResponse.java
Normal file
22
src/main/java/emu/nebula/server/routes/HttpJsonResponse.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
|
||||
public class HttpJsonResponse implements Handler {
|
||||
private final String json;
|
||||
|
||||
public HttpJsonResponse(String jsonString) {
|
||||
this.json = jsonString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
ctx.status(200);
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result(json);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.proto.Pb.ServerAgent;
|
||||
import emu.nebula.proto.Pb.ServerListMeta;
|
||||
import emu.nebula.server.HttpServer;
|
||||
import emu.nebula.util.AeadHelper;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
public class MetaServerlistHandler implements Handler {
|
||||
private HttpServer server;
|
||||
private ServerListMeta list;
|
||||
private byte[] proto;
|
||||
|
||||
public MetaServerlistHandler(HttpServer server) {
|
||||
this.server = server;
|
||||
|
||||
// Create server list
|
||||
this.list = ServerListMeta.newInstance()
|
||||
.setVersion(22)
|
||||
.setReportEndpoint(server.getServerConfig().getDisplayAddress() + "/report");
|
||||
|
||||
var agent = ServerAgent.newInstance()
|
||||
.setName("Nebula") // TODO allow change in config
|
||||
.setAddr(server.getServerConfig().getDisplayAddress() + "/agent-zone-1/")
|
||||
.setStatus(1)
|
||||
.setZone(1);
|
||||
|
||||
this.list.addAgent(agent);
|
||||
|
||||
var agent2 = ServerAgent.newInstance()
|
||||
.setName("Test") // TODO allow change in config
|
||||
.setAddr(server.getServerConfig().getDisplayAddress() + "/agent-zone-1/")
|
||||
.setStatus(1)
|
||||
.setZone(1);
|
||||
|
||||
this.list.addAgent(agent2);
|
||||
|
||||
// Cache proto
|
||||
this.proto = list.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Result
|
||||
try {
|
||||
ctx.contentType(ContentType.APPLICATION_OCTET_STREAM);
|
||||
ctx.result(AeadHelper.encryptCBC(this.getProto()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
35
src/main/java/emu/nebula/server/routes/MetaWinHandler.java
Normal file
35
src/main/java/emu/nebula/server/routes/MetaWinHandler.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.proto.Pb.ClientDiff;
|
||||
import emu.nebula.util.AeadHelper;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
public class MetaWinHandler implements Handler {
|
||||
private ClientDiff list;
|
||||
private byte[] proto;
|
||||
|
||||
public MetaWinHandler() {
|
||||
// Create client diff
|
||||
this.list = ClientDiff.newInstance();
|
||||
|
||||
// TODO load from json or something
|
||||
|
||||
// Cache proto
|
||||
this.proto = list.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Result
|
||||
ctx.contentType(ContentType.APPLICATION_OCTET_STREAM);
|
||||
ctx.result(AeadHelper.encryptCBC(this.getProto()));
|
||||
}
|
||||
|
||||
}
|
||||
51
src/main/java/emu/nebula/server/routes/UserLoginEntity.java
Normal file
51
src/main/java/emu/nebula/server/routes/UserLoginEntity.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserLoginEntity {
|
||||
public int Code;
|
||||
public UserDetailJson Data;
|
||||
public String Msg;
|
||||
|
||||
public static class UserDetailJson {
|
||||
public long AgeVerifyMethod;
|
||||
public Object Destroy;
|
||||
public boolean IsTestAccount;
|
||||
public List<UserKeyJson> Keys;
|
||||
public long ServerNowAt;
|
||||
public UserInfoJson UserInfo;
|
||||
public LoginYostarJson Yostar;
|
||||
public Object YostarDestroy;
|
||||
}
|
||||
|
||||
public static class UserKeyJson {
|
||||
public String ID;
|
||||
public String Type;
|
||||
public String Key;
|
||||
public String NickName;
|
||||
public long CreatedAt;
|
||||
}
|
||||
|
||||
public static class UserInfoJson {
|
||||
public String ID;
|
||||
public int UID2;
|
||||
public String PID;
|
||||
public String Token;
|
||||
public String Birthday;
|
||||
public String RegChannel;
|
||||
public String TransCode;
|
||||
public int State;
|
||||
public String DeviceID;
|
||||
public long CreatedAt;
|
||||
}
|
||||
|
||||
public static class LoginYostarJson {
|
||||
public String ID;
|
||||
public String Country;
|
||||
public String Nickname;
|
||||
public String Picture;
|
||||
public int State;
|
||||
public int AgreeAd;
|
||||
public long CreatedAt;
|
||||
}
|
||||
}
|
||||
127
src/main/java/emu/nebula/server/routes/UserLoginHandler.java
Normal file
127
src/main/java/emu/nebula/server/routes/UserLoginHandler.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.game.account.Account;
|
||||
import emu.nebula.game.account.AccountHelper;
|
||||
import emu.nebula.server.routes.UserLoginEntity.LoginYostarJson;
|
||||
import emu.nebula.server.routes.UserLoginEntity.UserDetailJson;
|
||||
import emu.nebula.server.routes.UserLoginEntity.UserInfoJson;
|
||||
import emu.nebula.server.routes.UserLoginEntity.UserKeyJson;
|
||||
import emu.nebula.util.JsonUtils;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class UserLoginHandler implements Handler {
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Get account from header first
|
||||
Account account = this.getAccountFromHeader(ctx);
|
||||
|
||||
// Check req body for account details
|
||||
if (account == null) {
|
||||
account = this.getAccountFromBody(ctx);
|
||||
}
|
||||
|
||||
// Check
|
||||
if (account == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100403,\"Data\":{},\"Msg\":\"Error\"}"); // TOKEN_AUTH_FAILED
|
||||
return;
|
||||
}
|
||||
|
||||
// Create response
|
||||
var response = new UserLoginEntity();
|
||||
|
||||
response.Code = 200;
|
||||
response.Msg = "OK";
|
||||
response.Data = new UserDetailJson();
|
||||
response.Data.Keys = new ArrayList<>();
|
||||
response.Data.UserInfo = new UserInfoJson();
|
||||
response.Data.Yostar = new LoginYostarJson();
|
||||
|
||||
response.Data.UserInfo.ID = account.getUid();
|
||||
response.Data.UserInfo.UID2 = 0;
|
||||
response.Data.UserInfo.PID = "NEBULA";
|
||||
response.Data.UserInfo.Token = account.getLoginToken();
|
||||
response.Data.UserInfo.Birthday = "";
|
||||
response.Data.UserInfo.RegChannel = "pc";
|
||||
response.Data.UserInfo.TransCode = "";
|
||||
response.Data.UserInfo.State = 1;
|
||||
response.Data.UserInfo.DeviceID = "";
|
||||
response.Data.UserInfo.CreatedAt = account.getCreatedAt();
|
||||
|
||||
response.Data.Yostar.ID = account.getUid();
|
||||
response.Data.Yostar.Country = "US";
|
||||
response.Data.Yostar.Nickname = account.getNickname();
|
||||
response.Data.Yostar.Picture = account.getPicture();
|
||||
response.Data.Yostar.State = 1;
|
||||
response.Data.Yostar.AgreeAd = 0;
|
||||
response.Data.Yostar.CreatedAt = account.getCreatedAt();
|
||||
|
||||
var key = new UserKeyJson();
|
||||
key.ID = account.getUid();
|
||||
key.Type = "yostar";
|
||||
key.Key = account.getEmail();
|
||||
key.NickName = account.getEmail();
|
||||
key.CreatedAt = account.getCreatedAt();
|
||||
|
||||
response.Data.Keys.add(key);
|
||||
|
||||
// Result
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result(JsonUtils.encode(response, true));
|
||||
}
|
||||
|
||||
protected Account getAccountFromBody(Context ctx) {
|
||||
// Parse request
|
||||
var req = JsonUtils.decode(ctx.body(), UserLoginRequestJson.class);
|
||||
|
||||
if (req == null || req.OpenID == null || req.Token == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get account
|
||||
return AccountHelper.getAccountByLoginToken(req.Token);
|
||||
}
|
||||
|
||||
protected Account getAccountFromHeader(Context ctx) {
|
||||
// Parse request
|
||||
var req = JsonUtils.decode(ctx.header("Authorization"), UserAuthDataJson.class);
|
||||
|
||||
if (req == null || req.Head == null || req.Head.Token == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get account
|
||||
return AccountHelper.getAccountByLoginToken(req.Head.Token);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class UserLoginRequestJson {
|
||||
public String OpenID;
|
||||
public String Token;
|
||||
public String Type;
|
||||
public String UserName;
|
||||
public String Secret;
|
||||
public int CheckAccount;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class UserAuthDataJson {
|
||||
public UserAuthHeadJson Head;
|
||||
public String Sign;
|
||||
|
||||
protected static class UserAuthHeadJson {
|
||||
public String UID;
|
||||
public String Token;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.game.account.Account;
|
||||
import emu.nebula.util.JsonUtils;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class UserSetDataHandler extends UserLoginHandler {
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Get account from header first
|
||||
Account account = this.getAccountFromHeader(ctx);
|
||||
|
||||
// Check
|
||||
if (account == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100403,\"Data\":{},\"Msg\":\"Error\"}"); // TOKEN_AUTH_FAILED
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse request
|
||||
var req = JsonUtils.decode(ctx.body(), UserSetDataReqJson.class);
|
||||
|
||||
if (req.Key == null || req.Value == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100110,\"Data\":{},\"Msg\":\"Error\"}"); // VALID_FAIL
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.Key.equals("Nickname")) {
|
||||
account.setNickname(req.Value);
|
||||
account.save();
|
||||
}
|
||||
|
||||
// Result
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":200,\"Data\":{},\"Msg\":\"OK\"}");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class UserSetDataReqJson {
|
||||
public String Key;
|
||||
public String Value;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user