diff --git a/hsweb-authorization/hsweb-authorization-api/pom.xml b/hsweb-authorization/hsweb-authorization-api/pom.xml index 67da5a491..c4f35aff1 100644 --- a/hsweb-authorization/hsweb-authorization-api/pom.xml +++ b/hsweb-authorization/hsweb-authorization-api/pom.xml @@ -18,6 +18,12 @@ ${project.version} + + org.springframework.data + spring-data-redis + true + + com.alibaba fastjson @@ -34,10 +40,12 @@ reactor-test test + io.swagger swagger-annotations + javax.servlet javax.servlet-api diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java index 7d7c43dbe..c257163f6 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java @@ -51,14 +51,6 @@ public interface UserToken extends Serializable, Comparable { long getMaxInactiveInterval(); - /** - * @return 是否正常 - */ - @Deprecated - default boolean isEffective() { - return isNormal(); - } - default boolean isNormal() { return getState() == TokenState.normal; } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java index 8a6f6b716..cc301c8f2 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java @@ -71,12 +71,7 @@ public class UserTokenReactiveAuthenticationSupplier implements ReactiveAuthenti context.get(ContextKey.of(ParsedToken.class)) .map(t -> userTokenManager .getByToken(t.getToken()) - .map(token -> { - if (!token.isNormal()) { - throw new UnAuthorizedException(token.getState()); - } - return token; - })) + .filter(UserToken::validate)) .map(tokenMono -> tokenMono .doOnNext(token->userTokenManager.touch(token.getToken())) .flatMap(token -> get(thirdPartAuthenticationManager.get(token.getType()), token.getUserId()))) diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedReactiveAuthenticationManager.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedReactiveAuthenticationManager.java index 3e1448df4..a9505d527 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedReactiveAuthenticationManager.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedReactiveAuthenticationManager.java @@ -15,7 +15,7 @@ import reactor.core.publisher.Mono; * @since 3.0.0-RC */ -@Order(Ordered.HIGHEST_PRECEDENCE) +@Order(10) @AllArgsConstructor public class EmbedReactiveAuthenticationManager implements ReactiveAuthenticationManagerProvider { diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/DefaultUserTokenGenPar.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/DefaultUserTokenGenPar.java index 47cb03374..0e4c1810f 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/DefaultUserTokenGenPar.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/DefaultUserTokenGenPar.java @@ -10,6 +10,7 @@ import reactor.core.publisher.Mono; import java.util.Collections; import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; @Getter @@ -54,10 +55,11 @@ public class DefaultUserTokenGenPar implements ReactiveUserTokenGenerator, React @Override public Mono parseToken(ServerWebExchange exchange) { - String token =exchange.getRequest() + String token = Optional.ofNullable(exchange.getRequest() .getHeaders() - .getFirst(headerName); - if(token==null){ + .getFirst(headerName)) + .orElseGet(() -> exchange.getRequest().getQueryParams().getFirst(":X_Access_Token")); + if (token == null) { return Mono.empty(); } return Mono.just(new ParsedToken() { diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DataAccessEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DataAccessEntity.java index 3fd682667..c8fad2ef4 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DataAccessEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DataAccessEntity.java @@ -3,6 +3,7 @@ package org.hswebframework.web.system.authorization.api.entity; import lombok.Getter; import lombok.Setter; +import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -17,4 +18,17 @@ public class DataAccessEntity { private String describe; private Map config; + + public Map toMap(){ + Map map = new HashMap<>(); + map.put("type",type); + map.put("action",action); + map.put("describe",describe); + + if(config!=null){ + map.putAll(config); + } + + return map; + } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java index 3a1e3497a..a7968c649 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java @@ -32,13 +32,13 @@ public class UserEntity extends GenericEntity implements RecordCreationE @Column(nullable = false) @ToString.Ignore(cover = false) - @JsonProperty(access = JsonProperty.Access.READ_ONLY) + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @NotBlank(message = "密码不能为空", groups = CreateGroup.class) private String password; @Column(nullable = false) @ToString.Ignore(cover = false) - @JsonProperty(access = JsonProperty.Access.READ_ONLY) + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String salt; @Column diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionService.java index 25fce88d8..86da611d2 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionService.java @@ -7,12 +7,15 @@ import org.hswebframework.web.authorization.DimensionType; import org.hswebframework.web.crud.service.GenericReactiveCrudService; import org.hswebframework.web.crud.service.ReactiveTreeSortEntityService; import org.hswebframework.web.id.IDGenerator; +import org.hswebframework.web.system.authorization.api.entity.AuthorizationSettingEntity; import org.hswebframework.web.system.authorization.api.entity.DimensionEntity; import org.hswebframework.web.system.authorization.api.entity.DimensionTypeEntity; import org.hswebframework.web.system.authorization.api.entity.DimensionUserEntity; +import org.reactivestreams.Publisher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import java.util.List; import java.util.function.Function; @@ -29,6 +32,9 @@ public class DefaultDimensionService @Autowired private ReactiveRepository dimensionTypeRepository; + @Autowired + private ReactiveRepository settingRepository; + @Override public IDGenerator getIDGenerator() { return IDGenerator.MD5; @@ -57,7 +63,6 @@ public class DefaultDimensionService .where(DimensionUserEntity::getUserId, userId) .fetch() .map(entity -> DynamicDimension.of(entity, typeGrouping.get(entity.getDimensionTypeId())))); - } @Override @@ -70,4 +75,25 @@ public class DefaultDimensionService .fetch() .map(DimensionUserEntity::getUserId); } + + @Override + public Mono deleteById(Publisher idPublisher) { + return Flux.from(idPublisher) + .collectList() + .flatMap(list -> super.deleteById(Flux.fromIterable(list)) + .then(dimensionUserRepository.createDelete() //删除维度用户关联 + .where() + .in(DimensionUserEntity::getDimensionId, list) + .execute()) + .then(findById(Flux.fromIterable(list)) + .groupBy(DimensionEntity::getTypeId, DimensionEntity::getId)//按维度类型分组 + .flatMap(grouping -> grouping.collectList() + .flatMap(dimensionId -> settingRepository //删除权限设置 + .createDelete() + .where(AuthorizationSettingEntity::getDimensionType, grouping.key()) + .in(AuthorizationSettingEntity::getDimensionTarget, dimensionId).execute())) + .collect(Collectors.summarizingInt(Integer::intValue)) + ).thenReturn(list.size())); + } + } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java index 54c4833cd..1ed18e244 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java @@ -1,5 +1,6 @@ package org.hswebframework.web.system.authorization.defaults.service; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository; import org.hswebframework.web.authorization.Authentication; @@ -28,6 +29,7 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +@Slf4j public class DefaultReactiveAuthenticationInitializeService implements ReactiveAuthenticationInitializeService { @@ -101,76 +103,76 @@ public class DefaultReactiveAuthenticationInitializeService Map> settings) { Map permissionMap = new HashMap<>(); Map allowed = new HashMap<>(); - - for (PermissionEntity permissionEntity : permissions.values()) { - permissionMap.put(permissionEntity.getId(), permissionEntity); - List permissionSettings = settings.get(permissionEntity.getId()); - if (CollectionUtils.isEmpty(permissionSettings)) { - continue; - } - permissionSettings.sort(Comparator.comparingInt(e -> e.getPriority() == null ? 0 : e.getPriority())); - SimplePermission permission = new SimplePermission(); - permission.setId(permissionEntity.getId()); - permission.setName(permissionEntity.getName()); - Map configs = new HashMap<>(); - - for (AuthorizationSettingEntity permissionSetting : permissionSettings) { - - boolean merge = Boolean.TRUE.equals(permissionSetting.getMerge()); - - if (!merge) { - permission.getActions().clear(); - } - - if (permissionSetting.getDataAccesses() != null) { - permissionSetting.getDataAccesses() - .stream() - .map(conf -> builderFactory.create().fromMap(conf.getConfig()).build()) - .forEach(access -> configs.put(access.getType(), access)); - } - if (CollectionUtils.isNotEmpty(permissionSetting.getActions())) { - permission.getActions().addAll(permissionSetting.getActions()); - } - - } - allowed.put(permissionEntity.getId(), permission); - permission.setDataAccesses(new HashSet<>(configs.values())); - } - - //处理关联权限 - for (PermissionEntity permissionEntity : permissions.values()) { - SimplePermission allow = allowed.get(permissionEntity.getId()); - if (allow == null || CollectionUtils.isEmpty(permissionEntity.getParents())) { - continue; - } - for (ParentPermission parent : permissionEntity.getParents()) { - if (StringUtils.isEmpty(parent.getPermission())) { + try { + for (PermissionEntity permissionEntity : permissions.values()) { + permissionMap.put(permissionEntity.getId(), permissionEntity); + List permissionSettings = settings.get(permissionEntity.getId()); + if (CollectionUtils.isEmpty(permissionSettings)) { continue; } - Set pre = parent.getPreActions(); - //满足前置条件 - if (CollectionUtils.isEmpty(pre) || allow.getActions().containsAll(pre)) { - PermissionEntity mergePermission = permissionMap.get(parent.getPermission()); - if (mergePermission == null) { + permissionSettings.sort(Comparator.comparingInt(e -> e.getPriority() == null ? 0 : e.getPriority())); + SimplePermission permission = new SimplePermission(); + permission.setId(permissionEntity.getId()); + permission.setName(permissionEntity.getName()); + Map configs = new HashMap<>(); + + for (AuthorizationSettingEntity permissionSetting : permissionSettings) { + + boolean merge = Boolean.TRUE.equals(permissionSetting.getMerge()); + + if (!merge) { + permission.getActions().clear(); + } + + if (permissionSetting.getDataAccesses() != null) { + permissionSetting.getDataAccesses() + .stream() + .map(conf -> builderFactory.create().fromMap(conf.toMap()).build()) + .forEach(access -> configs.put(access.getType(), access)); + } + if (CollectionUtils.isNotEmpty(permissionSetting.getActions())) { + permission.getActions().addAll(permissionSetting.getActions()); + } + + } + allowed.put(permissionEntity.getId(), permission); + permission.setDataAccesses(new HashSet<>(configs.values())); + } + + //处理关联权限 + for (PermissionEntity permissionEntity : permissions.values()) { + SimplePermission allow = allowed.get(permissionEntity.getId()); + if (allow == null || CollectionUtils.isEmpty(permissionEntity.getParents())) { + continue; + } + for (ParentPermission parent : permissionEntity.getParents()) { + if (StringUtils.isEmpty(parent.getPermission())) { continue; } - SimplePermission merge = allowed.get(parent.getPermission()); - if (merge == null) { - merge = new SimplePermission(); - merge.setName(mergePermission.getName()); - merge.setId(mergePermission.getId()); - allowed.put(merge.getId(), merge); - } - if (CollectionUtils.isNotEmpty(parent.getActions())) { - merge.getActions().addAll(parent.getActions()); + Set pre = parent.getPreActions(); + //满足前置条件 + if (CollectionUtils.isEmpty(pre) || allow.getActions().containsAll(pre)) { + PermissionEntity mergePermission = permissionMap.get(parent.getPermission()); + if (mergePermission == null) { + continue; + } + SimplePermission merge = allowed.get(parent.getPermission()); + if (merge == null) { + merge = new SimplePermission(); + merge.setName(mergePermission.getName()); + merge.setId(mergePermission.getId()); + allowed.put(merge.getId(), merge); + } + if (CollectionUtils.isNotEmpty(parent.getActions())) { + merge.getActions().addAll(parent.getActions()); + } } } } + authentication.setPermissions(new ArrayList<>(allowed.values())); + } catch (Exception e) { + log.error(e.getMessage(), e); } - - - authentication.setPermissions(new ArrayList<>(allowed.values())); - return authentication; } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationManager.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationManager.java index 9589734c2..5990036cd 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationManager.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationManager.java @@ -12,9 +12,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; import org.springframework.cache.support.SimpleValueWrapper; import org.springframework.context.event.EventListener; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import reactor.core.publisher.Mono; @Slf4j +@Order(100) public class DefaultReactiveAuthenticationManager implements ReactiveAuthenticationManagerProvider { @Autowired @@ -65,7 +68,6 @@ public class DefaultReactiveAuthenticationManager implements ReactiveAuthenticat .flatMap(_id -> Mono.justOrEmpty(cacheManager) .map(cm -> cacheManager.getCache("user-auth")) .flatMap(cache -> cache.mono(userId).onCacheMissResume(() -> initializeService.initUserAuthorization(userId))) - .cast(Authentication.class) - .switchIfEmpty(initializeService.initUserAuthorization(userId))); + .cast(Authentication.class)); } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/PermissionSynchronization.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/PermissionSynchronization.java index 6bf3306ba..638d156f4 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/PermissionSynchronization.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/PermissionSynchronization.java @@ -78,7 +78,7 @@ public class PermissionSynchronization implements CommandLineRunner { .as(permissionRepository::save)) .doOnError(err -> log.warn("sync permission error", err)) .subscribe(l -> { - log.warn("sync permission success:{}", l); + log.info("sync permission success:{}", l); }); } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/webflux/WebFluxDimensionUserController.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/webflux/WebFluxDimensionUserController.java index 4bec45462..4abb31953 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/webflux/WebFluxDimensionUserController.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/webflux/WebFluxDimensionUserController.java @@ -1,19 +1,23 @@ package org.hswebframework.web.system.authorization.defaults.webflux; import org.hswebframework.web.authorization.annotation.Authorize; +import org.hswebframework.web.authorization.annotation.DeleteAction; import org.hswebframework.web.authorization.annotation.Resource; import org.hswebframework.web.crud.service.ReactiveCrudService; import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController; import org.hswebframework.web.system.authorization.api.entity.DimensionUserEntity; import org.hswebframework.web.system.authorization.defaults.service.DefaultDimensionUserService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; @RestController @RequestMapping("/dimension-user") @Authorize -@Resource(id = "dimension",name = "权限维度管理",group = "system") +@Resource(id = "dimension", name = "权限维度管理", group = "system") public class WebFluxDimensionUserController implements ReactiveServiceCrudController { @Autowired @@ -23,4 +27,33 @@ public class WebFluxDimensionUserController implements ReactiveServiceCrudContro public ReactiveCrudService getService() { return dimensionUserService; } + + + @DeleteAction + @DeleteMapping("/user/{userId}/dimension/{dimensionId}") + public Mono deleteByUserAndDimensionId(@PathVariable String userId, @PathVariable String dimensionId) { + return dimensionUserService + .createDelete() + .where(DimensionUserEntity::getUserId, userId) + .and(DimensionUserEntity::getDimensionId, dimensionId) + .execute(); + } + + @DeleteAction + @DeleteMapping("/user/{userId}") + public Mono deleteByUserId(@PathVariable String userId) { + return dimensionUserService + .createDelete() + .where(DimensionUserEntity::getUserId, userId) + .execute(); + } + + @DeleteAction + @DeleteMapping("/dimension/{dimensionId}") + public Mono deleteByDimension(@PathVariable String dimensionId) { + return dimensionUserService + .createDelete() + .where(DimensionUserEntity::getDimensionId, dimensionId) + .execute(); + } }