Browse Source

Merge branch 'kris/acount_deletion' into kris/keep_billing_info

tags/v0.10.5
Kristijan Mitrovic 4 years ago
parent
commit
4a55512a60
10 changed files with 154 additions and 14 deletions
  1. +14
    -4
      bubble-server/src/main/java/bubble/dao/account/AccountPolicyDAO.java
  2. +1
    -1
      bubble-server/src/main/java/bubble/resources/account/AuthResource.java
  3. +1
    -0
      bubble-server/src/main/resources/logback.xml
  4. +3
    -1
      bubble-server/src/test/java/bubble/test/dev/BlankDevServerTest.java
  5. +4
    -1
      bubble-server/src/test/java/bubble/test/dev/DevServerTest.java
  6. +4
    -1
      bubble-server/src/test/java/bubble/test/dev/NewBlankDevServerTest.java
  7. +19
    -0
      bubble-server/src/test/java/bubble/test/system/AccountDeletionTest.java
  8. +0
    -1
      bubble-server/src/test/java/bubble/test/system/AuthTest.java
  9. +97
    -0
      bubble-server/src/test/resources/models/tests/account_deletion/block_delete_account.json
  10. +11
    -5
      bubble-server/src/test/resources/models/tests/account_deletion/full_delete_account.json

+ 14
- 4
bubble-server/src/main/java/bubble/dao/account/AccountPolicyDAO.java View File

@@ -8,8 +8,7 @@ import bubble.model.account.AccountPolicy;
import org.cobbzilla.wizard.validation.ValidationResult; import org.cobbzilla.wizard.validation.ValidationResult;
import org.springframework.stereotype.Repository; 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.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx; import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx;


@@ -32,8 +31,19 @@ public class AccountPolicyDAO extends AccountOwnedEntityDAO<AccountPolicy> {
} }


public AccountPolicy findSingleByAccount(String accountUuid) { 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);
} }


} }

+ 1
- 1
bubble-server/src/main/java/bubble/resources/account/AuthResource.java View File

@@ -306,7 +306,7 @@ public class AuthResource {
if (!request.hasName()) return invalid("err.name.required", "name is required"); if (!request.hasName()) return invalid("err.name.required", "name is required");
if (!request.hasPassword()) return invalid("err.password.required", "password is required"); if (!request.hasPassword()) return invalid("err.password.required", "password is required");
final Account account = accountDAO.findByName(request.getName()); 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())) { if (!account.getHashedPassword().isCorrectPassword(request.getPassword())) {
return notFound(request.getName()); return notFound(request.getName());
} }


+ 1
- 0
bubble-server/src/main/resources/logback.xml View File

@@ -28,6 +28,7 @@
<logger name="org.cobbzilla.util.daemon.ZillaRuntime" level="WARN" /> <logger name="org.cobbzilla.util.daemon.ZillaRuntime" level="WARN" />
<logger name="org.cobbzilla.wizard.server" level="WARN" /> <logger name="org.cobbzilla.wizard.server" level="WARN" />
<logger name="org.cobbzilla.wizard.client" 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.model.entityconfig.ModelSetup" level="INFO" />
<logger name="org.cobbzilla.wizard.resources.AbstractEntityConfigsResource" level="ERROR" /> <logger name="org.cobbzilla.wizard.resources.AbstractEntityConfigsResource" level="ERROR" />
<logger name="org.cobbzilla.wizard.resources.ResourceUtil" level="ERROR" /> <logger name="org.cobbzilla.wizard.resources.ResourceUtil" level="ERROR" />


+ 3
- 1
bubble-server/src/test/java/bubble/test/dev/BlankDevServerTest.java View File

@@ -10,6 +10,7 @@ import org.cobbzilla.wizard.server.RestServerLifecycleListener;
import org.cobbzilla.wizard.server.listener.FlywayMigrationListener; import org.cobbzilla.wizard.server.listener.FlywayMigrationListener;
import org.junit.Test; import org.junit.Test;


import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;


@@ -33,7 +34,8 @@ public class BlankDevServerTest extends NewBlankDevServerTest {
} }


@Test public void runBlankServer () throws Exception { @Test public void runBlankServer () throws Exception {
log.info("runBlankServer: Bubble API server started and model initialized. You may now begin testing.");
log.info("runBlankServer: Bubble API server started and model initialized. You may now begin testing on port: "
+ new URL(this.getApi().getBaseUri()).getPort());
sleep(DAYS.toMillis(30), "running dev server"); sleep(DAYS.toMillis(30), "running dev server");
} }




+ 4
- 1
bubble-server/src/test/java/bubble/test/dev/DevServerTest.java View File

@@ -11,6 +11,8 @@ import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.wizard.server.RestServer; import org.cobbzilla.wizard.server.RestServer;
import org.junit.Test; import org.junit.Test;


import java.net.URL;

import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.DAYS;
import static org.cobbzilla.util.system.Sleep.sleep; import static org.cobbzilla.util.system.Sleep.sleep;


@@ -31,7 +33,8 @@ public class DevServerTest extends ActivatedBubbleModelTestBase {
} }


@Test public void runDevServer () throws Exception { @Test public void runDevServer () throws Exception {
log.info("runDevServer: Bubble API server started and model initialized. You may now begin testing.");
log.info("runDevServer: Bubble API server started and model initialized. You may now begin testing on port: "
+ new URL(this.getApi().getBaseUri()).getPort());
sleep(DAYS.toMillis(30), "running dev server"); sleep(DAYS.toMillis(30), "running dev server");
} }




+ 4
- 1
bubble-server/src/test/java/bubble/test/dev/NewBlankDevServerTest.java View File

@@ -11,6 +11,8 @@ import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.wizard.server.RestServer; import org.cobbzilla.wizard.server.RestServer;
import org.junit.Test; import org.junit.Test;


import java.net.URL;

import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.DAYS;
import static org.cobbzilla.util.string.StringUtil.safeParseInt; import static org.cobbzilla.util.string.StringUtil.safeParseInt;
import static org.cobbzilla.util.system.Sleep.sleep; import static org.cobbzilla.util.system.Sleep.sleep;
@@ -35,7 +37,8 @@ public class NewBlankDevServerTest extends BubbleModelTestBase {
} }


@Test public void runBlankServer () throws Exception { @Test public void runBlankServer () throws Exception {
log.info("runBlankServer: Bubble API server started and model initialized. You may now begin testing.");
log.info("runBlankServer: Bubble API server started and model initialized. You may now begin testing on port: "
+ new URL(this.getApi().getBaseUri()).getPort());
sleep(DAYS.toMillis(30), "running dev server"); sleep(DAYS.toMillis(30), "running dev server");
} }




+ 19
- 0
bubble-server/src/test/java/bubble/test/system/AccountDeletionTest.java View File

@@ -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"); }

}

+ 0
- 1
bubble-server/src/test/java/bubble/test/system/AuthTest.java View File

@@ -24,7 +24,6 @@ public class AuthTest extends ActivatedBubbleModelTestBase {
accountDAO.update(rootUser.setHashedPassword(new HashedPassword(ROOT_PASSWORD))); 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 testBasicAuth () throws Exception { modelTest("auth/basic_auth"); }
@Test public void testAccountCrud () throws Exception { modelTest("auth/account_crud"); } @Test public void testAccountCrud () throws Exception { modelTest("auth/account_crud"); }
@Test public void testDeviceCrud () throws Exception { modelTest("auth/device_crud"); } @Test public void testDeviceCrud () throws Exception { modelTest("auth/device_crud"); }


+ 97
- 0
bubble-server/src/test/resources/models/tests/account_deletion/block_delete_account.json View File

@@ -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()" }] }
}
]

bubble-server/src/test/resources/models/tests/auth/delete_account.json → bubble-server/src/test/resources/models/tests/account_deletion/full_delete_account.json View File

@@ -12,7 +12,7 @@


{ {
"comment": "look up account policy", "comment": "look up account policy",
"request": { "uri": "users/user-to-delete/policy" },
"request": { "uri": "users/{{user.uuid}}/policy" },
"response": { "response": {
"store": "policy", "store": "policy",
"check": [ "check": [
@@ -25,7 +25,7 @@
{ {
"comment": "set deletion policy to full_delete", "comment": "set deletion policy to full_delete",
"request": { "request": {
"uri": "users/user-to-delete/policy",
"uri": "users/{{user.uuid}}/policy",
"data": "policy", "data": "policy",
"entity": { "entity": {
"deletionPolicy": "full_delete" "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", "comment": "as root, delete account",
"request": { "request": {
"session": "rootSession", "session": "rootSession",
"uri": "users/user-to-delete",
"uri": "users/{{user.uuid}}",
"method": "delete" "method": "delete"
} }
}, },
@@ -51,8 +57,8 @@
{ {
"comment": "lookup user, expect not found", "comment": "lookup user, expect not found",
"request": { "request": {
"uri": "users/user-to-delete"
"uri": "users/{{user.uuid}}"
}, },
"response": { "status": 404 } "response": { "status": 404 }
} }
]
]

Loading…
Cancel
Save