Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,3 @@ node_modules/
*.swp
.tern-port
npm-debug.log
.acl
profile/
accounts/
settings/
temp/
8 changes: 0 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,6 @@ $ ldnode --port 8443 --ssl-key path/to/ssl-key.pem --ssl-cert path/to/ssl-cert.p
# Solid server (ldnode v0.2.24) running on https://localhost:8443/
```

First time user? If you have never run `ldnode` before, let's get you a WebID to access your server.
```bash
$ ldnode --port 8443 --ssl-key path/to/ssl-key.pem --ssl-cert path/to/ssl-cert.pem --create-admin
# Action required: Create your admin account on https://localhost:8080/
# When done, stop your server (<ctrl>+c) and restart without "--create-admin"
```

If you want to run `ldnode` on a particular folder (different from the one you are in, e.g. `path/to/folder`):
```bash
$ ldnode --root path/to/folder --port 8443 --ssl-key path/to/ssl-key.pem --ssl-cert path/to/ssl-cert.pem
Expand Down Expand Up @@ -104,7 +97,6 @@ Options:
--ssl-cert Path to the SSL certificate key in PEM format
--allow-signup Allow users to register their WebID on subdomains

--create-admin Allow a user to set up their initial identity in single-user mode
--no-live Disable live support through WebSockets
--default-app URI to use as a default app for resources (default: https://linkeddata.github.io/warp/#/list/)
--proxy Use a proxy on example.tld/proxyPath
Expand Down
46 changes: 34 additions & 12 deletions bin/ldnode.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ var argv = require('nomnom')
full: 'webid',
flag: true
})
.option('owner', {
help: 'Set the owner of the storage'
})
.option('key', {
help: 'Path to the SSL private key in PEM format',
full: 'ssl-key'
Expand All @@ -42,11 +45,6 @@ var argv = require('nomnom')
full: 'allow-signup',
flag: true
})
.option('createAdmin', {
full: 'create-admin',
flag: true,
help: 'Allow a user to set up their initial identity in single-user mode'
})
.option('noLive', {
full: 'no-live',
help: 'Disable live support through WebSockets',
Expand Down Expand Up @@ -134,6 +132,35 @@ function bin (argv) {
})
}

if (argv.owner) {
var rootPath = argv.root
if (!rootPath) {
rootPath = process.cwd()
}
if (!(rootPath.endsWith('/'))) {
rootPath += '/'
}
rootPath += (argv.suffixAcl || '.acl')

var defaultAcl = `@prefix n0: <http://www.w3.org/ns/auth/acl#>.
@prefix n2: <http://xmlns.com/foaf/0.1/>.

<#owner>
a n0:Authorization;
n0:accessTo <./>;
n0:agent <${argv.owner}>;
n0:defaultForNew <./>;
n0:mode n0:Control, n0:Read, n0:Write.
<#everyone>
a n0:Authorization;
n0: n2:Agent;
n0:accessTo <./>;
n0:defaultForNew <./>;
n0:mode n0:Read.' > .acl`

fs.writeFileSync(rootPath, defaultAcl)
}

// Finally starting ldnode
var ldnode = require('../')
var app
Expand All @@ -154,13 +181,8 @@ function bin (argv) {
}
app.listen(argv.port, function () {
fs.readFile(path.resolve(__dirname, '../package.json'), 'utf-8', function (_, file) {
if (argv.createAdmin) {
console.log('Action required: Create your admin account on \u001b[4mhttps://localhost:' + argv.port + '/\u001b[0m')
console.log('When done, stop your server (<ctrl>+c) and restart without "--create-admin"')
} else {
console.log('Solid server (ldnode v' + JSON.parse(file).version + ') running on \u001b[4mhttps://localhost:' + argv.port + '/\u001b[0m')
console.log('Press <ctrl>+c to stop')
}
console.log('Solid server (ldnode v' + JSON.parse(file).version + ') running on \u001b[4mhttps://localhost:' + argv.port + '/\u001b[0m')
console.log('Press <ctrl>+c to stop')
})
})
}
Expand Down
53 changes: 44 additions & 9 deletions lib/create-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ function createApp (argv) {
var ldp = new LDP(argv)
var app = express()

// check if we have master ACL or not
var masterAcl
var checkMasterAcl = function (req, callback) {
if (masterAcl) {
return callback(true)
}

ldp.exists(req.hostname, '/' + ldp.suffixAcl, function (err) {
if (!err) {
masterAcl = true
}
callback(!err)
})
}

// Setting options as local variable
app.locals.ldp = ldp

Expand Down Expand Up @@ -63,29 +78,49 @@ function createApp (argv) {
}

// Adding Multi-user support
if (ldp.idp || ldp.createAdmin) {
if (ldp.webid) {
var idp = IdentityProvider({
store: ldp,
suffixAcl: ldp.suffixAcl,
overwrite: ldp.createAdmin,
settings: 'settings',
inbox: 'inbox'
})
app.use('/accounts', idp.middleware(corsSettings))
var needsOverwrite = function (req, res, next) {
checkMasterAcl(req, function (found) {
if (!found) {
// this allows IdentityProvider to overwrite root acls
idp.middleware(corsSettings, true)(req, res, next)
} else if (found && ldp.idp) {
idp.middleware(corsSettings)(req, res, next)
} else {
next()
}
})
}
app.use('/accounts', needsOverwrite)
app.use('/', corsSettings, idp.get.bind(idp))
}

if (ldp.idp) {
app.use(vhost('*', LdpMiddleware(corsSettings)))
}

if (ldp.createAdmin) {
app.get('/', function (req, res) {
res.set('Content-Type', 'text/html')
var signup = path.join(__dirname, '../static/signup.html')
res.sendFile(signup)
app.get('/', function (req, res, next) {
// Do not bother showing html page can't be read
if (!req.accepts('text/html') || !ldp.webid) {
return next()
}

checkMasterAcl(req, function (found) {
if (!found) {
res.set('Content-Type', 'text/html')
var signup = path.join(__dirname, '../static/signup.html')
res.sendFile(signup)
} else {
next()
}
})
}
})
app.use('/', LdpMiddleware(corsSettings))

return app
Expand Down
16 changes: 12 additions & 4 deletions lib/identity-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ function IdentityProvider (options) {
this.buildURI = options.buildURI || defaultBuildURI
this.suffixAcl = options.suffixAcl
this.defaultContainers = options.defaultContainers || defaultContainers
this.overwrite = options.overwrite
this.inbox = options.inbox
this.settings = options.settings
}
Expand Down Expand Up @@ -113,7 +112,7 @@ IdentityProvider.prototype.create = function (options, cert, callback) {
var subdomain = options.host.split(':')[0]
self.store.exists(subdomain, '/', function (err) {
// if page exists, cannot create account
if (!self.overwrite && (!err || err.status !== 404)) {
if (!options.firstUser && (!err || err.status !== 404)) {
debug('Cannot create ' + subdomain + ', it already exists')
var error = new Error('Account already exists')
error.status = 406
Expand Down Expand Up @@ -511,6 +510,7 @@ IdentityProvider.prototype.post = function (req, res, next) {
var self = this
var options = req.body
options.host = req.get('host')
options.firstUser = res.locals.firstUser
var agent = self.agent(options)
var spkac = null
var cert = null
Expand Down Expand Up @@ -558,14 +558,15 @@ IdentityProvider.prototype.post = function (req, res, next) {
}

// Middleware (or Router) to serve the IdentityProvider
IdentityProvider.prototype.middleware = function (corsSettings) {
IdentityProvider.prototype.middleware = function (corsSettings, firstUser) {
var router = express.Router('/')
var parser = bodyParser.urlencoded({ extended: false })

if (corsSettings) {
router.use(corsSettings)
}
router.post('/new', parser, this.post.bind(this))

router.post('/new', parser, setFirstUser(firstUser), this.post.bind(this))
router.post('/cert', parser, this.newCert.bind(this))
router.all('/*', function (req, res) {
var host = uriAbs(req)
Expand All @@ -576,3 +577,10 @@ IdentityProvider.prototype.middleware = function (corsSettings) {

return router
}

function setFirstUser (isFirstUser) {
return function (req, res, next) {
res.locals.firstUser = isFirstUser
next()
}
}
3 changes: 1 addition & 2 deletions static/signup.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ <h2>Finish by issuing credentials in the form of a certificate</h2>
document.getElementById('cert').style.display = 'none'
var done = document.createElement('div')
done.innerHTML = '<h2>You\'re all set!</h2>'
done.innerHTML += '<p>Please restart your server without the <strong>--create-admin</strong> parameter.</p>'
done.innerHTML += '<p>If an error occured and a certificate was not installed, please reload this page and start again.</p>'
done.innerHTML += '<p>as soon as you will reset the page, you will be logged in!</p>'
document.querySelector('body').appendChild(done)
}

Expand Down
4 changes: 4 additions & 0 deletions test/resources/acl/owner-only/.acl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<#0>
<http://www.w3.org/ns/auth/acl#defaultForNew> <./> ;
<http://www.w3.org/ns/auth/acl#agent> <https://user1.databox.me/profile/card#me> ;
<http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Write>, <http://www.w3.org/ns/auth/acl#Control>.