mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
* Refactor UserManager to use Datastore * Rename lib.User to UserDetails also adds to/fromUserDetails * Fix existing tests * Add user class tests * Add tests for finaliseUsers * Move HostDetails to own file with tests * Move InstanceDetails to its own file with tests * Rename HostInfo and add tests * Rename InstanceInfo and add tests - Also changes the names of the host properties related to instances - Also removes the need to specify the location of InstanceInfo * Make json round trip test validate schema * Add InstanceManager * Fix lint errors * Extra tests * Add final test coverage * Add one last test to InstanceManager * Response to comments * Use generator rather than return anonumous generator Co-authored-by: Hornwitser <github@hornwitser.no> * Fix lint issue with generator --------- Co-authored-by: Hornwitser <github@hornwitser.no>
157 lines
4.7 KiB
JavaScript
157 lines
4.7 KiB
JavaScript
"use strict";
|
|
const assert = require("assert").strict;
|
|
const { Role, SubscribableDatastore } = require("@clusterio/lib");
|
|
const { User } = require("@clusterio/controller");
|
|
|
|
describe("controller/User", function () {
|
|
/** @type {SubscribableDatastore<UserRecord>} */
|
|
let users;
|
|
/** @type {SubscribableDatastore<Role>} */
|
|
let roles;
|
|
/** @type {User} */
|
|
let user;
|
|
|
|
beforeEach(function () {
|
|
users = new SubscribableDatastore();
|
|
roles = new SubscribableDatastore();
|
|
|
|
// Create a role and user used in most tests
|
|
roles.set(Role.fromJSON({ id: 1, name: "connectRole", permissions: ["core.control.connect"] }));
|
|
user = User.fromJSON({ name: "Alice", roles: [1] }, users, roles);
|
|
|
|
users.set(user);
|
|
user.updatedAtMs = 1000; // Known low value
|
|
});
|
|
|
|
describe("get roles", function () {
|
|
it("should return roles from _controllerRoles", function () {
|
|
const roleSet = user.roles;
|
|
assert.equal(roleSet.size, 1);
|
|
assert.equal([...roleSet][0].id, 1);
|
|
});
|
|
});
|
|
|
|
describe(".saveRecord() / set", function () {
|
|
it("should update updatedAtMs", function () {
|
|
const prev = user.updatedAtMs;
|
|
user.saveRecord();
|
|
assert(user.updatedAtMs > prev);
|
|
});
|
|
});
|
|
|
|
describe(".set()", function () {
|
|
it("should update updatedAtMs", function () {
|
|
const prev = user.updatedAtMs;
|
|
user.set("isAdmin", true);
|
|
assert.equal(user.isAdmin, true);
|
|
assert(user.updatedAtMs > prev);
|
|
});
|
|
});
|
|
|
|
describe(".invalidateToken()", function () {
|
|
it("should update tokenValidAfter to current time", function () {
|
|
const prevValid = user.tokenValidAfter;
|
|
const prevUpdate = user.updatedAtMs;
|
|
user.invalidateToken();
|
|
assert(user.tokenValidAfter > prevValid);
|
|
assert(user.updatedAtMs > prevUpdate);
|
|
});
|
|
});
|
|
|
|
describe(".addRole()", function () {
|
|
it("should add role if exists", function () {
|
|
roles.set(Role.fromJSON({ id: 2, name: "admin", permissions: ["core.admin"] }));
|
|
const prev = user.updatedAtMs;
|
|
|
|
user.addRole(2);
|
|
assert(user.roleIds.has(2));
|
|
assert(user.updatedAtMs > prev);
|
|
});
|
|
|
|
it("should throw if role does not exist", function () {
|
|
assert.throws(() => user.addRole(999), /role 999 does not exist/);
|
|
});
|
|
});
|
|
|
|
describe(".removeRole()", function () {
|
|
it("should remove existing role", function () {
|
|
const prev = user.updatedAtMs;
|
|
const result = user.removeRole(1);
|
|
assert(result);
|
|
assert(!user.roleIds.has(1));
|
|
assert(user.updatedAtMs > prev);
|
|
});
|
|
|
|
it("should return false if role was not assigned", function () {
|
|
const prev = user.updatedAtMs;
|
|
const result = user.removeRole(999);
|
|
assert.equal(result, false);
|
|
assert(user.updatedAtMs === prev); // unchanged
|
|
});
|
|
});
|
|
|
|
describe(".notifyJoin() / .notifyLeave()", function () {
|
|
it("should add instance on notifyJoin", function () {
|
|
const prev = user.updatedAtMs;
|
|
user.notifyJoin(10);
|
|
assert(user.instances.has(10));
|
|
assert(user.updatedAtMs > prev);
|
|
});
|
|
|
|
it("should remove instance on notifyLeave", function () {
|
|
user.notifyJoin(10);
|
|
user.updatedAtMs = 1000; // Known low value
|
|
user.notifyLeave(10);
|
|
assert(!user.instances.has(10));
|
|
assert(user.updatedAtMs > 1000);
|
|
});
|
|
});
|
|
|
|
describe(".clearInstanceStats()", function () {
|
|
it("should remove instanceStats and recalculate playerStats", function () {
|
|
const instanceId = 5;
|
|
const userWithStats = User.fromJSON({
|
|
name: "Bob",
|
|
instanceStats: [[instanceId, { join_count: 1 }]],
|
|
}, users, roles);
|
|
|
|
users.set(userWithStats);
|
|
userWithStats.updatedAtMs = 1000; // Known low value
|
|
|
|
userWithStats.clearInstanceStats(instanceId);
|
|
assert(!userWithStats.instanceStats.has(instanceId));
|
|
assert(userWithStats.updatedAtMs > 1000);
|
|
});
|
|
});
|
|
|
|
describe(".checkPermission()", function () {
|
|
it("should allow if role has core.control.connect", function () {
|
|
assert.doesNotThrow(() => user.checkPermission("core.control.connect"));
|
|
});
|
|
|
|
it("should allow if role has core.admin", function () {
|
|
roles.set(Role.fromJSON({ id: 2, name: "admin", permissions: ["core.admin"] }));
|
|
const adminUser = User.fromJSON({ name: "Charlie", roles: [2] }, users, roles);
|
|
assert.doesNotThrow(() => adminUser.checkPermission("core.admin"));
|
|
});
|
|
|
|
it("should not error if user has invalid role", function () {
|
|
user.roleIds = {
|
|
[Symbol.iterator]: function* () {
|
|
// We need the invalid id (99) to be before the valid id (1)
|
|
for (const roleId of [99, 1]) { yield roleId; }
|
|
},
|
|
};
|
|
assert.doesNotThrow(() => user.checkPermission("core.control.connect"));
|
|
});
|
|
|
|
it("should throw if permission not granted", function () {
|
|
assert.throws(() => user.checkPermission("core.admin"), /Permission denied/);
|
|
});
|
|
|
|
it("should throw if permission does not exist", function () {
|
|
assert.throws(() => user.checkPermission("nonexistent.permission"), /does not exist/);
|
|
});
|
|
});
|
|
});
|