Reviewed-on: #6tags/v0.10.5
@@ -8,8 +8,7 @@ import bubble.model.account.AccountPolicy; | |||
import org.cobbzilla.wizard.validation.ValidationResult; | |||
import org.springframework.stereotype.Repository; | |||
import java.util.List; | |||
import static bubble.model.account.AccountDeletionPolicy.full_delete; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.die; | |||
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx; | |||
@@ -32,8 +31,19 @@ public class AccountPolicyDAO extends AccountOwnedEntityDAO<AccountPolicy> { | |||
} | |||
public AccountPolicy findSingleByAccount(String accountUuid) { | |||
final List<AccountPolicy> found = findByAccount(accountUuid); | |||
return found.isEmpty() ? create(new AccountPolicy().setAccount(accountUuid)) : found.size() > 1 ? die("findSingleByAccount: "+found.size()+" found!") : found.get(0); | |||
final var found = findByAccount(accountUuid); | |||
if (found.size() == 1) return found.get(0); | |||
if (found.size() > 1) { | |||
die("findSingleByAccount: More than 1 policy found for account " + accountUuid + " - " + found.size()); | |||
} | |||
// If there's no policy, create one. Note that is account is marked as deleted, the new policy will be with full | |||
// deletion set in. | |||
final var newPolicy = new AccountPolicy().setAccount(accountUuid); | |||
final var account = getConfiguration().getBean(AccountDAO.class).findById(accountUuid); | |||
if (account.deleted()) newPolicy.setDeletionPolicy(full_delete); | |||
return create(newPolicy); | |||
} | |||
} |
@@ -306,7 +306,7 @@ public class AuthResource { | |||
if (!request.hasName()) return invalid("err.name.required", "name is required"); | |||
if (!request.hasPassword()) return invalid("err.password.required", "password is required"); | |||
final Account account = accountDAO.findByName(request.getName()); | |||
if (account == null) return notFound(request.getName()); | |||
if (account == null || account.deleted()) return notFound(request.getName()); | |||
if (!account.getHashedPassword().isCorrectPassword(request.getPassword())) { | |||
return notFound(request.getName()); | |||
} | |||
@@ -28,6 +28,7 @@ | |||
<logger name="org.cobbzilla.util.daemon.ZillaRuntime" level="WARN" /> | |||
<logger name="org.cobbzilla.wizard.server" level="WARN" /> | |||
<logger name="org.cobbzilla.wizard.client" level="WARN" /> | |||
<logger name="org.cobbzilla.wizard.client.script" level="INFO" /> | |||
<logger name="org.cobbzilla.wizard.model.entityconfig.ModelSetup" level="INFO" /> | |||
<logger name="org.cobbzilla.wizard.resources.AbstractEntityConfigsResource" level="ERROR" /> | |||
<logger name="org.cobbzilla.wizard.resources.ResourceUtil" level="ERROR" /> | |||
@@ -0,0 +1,19 @@ | |||
/** | |||
* Copyright (c) 2020 Bubble, Inc. All rights reserved. | |||
* For personal (non-commercial) use, see license: https://bubblev.com/bubble-license/ | |||
*/ | |||
package bubble.test.system; | |||
import bubble.test.ActivatedBubbleModelTestBase; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.junit.Test; | |||
@Slf4j | |||
public class AccountDeletionTest extends ActivatedBubbleModelTestBase { | |||
@Override protected String getManifest() { return "manifest-test"; } | |||
@Test public void testFullAccountDeletion() throws Exception { modelTest("account_deletion/full_delete_account"); } | |||
@Test public void testBlockAccountDeletion() throws Exception { modelTest("account_deletion/block_delete_account"); } | |||
} |
@@ -24,7 +24,6 @@ public class AuthTest extends ActivatedBubbleModelTestBase { | |||
accountDAO.update(rootUser.setHashedPassword(new HashedPassword(ROOT_PASSWORD))); | |||
} | |||
@Test public void testAccountDeletion () throws Exception { modelTest("auth/delete_account"); } | |||
@Test public void testBasicAuth () throws Exception { modelTest("auth/basic_auth"); } | |||
@Test public void testAccountCrud () throws Exception { modelTest("auth/account_crud"); } | |||
@Test public void testDeviceCrud () throws Exception { modelTest("auth/device_crud"); } | |||
@@ -0,0 +1,97 @@ | |||
[ | |||
{ | |||
"comment": "activate service, create account, login for block_delete", | |||
"include": "new_account", | |||
"params": { | |||
"username": "user-to-partially-delete", | |||
"password": "foobar1!", | |||
"email": "user-partially-account-deletion@example.com", | |||
"verifyEmail": "true" | |||
} | |||
}, | |||
{ | |||
"comment": "look up account policy for block_delete", | |||
"request": { "uri": "users/{{user.uuid}}/policy" }, | |||
"response": { | |||
"store": "policy", | |||
"check": [ | |||
{"condition": "json.getAccountContacts() != null"}, | |||
{"condition": "json.getAccountContacts().length == 1"} | |||
] | |||
} | |||
}, | |||
{ | |||
"comment": "set deletion policy to block_delete", | |||
"request": { | |||
"uri": "users/{{user.uuid}}/policy", | |||
"data": "policy", | |||
"entity": { | |||
"deletionPolicy": "block_delete" | |||
} | |||
}, | |||
"response": { | |||
"store": "policy", | |||
"check": [ | |||
{"condition": "json.getDeletionPolicy().name() == 'block_delete'"} | |||
] | |||
} | |||
}, | |||
{ | |||
"comment": "as root, block delete account", | |||
"request": { | |||
"session": "rootSession", | |||
"uri": "users/{{user.uuid}}", | |||
"method": "delete" | |||
} | |||
}, | |||
{ | |||
"comment": "lookup user, expect that it is still there, just empty", | |||
"request": { "uri": "users/{{user.uuid}}" }, | |||
"response": { | |||
"check": [ | |||
{ "condition": "json.getUuid() == user.getUuid()" }, | |||
{ "condition": "json.getName() == user.getName()" }, | |||
{ "condition": "json.deleted()" } | |||
] | |||
} | |||
}, | |||
{ | |||
"comment": "try logging in as deleted user - failing now", | |||
"request": { | |||
"session": "new", | |||
"uri": "auth/login", | |||
"entity": { | |||
"name": "{{user.name}}", | |||
"password": "foobar1!" | |||
} | |||
}, | |||
"response": { "status": 404 } | |||
}, | |||
{ | |||
"comment": "as root, look up account policy again - it should recreated for this object with full deletion policy", | |||
"request": { "session": "rootSession", "uri": "users/{{user.uuid}}/policy" }, | |||
"response": { "check": [{ "condition": "json.getDeletionPolicy().name() == 'full_delete'" }] } | |||
}, | |||
{ | |||
"comment": "try deleting the same account again - expect fully deletion this time even without policy", | |||
"request": { "uri": "users/{{user.uuid}}", "method": "delete" } | |||
}, | |||
{ | |||
"comment": "lookup user, expect there's no such user now", | |||
"request": { "uri": "users/{{user.uuid}}" }, | |||
"response": { "status": 404 } | |||
}, | |||
{ | |||
"comment": "as root, look up account policy again - not found, and account uuid reported as not found resource", | |||
"request": { "session": "rootSession", "uri": "users/{{user.uuid}}/policy" }, | |||
"response": { "status": 404, "check": [{ "condition": "json.get('resource') == user.getUuid()" }] } | |||
} | |||
] |
@@ -12,7 +12,7 @@ | |||
{ | |||
"comment": "look up account policy", | |||
"request": { "uri": "users/user-to-delete/policy" }, | |||
"request": { "uri": "users/{{user.uuid}}/policy" }, | |||
"response": { | |||
"store": "policy", | |||
"check": [ | |||
@@ -25,7 +25,7 @@ | |||
{ | |||
"comment": "set deletion policy to full_delete", | |||
"request": { | |||
"uri": "users/user-to-delete/policy", | |||
"uri": "users/{{user.uuid}}/policy", | |||
"data": "policy", | |||
"entity": { | |||
"deletionPolicy": "full_delete" | |||
@@ -39,11 +39,17 @@ | |||
} | |||
}, | |||
{ | |||
"comment": "lookup user - just checking it is the one for deletion", | |||
"request": { "uri": "users/{{user.uuid}}" }, | |||
"response": { "check": [{ "condition": "json.getName() == 'user-to-delete'" }] } | |||
}, | |||
{ | |||
"comment": "as root, delete account", | |||
"request": { | |||
"session": "rootSession", | |||
"uri": "users/user-to-delete", | |||
"uri": "users/{{user.uuid}}", | |||
"method": "delete" | |||
} | |||
}, | |||
@@ -51,8 +57,8 @@ | |||
{ | |||
"comment": "lookup user, expect not found", | |||
"request": { | |||
"uri": "users/user-to-delete" | |||
"uri": "users/{{user.uuid}}" | |||
}, | |||
"response": { "status": 404 } | |||
} | |||
] | |||
] |