1- import url from 'url'
1+ import { URL } from 'url'
22import rdf from 'rdflib'
33import vocab from 'solid-namespace'
44import defaults from '../../config/defaults.mjs'
@@ -25,56 +25,57 @@ class AccountManager {
2525 this . pathCard = options . pathCard || 'profile/card'
2626 this . suffixURI = options . suffixURI || '#me'
2727 this . accountTemplatePath = options . accountTemplatePath || './default-templates/new-account/'
28- }
28+ }
2929
3030 static from ( options ) {
3131 return new AccountManager ( options )
32- }
32+ }
3333
3434 accountExists ( accountName ) {
3535 let accountUri
3636 let cardPath
3737 try {
3838 accountUri = this . accountUriFor ( accountName )
39- accountUri = url . parse ( accountUri ) . hostname
40- cardPath = url . resolve ( '/' , this . pathCard )
39+ accountUri = new URL ( accountUri ) . hostname
40+ // `pathCard` is a path fragment like 'profile/card' -> ensure it starts with '/'
41+ cardPath = this . pathCard && this . pathCard . startsWith ( '/' ) ? this . pathCard : '/' + this . pathCard
4142 } catch ( err ) {
4243 return Promise . reject ( err )
4344 }
4445 return this . accountUriExists ( accountUri , cardPath )
45- }
46+ }
4647
4748 async accountUriExists ( accountUri , accountResource = '/' ) {
4849 try {
4950 return await this . store . exists ( accountUri , accountResource )
5051 } catch ( err ) {
5152 return false
5253 }
53- }
54+ }
5455
5556 accountDirFor ( accountName ) {
56- const { hostname } = url . parse ( this . accountUriFor ( accountName ) )
57+ const { hostname } = new URL ( this . accountUriFor ( accountName ) )
5758 return this . store . resourceMapper . resolveFilePath ( hostname )
58- }
59+ }
5960
6061 accountUriFor ( accountName ) {
6162 const accountUri = this . multiuser
6263 ? this . host . accountUriFor ( accountName )
6364 : this . host . serverUri
6465 return accountUri
65- }
66+ }
6667
6768 accountWebIdFor ( accountName ) {
6869 const accountUri = this . accountUriFor ( accountName )
69- const webIdUri = url . parse ( url . resolve ( accountUri , this . pathCard ) )
70+ const webIdUri = new URL ( this . pathCard , accountUri )
7071 webIdUri . hash = this . suffixURI
71- return webIdUri . format ( )
72- }
72+ return webIdUri . toString ( )
73+ }
7374
7475 rootAclFor ( userAccount ) {
7576 const accountUri = this . accountUriFor ( userAccount . username )
76- return url . resolve ( accountUri , this . store . suffixAcl )
77- }
77+ return new URL ( this . store . suffixAcl , accountUri ) . toString ( )
78+ }
7879
7980 addCertKeyToProfile ( certificate , userAccount ) {
8081 if ( ! certificate ) {
@@ -83,7 +84,7 @@ class AccountManager {
8384 return this . getProfileGraphFor ( userAccount )
8485 . then ( profileGraph => this . addCertKeyToGraph ( certificate , profileGraph ) )
8586 . then ( profileGraph => this . saveProfileGraph ( profileGraph , userAccount ) )
86- }
87+ }
8788
8889 getProfileGraphFor ( userAccount , contentType = DEFAULT_PROFILE_CONTENT_TYPE ) {
8990 const webId = userAccount . webId
@@ -98,7 +99,7 @@ class AccountManager {
9899 error . message = `Error retrieving profile graph ${ uri } : ` + error . message
99100 throw error
100101 } )
101- }
102+ }
102103
103104 saveProfileGraph ( profileGraph , userAccount , contentType = DEFAULT_PROFILE_CONTENT_TYPE ) {
104105 const webId = userAccount . webId
@@ -109,7 +110,7 @@ class AccountManager {
109110 }
110111 const uri = userAccount . profileUri
111112 return this . store . putGraph ( profileGraph , uri , contentType )
112- }
113+ }
113114
114115 addCertKeyToGraph ( certificate , graph ) {
115116 const webId = rdf . namedNode ( certificate . webId )
@@ -127,7 +128,7 @@ class AccountManager {
127128 graph . add ( key , ns . cert ( 'modulus' ) , modulus )
128129 graph . add ( key , ns . cert ( 'exponent' ) , exponent )
129130 return graph
130- }
131+ }
131132
132133 userAccountFrom ( userData ) {
133134 const userConfig = {
@@ -164,16 +165,16 @@ class AccountManager {
164165 }
165166 }
166167 return UserAccount . from ( userConfig )
167- }
168+ }
168169
169170 usernameFromWebId ( webId ) {
170171 if ( ! this . multiuser ) {
171172 return DEFAULT_ADMIN_USERNAME
172173 }
173- const profileUrl = url . parse ( webId )
174+ const profileUrl = new URL ( webId )
174175 const hostname = profileUrl . hostname
175176 return hostname . split ( '.' ) [ 0 ]
176- }
177+ }
177178
178179 createAccountFor ( userAccount ) {
179180 const template = AccountTemplate . for ( userAccount )
@@ -182,46 +183,46 @@ class AccountManager {
182183 debug ( `Creating account folder for ${ userAccount . webId } at ${ accountDir } ` )
183184 return AccountTemplate . copyTemplateDir ( templatePath , accountDir )
184185 . then ( ( ) => template . processAccount ( accountDir ) )
185- }
186+ }
186187
187188 generateResetToken ( userAccount ) {
188189 return this . tokenService . generate ( 'reset-password' , { webId : userAccount . webId } )
189- }
190+ }
190191
191192 generateDeleteToken ( userAccount ) {
192193 return this . tokenService . generate ( 'delete-account.mjs' , {
193194 webId : userAccount . webId ,
194195 email : userAccount . email
195196 } )
196- }
197+ }
197198
198199 validateDeleteToken ( token ) {
199200 const tokenValue = this . tokenService . verify ( 'delete-account.mjs' , token )
200201 if ( ! tokenValue ) {
201202 throw new Error ( 'Invalid or expired delete account token' )
202203 }
203204 return tokenValue
204- }
205+ }
205206
206207 validateResetToken ( token ) {
207208 const tokenValue = this . tokenService . verify ( 'reset-password' , token )
208209 if ( ! tokenValue ) {
209210 throw new Error ( 'Invalid or expired reset token' )
210211 }
211212 return tokenValue
212- }
213+ }
213214
214215 passwordResetUrl ( token , returnToUrl ) {
215- let resetUrl = url . resolve ( this . host . serverUri , `/account/password/change?token=${ token } ` )
216+ let resetUrl = new URL ( `/account/password/change?token=${ token } ` , this . host . serverUri ) . toString ( )
216217 if ( returnToUrl ) {
217218 resetUrl += `&returnToUrl=${ returnToUrl } `
218219 }
219220 return resetUrl
220- }
221+ }
221222
222223 getAccountDeleteUrl ( token ) {
223- return url . resolve ( this . host . serverUri , `/account/delete/confirm?token=${ token } ` )
224- }
224+ return new URL ( `/account/delete/confirm?token=${ token } ` , this . host . serverUri ) . toString ( )
225+ }
225226
226227 loadAccountRecoveryEmail ( userAccount ) {
227228 return Promise . resolve ( )
@@ -237,7 +238,7 @@ class AccountManager {
237238 }
238239 return recoveryMailto
239240 } )
240- }
241+ }
241242
242243 verifyEmailDependencies ( userAccount ) {
243244 if ( ! this . emailService ) {
@@ -246,7 +247,7 @@ class AccountManager {
246247 if ( userAccount && ! userAccount . email ) {
247248 throw new Error ( 'Account recovery email has not been provided' )
248249 }
249- }
250+ }
250251
251252 sendDeleteAccountEmail ( userAccount ) {
252253 return Promise . resolve ( )
@@ -261,7 +262,7 @@ class AccountManager {
261262 }
262263 return this . emailService . sendWithTemplate ( 'delete-account.mjs' , emailData )
263264 } )
264- }
265+ }
265266
266267 sendPasswordResetEmail ( userAccount , returnToUrl ) {
267268 return Promise . resolve ( )
@@ -276,7 +277,7 @@ class AccountManager {
276277 }
277278 return this . emailService . sendWithTemplate ( 'reset-password' , emailData )
278279 } )
279- }
280+ }
280281
281282 sendWelcomeEmail ( newUser ) {
282283 const emailService = this . emailService
0 commit comments