mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-14 22:04:51 +00:00
Added primitive support for basic authentication
Note that the password will be passed over HTTP in plain text.
This commit is contained in:
parent
c0a6e94b21
commit
7d12d89a0a
@ -555,6 +555,7 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
|
|||||||
clearInterval: clearInterval,
|
clearInterval: clearInterval,
|
||||||
setTimeout: setTimeout,
|
setTimeout: setTimeout,
|
||||||
clearTimeout: clearTimeout,
|
clearTimeout: clearTimeout,
|
||||||
|
Buffer: $tw.browser ? {} : Buffer,
|
||||||
$tw: $tw,
|
$tw: $tw,
|
||||||
require: function(title) {
|
require: function(title) {
|
||||||
return $tw.modules.execute(title, name);
|
return $tw.modules.execute(title, name);
|
||||||
|
@ -49,27 +49,58 @@ SimpleServer.prototype.addRoute = function(route) {
|
|||||||
this.routes.push(route);
|
this.routes.push(route);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SimpleServer.prototype.findMatchingRoute = function(request,state) {
|
||||||
|
for(var t=0; t<this.routes.length; t++) {
|
||||||
|
var potentialRoute = this.routes[t],
|
||||||
|
pathRegExp = potentialRoute.path,
|
||||||
|
match = potentialRoute.path.exec(state.urlInfo.pathname);
|
||||||
|
if(match && request.method === potentialRoute.method) {
|
||||||
|
state.params = [];
|
||||||
|
for(var p=1; p<match.length; p++) {
|
||||||
|
state.params.push(match[p]);
|
||||||
|
}
|
||||||
|
return potentialRoute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
SimpleServer.prototype.checkCredentials = function(request,incomingUsername,incomingPassword) {
|
||||||
|
var header = request.headers["authorization"] || "",
|
||||||
|
token = header.split(/\s+/).pop() || "",
|
||||||
|
auth = $tw.utils.base64Decode(token),
|
||||||
|
parts = auth.split(/:/),
|
||||||
|
username = parts[0],
|
||||||
|
password = parts[1];
|
||||||
|
if(incomingUsername === username && incomingPassword === password) {
|
||||||
|
return "ALLOWED";
|
||||||
|
} else {
|
||||||
|
return "DENIED";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SimpleServer.prototype.listen = function(port) {
|
SimpleServer.prototype.listen = function(port) {
|
||||||
var self = this;
|
var self = this;
|
||||||
http.createServer(function(request, response) {
|
http.createServer(function(request,response) {
|
||||||
// Compose the state object
|
// Compose the state object
|
||||||
var state = {};
|
var state = {};
|
||||||
state.wiki = self.wiki;
|
state.wiki = self.wiki;
|
||||||
state.server = self;
|
state.server = self;
|
||||||
state.urlInfo = url.parse(request.url);
|
state.urlInfo = url.parse(request.url);
|
||||||
// Find the route that matches this path
|
// Find the route that matches this path
|
||||||
var route;
|
var route = self.findMatchingRoute(request,state);
|
||||||
for(var t=0; t<self.routes.length; t++) {
|
// Check for the username and password if we've got one
|
||||||
var potentialRoute = self.routes[t],
|
var username = self.get("username"),
|
||||||
pathRegExp = potentialRoute.path,
|
password = self.get("password");
|
||||||
match = potentialRoute.path.exec(state.urlInfo.pathname);
|
if(username && password) {
|
||||||
if(request.method === potentialRoute.method && match) {
|
// Check they match
|
||||||
state.params = [];
|
if(self.checkCredentials(request,username,password) !== "ALLOWED") {
|
||||||
for(var p=1; p<match.length; p++) {
|
response.setHeader("WWW-Authenticate", 'Basic realm="Admin Area"');
|
||||||
state.params.push(match[p]);
|
response.writeHead(401,"Authentication required",{
|
||||||
}
|
"WWW-Authenticate": 'Basic realm="TiddlyWiki5"'
|
||||||
route = potentialRoute;
|
});
|
||||||
break;
|
response.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Return a 404 if we didn't find a route
|
// Return a 404 if we didn't find a route
|
||||||
@ -224,12 +255,14 @@ Command.prototype.execute = function() {
|
|||||||
rootTiddler = this.params[1] || "$:/core/save/all",
|
rootTiddler = this.params[1] || "$:/core/save/all",
|
||||||
renderType = this.params[2] || "text/plain",
|
renderType = this.params[2] || "text/plain",
|
||||||
serveType = this.params[3] || "text/html",
|
serveType = this.params[3] || "text/html",
|
||||||
username = this.params[4] || "ANONYMOUS";
|
username = this.params[4] || "ANONYMOUS",
|
||||||
|
password = this.params[5];
|
||||||
this.server.set({
|
this.server.set({
|
||||||
rootTiddler: rootTiddler,
|
rootTiddler: rootTiddler,
|
||||||
renderType: renderType,
|
renderType: renderType,
|
||||||
serveType: serveType,
|
serveType: serveType,
|
||||||
username: username
|
username: username,
|
||||||
|
password: password
|
||||||
});
|
});
|
||||||
this.server.listen(port);
|
this.server.listen(port);
|
||||||
if(this.commander.verbose) {
|
if(this.commander.verbose) {
|
||||||
|
@ -413,4 +413,16 @@ exports.hashString = function(str) {
|
|||||||
},0);
|
},0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Decode a base64 string
|
||||||
|
*/
|
||||||
|
exports.base64Decode = function(string64) {
|
||||||
|
if($tw.browser) {
|
||||||
|
// TODO
|
||||||
|
throw "$tw.utils.base64Decode() doesn't work in the browser";
|
||||||
|
} else {
|
||||||
|
return (new Buffer(string64,"base64")).toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -21,6 +21,7 @@ tags: releasenote
|
|||||||
* Refactored control panel to add ''Saving'' tab that includes TiddlySpot options
|
* Refactored control panel to add ''Saving'' tab that includes TiddlySpot options
|
||||||
* Improved notifications when saving to TiddlySpot
|
* Improved notifications when saving to TiddlySpot
|
||||||
* Added backup URL to TiddlySpot control panel tab
|
* Added backup URL to TiddlySpot control panel tab
|
||||||
|
* Extended the ServerCommand to add primitive support for basic authentication when running under [[Node.js]]
|
||||||
|
|
||||||
!! Bug fixes
|
!! Bug fixes
|
||||||
|
|
||||||
|
@ -16,6 +16,9 @@ The parameters are:
|
|||||||
* ''rendertype'' - the content type to which the root tiddler should be rendered (defaults to "text/plain")
|
* ''rendertype'' - the content type to which the root tiddler should be rendered (defaults to "text/plain")
|
||||||
* ''servetype'' - the content type with which the root tiddler should be served (defaults to "text/html")
|
* ''servetype'' - the content type with which the root tiddler should be served (defaults to "text/html")
|
||||||
* ''username'' - the default username for signing edits
|
* ''username'' - the default username for signing edits
|
||||||
|
* ''password'' - optional password for basic authentication
|
||||||
|
|
||||||
|
If the password parameter is specified then the browser will prompt the user for the username and password. Note that the password is transmitted in plain text so this implementation isn't suitable for general use.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@ rem Optional parameter is the username for signing edits
|
|||||||
node .\tiddlywiki.js ^
|
node .\tiddlywiki.js ^
|
||||||
editions\clientserver ^
|
editions\clientserver ^
|
||||||
--verbose ^
|
--verbose ^
|
||||||
--server 8080 $:/core/save/all text/plain text/html %1^
|
--server 8080 $:/core/save/all text/plain text/html %1 %2^
|
||||||
|| exit 1
|
|| exit 1
|
||||||
|
Loading…
Reference in New Issue
Block a user