Begin to add a new ACL system

This commit is contained in:
zontreck 2024-07-02 16:01:06 -07:00
parent 03fef9863f
commit f7c71230f0
9 changed files with 293 additions and 44 deletions

View file

@ -1,5 +1,9 @@
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/utils/Hashing.dart';
import 'package:servermanager/structs/discordHookHelper.dart';
import 'package:servermanager/structs/settings.dart';
class Credentials {
String username;
@ -28,3 +32,121 @@ class Credentials {
static const TAG_USERNAME = "username";
static const TAG_PASSWORD = "password";
}
class User {
String name;
String passwordHash;
String passwordSalt;
UserLevel permissions;
final String userHash;
bool login(String username, String passwordHash) {
if (userHash != generateValidityCheck())
return false; // User will be thrown away next time the data is reloaded
if (name == username) {
if (Hashing.sha256Hash("${passwordSalt}:${passwordHash}") ==
this.passwordHash) {
return true;
} else
return false;
} else
return false;
}
Future<void> sendDiscordActionLog(String actionMessage) async {
Settings settings = Settings();
DiscordHookHelper.sendWebHook(
settings.inst!.discord,
DiscordHookProps.ALERT,
"User Action Alert",
"${this}: ${actionMessage}");
}
User(
{required this.name,
required this.passwordHash,
required this.passwordSalt,
required this.permissions,
required this.userHash});
CompoundTag serialize() {
CompoundTag ct = CompoundTag();
ct.put(TAG_NAME, StringTag.valueOf(name));
ct.put(TAG_HASH, StringTag.valueOf(passwordHash));
ct.put(TAG_SALT, StringTag.valueOf(passwordSalt));
ct.put(TAG_PERMS, IntTag.valueOf(permissions.ord()));
ct.put(TAG_SEC_CODE, StringTag.valueOf(userHash));
return ct;
}
static User deserialize(CompoundTag ct) {
return User(
name: ct.get(TAG_NAME)!.asString(),
passwordHash: ct.get(TAG_HASH)!.asString(),
passwordSalt: ct.get(TAG_SALT)!.asString(),
permissions: UserLevel.of(ct.get(TAG_PERMS)!.asInt()),
userHash: ct.get(TAG_SEC_CODE)!.asString());
}
factory User.make(String name, String password, UserLevel level) {
String salt = Hashing.sha256Hash(
"${Hashing.md5Hash("${Hashing.sha256Hash("${DateTime.now().millisecondsSinceEpoch}")}")}");
String hash = Hashing.sha256Hash("${salt}:${Hashing.sha256Hash(password)}");
String validityCode = generateValidityCode(name, hash, salt, level);
return User(
name: name,
passwordHash: hash,
passwordSalt: salt,
permissions: level,
userHash: validityCode);
}
String generateValidityCheck() {
return Hashing.sha256Hash(
"${name}:${passwordHash}:${passwordSalt}:${permissions.ord()}}");
}
static String generateValidityCode(String name, String passwordHash,
String passwordSalt, UserLevel permissions) {
return Hashing.sha256Hash(
"${name}:${passwordHash}:${passwordSalt}:${permissions.ord()}}");
}
static const TAG_NAME = "name";
static const TAG_HASH = "hash";
static const TAG_SALT = "salt";
static const TAG_PERMS = "perms";
static const TAG_SEC_CODE = "validity";
@override
String toString() {
return "${permissions.name}: ${name}";
}
}
enum UserLevel {
Super_User(0),
Administrator(1),
Operator(2),
None(99);
final int _id;
const UserLevel(this._id);
int ord() {
return _id;
}
static UserLevel of(int ord) {
for (var lvl in values) {
if (lvl.ord() == ord) {
return lvl;
}
}
return UserLevel.None;
}
}

View file

@ -40,6 +40,9 @@ class Settings {
UUID remoteLoginToken = UUID.ZERO;
PacketClient? client;
User? superuser;
User? loggedInUser;
StateMachine subsys = StateMachine();

View file

@ -11,6 +11,8 @@ import 'package:servermanager/structs/serversettings.dart';
class SettingsEntry {
List<Mod> mods = [];
List<User> admins = [];
DiscordHookProps discord =
DiscordHookProps(url: "", serverName: "", enabled: false);
Credentials? steam_creds;
@ -41,6 +43,20 @@ class SettingsEntry {
tag.get(DiscordHookProps.TAG_NAME)!.asCompoundTag());
}
if (tag.containsKey("admins")) {
ListTag adminUsers = tag.get("admins")! as ListTag;
for (int i = 0; i < adminUsers.size(); i++) {
CompoundTag entry = adminUsers.get(i).asCompoundTag();
User loadedUser = User.deserialize(entry);
if (loadedUser.userHash == loadedUser.generateValidityCheck()) {
st.admins.add(loadedUser);
} else {
print(
"/!\\ FATAL /!\\\n\n${loadedUser} failed to pass the validity check and has been tampered with");
}
}
}
st.mods.clear();
ListTag lMods = tag.get("mods") as ListTag;
for (Tag tag in lMods.value) {
@ -65,6 +81,13 @@ class SettingsEntry {
tag.put(DiscordHookProps.TAG_NAME, discord.serialize());
ListTag adminUsers = ListTag();
for (User usr in admins) {
adminUsers.add(usr.serialize());
}
tag.put("admins", adminUsers);
return tag;
}
}