content: package com.ctrip.framework.apollo.openapi.service;
  
  import com.google.common.base.Charsets;
  import com.google.common.base.Joiner;
  import com.google.common.base.Preconditions;
  import com.google.common.base.Strings;
  import com.google.common.hash.Hashing;
  
  import com.ctrip.framework.apollo.common.exception.BadRequestException;
  import com.ctrip.framework.apollo.openapi.entity.Consumer;
  import com.ctrip.framework.apollo.openapi.entity.ConsumerAudit;
  import com.ctrip.framework.apollo.openapi.entity.ConsumerRole;
  import com.ctrip.framework.apollo.openapi.entity.ConsumerToken;
  import com.ctrip.framework.apollo.openapi.repository.ConsumerAuditRepository;
  import com.ctrip.framework.apollo.openapi.repository.ConsumerRepository;
  import com.ctrip.framework.apollo.openapi.repository.ConsumerRoleRepository;
  import com.ctrip.framework.apollo.openapi.repository.ConsumerTokenRepository;
  import com.ctrip.framework.apollo.portal.component.config.PortalConfig;
  import com.ctrip.framework.apollo.portal.entity.bo.UserInfo;
  import com.ctrip.framework.apollo.portal.entity.po.Role;
  import com.ctrip.framework.apollo.portal.service.RolePermissionService;
  import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
  import com.ctrip.framework.apollo.portal.spi.UserService;
  import com.ctrip.framework.apollo.portal.util.RoleUtils;
  
  import org.apache.commons.lang.time.FastDateFormat;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  import org.springframework.transaction.annotation.Transactional;
  
  import java.util.Arrays;
  import java.util.Date;
  import java.util.List;
  
  /**
   * @author Jason Song(song_s@ctrip.com)
   */
  @Service
  public class ConsumerService {
  
    private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmss");
    private static final Joiner KEY_JOINER = Joiner.on("|");
  
    @Autowired
    private UserInfoHolder userInfoHolder;
    @Autowired
    private ConsumerTokenRepository consumerTokenRepository;
    @Autowired
    private ConsumerRepository consumerRepository;
    @Autowired
    private ConsumerAuditRepository consumerAuditRepository;
    @Autowired
    private ConsumerRoleRepository consumerRoleRepository;
    @Autowired
    private PortalConfig portalConfig;
    @Autowired
    private RolePermissionService rolePermissionService;
    @Autowired
    private UserService userService;
  
  
    public Consumer createConsumer(Consumer consumer) {
      String appId = consumer.getAppId();
  
      Consumer managedConsumer = consumerRepository.findByAppId(appId);
      if (managedConsumer != null) {
        throw new BadRequestException("Consumer already exist");
      }
  
      String ownerName = consumer.getOwnerName();
      UserInfo owner = userService.findByUserId(ownerName);
      if (owner == null) {
        throw new BadRequestException(String.format("User does not exist. UserId = %s", ownerName));
      }
      consumer.setOwnerEmail(owner.getEmail());
  
      String operator = userInfoHolder.getUser().getUserId();
      consumer.setDataChangeCreatedBy(operator);
      consumer.setDataChangeLastModifiedBy(operator);
  
      return consumerRepository.save(consumer);
    }
  
    public ConsumerToken generateAndSaveConsumerToken(Consumer consumer, Date expires) {
      Preconditions.checkArgument(consumer != null, "Consumer can not be null");
  
      ConsumerToken consumerToken = generateConsumerToken(consumer, expires);
      consumerToken.setId(0);
  
      return consumerTokenRepository.save(consumerToken);
    }
  
    public ConsumerToken getConsumerTokenByAppId(String appId) {
      Consumer consumer = consumerRepository.findByAppId(appId);
      if (consumer == null) {
        return null;
      }
  
      return consumerTokenRepository.findByConsumerId(consumer.getId());
    }
  
    public Long getConsumerIdByToken(String token) {
      if (Strings.isNullOrEmpty(token)) {
        return null;
      }
      ConsumerToken consumerToken = consumerTokenRepository.findTopByTokenAndExpiresAfter(token,
                                                                                          new Date());
      return consumerToken == null ? null : consumerToken.getConsumerId();
    }
  
    public Consumer getConsumerByConsumerId(long consumerId) {
      return consumerRepository.findOne(consumerId);
    }
  
    @Transactional
    public List<ConsumerRole> assignNamespaceRoleToConsumer(String token, String appId, String namespaceName) {
      Long consumerId = getConsumerIdByToken(token);
      if (consumerId == null) {
        throw new BadRequestException("Token is Illegal");
      }
  
      Role namespaceModifyRole =
          rolePermissionService.findRoleByRoleName(RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName));
      Role namespaceReleaseRole =
          rolePermissionService.findRoleByRoleName(RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName));
  
      if (namespaceModifyRole == null || namespaceReleaseRole == null) {
        throw new BadRequestException("Namespace's role does not exist. Please check whether namespace has created.");
      }
  
      long namespaceModifyRoleId = namespaceModifyRole.getId();
      long namespaceReleaseRoleId = namespaceReleaseRole.getId();
  
      ConsumerRole managedModifyRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, namespaceModifyRoleId);
      ConsumerRole managedReleaseRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, namespaceReleaseRoleId);
      if (managedModifyRole != null && managedReleaseRole != null) {
        return Arrays.asList(managedModifyRole, managedReleaseRole);
      }
  
      String operator = userInfoHolder.getUser().getUserId();
  
      ConsumerRole namespaceModifyConsumerRole = createConsumerRole(consumerId, namespaceModifyRoleId, operator);
      ConsumerRole namespaceReleaseConsumerRole = createConsumerRole(consumerId, namespaceReleaseRoleId, operator);
  
      ConsumerRole createdModifyConsumerRole = consumerRoleRepository.save(namespaceModifyConsumerRole);
      ConsumerRole createdReleaseConsumerRole = consumerRoleRepository.save(namespaceReleaseConsumerRole);
  
      return Arrays.asList(createdModifyConsumerRole, createdReleaseConsumerRole);
    }
  
    @Transactional
    public ConsumerRole assignAppRoleToConsumer(String token, String appId) {
      Long consumerId = getConsumerIdByToken(token);
      if (consumerId == null) {
        throw new BadRequestException("Token is Illegal");
      }
  
      Role masterRole = rolePermissionService.findRoleByRoleName(RoleUtils.buildAppMasterRoleName(appId));
      if (masterRole == null) {
        throw new BadRequestException("App's role does not exist. Please check whether app has created.");
      }
  
      long roleId = masterRole.getId();
      ConsumerRole managedModifyRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, roleId);
      if (managedModifyRole != null) {
        return managedModifyRole;
      }
  
      String operator = userInfoHolder.getUser().getUserId();
      ConsumerRole consumerRole = createConsumerRole(consumerId, roleId, operator);
      return consumerRoleRepository.save(consumerRole);
    }
  
    @Transactional
    public void createConsumerAudits(Iterable<ConsumerAudit> consumerAudits) {
      consumerAuditRepository.save(consumerAudits);
    }
  
    @Transactional
    public ConsumerToken createConsumerToken(ConsumerToken entity) {
      entity.setId(0); //for protection
  
      return consumerTokenRepository.save(entity);
    }
  
    private ConsumerToken generateConsumerToken(Consumer consumer, Date expires) {
      long consumerId = consumer.getId();
      String createdBy = userInfoHolder.getUser().getUserId();
      Date createdTime = new Date();
  
      ConsumerToken consumerToken = new ConsumerToken();
      consumerToken.setConsumerId(consumerId);
      consumerToken.setExpires(expires);
      consumerToken.setDataChangeCreatedBy(createdBy);
      consumerToken.setDataChangeCreatedTime(createdTime);
      consumerToken.setDataChangeLastModifiedBy(createdBy);
      consumerToken.setDataChangeLastModifiedTime(createdTime);
  
      generateAndEnrichToken(consumer, consumerToken);
  
      return consumerToken;
    }
  
    void generateAndEnrichToken(Consumer consumer, ConsumerToken consumerToken) {
  
      Preconditions.checkArgument(consumer != null);
  
      if (consumerToken.getDataChangeCreatedTime() == null) {
        consumerToken.setDataChangeCreatedTime(new Date());
      }
      consumerToken.setToken(generateToken(consumer.getAppId(), consumerToken
          .getDataChangeCreatedTime(), portalConfig.consumerTokenSalt()));
    }
  
    String generateToken(String consumerAppId, Date generationTime, String
        consumerTokenSalt) {
      return Hashing.sha1().hashString(KEY_JOINER.join(consumerAppId, TIMESTAMP_FORMAT.format
          (generationTime), consumerTokenSalt), Charsets.UTF_8).toString();
    }
  
      ConsumerRole createConsumerRole(Long consumerId, Long roleId, String operator) {
      ConsumerRole consumerRole = new ConsumerRole();
  
      consumerRole.setConsumerId(consumerId);
      consumerRole.setRoleId(roleId);
      consumerRole.setDataChangeCreatedBy(operator);
      consumerRole.setDataChangeLastModifiedBy(operator);
  
      return consumerRole;
    }
  
  }
  