Search in sources :

Example 31 with CustomerData

use of io.codekvast.common.customer.CustomerData in project codekvast by crispab.

the class AgentServiceImpl method updateAgentState.

private boolean updateAgentState(CustomerData customerData, String jvmUuid) {
    long customerId = customerData.getCustomerId();
    Instant now = Instant.now();
    // Disable all agents that have been dead for more than two file import intervals...
    int updated = jdbcTemplate.update("UPDATE agent_state SET enabled = FALSE " + "WHERE customerId = ? AND nextPollExpectedAt < ? AND enabled = TRUE ", customerId, Timestamp.from(now.minusSeconds(settings.getQueuePathPollIntervalSeconds() * 2)));
    if (updated > 0) {
        logger.info("Disabled {} dead agents for {}", updated, customerData);
    }
    Timestamp nextExpectedPollTimestamp = Timestamp.from(now.plusSeconds(customerData.getPricePlan().getPollIntervalSeconds()));
    updated = jdbcTemplate.update("UPDATE agent_state SET lastPolledAt = ?, nextPollExpectedAt = ? WHERE customerId = ? AND jvmUuid = ?", Timestamp.from(now), nextExpectedPollTimestamp, customerId, jvmUuid);
    if (updated == 0) {
        logger.info("The agent {}:{} has started", customerId, jvmUuid);
        jdbcTemplate.update("INSERT INTO agent_state(customerId, jvmUuid, lastPolledAt, nextPollExpectedAt, enabled) VALUES (?, ?, ?, ?, ?)", customerId, jvmUuid, Timestamp.from(now), nextExpectedPollTimestamp, Boolean.TRUE);
    } else {
        logger.debug("The agent {}:{} has polled", customerId, jvmUuid);
    }
    Integer numOtherEnabledLiveAgents = jdbcTemplate.queryForObject("SELECT COUNT(1) FROM agent_state " + "WHERE enabled = TRUE AND customerId = ? AND nextPollExpectedAt >= ? AND jvmUuid != ? ", Integer.class, customerId, Timestamp.from(now.minusSeconds(10)), jvmUuid);
    String planName = customerData.getPricePlan().getName();
    int maxNumberOfAgents = customerData.getPricePlan().getMaxNumberOfAgents();
    boolean enabled = numOtherEnabledLiveAgents < maxNumberOfAgents;
    if (!enabled) {
        logger.warn("Customer {} has already {} live agents (max for price plan '{}' is {})", customerId, numOtherEnabledLiveAgents, planName, maxNumberOfAgents);
    } else {
        logger.debug("Customer {} now has {} live agents (max for price plan '{}' is {})", customerId, numOtherEnabledLiveAgents + 1, planName, maxNumberOfAgents);
    }
    jdbcTemplate.update("UPDATE agent_state SET enabled = ? WHERE jvmUuid = ?", enabled, jvmUuid);
    CustomerData cd = customerService.registerAgentDataPublication(customerData, now);
    if (cd.isTrialPeriodExpired(now)) {
        logger.info("Trial period expired for {}", cd);
        enabled = false;
    }
    return enabled;
}
Also used : CustomerData(io.codekvast.common.customer.CustomerData) Instant(java.time.Instant) Timestamp(java.sql.Timestamp)

Example 32 with CustomerData

use of io.codekvast.common.customer.CustomerData in project codekvast by crispab.

the class CustomerServiceImpl method deleteCustomerByExternalId.

@Override
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = CUSTOMERS_CACHE, allEntries = true)
public void deleteCustomerByExternalId(@NonNull String source, String externalId) {
    CustomerData customerData = getCustomerDataByExternalId(source, externalId);
    long customerId = customerData.getCustomerId();
    deleteFromTable("invocations", customerId);
    deleteFromTable("method_locations", customerId);
    deleteFromTable("methods", customerId);
    deleteFromTable("jvms", customerId);
    deleteFromTable("environments", customerId);
    deleteFromTable("applications", customerId);
    deleteFromTable("users", customerId);
    deleteFromTable("agent_state", customerId);
    deleteFromTable("price_plan_overrides", customerId);
    deleteFromTable("heroku_details", customerId);
    deleteFromTable("facts", customerId);
    deleteFromTable("customers", customerId);
    eventService.send(CustomerDeletedEvent.builder().customerId(customerId).name(customerData.getCustomerName()).displayName(customerData.getDisplayName()).source(customerData.getSource()).plan(customerData.getPricePlan().getName()).build());
    slackService.sendNotification("Deleted `" + customerData + "`", SlackService.Channel.BUSINESS_EVENTS);
    logger.info("Deleted customer {}", customerData);
}
Also used : CustomerData(io.codekvast.common.customer.CustomerData) CacheEvict(org.springframework.cache.annotation.CacheEvict) Transactional(org.springframework.transaction.annotation.Transactional)

Example 33 with CustomerData

use of io.codekvast.common.customer.CustomerData in project codekvast by crispab.

the class CustomerServiceImpl method changePlanForExternalId.

@Override
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = CUSTOMERS_CACHE, allEntries = true)
public void changePlanForExternalId(String source, @NonNull String externalId, @NonNull String newPlanName) {
    CustomerData customerData = getCustomerDataByExternalId(source, externalId);
    PricePlan oldEffectivePricePlan = customerData.getPricePlan();
    String oldPlanName = oldEffectivePricePlan.getName();
    if (newPlanName.equals(oldPlanName)) {
        logger.info("{} is already on plan '{}'", customerData, newPlanName);
        return;
    }
    int count = jdbcTemplate.update("UPDATE customers SET plan = ? WHERE source = ? AND externalId = ? ORDER BY id ", newPlanName, source, externalId);
    if (count == 0) {
        logger.error("Failed to change plan for customer {} from '{}' to '{}'", customerData.getDisplayName(), oldPlanName, newPlanName);
        return;
    }
    String logMessage = String.format("Changed plan for customer %s from '%s' to '%s'", customerData.getDisplayName(), oldPlanName, newPlanName);
    logger.info(logMessage);
    slackService.sendNotification(logMessage, SlackService.Channel.BUSINESS_EVENTS);
    eventService.send(PlanChangedEvent.builder().customerId(customerData.getCustomerId()).oldPlan(oldPlanName).newPlan(newPlanName).build());
    count = jdbcTemplate.update("DELETE FROM price_plan_overrides WHERE customerId = ?", customerData.getCustomerId());
    if (count > 0) {
        PricePlan newEffectivePricePlan = PricePlan.of(PricePlanDefaults.ofDatabaseName(newPlanName));
        eventService.send(PlanOverridesDeletedEvent.builder().customerId(customerData.getCustomerId()).oldEffectivePlan(oldEffectivePricePlan).newEffectivePlan(newEffectivePricePlan).build());
        String pricePlanOverridesMessage = String.format("Removed price plan overrides for customer %s, effective price plan changed from `%s` to `%s`", customerData.getDisplayName(), oldEffectivePricePlan, newEffectivePricePlan);
        slackService.sendNotification(pricePlanOverridesMessage, SlackService.Channel.BUSINESS_EVENTS);
        logger.warn(pricePlanOverridesMessage);
    }
}
Also used : CustomerData(io.codekvast.common.customer.CustomerData) PricePlan(io.codekvast.common.customer.PricePlan) CacheEvict(org.springframework.cache.annotation.CacheEvict) Transactional(org.springframework.transaction.annotation.Transactional)

Example 34 with CustomerData

use of io.codekvast.common.customer.CustomerData in project codekvast by crispab.

the class SecurityServiceImpl method doHerokuSingleSignOn.

@Override
@Transactional(rollbackFor = Exception.class)
public String doHerokuSingleSignOn(String token, String externalId, String email, long timestampSeconds, String salt) throws AuthenticationException {
    String expectedToken = makeHerokuSsoToken(externalId, timestampSeconds, salt);
    logger.debug("id={}, token={}, timestamp={}, expectedToken={}", externalId, maskSecondHalf(token), timestampSeconds, maskSecondHalf(expectedToken));
    long nowSeconds = Instant.now().getEpochSecond();
    if (timestampSeconds > nowSeconds + 60) {
        throw new NonceExpiredException("Timestamp is too far into the future");
    }
    if (timestampSeconds < nowSeconds - 5 * 60) {
        throw new NonceExpiredException("Timestamp is too old");
    }
    if (!expectedToken.equals(token)) {
        throw new BadCredentialsException("Invalid token");
    }
    CustomerData customerData = customerService.getCustomerDataByExternalId(CustomerService.Source.HEROKU, externalId);
    customerService.registerLogin(CustomerService.LoginRequest.builder().customerId(customerData.getCustomerId()).source(CustomerService.Source.HEROKU).email(email).build());
    return createCodeForWebappToken(customerData.getCustomerId(), WebappCredentials.builder().customerName(customerData.getCustomerName()).email(email).source(CustomerService.Source.HEROKU).build());
}
Also used : CustomerData(io.codekvast.common.customer.CustomerData) BadCredentialsException(org.springframework.security.authentication.BadCredentialsException) NonceExpiredException(org.springframework.security.web.authentication.www.NonceExpiredException) Transactional(org.springframework.transaction.annotation.Transactional)

Example 35 with CustomerData

use of io.codekvast.common.customer.CustomerData in project codekvast by crispab.

the class DashboardIntegrationTest method should_reject_publication_invalid_licenseKey.

@Test(expected = AuthenticationCredentialsNotFoundException.class)
@Sql(scripts = "/sql/base-data.sql")
public void should_reject_publication_invalid_licenseKey() {
    CustomerData customerData = customerService.getCustomerDataByLicenseKey("undefined");
    customerService.assertPublicationSize(customerData, 10);
}
Also used : CustomerData(io.codekvast.common.customer.CustomerData) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) Test(org.junit.Test) Sql(org.springframework.test.context.jdbc.Sql)

Aggregations

CustomerData (io.codekvast.common.customer.CustomerData)48 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)28 Sql (org.springframework.test.context.jdbc.Sql)28 Test (org.junit.Test)22 Instant (java.time.Instant)13 Test (org.junit.jupiter.api.Test)10 Transactional (org.springframework.transaction.annotation.Transactional)9 PricePlanDefaults (io.codekvast.common.customer.PricePlanDefaults)4 PricePlan (io.codekvast.common.customer.PricePlan)3 GetStatusResponse (io.codekvast.dashboard.dashboard.model.status.GetStatusResponse)3 Timestamp (java.sql.Timestamp)3 CollectionStartedEvent (io.codekvast.common.messaging.model.CollectionStartedEvent)2 User (io.codekvast.login.model.User)2 CacheEvict (org.springframework.cache.annotation.CacheEvict)2 LicenseViolationException (io.codekvast.common.customer.LicenseViolationException)1 LicenseViolationEvent (io.codekvast.common.messaging.model.LicenseViolationEvent)1 GetMethodsFormData (io.codekvast.dashboard.dashboard.model.methods.GetMethodsFormData)1 AgentDescriptor (io.codekvast.dashboard.dashboard.model.status.AgentDescriptor)1 ApplicationDescriptor2 (io.codekvast.dashboard.dashboard.model.status.ApplicationDescriptor2)1 EnvironmentStatusDescriptor (io.codekvast.dashboard.dashboard.model.status.EnvironmentStatusDescriptor)1