mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-11-03 09:02:59 +00:00
MWS authentication (#8596)
* mws authentication * add more tests and permission checkers * add logic to ensure that only authenticated users' requests are handled * add custom login page * Implement user authentication as well as session handling * work on user operations authorization * add middleware to route handlers for bags & tiddlers routes * add feature that only returns the tiddlers and bags which the user has permission to access on index page * refactor auth routes & added user management page * fix Ci Test failure issue * fix users list page, add manage roles page * add commands and scripts to create new user & assign roles and permissions * resolved ci-test failure * add ACL permissions to bags & tiddlers on creation * fix comments and access control list bug * fix indentation issues * working on user profile edit * remove list users command & added support for database in server options * implement user profile update and password change feature * update plugin readme * implement command which triggers protected mode on the server * revert server-wide auth flag. Implement selective authorization * ACL management feature * Complete Access control list implementation * Added support to manage users' assigned role by admin * fix comments * fix comment
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/commands/mws-add-permission.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to create a permission
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "mws-add-permission",
|
||||
synchronous: false
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var self = this;
|
||||
|
||||
if(this.params.length < 2) {
|
||||
return "Usage: --mws-add-permission <permission_name> <description>";
|
||||
}
|
||||
|
||||
if(!$tw.mws || !$tw.mws.store || !$tw.mws.store.sqlTiddlerDatabase) {
|
||||
return "Error: MultiWikiServer or SQL database not initialized.";
|
||||
}
|
||||
|
||||
var permission_name = this.params[0];
|
||||
var description = this.params[1];
|
||||
|
||||
$tw.mws.store.sqlTiddlerDatabase.createPermission(permission_name, description);
|
||||
|
||||
console.log(permission_name+" Permission Created Successfully!")
|
||||
self.callback();
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,49 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/commands/mws-add-role.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to create a role
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "mws-add-role",
|
||||
synchronous: false
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var self = this;
|
||||
|
||||
if(this.params.length < 2) {
|
||||
return "Usage: --mws-add-role <role_name> <description>";
|
||||
}
|
||||
|
||||
if(!$tw.mws || !$tw.mws.store || !$tw.mws.store.sqlTiddlerDatabase) {
|
||||
return "Error: MultiWikiServer or SQL database not initialized.";
|
||||
}
|
||||
|
||||
var role_name = this.params[0];
|
||||
var description = this.params[1];
|
||||
|
||||
$tw.mws.store.sqlTiddlerDatabase.createRole(role_name, description);
|
||||
|
||||
console.log(role_name+" Role Created Successfully!")
|
||||
self.callback(null, "Role Created Successfully!");
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,58 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/commands/mws-add-user.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to create users and grant permission
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
if($tw.node) {
|
||||
var crypto = require("crypto");
|
||||
}
|
||||
exports.info = {
|
||||
name: "mws-add-user",
|
||||
synchronous: false
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var self = this;
|
||||
|
||||
if(this.params.length < 2) {
|
||||
return "Usage: --mws-add-user <username> <password> [email]";
|
||||
}
|
||||
|
||||
if(!$tw.mws || !$tw.mws.store || !$tw.mws.store.sqlTiddlerDatabase) {
|
||||
return "Error: MultiWikiServer or SQL database not initialized.";
|
||||
}
|
||||
|
||||
var username = this.params[0];
|
||||
var password = this.params[1];
|
||||
var email = this.params[2] || username + "@example.com";
|
||||
var hashedPassword = crypto.createHash("sha256").update(password).digest("hex");
|
||||
|
||||
var user = $tw.mws.store.sqlTiddlerDatabase.getUserByUsername(username);
|
||||
|
||||
if(user) {
|
||||
self.callback("WARNING: An account with the username (" + username + ") already exists");
|
||||
} else {
|
||||
$tw.mws.store.sqlTiddlerDatabase.createUser(username, email, hashedPassword);
|
||||
console.log("User Account Created Successfully!")
|
||||
self.callback();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,62 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/commands/mws-assign-role-permission.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to assign permission to a role
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "mws-assign-role-permission",
|
||||
synchronous: false
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var self = this;
|
||||
|
||||
if(this.params.length < 2) {
|
||||
return "Usage: --mws-assign-role-permission <role_name> <permission_name>";
|
||||
}
|
||||
|
||||
if(!$tw.mws || !$tw.mws.store || !$tw.mws.store.sqlTiddlerDatabase) {
|
||||
return "Error: MultiWikiServer or SQL database not initialized.";
|
||||
}
|
||||
|
||||
var role_name = this.params[0];
|
||||
var permission_name = this.params[1];
|
||||
var role = $tw.mws.store.sqlTiddlerDatabase.getRoleByName(role_name);
|
||||
var permission = $tw.mws.store.sqlTiddlerDatabase.getPermissionByName(permission_name);
|
||||
|
||||
if(!role) {
|
||||
return "Error: Unable to find Role: "+role_name;
|
||||
}
|
||||
|
||||
if(!permission) {
|
||||
return "Error: Unable to find Permission: "+permission_name;
|
||||
}
|
||||
|
||||
var permission = $tw.mws.store.sqlTiddlerDatabase.getPermissionByName(permission_name);
|
||||
|
||||
|
||||
$tw.mws.store.sqlTiddlerDatabase.addPermissionToRole(role.role_id, permission.permission_id);
|
||||
|
||||
console.log(permission_name+" permission assigned to "+role_name+" role successfully!")
|
||||
self.callback();
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,59 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/commands/mws-assign-user-role.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to assign a role to a user
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "mws-assign-user-role",
|
||||
synchronous: false
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var self = this;
|
||||
|
||||
if(this.params.length < 2) {
|
||||
return "Usage: --mws-assign-user-role <username> <role_name>";
|
||||
}
|
||||
|
||||
if(!$tw.mws || !$tw.mws.store || !$tw.mws.store.sqlTiddlerDatabase) {
|
||||
return "Error: MultiWikiServer or SQL database not initialized.";
|
||||
}
|
||||
|
||||
var username = this.params[0];
|
||||
var role_name = this.params[1];
|
||||
var role = $tw.mws.store.sqlTiddlerDatabase.getRoleByName(role_name);
|
||||
var user = $tw.mws.store.sqlTiddlerDatabase.getUserByUsername(username);
|
||||
|
||||
if(!role) {
|
||||
return "Error: Unable to find Role: "+role_name;
|
||||
}
|
||||
|
||||
if(!user) {
|
||||
return "Error: Unable to find user with the username "+username;
|
||||
}
|
||||
|
||||
$tw.mws.store.sqlTiddlerDatabase.addRoleToUser(user.user_id, role.role_id);
|
||||
|
||||
console.log(role_name+" role has been assigned to user with username "+username)
|
||||
self.callback();
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
@@ -50,11 +50,18 @@ TestRunner.prototype.runTests = function(callback) {
|
||||
const self = this;
|
||||
let currentTestSpec = 0;
|
||||
let hasFailed = false;
|
||||
let sessionId;
|
||||
function runNextTest() {
|
||||
if(currentTestSpec < testSpecs.length) {
|
||||
const testSpec = testSpecs[currentTestSpec];
|
||||
if(!!sessionId) {
|
||||
testSpec.headers['Cookie'] = `session=${sessionId}; HttpOnly; Path=/`;
|
||||
}
|
||||
currentTestSpec += 1;
|
||||
self.runTest(testSpec,function(err) {
|
||||
self.runTest(testSpec,function(err, data) {
|
||||
if(data?.sessionId) {
|
||||
sessionId = data?.sessionId;
|
||||
}
|
||||
if(err) {
|
||||
hasFailed = true;
|
||||
console.log(`Failed "${testSpec.description}" with "${err}"`)
|
||||
@@ -96,7 +103,7 @@ TestRunner.prototype.runTest = function(testSpec,callback) {
|
||||
response.on("end", () => {
|
||||
const jsonData = $tw.utils.parseJSONSafe(buffer,function() {return undefined;});
|
||||
const testResult = testSpec.expectedResult(jsonData,buffer,response.headers);
|
||||
callback(testResult ? null : "Test failed");
|
||||
callback(testResult ? null : "Test failed", jsonData);
|
||||
});
|
||||
});
|
||||
request.on("error", (e) => {
|
||||
@@ -112,6 +119,20 @@ TestRunner.prototype.runTest = function(testSpec,callback) {
|
||||
};
|
||||
|
||||
const testSpecs = [
|
||||
{
|
||||
description: "Login Test User",
|
||||
method: "POST",
|
||||
path: "/login",
|
||||
headers: {
|
||||
"Accept": 'application/json',
|
||||
"Content-Type": 'application/x-www-form-urlencoded',
|
||||
"User-Agent": 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'
|
||||
},
|
||||
data: "username=user&password=pass123",
|
||||
expectedResult: (jsonData,data,headers) => {
|
||||
return !!jsonData.sessionId;
|
||||
}
|
||||
},
|
||||
{
|
||||
description: "Check index page",
|
||||
method: "GET",
|
||||
|
||||
Reference in New Issue
Block a user