parent
9f0986a093
commit
1b699a49fb
|
@ -18,9 +18,10 @@ package org.springframework.security.config.annotation.rsocket;
|
|||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
|
||||
/**
|
||||
* The standard order for {@link org.springframework.security.rsocket.PayloadInterceptor} to be
|
||||
* The standard order for {@link PayloadInterceptor} to be
|
||||
* sorted. The actual values might change, so users should use the {@link #getOrder()} method to
|
||||
* calculate the position dynamically rather than copy values.
|
||||
*
|
||||
|
|
|
@ -29,8 +29,8 @@ import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
|||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtReactiveAuthenticationManager;
|
||||
import org.springframework.security.rsocket.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.authentication.AnonymousPayloadInterceptor;
|
||||
import org.springframework.security.rsocket.authentication.AuthenticationPayloadInterceptor;
|
||||
import org.springframework.security.rsocket.authentication.BearerPayloadExchangeConverter;
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.springframework.security.config.Customizer;
|
|||
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
|
||||
import org.springframework.security.rsocket.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder;
|
||||
import org.springframework.security.rsocket.metadata.BearerTokenMetadata;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.springframework.security.config.Customizer;
|
|||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.rsocket.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder;
|
||||
import org.springframework.security.rsocket.metadata.UsernamePasswordMetadata;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.springframework.security.config.Customizer;
|
|||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.rsocket.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder;
|
||||
import org.springframework.security.rsocket.metadata.UsernamePasswordMetadata;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.api;
|
||||
|
||||
import io.rsocket.Payload;
|
||||
import org.springframework.util.MimeType;
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.api;
|
||||
|
||||
/**
|
||||
* The {@link PayloadExchange} type
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.api;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.api;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
|
@ -23,9 +23,9 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
|||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ import org.springframework.core.Ordered;
|
|||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptorChain;
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import org.springframework.messaging.rsocket.DefaultMetadataExtractor;
|
|||
import org.springframework.messaging.rsocket.MetadataExtractor;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.metadata.BasicAuthenticationDecoder;
|
||||
import org.springframework.security.rsocket.metadata.UsernamePasswordMetadata;
|
||||
import org.springframework.util.MimeType;
|
||||
|
|
|
@ -20,7 +20,7 @@ import io.netty.buffer.ByteBuf;
|
|||
import io.rsocket.metadata.CompositeMetadata;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.metadata.BearerTokenMetadata;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.springframework.security.rsocket.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,9 +23,9 @@ import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
|||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
|
||||
/**
|
||||
* Provides authorization of the {@link PayloadExchange}.
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.springframework.security.core.Authentication;
|
|||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.util.matcher.PayloadExchangeAuthorizationContext;
|
||||
import org.springframework.security.rsocket.util.matcher.PayloadExchangeMatcher;
|
||||
import org.springframework.security.rsocket.util.matcher.PayloadExchangeMatcherEntry;
|
||||
|
|
|
@ -14,8 +14,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.core;
|
||||
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptorChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.context.Context;
|
||||
|
|
@ -14,9 +14,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.core;
|
||||
|
||||
import io.rsocket.Payload;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchangeType;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
|
|
@ -14,13 +14,15 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.core;
|
||||
|
||||
import io.rsocket.Payload;
|
||||
import io.rsocket.RSocket;
|
||||
import io.rsocket.ResponderRSocket;
|
||||
import io.rsocket.util.RSocketProxy;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.security.rsocket.api.PayloadExchangeType;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.util.MimeType;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.core;
|
||||
|
||||
import io.rsocket.ConnectionSetupPayload;
|
||||
import io.rsocket.Payload;
|
||||
|
@ -22,6 +22,8 @@ import io.rsocket.RSocket;
|
|||
import io.rsocket.SocketAcceptor;
|
||||
import io.rsocket.metadata.WellKnownMimeType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.rsocket.api.PayloadExchangeType;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
|
@ -14,12 +14,13 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.core;
|
||||
|
||||
import io.rsocket.SocketAcceptor;
|
||||
import io.rsocket.metadata.WellKnownMimeType;
|
||||
import io.rsocket.plugins.SocketAcceptorInterceptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package org.springframework.security.rsocket.util.matcher;
|
||||
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package org.springframework.security.rsocket.util.matcher;
|
||||
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
package org.springframework.security.rsocket.util.matcher;
|
||||
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadExchangeType;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchangeType;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.springframework.security.rsocket.util.matcher;
|
||||
|
||||
import org.springframework.messaging.rsocket.MetadataExtractor;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.RouteMatcher;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.springframework.security.core.Authentication;
|
|||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ import org.springframework.security.core.Authentication;
|
|||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import reactor.core.publisher.Mono;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.springframework.security.authentication.ReactiveAuthenticationManager
|
|||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.rsocket.PayloadExchangeType;
|
||||
import org.springframework.security.rsocket.api.PayloadExchangeType;
|
||||
import org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder;
|
||||
import org.springframework.security.rsocket.metadata.UsernamePasswordMetadata;
|
||||
import org.springframework.util.MimeType;
|
||||
|
@ -45,9 +45,9 @@ import org.springframework.util.MimeTypeUtils;
|
|||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import reactor.test.publisher.PublisherProbe;
|
||||
import org.springframework.security.rsocket.DefaultPayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.core.DefaultPayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ import reactor.core.publisher.Mono;
|
|||
import reactor.test.StepVerifier;
|
||||
import reactor.test.publisher.PublisherProbe;
|
||||
import reactor.util.context.Context;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.mockito.Mock;
|
|||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.util.matcher.PayloadExchangeAuthorizationContext;
|
||||
import org.springframework.security.rsocket.util.matcher.PayloadExchangeMatcher;
|
||||
import org.springframework.security.rsocket.util.matcher.PayloadExchangeMatcherEntry;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.core;
|
||||
|
||||
import io.rsocket.Payload;
|
||||
import io.rsocket.RSocket;
|
||||
|
@ -33,12 +33,12 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
|
|||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.rsocket.DefaultPayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadExchangeType;
|
||||
import org.springframework.security.rsocket.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorRSocket;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchangeType;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptorChain;
|
||||
import org.springframework.security.rsocket.core.DefaultPayloadExchange;
|
||||
import org.springframework.security.rsocket.core.PayloadInterceptorRSocket;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import reactor.core.publisher.Flux;
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.core;
|
||||
|
||||
import io.rsocket.ConnectionSetupPayload;
|
||||
import io.rsocket.Payload;
|
||||
|
@ -28,10 +28,10 @@ import org.mockito.ArgumentCaptor;
|
|||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorRSocket;
|
||||
import org.springframework.security.rsocket.PayloadSocketAcceptorInterceptor;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.core.PayloadInterceptorRSocket;
|
||||
import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Arrays;
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.rsocket;
|
||||
package org.springframework.security.rsocket.core;
|
||||
|
||||
import io.rsocket.ConnectionSetupPayload;
|
||||
import io.rsocket.Payload;
|
||||
|
@ -28,10 +28,10 @@ import org.mockito.ArgumentCaptor;
|
|||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.PayloadInterceptorRSocket;
|
||||
import org.springframework.security.rsocket.PayloadSocketAcceptor;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadInterceptor;
|
||||
import org.springframework.security.rsocket.core.PayloadInterceptorRSocket;
|
||||
import org.springframework.security.rsocket.core.PayloadSocketAcceptor;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Arrays;
|
|
@ -25,9 +25,9 @@ import org.mockito.Mock;
|
|||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.messaging.rsocket.MetadataExtractor;
|
||||
import org.springframework.security.rsocket.DefaultPayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadExchange;
|
||||
import org.springframework.security.rsocket.PayloadExchangeType;
|
||||
import org.springframework.security.rsocket.core.DefaultPayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchange;
|
||||
import org.springframework.security.rsocket.api.PayloadExchangeType;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.util.RouteMatcher;
|
||||
|
|
Loading…
Reference in New Issue