@@ -63,8 +63,9 @@ public class AccountDAO extends AbstractCRUDDAO<Account> implements SqlViewSearc | |||||
@Autowired private BillDAO billDAO; | @Autowired private BillDAO billDAO; | ||||
@Autowired private SearchService searchService; | @Autowired private SearchService searchService; | ||||
public Account newAccount(Request req, AccountRegistration request, Account parent) { | |||||
public Account newAccount(Request req, Account caller, AccountRegistration request, Account parent) { | |||||
return create(new Account(request) | return create(new Account(request) | ||||
.setAdmin(caller != null && caller.admin() && request.admin()) // only admins can create other admins | |||||
.setRemoteHost(getRemoteHost(req)) | .setRemoteHost(getRemoteHost(req)) | ||||
.setParent(parent.getUuid()) | .setParent(parent.getUuid()) | ||||
.setPolicy(new AccountPolicy().setContact(request.getContact()))); | .setPolicy(new AccountPolicy().setContact(request.getContact()))); | ||||
@@ -86,6 +86,10 @@ public class AccountsResource { | |||||
final AccountContext c = new AccountContext(ctx, request.getName(), true); | final AccountContext c = new AccountContext(ctx, request.getName(), true); | ||||
// only admins can use this endpoint | |||||
// regular users must use AuthResource.register | |||||
if (!c.caller.admin()) return forbidden(); | |||||
final ValidationResult errors = new ValidationResult(); | final ValidationResult errors = new ValidationResult(); | ||||
if (c.account != null) return invalid("err.user.exists", "User with name "+request.getName()+" already exists", request.getName()); | if (c.account != null) return invalid("err.user.exists", "User with name "+request.getName()+" already exists", request.getName()); | ||||
@@ -117,7 +121,7 @@ public class AccountsResource { | |||||
final AccountRegistration reg = (AccountRegistration) request | final AccountRegistration reg = (AccountRegistration) request | ||||
.setRemoteHost(getRemoteHost(req)) | .setRemoteHost(getRemoteHost(req)) | ||||
.setVerifyContact(true); | .setVerifyContact(true); | ||||
final Account created = accountDAO.newAccount(req, reg, parent); | |||||
final Account created = accountDAO.newAccount(req, c.caller, reg, parent); | |||||
return ok(created.waitForAccountInit()); | return ok(created.waitForAccountInit()); | ||||
} | } | ||||
@@ -199,7 +199,7 @@ public class AuthResource { | |||||
final Account parent = accountDAO.findByUuid(parentUuid); | final Account parent = accountDAO.findByUuid(parentUuid); | ||||
if (parent == null) return invalid("err.parent.notFound", "Parent account does not exist: "+parentUuid); | if (parent == null) return invalid("err.parent.notFound", "Parent account does not exist: "+parentUuid); | ||||
final Account account = accountDAO.newAccount(req, request, parent); | |||||
final Account account = accountDAO.newAccount(req, null, request, parent); | |||||
return ok(account.waitForAccountInit().setToken(newLoginSession(account))); | return ok(account.waitForAccountInit().setToken(newLoginSession(account))); | ||||
} | } | ||||
@@ -277,7 +277,8 @@ public class StandardSelfNodeService implements SelfNodeService { | |||||
log.debug("initSelf: starting with selfNode="+selfNode.id()); | log.debug("initSelf: starting with selfNode="+selfNode.id()); | ||||
final BubbleNode foundByUuid = nodeDAO.findByUuid(selfNode.getUuid()); | final BubbleNode foundByUuid = nodeDAO.findByUuid(selfNode.getUuid()); | ||||
final BubbleNode foundByFqdn = nodeDAO.findByFqdn(selfNode.getFqdn()); | final BubbleNode foundByFqdn = nodeDAO.findByFqdn(selfNode.getFqdn()); | ||||
if (foundByUuid == null && foundByFqdn == null) { | |||||
final BubbleNode foundByIp4 = nodeDAO.findByIp4(selfNode.getIp4()); | |||||
if (foundByUuid == null && foundByFqdn == null && foundByIp4 == null) { | |||||
// node exists in JSON but not in DB: write it to DB | // node exists in JSON but not in DB: write it to DB | ||||
return ensureRunning(nodeDAO.create(selfNode)); | return ensureRunning(nodeDAO.create(selfNode)); | ||||
@@ -293,10 +294,15 @@ public class StandardSelfNodeService implements SelfNodeService { | |||||
nodeDAO.delete(foundByFqdn.getUuid()); | nodeDAO.delete(foundByFqdn.getUuid()); | ||||
return ensureRunning(nodeDAO.create(selfNode)); | return ensureRunning(nodeDAO.create(selfNode)); | ||||
} else if (foundByUuid == null) { | |||||
// found by fqdn but not uuid, remove fqdn and add | |||||
} else if (foundByUuid == null && foundByIp4 == null) { | |||||
// found by fqdn but not uuid or ip4, remove fqdn and add | |||||
nodeDAO.delete(foundByFqdn.getUuid()); | nodeDAO.delete(foundByFqdn.getUuid()); | ||||
return ensureRunning(nodeDAO.create(selfNode)); | return ensureRunning(nodeDAO.create(selfNode)); | ||||
} else if (foundByIp4 != null) { | |||||
// OK, use the one we found by ip4 | |||||
return foundByIp4; | |||||
} else { | } else { | ||||
// found by uuid but not fqdn, error | // found by uuid but not fqdn, error | ||||
return die("initSelf: wrong FQDN (expected "+selfNode.getFqdn()+") in foundByUuid="+foundByUuid.id()); | return die("initSelf: wrong FQDN (expected "+selfNode.getFqdn()+") in foundByUuid="+foundByUuid.id()); | ||||
@@ -6,6 +6,7 @@ | |||||
"username": "user-{{rand 10}}", | "username": "user-{{rand 10}}", | ||||
"password": "foobar1!", | "password": "foobar1!", | ||||
"email": "user-{{rand 5}}@example.com", | "email": "user-{{rand 5}}@example.com", | ||||
"rootSessionName": "rootSession", | |||||
"userSessionName": "userSession", | "userSessionName": "userSession", | ||||
"userVar": "userAccount", | "userVar": "userAccount", | ||||
"verifyEmail": "false", | "verifyEmail": "false", | ||||
@@ -16,6 +17,7 @@ | |||||
{ | { | ||||
"comment": "as root, create a new account", | "comment": "as root, create a new account", | ||||
"request": { | "request": { | ||||
"session": "<<rootSessionName>>", | |||||
"uri": "users", | "uri": "users", | ||||
"method": "put", | "method": "put", | ||||
"entity": { | "entity": { | ||||
@@ -427,6 +427,14 @@ | |||||
} | } | ||||
}, | }, | ||||
{ | |||||
"comment": "as second admin, read self-profile, succeeds. verify we are admin", | |||||
"request": { "uri": "me" }, | |||||
"response": { | |||||
"check": [ {"condition": "json.admin() == true"} ] | |||||
} | |||||
}, | |||||
{ | { | ||||
"comment": "as root user, try to change admin user password without sending current password, fails", | "comment": "as root user, try to change admin user password without sending current password, fails", | ||||
"request": { | "request": { | ||||
@@ -438,7 +446,7 @@ | |||||
}, | }, | ||||
"response": { | "response": { | ||||
"status": 422, | "status": 422, | ||||
"check": [ {"condition": "json.has('err.password.invalid')"} ] | |||||
"check": [ {"condition": "json.has('err.currentPassword.invalid')"} ] | |||||
} | } | ||||
}, | }, | ||||
@@ -1 +1 @@ | |||||
Subproject commit 689734e6c9fa7a51cbe19b47105520d0801c47f0 | |||||
Subproject commit 194dbc005456a36dc8bbebff2fa7726fa03281a5 |