Pārlūkot izejas kodu

introduce per-plan account limit

tags/v0.8.0
Jonathan Cobb pirms 4 gadiem
vecāks
revīzija
687753d92d
10 mainītis faili ar 61 papildinājumiem un 19 dzēšanām
  1. +1
    -1
      LICENSE.md
  2. +12
    -0
      bubble-server/src/main/java/bubble/dao/account/AccountDAO.java
  3. +2
    -0
      bubble-server/src/main/java/bubble/dao/bill/AccountPlanDAO.java
  4. +1
    -0
      bubble-server/src/main/java/bubble/model/account/Account.java
  5. +20
    -14
      bubble-server/src/main/java/bubble/model/bill/BubblePlan.java
  6. +3
    -0
      bubble-server/src/main/java/bubble/service/boot/SelfNodeService.java
  7. +17
    -4
      bubble-server/src/main/java/bubble/service/boot/StandardSelfNodeService.java
  8. +3
    -0
      bubble-server/src/main/java/bubble/service_dbfilter/DbFilterSelfNodeService.java
  9. +1
    -0
      bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties
  10. +1
    -0
      bubble-server/src/main/resources/models/defaults/bubblePlan.json

+ 1
- 1
LICENSE.md Parādīt failu

@@ -1,4 +1,4 @@
# Copyright (C) 2019 Bubble, Inc.
# Copyright (C) 2020 Bubble, Inc.

## For ANY commercial use of this software
All rights are reserved. Please contact licensing@bubblev.com for more information.


+ 12
- 0
bubble-server/src/main/java/bubble/dao/account/AccountDAO.java Parādīt failu

@@ -12,6 +12,7 @@ import bubble.dao.device.DeviceDAO;
import bubble.model.account.*;
import bubble.model.app.*;
import bubble.model.bill.Bill;
import bubble.model.bill.BubblePlan;
import bubble.model.cloud.*;
import bubble.server.BubbleConfiguration;
import bubble.service.SearchService;
@@ -83,6 +84,15 @@ public class AccountDAO extends AbstractCRUDDAO<Account> implements SqlViewSearc
@Override public Object preCreate(Account account) {
if (!account.hasLocale()) account.setLocale(getDEFAULT_LOCALE());

// check account limit for plan, if there is a plan
final BubblePlan plan = selfNodeService.getThisPlan();
if (plan != null && plan.hasMaxAccounts()) {
final int numAccounts = countNotDeleted();
if (numAccounts > plan.getMaxAccounts()) {
throw invalidEx("err.name.planMaxAccountLimit", "Account limit for plan reached (max "+plan.getMaxAccounts()+" accounts)");
}
}

final ValidationResult result = account.validateName();
if (result.isInvalid()) throw invalidEx(result);

@@ -94,6 +104,8 @@ public class AccountDAO extends AbstractCRUDDAO<Account> implements SqlViewSearc
return super.preCreate(account);
}

public int countNotDeleted() { return findByField("deleted", null).size(); }

private void ensureThisNodeExists() {
if (activated()) {
BubbleNode thisNode = selfNodeService.getThisNode();


+ 2
- 0
bubble-server/src/main/java/bubble/dao/bill/AccountPlanDAO.java Parādīt failu

@@ -46,6 +46,8 @@ public class AccountPlanDAO extends AccountOwnedEntityDAO<AccountPlan> {
return findByUniqueFields("account", accountUuid, "network", networkUuid);
}

public AccountPlan findByNetwork(String networkUuid) { return findByUniqueField("network", networkUuid); }

public List<AccountPlan> findByAccountAndNotDeleted(String account) {
return findByFields("account", account, "deleted", null);
}


+ 1
- 0
bubble-server/src/main/java/bubble/model/account/Account.java Parādīt failu

@@ -91,6 +91,7 @@ public class Account extends IdentifiableBaseParentEntity implements TokenPrinci
public static Account sageMask(Account sage) {
final Account masked = new Account(sage)
.setAdmin(false)
.setDeleted(now())
.setHashedPassword(HashedPassword.DISABLED);
masked.setUuid(sage.getUuid());
return masked;


+ 20
- 14
bubble-server/src/main/java/bubble/model/bill/BubblePlan.java Parādīt failu

@@ -40,12 +40,13 @@ public class BubblePlan extends IdentifiableBaseParentEntity implements HasAccou
public static final int MAX_CHARGENAME_LEN = 12;

public static final String[] UPDATE_FIELDS = {
"enabled", "price", "additionalPerNodePrice", "additionalStoragePerGbPrice", "additionalBandwidthPerGbPrice"
"enabled", "chargeName", "priority", "price", "maxAccounts",
"nodesIncluded", "storageGbIncluded", "bandwidthGbIncluded",
"additionalPerNodePrice", "additionalStoragePerGbPrice", "additionalBandwidthPerGbPrice"
};

public static final String[] CREATE_FIELDS = ArrayUtil.append(UPDATE_FIELDS,
"name", "chargeName", "priority", "period", "computeSizeType",
"nodesIncluded", "storageGbIncluded", "bandwidthGbIncluded"
"name", "period", "computeSizeType"
);

public BubblePlan (BubblePlan other) { copy(this, other, CREATE_FIELDS); }
@@ -104,27 +105,32 @@ public class BubblePlan extends IdentifiableBaseParentEntity implements HasAccou
@Enumerated(EnumType.STRING) @Getter @Setter private ComputeNodeSizeType computeSizeType;

@ECSearchable @ECField(index=100)
@Column(nullable=false, updatable=false)
@Getter @Setter private Integer nodesIncluded;
@Getter @Setter private Integer maxAccounts;
public boolean hasMaxAccounts () { return maxAccounts != null; }
public int maxAccounts () { return hasMaxAccounts() ? getMaxAccounts() : Integer.MAX_VALUE; }

@ECSearchable @ECField(index=110)
@Column(nullable=false, updatable=false)
@Getter @Setter private Integer additionalPerNodePrice;
@Column(nullable=false)
@Getter @Setter private Integer nodesIncluded;

@ECSearchable @ECField(index=120)
@Column(nullable=false, updatable=false)
@Getter @Setter private Integer storageGbIncluded;
@Column(nullable=false)
@Getter @Setter private Integer additionalPerNodePrice;

@ECSearchable @ECField(index=130)
@Column(nullable=false, updatable=false)
@Getter @Setter private Integer additionalStoragePerGbPrice;
@Column(nullable=false)
@Getter @Setter private Integer storageGbIncluded;

@ECSearchable @ECField(index=140)
@Column(nullable=false, updatable=false)
@Getter @Setter private Integer bandwidthGbIncluded;
@Column(nullable=false)
@Getter @Setter private Integer additionalStoragePerGbPrice;

@ECSearchable @ECField(index=150)
@Column(nullable=false, updatable=false)
@Column(nullable=false)
@Getter @Setter private Integer bandwidthGbIncluded;

@ECSearchable @ECField(index=160)
@Column(nullable=false)
@Getter @Setter private Integer additionalBandwidthPerGbPrice;

@Transient @Getter @Setter private transient List<BubbleApp> apps;


+ 3
- 0
bubble-server/src/main/java/bubble/service/boot/SelfNodeService.java Parādīt failu

@@ -1,5 +1,6 @@
package bubble.service.boot;

import bubble.model.bill.BubblePlan;
import bubble.model.cloud.BubbleNetwork;
import bubble.model.cloud.BubbleNode;

@@ -16,4 +17,6 @@ public interface SelfNodeService {
BubbleNode getSoleNode();

void setActivated(BubbleNode thisNode);

BubblePlan getThisPlan();
}

+ 17
- 4
bubble-server/src/main/java/bubble/service/boot/StandardSelfNodeService.java Parādīt failu

@@ -3,14 +3,15 @@ package bubble.service.boot;
import bubble.cloud.CloudServiceType;
import bubble.cloud.storage.local.LocalStorageDriver;
import bubble.dao.account.AccountSshKeyDAO;
import bubble.dao.bill.AccountPlanDAO;
import bubble.dao.bill.BubblePlanDAO;
import bubble.dao.cloud.BubbleNetworkDAO;
import bubble.dao.cloud.BubbleNodeDAO;
import bubble.dao.cloud.BubbleNodeKeyDAO;
import bubble.dao.cloud.CloudServiceDAO;
import bubble.model.cloud.BubbleNetwork;
import bubble.model.cloud.BubbleNode;
import bubble.model.cloud.BubbleNodeKey;
import bubble.model.cloud.BubbleNodeState;
import bubble.model.bill.AccountPlan;
import bubble.model.bill.BubblePlan;
import bubble.model.cloud.*;
import bubble.model.cloud.notify.NotificationReceipt;
import bubble.model.cloud.notify.NotificationType;
import bubble.server.BubbleConfiguration;
@@ -60,6 +61,8 @@ public class StandardSelfNodeService implements SelfNodeService {
@Autowired private BubbleNodeKeyDAO nodeKeyDAO;
@Autowired private BubbleNetworkDAO networkDAO;
@Autowired private CloudServiceDAO cloudDAO;
@Autowired private AccountPlanDAO accountPlanDAO;
@Autowired private BubblePlanDAO planDAO;
@Autowired private NotificationService notificationService;
@Autowired private BubbleConfiguration configuration;

@@ -383,4 +386,14 @@ public class StandardSelfNodeService implements SelfNodeService {
return existingByUuid;
}
}

@Override public BubblePlan getThisPlan() {
final BubbleNetwork network = safeGetThisNetwork();
if (network == null) return null;
if (network.getInstallType() != AnsibleInstallType.node) return null;
final AccountPlan accountPlan = accountPlanDAO.findByNetwork(network.getUuid());
if (accountPlan == null) return null;
return planDAO.findByUuid(accountPlan.getPlan());
}

}

+ 3
- 0
bubble-server/src/main/java/bubble/service_dbfilter/DbFilterSelfNodeService.java Parādīt failu

@@ -1,5 +1,6 @@
package bubble.service_dbfilter;

import bubble.model.bill.BubblePlan;
import bubble.model.cloud.BubbleNetwork;
import bubble.model.cloud.BubbleNode;
import bubble.service.boot.SelfNodeService;
@@ -22,4 +23,6 @@ public class DbFilterSelfNodeService implements SelfNodeService {

@Override public void setActivated(BubbleNode thisNode) { notSupported("setActivated"); }

@Override public BubblePlan getThisPlan() { return notSupported("getThisPlan"); }

}

+ 1
- 0
bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties Parādīt failu

@@ -151,6 +151,7 @@ err.app.notFound=App not found
err.name.required=Name is required
err.name.tooShort=Name must be at least 4 characters
err.name.tooLong=Name cannot be longer than 100 characters
err.name.planMaxAccountLimit=No more accounts can be created on this plan. Upgrade your plan or delete some accounts.
err.password.required=Password is required
err.password.tooShort=Password must be at least 8 characters
err.password.invalid=Password must contain at least one letter, one number, and one special character


+ 1
- 0
bubble-server/src/main/resources/models/defaults/bubblePlan.json Parādīt failu

@@ -13,6 +13,7 @@
"additionalBandwidthPerGbPrice": 0,
"children": {
"BubblePlanApp": [
{"app": "TrafficAnalytics"},
{"app": "BubbleBlock"},
{"app": "UserBlocker"}
]


Notiek ielāde…
Atcelt
Saglabāt