import 'dart:convert'; import 'package:bugvault/server/main.dart'; import 'package:bugvault/users/User.dart'; import 'package:libac_dart/nbt/Tag.dart'; import 'package:libac_dart/nbt/impl/CompoundTag.dart'; import 'package:libac_dart/nbt/impl/IntTag.dart'; import 'package:libac_dart/nbt/impl/StringTag.dart'; import 'package:libac_dart/packets/packets.dart'; class C2SPacketLogin implements IPacket { String username = ""; @override void decodeJson(String params) { fromJson(json.decode(params)); } @override void decodeTag(Tag tag) { CompoundTag ct = tag.asCompoundTag(); username = ct.get("user")?.asString() ?? ""; } @override NetworkDirection direction() { return NetworkDirection.ClientToServer; } @override String encodeJson() { return json.encode(toJson()); } @override Tag encodeTag() { CompoundTag ct = CompoundTag(); ct.put("user", StringTag.valueOf(username)); return ct; } @override void fromJson(Map js) { username = js['user'] as String; } @override String getChannelID() { return "BVPKTLOGIN"; } @override Future handleClientPacket() async { return; } @override Future handleServerPacket() async { S2CResponse response = S2CResponse(); S2CLoginReply loginReply = S2CLoginReply(); loginReply.username = username; // Check if the user exists DBUser? user = BugVaultServer.TryGetUser(username); if (user == null && username != "") { loginReply.g_ixLoginState |= LoginStates.NOT_FOUND; loginReply.g_ixLoginState |= LoginStates.PROVIDE_EMAIL; } if (user != null) { // Tell the user to send their TOTP Code loginReply.g_ixLoginState |= LoginStates.FOUND; loginReply.g_ixLoginState |= LoginStates.REQUIRE_MFA; } if (username == "") { if (BugVaultServer.g_bAllowAnonymousLogin) { loginReply.g_ixLoginState = LoginStates.LOGGED_IN; } else { loginReply.g_ixLoginState = LoginStates.ANONYMOUS_NOT_ALLOWED; } } response.contents = loginReply.encodeTag().asCompoundTag(); return PacketResponse(replyDataTag: response.encodeTag().asCompoundTag()); } @override Map toJson() { return {"user": username}; } } class LoginStates { static const NOT_FOUND = 1; static const FOUND = 2; static const REQUIRE_MFA = 4; static const PROVIDE_EMAIL = 8; static const REQUIRE_EMAIL_CODE = 16; static const LOGGED_IN = 32; static const ANONYMOUS_NOT_ALLOWED = 64; } class S2CLoginReply implements IPacket { String username = ""; int g_ixLoginState = 0; @override void decodeJson(String params) { return fromJson(json.decode(params)); } @override void decodeTag(Tag tag) { CompoundTag ct = tag.asCompoundTag(); username = ct.get("user")?.asString() ?? ""; g_ixLoginState = ct.get("state")?.asInt() ?? 0; } @override NetworkDirection direction() { return NetworkDirection.ServerToClient; } @override String encodeJson() { return json.encode(toJson()); } @override Tag encodeTag() { CompoundTag ct = CompoundTag(); ct.put("user", StringTag.valueOf(username)); ct.put("state", IntTag.valueOf(g_ixLoginState)); return ct; } @override void fromJson(Map js) { username = js['user'] as String; g_ixLoginState = js['state'] as int; } @override String getChannelID() { return "BVSPKTLOGINREPLY"; } @override Future handleClientPacket() async { // do handling stuff } @override Future handleServerPacket() async { throw UnimplementedError(); // Client side only, so this never gets invoked. } @override Map toJson() { return {"user": username, "state": g_ixLoginState}; } }