package io.cattle.platform.core.dao.impl;
import static io.cattle.platform.core.model.tables.AccountLinkTable.*;
import static io.cattle.platform.core.model.tables.AccountTable.*;
import static io.cattle.platform.core.model.tables.CredentialTable.*;
import static io.cattle.platform.core.model.tables.GenericObjectTable.*;
import static io.cattle.platform.core.model.tables.ProjectMemberTable.*;
import static io.cattle.platform.core.model.tables.UserPreferenceTable.*;
import io.cattle.platform.core.constants.AccountConstants;
import io.cattle.platform.core.constants.CommonStatesConstants;
import io.cattle.platform.core.constants.CredentialConstants;
import io.cattle.platform.core.constants.ProjectConstants;
import io.cattle.platform.core.constants.ServiceConstants;
import io.cattle.platform.core.dao.AccountDao;
import io.cattle.platform.core.model.Account;
import io.cattle.platform.core.model.AccountLink;
import io.cattle.platform.core.model.Credential;
import io.cattle.platform.core.model.GenericObject;
import io.cattle.platform.core.model.ProjectMember;
import io.cattle.platform.core.model.UserPreference;
import io.cattle.platform.core.model.tables.records.GenericObjectRecord;
import io.cattle.platform.core.model.tables.records.ProjectMemberRecord;
import io.cattle.platform.core.model.tables.records.UserPreferenceRecord;
import io.cattle.platform.object.process.ObjectProcessManager;
import io.cattle.platform.object.process.StandardProcess;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import org.jooq.Condition;
import org.jooq.Record1;
import org.jooq.impl.DSL;
@Named
public class AccountDaoImpl extends AbstractCoreDao implements AccountDao {
@Inject
ObjectProcessManager objectProcessManager;
@Override
public Account getSystemAccount() {
Account system = objectManager.findOne(Account.class,
ACCOUNT.UUID, AccountConstants.SYSTEM_UUID);
if ( system == null ) {
throw new IllegalStateException("Failed to find system account");
}
return system;
}
@Override
public List<? extends Credential> getApiKeys(Account account, String kind, boolean active) {
if (kind == null) {
kind = CredentialConstants.KIND_API_KEY;
}
Condition stateCondition = DSL.trueCondition();
if ( active ) {
stateCondition = CREDENTIAL.STATE.eq(CommonStatesConstants.ACTIVE);
}
return create().selectFrom(CREDENTIAL)
.where(CREDENTIAL.ACCOUNT_ID.eq(account.getId())
.and(CREDENTIAL.REMOVED.isNull())
.and(stateCondition)
.and(CREDENTIAL.KIND.eq(kind)))
.fetch();
}
@Override
public Account findByUuid(String uuid) {
return create()
.selectFrom(ACCOUNT)
.where(ACCOUNT.UUID.eq(uuid))
.fetchOne();
}
@Override
public void deleteProjectMemberEntries(Account account) {
if (!ProjectConstants.TYPE.equalsIgnoreCase(account.getKind())
&& StringUtils.isNotBlank(account.getExternalId())
&& StringUtils.isNotBlank(account.getExternalIdType())){
create().delete(PROJECT_MEMBER)
.where(PROJECT_MEMBER.EXTERNAL_ID.eq(account.getExternalId())
.and(PROJECT_MEMBER.EXTERNAL_ID_TYPE.eq(account.getExternalIdType())))
.execute();
}
create().delete(PROJECT_MEMBER)
.where(PROJECT_MEMBER.PROJECT_ID.eq(account.getId()))
.execute();
}
@Override
public Account getAdminAccountExclude(long accountId) {
return create()
.selectFrom(ACCOUNT)
.where(ACCOUNT.STATE.in(getAccountActiveStates())
.and(ACCOUNT.KIND.eq(AccountConstants.ADMIN_KIND))
.and(ACCOUNT.ID.ne(accountId)))
.orderBy(ACCOUNT.ID.asc()).limit(1).fetchOne();
}
@Override
public Account getAccountById(Long id) {
return create()
.selectFrom(ACCOUNT)
.where(
ACCOUNT.ID.eq(id)
.and(ACCOUNT.STATE.ne(CommonStatesConstants.PURGED))
.and(ACCOUNT.REMOVED.isNull())
).fetchOne();
}
@Override
public boolean isActiveAccount(Account account) {
List<String> goodStates = Arrays.asList(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE,
ServiceConstants.STATE_UPGRADING);
return goodStates.contains(account.getState());
}
@Override
public List<String> getAccountActiveStates() {
return Arrays.asList(CommonStatesConstants.ACTIVE, ServiceConstants.STATE_UPGRADING);
}
@Override
public List<? extends GenericObject> findBadGO(int count) {
return create().select(GENERIC_OBJECT.fields())
.from(GENERIC_OBJECT)
.join(ACCOUNT)
.on(ACCOUNT.ID.eq(GENERIC_OBJECT.ACCOUNT_ID))
.where(GENERIC_OBJECT.REMOVED.isNull()
.and(ACCOUNT.STATE.eq(CommonStatesConstants.PURGED))
.and(GENERIC_OBJECT.STATE.notIn(CommonStatesConstants.REMOVING, CommonStatesConstants.DEACTIVATING)))
.limit(count)
.fetchInto(GenericObjectRecord.class);
}
@Override
public List<? extends UserPreference> findBadUserPreference(int count) {
return create().select(USER_PREFERENCE.fields())
.from(USER_PREFERENCE)
.join(ACCOUNT)
.on(ACCOUNT.ID.eq(USER_PREFERENCE.ACCOUNT_ID))
.where(USER_PREFERENCE.REMOVED.isNull()
.and(ACCOUNT.STATE.eq(CommonStatesConstants.PURGED))
.and(USER_PREFERENCE.STATE.notIn(CommonStatesConstants.REMOVING, CommonStatesConstants.DEACTIVATING)))
.limit(count)
.fetchInto(UserPreferenceRecord.class);
}
@Override
public List<? extends ProjectMember> findBadProjectMembers(int count) {
return create().select(PROJECT_MEMBER.fields())
.from(PROJECT_MEMBER)
.join(ACCOUNT)
.on(ACCOUNT.ID.eq(PROJECT_MEMBER.PROJECT_ID))
.where(ACCOUNT.STATE.eq(CommonStatesConstants.PURGED)
.and(PROJECT_MEMBER.REMOVED.isNull())
.and(PROJECT_MEMBER.STATE.notIn(CommonStatesConstants.DEACTIVATING, CommonStatesConstants.REMOVING)))
.limit(count)
.fetchInto(ProjectMemberRecord.class);
}
@Override
public void generateAccountLinks(Account account, List<? extends Long> links) {
createNewAccountLinks(account, links);
deleteOldAccountLinks(account, links);
}
protected void createNewAccountLinks(Account account, List<? extends Long> newAccountIds) {
for (Long accountId : newAccountIds) {
AccountLink link = objectManager.findAny(AccountLink.class, ACCOUNT_LINK.ACCOUNT_ID,
account.getId(),
ACCOUNT_LINK.LINKED_ACCOUNT_ID, accountId,
ACCOUNT_LINK.REMOVED, null);
if (link == null) {
link = objectManager.create(AccountLink.class, ACCOUNT_LINK.ACCOUNT_ID,
account.getId(), ACCOUNT_LINK.LINKED_ACCOUNT_ID, accountId);
}
if (link.getState().equalsIgnoreCase(CommonStatesConstants.REQUESTED)) {
objectProcessManager.executeStandardProcess(StandardProcess.CREATE, link, null);
}
}
}
protected void deleteOldAccountLinks(Account account, List<? extends Long> newAccountIds) {
List<? extends AccountLink> allLinks = objectManager.find(AccountLink.class,
ACCOUNT_LINK.ACCOUNT_ID, account.getId(),
ACCOUNT_LINK.REMOVED, null);
for (AccountLink link : allLinks) {
if (!newAccountIds.contains(link.getLinkedAccountId())) {
objectProcessManager.scheduleStandardProcessAsync(StandardProcess.REMOVE, link, null);
}
}
}
@Override
public List<Long> getLinkedAccounts(long accountId) {
List<Long> accountIds = new ArrayList<>();
List<Long> linkedToAccounts = Arrays.asList(create().select(ACCOUNT_LINK.LINKED_ACCOUNT_ID)
.from(ACCOUNT_LINK)
.where(ACCOUNT_LINK.ACCOUNT_ID.eq(accountId)
.and(ACCOUNT_LINK.REMOVED.isNull()))
.fetch().intoArray(ACCOUNT_LINK.LINKED_ACCOUNT_ID));
List<Long> linkedFromAccounts = Arrays.asList(create().select(ACCOUNT_LINK.ACCOUNT_ID)
.from(ACCOUNT_LINK)
.where(ACCOUNT_LINK.LINKED_ACCOUNT_ID.eq(accountId)
.and(ACCOUNT_LINK.REMOVED.isNull()))
.fetch().intoArray(ACCOUNT_LINK.ACCOUNT_ID));
accountIds.addAll(linkedToAccounts);
accountIds.addAll(linkedFromAccounts);
return accountIds;
}
@Override
public Long incrementRevision(long accountId) {
Record1<Long> row = create().select(ACCOUNT.REVISION)
.from(ACCOUNT)
.where(ACCOUNT.ID.eq(accountId))
.fetchAny();
if (row == null) {
return 0L;
}
create().update(ACCOUNT)
.set(ACCOUNT.REVISION, ACCOUNT.REVISION.plus(1))
.where(ACCOUNT.ID.eq(accountId))
.execute();
return row.value1() + 1;
}
}