Skip to content

Commit 4220d66

Browse files
Redirect to original url after account creation
1 parent fa20647 commit 4220d66

File tree

7 files changed

+113
-147
lines changed

7 files changed

+113
-147
lines changed

lib/api/accounts/user-accounts.js

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,33 +31,6 @@ function checkAccountExists (accountManager) {
3131
}
3232
}
3333

34-
/**
35-
* Returns an Express middleware handler for creating a new user account
36-
* (POST /api/accounts/new).
37-
*
38-
* @param accountManager {AccountManager}
39-
*
40-
* @return {Function}
41-
*/
42-
function createAccount (accountManager) {
43-
return (req, res, next) => {
44-
let request
45-
46-
try {
47-
request = CreateAccountRequest.fromParams(req, res, accountManager)
48-
} catch (err) {
49-
err.status = err.status || 400
50-
return next(err)
51-
}
52-
53-
return request.createAccount()
54-
.catch(err => {
55-
err.status = err.status || 400
56-
next(err)
57-
})
58-
}
59-
}
60-
6134
/**
6235
* Returns an Express middleware handler for intercepting any GET requests
6336
* for first time users (in single user mode), and redirecting them to the
@@ -132,7 +105,8 @@ function middleware (accountManager) {
132105
})
133106
}
134107

135-
router.post('/api/accounts/new', bodyParser, createAccount(accountManager))
108+
router.post('/api/accounts/new', bodyParser, CreateAccountRequest.post)
109+
router.get(['/register', '/api/accounts/new'], CreateAccountRequest.get)
136110

137111
router.post('/api/accounts/cert', bodyParser, newCertificate(accountManager))
138112

@@ -142,7 +116,6 @@ function middleware (accountManager) {
142116
module.exports = {
143117
middleware,
144118
checkAccountExists,
145-
createAccount,
146119
firstTimeSignupRedirect,
147120
newCertificate
148121
}

lib/api/authn/webid-oidc.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
const express = require('express')
77
const debug = require('../../debug')
88
const util = require('../../utils')
9-
const url = require('url')
109
const error = require('../../http-error')
1110
const bodyParser = require('body-parser').urlencoded({ extended: false })
1211

@@ -44,11 +43,6 @@ function middleware (oidc) {
4443
router.get(['/login', '/signin'], LoginByPasswordRequest.get)
4544
router.post(['/login', '/signin'], bodyParser, LoginByPasswordRequest.post)
4645

47-
router.get('/register', (req, res) => {
48-
let params = Object.assign({}, req.query, { authParams: url.parse(req.url).query })
49-
res.render('account/register', params)
50-
})
51-
5246
router.get('/goodbye', (req, res) => {
5347
res.render('auth/goodbye')
5448
})

lib/requests/create-account-request.js

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ const WebIdTlsCertificate = require('../models/webid-tls-certificate')
44
const debug = require('../debug').accounts
55

66
/**
7-
* Represents a 'create new user account' http request (a POST to the
8-
* `/accounts/api/new` endpoint).
7+
* Represents a 'create new user account' http request (either a POST to the
8+
* `/accounts/api/new` endpoint, or a GET to `/register`).
99
*
1010
* Intended just for browser-based requests; to create new user accounts from
1111
* a command line, use the `AccountManager` class directly.
@@ -23,12 +23,15 @@ class CreateAccountRequest {
2323
* @param [options.userAccount] {UserAccount}
2424
* @param [options.session] {Session} e.g. req.session
2525
* @param [options.response] {HttpResponse}
26+
* @param [options.returnToUrl] {string} If present, redirect the agent to
27+
* this url on successful account creation
2628
*/
2729
constructor (options) {
2830
this.accountManager = options.accountManager
2931
this.userAccount = options.userAccount
3032
this.session = options.session
3133
this.response = options.response
34+
this.returnToUrl = options.returnToUrl
3235
}
3336

3437
/**
@@ -37,33 +40,35 @@ class CreateAccountRequest {
3740
*
3841
* @param req
3942
* @param res
40-
* @param accountManager {AccountManager}
4143
*
4244
* @throws {Error} If required parameters are missing (via
4345
* `userAccountFrom()`), or it encounters an unsupported authentication
4446
* scheme.
4547
*
4648
* @return {CreateAccountRequest|CreateTlsAccountRequest}
4749
*/
48-
static fromParams (req, res, accountManager) {
49-
if (!req.app || !req.app.locals) {
50-
throw new Error('Missing req.app.local params')
50+
static fromParams (req, res) {
51+
if (!req.body.username) {
52+
throw new Error('Username required to create an account')
5153
}
5254

53-
let authMethod = req.app.locals.authMethod
55+
let locals = req.app.locals
56+
let accountManager = locals.accountManager
57+
let authMethod = locals.authMethod
58+
let returnToUrl = CreateAccountRequest.parseReturnUrl(req)
5459
let userAccount = accountManager.userAccountFrom(req.body)
5560

5661
let options = {
5762
accountManager,
5863
userAccount,
5964
session: req.session,
60-
response: res
65+
response: res,
66+
returnToUrl
6167
}
6268

6369
switch (authMethod) {
6470
case 'oidc':
6571
options.password = req.body.password
66-
let locals = req.app.locals
6772
options.userStore = locals.oidc.users
6873
return new CreateOidcAccountRequest(options)
6974
case 'tls':
@@ -74,6 +79,48 @@ class CreateAccountRequest {
7479
}
7580
}
7681

82+
static renderView (response, returnToUrl, error) {
83+
let params = { returnToUrl }
84+
85+
if (error) {
86+
response.status(error.statusCode || 400)
87+
params.error = error.message
88+
}
89+
90+
response.render('account/register', params)
91+
}
92+
93+
static parseReturnUrl (req) {
94+
let body = req.body || {}
95+
if (body.returnToUrl) { return req.body.returnToUrl }
96+
97+
if (req.query && req.query.returnToUrl) { return req.query.returnToUrl }
98+
99+
return null
100+
}
101+
102+
static post (req, res) {
103+
let request
104+
let returnToUrl = req.body.returnToUrl
105+
106+
try {
107+
request = CreateAccountRequest.fromParams(req, res)
108+
} catch (error) {
109+
return CreateAccountRequest.renderView(res, returnToUrl, error)
110+
}
111+
112+
return request.createAccount()
113+
.catch(error => {
114+
CreateAccountRequest.renderView(res, returnToUrl, error)
115+
})
116+
}
117+
118+
static get (req, res) {
119+
let returnToUrl = req.query.returnToUrl
120+
121+
CreateAccountRequest.renderView(res, returnToUrl)
122+
}
123+
77124
/**
78125
* Creates an account for a given user (from a POST to `/api/accounts/new`)
79126
*
@@ -150,11 +197,6 @@ class CreateAccountRequest {
150197
})
151198
}
152199

153-
error (error) {
154-
// Default error handler, to be overriden in subclasses
155-
throw error
156-
}
157-
158200
/**
159201
* Initializes the session with the newly created user's credentials
160202
*
@@ -200,13 +242,6 @@ class CreateOidcAccountRequest extends CreateAccountRequest {
200242
this.userStore = options.userStore
201243
}
202244

203-
error (error) {
204-
let res = this.response
205-
let params = Object.assign({}, this.authQueryParams, { error: error.message })
206-
res.statusCode(error.statusCode || 400)
207-
res.render('auth/login', params)
208-
}
209-
210245
/**
211246
* Generate salted password hash, etc.
212247
*
@@ -223,8 +258,9 @@ class CreateOidcAccountRequest extends CreateAccountRequest {
223258
}
224259

225260
sendResponse (userAccount) {
226-
let res = this.response
227-
res.sendStatus(201)
261+
let redirectUrl = this.returnToUrl ||
262+
this.accountManager.accountUriFor(userAccount.username)
263+
this.response.redirect(redirectUrl)
228264
}
229265
}
230266

test/integration/account-creation-oidc.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ describe('AccountManager (OIDC account creation tests)', function () {
9090
var subdomain = supertest('https://nicola.' + host)
9191
subdomain.post('/api/accounts/new')
9292
.send('username=nicola&password=12345')
93-
.expect(201)
93+
.expect(302)
9494
.end((err, res) => {
9595
if (err) {
9696
return done(err)
@@ -102,13 +102,13 @@ describe('AccountManager (OIDC account creation tests)', function () {
102102
done(err)
103103
})
104104
})
105-
}).timeout(20000)
105+
})
106106

107107
it('should create the default folders', function (done) {
108108
var subdomain = supertest('https://nicola.' + host)
109109
subdomain.post('/api/accounts/new')
110110
.send('username=nicola&password=12345')
111-
.expect(201)
111+
.expect(302)
112112
.end(function (err) {
113113
if (err) {
114114
return done(err)
@@ -139,7 +139,7 @@ describe('AccountManager (OIDC account creation tests)', function () {
139139
var subdomain = supertest('https://nicola.' + host)
140140
subdomain.post('/api/accounts/new')
141141
.send('username=nicola&password=12345')
142-
.expect(201)
142+
.expect(302)
143143
.end(function (err) {
144144
if (err) {
145145
return done(err)

test/unit/add-cert-request.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ describe('AddCertificateRequest', () => {
111111
expect(graph.anyStatementMatching(key, ns.cert('exponent')))
112112
.to.exist
113113
})
114-
})
114+
}).timeout(3000)
115115
})
116116
})
117117

0 commit comments

Comments
 (0)