Skip to content

Commit

Permalink
Implemented User management + HTTP authentication + the structure of …
Browse files Browse the repository at this point in the history
…the privilege management + some privilege/lock checkers
  • Loading branch information
AdrienCastex committed May 20, 2017
1 parent af18fcd commit 5e7325a
Show file tree
Hide file tree
Showing 54 changed files with 1,482 additions and 449 deletions.
7 changes: 4 additions & 3 deletions lib/resource/IResource.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ export interface IResource {
read(callback: ReturnCallback<Int8Array>): any;
mimeType(callback: ReturnCallback<string>): any;
size(callback: ReturnCallback<number>): any;
getLocks(lockKind: LockKind, callback: ReturnCallback<Lock[]>): any;
getLocks(callback: ReturnCallback<Lock[]>): any;
setLock(lock: Lock, callback: SimpleCallback): any;
removeLock(uuid: string, owner: string, callback: ReturnCallback<boolean>): any;
removeLock(uuid: string, callback: ReturnCallback<boolean>): any;
canLock(lockKind: LockKind, callback: ReturnCallback<boolean>): any;
getAvailableLocks(callback: ReturnCallback<LockKind[]>): any;
canRemoveLock(uuid: string, owner: string, callback: ReturnCallback<boolean>): any;
canRemoveLock(uuid: string, callback: ReturnCallback<boolean>): any;
getLock(uuid: string, callback: ReturnCallback<Lock>): any;
addChild(resource: IResource, callback: SimpleCallback): any;
removeChild(resource: IResource, callback: SimpleCallback): any;
getChildren(callback: ReturnCallback<IResource[]>): any;
Expand Down
7 changes: 4 additions & 3 deletions lib/resource/std/StandardResource.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ export declare abstract class StandardResource implements IResource {
isSame(resource: IResource, callback: ReturnCallback<boolean>): void;
isOnTheSameFSWith(resource: IResource, callback: ReturnCallback<boolean>): void;
getAvailableLocks(callback: ReturnCallback<LockKind[]>): void;
getLocks(lockKind: LockKind, callback: ReturnCallback<Lock[]>): void;
getLocks(callback: ReturnCallback<Lock[]>): void;
setLock(lock: Lock, callback: SimpleCallback): void;
removeLock(uuid: string, owner: string, callback: ReturnCallback<boolean>): void;
canRemoveLock(uuid: string, owner: string, callback: ReturnCallback<boolean>): void;
removeLock(uuid: string, callback: ReturnCallback<boolean>): void;
canRemoveLock(uuid: string, callback: ReturnCallback<boolean>): void;
canLock(lockKind: LockKind, callback: ReturnCallback<boolean>): void;
getLock(uuid: string, callback: ReturnCallback<Lock>): void;
setProperty(name: string, value: ResourcePropertyValue, callback: SimpleCallback): void;
getProperty(name: string, callback: ReturnCallback<ResourcePropertyValue>): void;
removeProperty(name: string, callback: SimpleCallback): void;
Expand Down
46 changes: 12 additions & 34 deletions lib/resource/std/StandardResource.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,50 +42,28 @@ var StandardResource = (function () {
new LockKind_1.LockKind(LockScope_1.LockScope.Shared, LockType_1.LockType.Write)
]);
};
StandardResource.prototype.getLocks = function (lockKind, callback) {
callback(null, this.lockBag.getLocks(lockKind));
StandardResource.prototype.getLocks = function (callback) {
callback(null, this.lockBag.getLocks());
};
StandardResource.prototype.setLock = function (lock, callback) {
var locked = this.lockBag.setLock(lock);
this.updateLastModified();
callback(locked ? null : new Error('Can\'t lock the resource.'));
};
StandardResource.prototype.removeLock = function (uuid, owner, callback) {
this.getChildren(function (e, children) {
if (e) {
callback(e, false);
return;
}
var nb = children.length + 1;
children.forEach(function (child) {
child.canRemoveLock(uuid, owner, go);
});
go(null, true);
function go(e, can) {
if (e) {
nb = -1;
callback(e, false);
return;
}
if (!can) {
nb = -1;
callback(null, false);
return;
}
--nb;
if (nb === 0) {
this.lockBag.removeLock(uuid, owner);
this.updateLastModified();
callback(null, true);
}
}
});
StandardResource.prototype.removeLock = function (uuid, callback) {
this.lockBag.removeLock(uuid);
this.updateLastModified();
callback(null, true);
};
StandardResource.prototype.canRemoveLock = function (uuid, owner, callback) {
callback(null, this.lockBag.canRemoveLock(uuid, owner));
StandardResource.prototype.canRemoveLock = function (uuid, callback) {
callback(null, this.lockBag.canRemoveLock(uuid));
};
StandardResource.prototype.canLock = function (lockKind, callback) {
callback(null, this.lockBag.canLock(lockKind));
};
StandardResource.prototype.getLock = function (uuid, callback) {
callback(null, this.lockBag.getLock(uuid));
};
StandardResource.prototype.setProperty = function (name, value, callback) {
this.properties[name] = value;
this.updateLastModified();
Expand Down
10 changes: 9 additions & 1 deletion lib/server/MethodCallArgs.d.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
/// <reference types="node" />
import { BasicPrivilege } from '../user/privilege/IPrivilegeManager';
import { IResource, ReturnCallback } from '../resource/Resource';
import { XMLElement } from '../helper/XML';
import { WebDAVServer } from '../server/WebDAVServer';
import { FSPath } from '../manager/FSManager';
import { IUser } from '../user/IUser';
import * as http from 'http';
export declare class MethodCallArgs {
server: WebDAVServer;
request: http.IncomingMessage;
response: http.ServerResponse;
exit: () => void;
callback: () => void;
contentLength: number;
depth: number;
host: string;
path: FSPath;
uri: string;
data: string;
constructor(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, callback: () => void);
user: IUser;
protected constructor(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, exit: () => void, callback: () => void);
static create(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, callback: (error: Error, mca: MethodCallArgs) => void): void;
requireCustomPrivilege(privileges: string | string[], resource: IResource, callback: () => void): void;
requirePrivilege(privileges: BasicPrivilege | BasicPrivilege[], resource: IResource, callback: () => void): void;
askForAuthentication(checkForUser: boolean, callback: (error: Error) => void): void;
accept(regex: RegExp[]): number;
findHeader(name: string, defaultValue?: string): string;
getResource(callback: ReturnCallback<IResource>): void;
Expand Down
52 changes: 51 additions & 1 deletion lib/server/MethodCallArgs.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var IPrivilegeManager_1 = require("../user/privilege/IPrivilegeManager");
var XML_1 = require("../helper/XML");
var HTTPCodes_1 = require("./HTTPCodes");
var FSManager_1 = require("../manager/FSManager");
var Errors_1 = require("../Errors");
var http = require("http");
var url = require("url");
var MethodCallArgs = (function () {
function MethodCallArgs(server, request, response, callback) {
function MethodCallArgs(server, request, response, exit, callback) {
this.server = server;
this.request = request;
this.response = response;
this.exit = exit;
this.callback = callback;
this.contentLength = parseInt(this.findHeader('Content-length', '0'), 10);
this.depth = parseInt(this.findHeader('Depth', '0'), 10);
this.host = this.findHeader('Host');
this.uri = url.parse(request.url).pathname;
this.path = new FSManager_1.FSPath(this.uri);
}
MethodCallArgs.create = function (server, request, response, callback) {
var mca = new MethodCallArgs(server, request, response, null, null);
mca.askForAuthentication(false, function (e) {
if (e) {
callback(e, mca);
return;
}
server.httpAuthentication.getUser(mca, server.userManager, function (e, user) {
mca.user = user;
if (e) {
if (e === Errors_1.Errors.MissingAuthorisationHeader)
e = null;
}
callback(e, mca);
});
});
};
MethodCallArgs.prototype.requireCustomPrivilege = function (privileges, resource, callback) {
var _this = this;
IPrivilegeManager_1.requirePrivilege(privileges, this, resource, function (e, can) {
if (e) {
_this.setCode(HTTPCodes_1.HTTPCodes.InternalServerError);
_this.exit();
return;
}
if (!can) {
_this.setCode(HTTPCodes_1.HTTPCodes.Unauthorized);
_this.exit();
return;
}
callback();
});
};
MethodCallArgs.prototype.requirePrivilege = function (privileges, resource, callback) {
this.requireCustomPrivilege(privileges, resource, callback);
};
MethodCallArgs.prototype.askForAuthentication = function (checkForUser, callback) {
if (checkForUser && this.user !== null && !this.user.isDefaultUser) {
callback(new Error('Already authenticated'));
return;
}
var auth = this.server.httpAuthentication.askForAuthentication();
for (var name_1 in auth)
this.response.setHeader(name_1, auth[name_1]);
callback(null);
};
MethodCallArgs.prototype.accept = function (regex) {
var accepts = this.findHeader('Accept', 'text/xml').split(',');
for (var _i = 0, accepts_1 = accepts; _i < accepts_1.length; _i++) {
Expand Down
11 changes: 8 additions & 3 deletions lib/server/WebDAVServer.d.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
/// <reference types="node" />
import { WebDAVServerOptions } from './WebDAVServerOptions';
import { MethodCallArgs, WebDAVRequest } from './WebDAVRequest';
import { IResource, ReturnCallback } from '../resource/Resource';
import { WebDAVServerOptions } from './WebDAVServerOptions';
import { HTTPAuthentication } from '../user/authentication/HTTPAuthentication';
import { IPrivilegeManager } from '../user/privilege/IPrivilegeManager';
import { FSPath } from '../manager/FSManager';
import { IUserManager } from '../user/IUserManager';
import * as http from 'http';
export { WebDAVServerOptions } from './WebDAVServerOptions';
export declare class WebDAVServer {
httpAuthentication: HTTPAuthentication;
privilegeManager: IPrivilegeManager;
rootResource: IResource;
userManager: IUserManager;
options: WebDAVServerOptions;
methods: object;
protected beforeManagers: WebDAVRequest[];
protected afterManagers: WebDAVRequest[];
protected unknownMethod: WebDAVRequest;
protected options: WebDAVServerOptions;
protected server: http.Server;
constructor(options?: WebDAVServerOptions);
getResourceFromPath(path: FSPath | string[] | string, callback: ReturnCallback<IResource>): any;
Expand All @@ -22,7 +28,6 @@ export declare class WebDAVServer {
method(name: string, manager: WebDAVRequest): void;
beforeRequest(manager: WebDAVRequest): void;
afterRequest(manager: WebDAVRequest): void;
protected createMethodCallArgs(req: http.IncomingMessage, res: http.ServerResponse): MethodCallArgs;
protected normalizeMethodName(method: string): string;
protected invokeBARequest(collection: WebDAVRequest[], base: MethodCallArgs, callback: any): void;
protected invokeBeforeRequest(base: MethodCallArgs, callback: any): void;
Expand Down
75 changes: 43 additions & 32 deletions lib/server/WebDAVServer.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var WebDAVServerOptions_1 = require("./WebDAVServerOptions");
var WebDAVRequest_1 = require("./WebDAVRequest");
var Resource_1 = require("../resource/Resource");
var FSManager_1 = require("../manager/FSManager");
var Errors_1 = require("../Errors");
var Commands_1 = require("./commands/Commands");
var http = require("http");
var WebDAVServerOptions_1 = require("./WebDAVServerOptions");
exports.WebDAVServerOptions = WebDAVServerOptions_1.WebDAVServerOptions;
var WebDAVServerOptions_2 = require("./WebDAVServerOptions");
exports.WebDAVServerOptions = WebDAVServerOptions_2.WebDAVServerOptions;
var WebDAVServer = (function () {
function WebDAVServer(options) {
this.beforeManagers = [];
this.rootResource = new Resource_1.RootResource();
this.afterManagers = [];
this.methods = {};
this.options = options;
this.options = WebDAVServerOptions_1.setDefaultServerOptions(options);
this.httpAuthentication = this.options.httpAuthentication;
this.privilegeManager = this.options.privilegeManager;
this.rootResource = this.options.rootResource;
this.userManager = this.options.userManager;
for (var k in Commands_1.default)
if (k === 'NotImplemented')
this.onUnknownMethod(Commands_1.default[k]);
Expand Down Expand Up @@ -78,32 +82,42 @@ var WebDAVServer = (function () {
var method = _this.methods[_this.normalizeMethodName(req.method)];
if (!method)
method = _this.unknownMethod;
var base = _this.createMethodCallArgs(req, res);
if (!method.chunked) {
var data_1 = '';
var go_1 = function () {
base.data = data_1;
_this.invokeBeforeRequest(base, function () {
method(base, function () {
res.end();
_this.invokeAfterRequest(base, null);
});
});
};
if (base.contentLength === 0) {
go_1();
WebDAVRequest_1.MethodCallArgs.create(_this, req, res, function (e, base) {
if (e) {
if (e === Errors_1.Errors.AuenticationPropertyMissing)
base.setCode(WebDAVRequest_1.HTTPCodes.Unauthorized);
else
base.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
res.end();
return;
}
else {
req.on('data', function (chunk) {
data_1 += chunk.toString();
if (data_1.length >= base.contentLength) {
if (data_1.length > base.contentLength)
data_1 = data_1.substring(0, base.contentLength);
go_1();
}
});
if (!method.chunked) {
var data_1 = '';
var go_1 = function () {
base.data = data_1;
_this.invokeBeforeRequest(base, function () {
base.exit = function () {
res.end();
_this.invokeAfterRequest(base, null);
};
method(base, base.exit);
});
};
if (base.contentLength === 0) {
go_1();
}
else {
req.on('data', function (chunk) {
data_1 += chunk.toString();
if (data_1.length >= base.contentLength) {
if (data_1.length > base.contentLength)
data_1 = data_1.substring(0, base.contentLength);
go_1();
}
});
}
}
}
});
});
this.server.listen(port);
};
Expand All @@ -124,9 +138,6 @@ var WebDAVServer = (function () {
WebDAVServer.prototype.afterRequest = function (manager) {
this.afterManagers.push(manager);
};
WebDAVServer.prototype.createMethodCallArgs = function (req, res) {
return new WebDAVRequest_1.MethodCallArgs(this, req, res, null);
};
WebDAVServer.prototype.normalizeMethodName = function (method) {
return method.toLowerCase();
};
Expand Down
11 changes: 11 additions & 0 deletions lib/server/WebDAVServerOptions.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import { HTTPAuthentication } from '../user/authentication/HTTPAuthentication';
import { IPrivilegeManager } from '../user/privilege/IPrivilegeManager';
import { IUserManager } from '../user/IUserManager';
import { IResource } from '../resource/IResource';
export declare class WebDAVServerOptions {
requireAuthentification?: boolean;
httpAuthentication?: HTTPAuthentication;
privilegeManager?: IPrivilegeManager;
rootResource?: IResource;
userManager?: IUserManager;
lockTimeout?: number;
port?: number;
}
export default WebDAVServerOptions;
export declare function setDefaultServerOptions(options: WebDAVServerOptions): WebDAVServerOptions;
20 changes: 20 additions & 0 deletions lib/server/WebDAVServerOptions.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var HTTPBasicAuthentication_1 = require("../user/authentication/HTTPBasicAuthentication");
var FakePrivilegeManager_1 = require("../user/privilege/FakePrivilegeManager");
var SimpleUserManager_1 = require("../user/simple/SimpleUserManager");
var RootResource_1 = require("../resource/std/RootResource");
var WebDAVServerOptions = (function () {
function WebDAVServerOptions() {
this.requireAuthentification = false;
this.httpAuthentication = new HTTPBasicAuthentication_1.HTTPBasicAuthentication('default realm');
this.privilegeManager = new FakePrivilegeManager_1.FakePrivilegeManager();
this.rootResource = new RootResource_1.RootResource();
this.userManager = new SimpleUserManager_1.SimpleUserManager();
this.lockTimeout = 3600;
this.port = 1900;
}
return WebDAVServerOptions;
}());
exports.WebDAVServerOptions = WebDAVServerOptions;
exports.default = WebDAVServerOptions;
function setDefaultServerOptions(options) {
var def = new WebDAVServerOptions();
if (!options)
return def;
for (var name_1 in def)
if (options[name_1] === undefined)
options[name_1] = def[name_1];
return options;
}
exports.setDefaultServerOptions = setDefaultServerOptions;
Loading

0 comments on commit 5e7325a

Please sign in to comment.