forked from apolloconfig/apollo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request apolloconfig#552 from lepdou/token
apply consumer token and assign consumer role
- Loading branch information
Showing
13 changed files
with
675 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,7 @@ | |
* @author Jason Song([email protected]) | ||
*/ | ||
public interface ConsumerRepository extends PagingAndSortingRepository<Consumer, Long> { | ||
|
||
Consumer findByAppId(String appId); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,63 +6,150 @@ | |
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([email protected]) | ||
*/ | ||
@Service | ||
public class ConsumerService { | ||
static final String TOKEN_SALT_KEY = "consumer.token.salt"; | ||
private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance | ||
("yyyyMMddHHmmss"); | ||
|
||
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()); | ||
new Date()); | ||
return consumerToken == null ? null : consumerToken.getConsumerId(); | ||
} | ||
|
||
public Consumer getConsumerByConsumerId(long consumerId) { | ||
return consumerRepository.findOne(consumerId); | ||
} | ||
|
||
public void generateAndEnrichConsumerToken(ConsumerToken consumerToken) { | ||
Consumer consumer = getConsumerByConsumerId(consumerToken.getConsumerId()); | ||
@Transactional | ||
public List<ConsumerRole> assignNamespaceRoleToConsumer(String token, String appId, String namespaceName) { | ||
Long consumerId = getConsumerIdByToken(token); | ||
if (consumerId == null) { | ||
throw new BadRequestException("Token is Illegal"); | ||
} | ||
|
||
Preconditions.checkState(consumer != null, String.format("Consumer with id: %d not found!", | ||
consumerToken.getConsumerId())); | ||
Role namespaceModifyRole = | ||
rolePermissionService.findRoleByRoleName(RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName)); | ||
Role namespaceReleaseRole = | ||
rolePermissionService.findRoleByRoleName(RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName)); | ||
|
||
if (consumerToken.getDataChangeCreatedTime() == null) { | ||
consumerToken.setDataChangeCreatedTime(new Date()); | ||
if (namespaceModifyRole == null || namespaceReleaseRole == null) { | ||
throw new BadRequestException("Namespace's role does not exist. Please check whether namespace has created."); | ||
} | ||
consumerToken.setToken(generateConsumerToken(consumer.getAppId(), consumerToken | ||
.getDataChangeCreatedTime(), portalConfig.consumerTokenSalt())); | ||
|
||
long namespaceModifyRoleId = namespaceModifyRole.getId(); | ||
long namespaceReleaseRoleId = namespaceReleaseRole.getId(); | ||
|
||
ConsumerRole managedModifyRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, namespaceModifyRoleId); | ||
if (managedModifyRole != null) { | ||
throw new BadRequestException("Namespace's role has assigned to consumer."); | ||
} | ||
|
||
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 void createConsumerAudits(Iterable<ConsumerAudit> consumerAudits) { | ||
consumerAuditRepository.save(consumerAudits); | ||
} | ||
|
||
@Transactional | ||
|
@@ -72,15 +159,50 @@ public ConsumerToken createConsumerToken(ConsumerToken entity) { | |
return consumerTokenRepository.save(entity); | ||
} | ||
|
||
@Transactional | ||
public void createConsumerAudits(Iterable<ConsumerAudit> consumerAudits) { | ||
consumerAuditRepository.save(consumerAudits); | ||
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 generateConsumerToken(String consumerAppId, Date generationTime, String | ||
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; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,19 @@ | ||
package com.ctrip.framework.apollo.portal.controller; | ||
|
||
import com.ctrip.framework.apollo.common.dto.NamespaceDTO; | ||
import com.ctrip.framework.apollo.common.exception.BadRequestException; | ||
import com.ctrip.framework.apollo.core.utils.StringUtils; | ||
import com.ctrip.framework.apollo.openapi.entity.Consumer; | ||
import com.ctrip.framework.apollo.openapi.entity.ConsumerRole; | ||
import com.ctrip.framework.apollo.openapi.entity.ConsumerToken; | ||
import com.ctrip.framework.apollo.openapi.service.ConsumerService; | ||
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.format.annotation.DateTimeFormat; | ||
import org.springframework.security.access.prepost.PreAuthorize; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestMethod; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
|
@@ -16,50 +22,60 @@ | |
import java.util.Calendar; | ||
import java.util.Date; | ||
import java.util.GregorianCalendar; | ||
import java.util.List; | ||
|
||
/** | ||
* @author Jason Song([email protected]) | ||
*/ | ||
@RestController | ||
@RequestMapping("/consumers") | ||
public class ConsumerController { | ||
private static final Date DEFAULT_EXPIRES = new GregorianCalendar(2099, Calendar.JANUARY, 1) | ||
.getTime(); | ||
|
||
private static final Date DEFAULT_EXPIRES = new GregorianCalendar(2099, Calendar.JANUARY, 1).getTime(); | ||
|
||
@Autowired | ||
private ConsumerService consumerService; | ||
@Autowired | ||
private UserInfoHolder userInfoHolder; | ||
|
||
|
||
@Transactional | ||
@PreAuthorize(value = "@permissionValidator.isSuperAdmin()") | ||
@RequestMapping(value = "/{consumerId}/tokens", method = RequestMethod.POST) | ||
public ConsumerToken createConsumerToken(@PathVariable long consumerId, | ||
@RequestParam(value = "expires", required = false) | ||
@DateTimeFormat(pattern = "yyyyMMddHHmmss") Date | ||
expires) { | ||
@RequestMapping(value = "/consumers", method = RequestMethod.POST) | ||
public ConsumerToken createConsumer(@RequestBody Consumer consumer, | ||
@RequestParam(value = "expires", required = false) | ||
@DateTimeFormat(pattern = "yyyyMMddHHmmss") Date | ||
expires) { | ||
|
||
if (StringUtils.isContainEmpty(consumer.getAppId(), consumer.getName(), | ||
consumer.getOwnerName(), consumer.getOrgId())) { | ||
throw new BadRequestException("Params(appId、name、ownerName、orgId) can not be empty."); | ||
} | ||
|
||
Consumer createdConsumer = consumerService.createConsumer(consumer); | ||
|
||
if (expires == null) { | ||
expires = DEFAULT_EXPIRES; | ||
} | ||
|
||
ConsumerToken consumerToken = generateConsumerToken(consumerId, expires); | ||
return consumerService.generateAndSaveConsumerToken(createdConsumer, expires); | ||
} | ||
|
||
return consumerService.createConsumerToken(consumerToken); | ||
@RequestMapping(value = "/consumers/by-appId", method = RequestMethod.GET) | ||
public ConsumerToken getConsumerTokenByAppId(@RequestParam String appId) { | ||
return consumerService.getConsumerTokenByAppId(appId); | ||
} | ||
|
||
private ConsumerToken generateConsumerToken(long consumerId, Date expires) { | ||
String createdBy = userInfoHolder.getUser().getUserId(); | ||
Date createdTime = new Date(); | ||
@PreAuthorize(value = "@permissionValidator.isSuperAdmin()") | ||
@RequestMapping(value = "/consumers/{token}/assign-role", method = RequestMethod.POST) | ||
public List<ConsumerRole> assignRoleToConsumer(@PathVariable String token, @RequestBody NamespaceDTO namespace) { | ||
|
||
ConsumerToken consumerToken = new ConsumerToken(); | ||
consumerToken.setConsumerId(consumerId); | ||
consumerToken.setExpires(expires); | ||
consumerToken.setDataChangeCreatedBy(createdBy); | ||
consumerToken.setDataChangeCreatedTime(createdTime); | ||
consumerToken.setDataChangeLastModifiedBy(createdBy); | ||
consumerToken.setDataChangeLastModifiedTime(createdTime); | ||
String appId = namespace.getAppId(); | ||
String namespaceName = namespace.getNamespaceName(); | ||
|
||
consumerService.generateAndEnrichConsumerToken(consumerToken); | ||
if (StringUtils.isContainEmpty(appId, namespaceName)) { | ||
throw new BadRequestException("Params(AppId、NamespaceName) can not be empty."); | ||
} | ||
|
||
return consumerToken; | ||
return consumerService.assignNamespaceRoleToConsumer(token, appId, namespaceName); | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.