Begin to add a new ACL system
This commit is contained in:
parent
03fef9863f
commit
f7c71230f0
9 changed files with 293 additions and 44 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ class Settings {
|
|||
UUID remoteLoginToken = UUID.ZERO;
|
||||
|
||||
PacketClient? client;
|
||||
User? superuser;
|
||||
|
||||
User? loggedInUser;
|
||||
|
||||
StateMachine subsys = StateMachine();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue