Skip to content

Commit 76f98e0

Browse files
author
Martin Martinez Rivera
committed
Merge branch 'master' of https://github.com/martinmr/node-ldp-httpd into martinmr-master
Conflicts: .gitignore Makefile package.json server.js
2 parents 6035175 + bfe7b31 commit 76f98e0

20 files changed

Lines changed: 1424 additions & 548 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules/
22
*~
3+
*.swp

Makefile

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
2-
31
# see also JSON validator http://jsonformatter.curiousconcept.com for the package.json file
42

53
run-for-test:
6-
node server.js -p 3456 -v --uriBase http://localhost:3456/test/ --fileBase `pwd`/test
4+
node server.js -p 3456 -v --uriBase http://localhost:3456/test/ --fileBase `pwd`/test/
75

86
run-for-live-test:
97
NODE_PATH=.:../tabulator-firefox/content/js/rdf/dist/ node server.js \
@@ -13,13 +11,9 @@ run-for-test-special:
1311
NODE_PATH=.:../tabulator-firefox/content/js/rdf/dist/ node server.js \
1412
-p 3456 -v --uriBase http://localhost:3456/test/ --fileBase `pwd`/test/
1513

16-
# use --debug to run or --debug-brk to break immediately
14+
# use --debug to run or --debug-brk to break immediately
1715
run-for-test-special-debug:
1816
NODE_PATH=.:../tabulator-firefox/content/js/rdf/dist/ node --debug-brk server.js \
1917
-p 3456 -v --uriBase http://localhost:3456/test/ --fileBase `pwd`/test/
2018
# Then run node-inspector and open Chrome as it suggests
2119
# (If necessary, npm install -g node-inspector)
22-
23-
24-
25-

acl.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
var acl = require('acl');
2+
var fs = require('fs');
3+
var path = require('path');
4+
5+
var file = require('./fileStore.js');
6+
var options = require('./options.js');
7+
8+
var permissionExtension = '.permissions';
9+
var aclEnabled = false;
10+
11+
module.exports.readPermissions = function() {
12+
var permissionFile = options.fileBase + permissionExtension;
13+
fs.readFile(permissionFile, readPermissionsCallback);
14+
15+
function readPermissionsCallback(err, rawPermissions) {
16+
if (err) {
17+
return;
18+
} else {
19+
var jsonPermissions;
20+
try {
21+
jsonPermissions = JSON.parse(rawPermissions);
22+
} catch (parseErr) {
23+
return;
24+
}
25+
if ('roles' in jsonPermissions && 'users' in jsonPermissions) {
26+
try {
27+
acl = new acl(new acl.memoryBackend());
28+
for (var rIndex = 0; rIndex < jsonPermissions.roles.length; rIndex++) {
29+
acl.allow(jsonPermissions.roles[rIndex][0],
30+
jsonPermissions.roles[rIndex][1],
31+
jsonPermissions.roles[rIndex][2]);
32+
}
33+
for (var uIndex = 0; uIndex < jsonPermissions.users.length; uIndex++) {
34+
acl.addUserRoles(jsonPermissions.users[uIndex][0],
35+
jsonPermissions.users[uIndex][1]);
36+
}
37+
aclEnabled = true;
38+
return;
39+
} catch (permissionErr) {
40+
return;
41+
}
42+
} else {
43+
return;
44+
}
45+
}
46+
}
47+
};
48+
49+
module.exports.isAllowed = function(userId, resource, permissions, callback) {
50+
if (aclEnabled) {
51+
acl.isAllowed(userId, resource, permissions, callback);
52+
} else {
53+
callback(undefined, true);
54+
}
55+
};
56+
57+
module.exports.aclHandler = function(req, res, next) {
58+
//TODO authentication
59+
var filename = file.uriToFilename(req.path);
60+
var resource = path.relative(options.fileBase, filename);
61+
62+
//TODO complete this line
63+
// acl.isAllowed(userId, resource, req.method);
64+
next();
65+
66+
function aclCallback(err, allowed) {
67+
if (err) {
68+
return res.sendStatus(500);
69+
} else {
70+
if (allowed) {
71+
next();
72+
} else {
73+
return res.sendStatus(403);
74+
}
75+
}
76+
77+
}
78+
};

container.js

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
var fs = require('fs');
2+
var $rdf = require('rdflib');
3+
var path = require('path');
4+
var uuid = require('node-uuid');
5+
6+
var logging = require('./logging.js');
7+
var metadata = require('./metadata.js');
8+
var options = require('./options.js');
9+
10+
var rdfVocab = require('./vocab/rdf.js');
11+
var ldpVocab = require('./vocab/ldp.js');
12+
13+
var addUriTriple = function(kb, s, o, p) {
14+
kb.add(kb.sym(s), kb.sym(o), kb.sym(p));
15+
};
16+
17+
var usedURIs = {};
18+
19+
module.exports.createRootContainer = function() {
20+
if (!metadata.hasMetadata(options.fileBase)) {
21+
logging.log("Creating root metadata");
22+
var rootMetadata = new metadata.Metadata();
23+
rootMetadata.filename = options.fileBase;
24+
rootMetadata.isResource = true;
25+
rootMetadata.isContainer = true;
26+
rootMetadata.isSourceResource = true;
27+
rootMetadata.isBasicContainer = true;
28+
metadata.writeMetadata(options.fileBase, rootMetadata,
29+
writeCallback);
30+
}
31+
//TODO handle case when .container file does not exist
32+
33+
function writeCallback(err) {
34+
logging.log(options.pathStart);
35+
if (err) {
36+
process.exit(1);
37+
} else if (!metadata.hasContainerMetadata(options.fileBase)) {
38+
var rootContainer = $rdf.graph();
39+
addUriTriple(rootContainer, options.pathStart, rdfVocab.type,
40+
ldpVocab.Resource);
41+
addUriTriple(rootContainer, options.pathStart, rdfVocab.type,
42+
ldpVocab.RDFSource);
43+
addUriTriple(rootContainer, options.pathStart, rdfVocab.type,
44+
ldpVocab.Container);
45+
addUriTriple(rootContainer, options.pathStart, rdfVocab.type,
46+
ldpVocab.BasicContainer);
47+
rootContainer.add(rootContainer.sym(options.pathStart),
48+
rootContainer.sym('http://purl.org/dc/terms/title'),
49+
'"Root Container"');
50+
var serializedContainer = $rdf.serialize(undefined, rootContainer,
51+
options.pathStart, 'text/turtle');
52+
logging.log("Root container: ", serializedContainer);
53+
metadata.writeContainerMetadata(options.fileBase,
54+
serializedContainer, function(err) {
55+
if (err) {
56+
//TODO handle error
57+
logging.log("Could not write root container");
58+
} else {
59+
logging.log("Wrote root container to " + options.fileBase);
60+
}
61+
});
62+
}
63+
}
64+
};
65+
66+
module.exports.createNewContainer = function(container, type, callback) {
67+
fs.mkdir(container, function(err) {
68+
if (err) {
69+
this.releaseResourceUri(container);
70+
callback(err);
71+
} else {
72+
var containerMetadata = new metadata.Metadata();
73+
containerMetadata.filename = container;
74+
containerMetadata.isResource = true;
75+
containerMetadata.isContainer = true;
76+
containerMetadata.isSourceResource = true;
77+
if (type === ldpVocab.BasicContainer)
78+
containerMetadata.isBasicContainer = true;
79+
if (type === ldpVocab.DirectContainer)
80+
containerMetadata.isDirectContainer = true;
81+
metadata.writeMetadata(options.fileBase, rootMetadata, writeCallback);
82+
}
83+
});
84+
85+
function writeCallback(err) {
86+
if (err) {
87+
this.releaseResourceUri(container);
88+
callback(err);
89+
} else {
90+
var newContainer = $rdf.graph();
91+
addUriTriple(newContainer, options.pathStart, rdfVocab.type,
92+
ldpVocab.Resource);
93+
addUriTriple(newContainer, options.pathStart, rdfVocab.type,
94+
ldpVocab.RDFSource);
95+
addUriTriple(newContainer, options.pathStart, rdfVocab.type,
96+
ldpVocab.Container);
97+
if (type === ldpVocab.BasicContainer)
98+
addUriTriple(newContainer, options.pathStart, rdfVocab.type,
99+
ldpVocab.BasicContainer);
100+
else if (type === ldpVocab.DirectContainer)
101+
addUriTriple(newContainer, options.pathStart, rdfVocab.type,
102+
ldpVocab.DirectContainer);
103+
104+
newContainer.add(newContainer.sym(options.pathStart),
105+
newContainer.sym('http://purl.org/dc/terms/title'),
106+
container);
107+
var serializedContainer = $rdf.serialize(undefined, newContainer,
108+
container, 'text/turtle');
109+
metadata.writeContainerMetadata(container, serializedContainer,
110+
function(err) {
111+
this.releaseResourceUri(container);
112+
if (err) {
113+
callback(err);
114+
} else {
115+
logging.log("Wrote new container");
116+
callback(err);
117+
}
118+
});
119+
}
120+
}
121+
122+
};
123+
124+
module.exports.createResourceUri = function(containerURI, slug) {
125+
var newPath;
126+
if (slug) {
127+
newPath = path.join(containerURI, slug);
128+
} else {
129+
newPath = path.join(containerURI, uuid.v1());
130+
}
131+
if (!(fs.existsSync(newPath) || containerURI in usedURIs)) {
132+
usedURIs[newPath] = true;
133+
} else {
134+
return null;
135+
}
136+
return newPath;
137+
};
138+
139+
module.exports.releaseResourceUri = function(uri) {
140+
delete usedURIs[uri];
141+
};
142+
143+
module.exports.verify = function(containerGraph, type) {
144+
//TODO work on this method
145+
var results = containerGraph.each(undefined, "a", type);
146+
if (results.length === 1) {
147+
return true;
148+
} else {
149+
return false;
150+
}
151+
};
152+
153+
module.exports.verifyDirectContainer = function(containerGraph) {
154+
155+
};
156+
157+
module.exports.createNewResource = function(containerPath, containerGraph,
158+
resourcePath, resourceGraph, resourceMetadata, callback) {
159+
var containerURI = path.relative(options.fileBase, containerPath);
160+
var resourceURI = path.relative(options.fileBase, resourcePath);
161+
//TODO replace url with resource url
162+
var rawResource = $rdf.serialize(undefined,
163+
resourceGraph, options.baseUri + resourceURI, 'text/turtle');
164+
logging.log("Writing new resource to ", resourcePath);
165+
logging.log(rawResource);
166+
fs.writeFile(resourcePath, rawResource, writeResourceCallback);
167+
168+
function writeResourceCallback(err) {
169+
if (err) {
170+
container.releaseResourceUri(resoucePath);
171+
callback(err);
172+
} else {
173+
addUriTriple(containerGraph, containerURI, ldpVocab.contains,
174+
resourceURI);
175+
var rawContainer = $rdf.serialize(undefined, containerGraph,
176+
options.uriBase, 'text/turtle');
177+
metadata.writeContainerMetadata(containerPath, rawContainer,
178+
writeContainerCallback);
179+
}
180+
}
181+
182+
function writeContainerCallback(err) {
183+
if (err) {
184+
module.exports.releaseResourceUri(resourcePath);
185+
return callback(err);
186+
} else {
187+
metadata.writeMetadata(resourcePath, resourceMetadata,
188+
writeMetadataCallback);
189+
}
190+
}
191+
192+
function writeMetadataCallback(err) {
193+
module.exports.releaseResourceUri(resourcePath);
194+
return callback(err);
195+
}
196+
};
197+
198+
module.exports.createNewContainer = function(containerPath, containerGraph,
199+
containerMetadata, callback) {
200+
fs.mkdir(containerPath, mkdirCallback);
201+
202+
function mkdirCallback(err) {
203+
if (err) {
204+
module.exports.releaseResourceUri(containerPath);
205+
return callback(err);
206+
} else {
207+
var rawContainer = $rdf.serialize(undefined, containerGraph,
208+
options.uriBase, 'text/turtle');
209+
metadata.writeContainerMetadata(containerPath, rawContainer,
210+
writeContainerCallback);
211+
}
212+
}
213+
214+
function writeContainerCallback(err) {
215+
if (err) {
216+
module.exports.releaseResourceUri(containerPath);
217+
return callback(err);
218+
} else {
219+
metadata.writeMetadata(containerPath, containerMetadata,
220+
writeMetadataCallback);
221+
}
222+
}
223+
224+
function writeMetadataCallback(err) {
225+
module.exports.releaseResourceUri(containerPath);
226+
return callback(err);
227+
}
228+
};

fileStore.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
var path = require('path');
2+
3+
var options = require('./options.js');
4+
var logging = require('./logging.js');
5+
6+
module.exports.uriToFilename = function(uri) {
7+
//if (uri.slice(0, options.pathStart.length) !== options.pathStart) {
8+
//throw "Path '" + uri + "'not starting with base '" + options.pathStart + "'.";
9+
//}
10+
//var filename = options.fileBase + uri.slice(options.pathStart.length);
11+
var filename = path.join(options.fileBase, uri);
12+
logging.log(' -- filename ' +filename);
13+
return filename;
14+
};

handlers/delete.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
var fs = require('fs');
2+
3+
var file = require('../fileStore.js');
4+
var logging = require('../logging.js');
5+
var metadata = require('../metadata.js');
6+
7+
module.exports.handler = function(req, res) {
8+
logging.log('DELETE -- ' + req.path);
9+
// res.header('MS-Author-Via' , 'SPARQL' );
10+
var filename = file.uriToFilename(req.path);
11+
fs.stat(filename, function(err, stats) {
12+
if (err) {
13+
logging.log(" ### DELETE unlink() error: " + err);
14+
return res.status(404).send("Can't delete file: " + err);
15+
} else if (stats.isDirectory()) {
16+
if (filename.charAt(filename.length - 1) !== '/')
17+
filename += '/';
18+
metadata.deleteContainerMetadata(filename, containerCallback);
19+
} else {
20+
fs.unlink(filename, fileCallback);
21+
}
22+
});
23+
24+
function fileCallback(err) {
25+
if (err) {
26+
logging.log(" ### DELETE unlink() error: " + err);
27+
return res.status(404).send("Can't delete file: " + err); // @@ best
28+
} else {
29+
//TODO remove file from container
30+
metadata.deleteMetadata(filename, function(err) {});
31+
logging.log(" -- delete Ok " + req.text.length);
32+
res.sendStatus(200);
33+
}
34+
}
35+
36+
function containerCallback(err) {
37+
if (err) {
38+
logging.log("DELETE unlink() error: " + err);
39+
return res.status(404).send("Can't delete container: " + err);
40+
} else {
41+
metadata.deleteMetadata(filename, function(err) {});
42+
logging.log(" -- delete Ok " + req.text.length);
43+
res.sendStatus(200);
44+
}
45+
}
46+
};

0 commit comments

Comments
 (0)