11package org .lowcoder .api .framework .plugin .endpoint ;
22
3+ import static org .lowcoder .sdk .exception .BizError .NOT_AUTHORIZED ;
34import static org .springframework .web .reactive .function .server .RequestPredicates .DELETE ;
45import static org .springframework .web .reactive .function .server .RequestPredicates .GET ;
56import static org .springframework .web .reactive .function .server .RequestPredicates .OPTIONS ;
89import static org .springframework .web .reactive .function .server .RequestPredicates .PUT ;
910import static org .springframework .web .reactive .function .server .RouterFunctions .route ;
1011
12+ import java .lang .reflect .AccessibleObject ;
1113import java .lang .reflect .InvocationTargetException ;
1214import java .lang .reflect .Method ;
1315import java .util .ArrayList ;
16+ import java .util .Collections ;
1417import java .util .List ;
1518
19+ import org .aopalliance .intercept .MethodInvocation ;
1620import org .apache .commons .collections4 .CollectionUtils ;
1721import org .apache .commons .lang3 .StringUtils ;
22+ import org .jetbrains .annotations .NotNull ;
23+ import org .jetbrains .annotations .Nullable ;
1824import org .lowcoder .api .framework .plugin .data .PluginServerRequest ;
25+ import org .lowcoder .api .framework .plugin .security .PluginAuthorizationManager ;
1926import org .lowcoder .api .framework .plugin .security .SecuredEndpoint ;
2027import org .lowcoder .plugin .api .EndpointExtension ;
2128import org .lowcoder .plugin .api .PluginEndpoint ;
2229import org .lowcoder .plugin .api .data .EndpointRequest ;
2330import org .lowcoder .plugin .api .data .EndpointResponse ;
2431import org .lowcoder .sdk .exception .BaseException ;
32+ import org .lowcoder .sdk .exception .BizException ;
2533import org .springframework .aop .TargetSource ;
2634import org .springframework .aop .framework .ProxyFactoryBean ;
35+ import org .springframework .aop .framework .ReflectiveMethodInvocation ;
2736import org .springframework .aop .target .SimpleBeanTargetSource ;
2837import org .springframework .beans .factory .support .DefaultListableBeanFactory ;
2938import org .springframework .context .ApplicationContext ;
3039import org .springframework .context .support .GenericApplicationContext ;
3140import org .springframework .core .ResolvableType ;
3241import org .springframework .http .ResponseCookie ;
3342import org .springframework .security .access .prepost .PreAuthorize ;
43+ import org .springframework .security .authentication .UsernamePasswordAuthenticationToken ;
44+ import org .springframework .security .authorization .AuthorizationDecision ;
45+ import org .springframework .security .core .Authentication ;
3446import org .springframework .security .core .context .ReactiveSecurityContextHolder ;
47+ import org .springframework .security .core .context .SecurityContext ;
3548import org .springframework .stereotype .Component ;
3649import org .springframework .web .reactive .function .server .RequestPredicate ;
3750import org .springframework .web .reactive .function .server .RouterFunction ;
@@ -52,6 +65,7 @@ public class PluginEndpointHandlerImpl implements PluginEndpointHandler
5265
5366 private final ApplicationContext applicationContext ;
5467 private final DefaultListableBeanFactory beanFactory ;
68+ private final PluginAuthorizationManager pluginAuthorizationManager ;
5569
5670 @ Override
5771 public void registerEndpoints (String pluginUrlPrefix , List <PluginEndpoint > endpoints )
@@ -101,26 +115,69 @@ private void registerEndpointHandler(String urlPrefix, PluginEndpoint endpoint,
101115
102116 log .info ("Registered endpoint: {} -> {}: {}" , endpoint .getClass ().getSimpleName (), endpointMeta .method (), urlPrefix + endpointMeta .uri ());
103117 }
104-
105- @ SecuredEndpoint
118+
106119 public Mono <ServerResponse > runPluginEndpointMethod (PluginEndpoint endpoint , EndpointExtension endpointMeta , Method handler , ServerRequest request )
107120 {
108- Mono <ServerResponse > result = null ;
109- try
110- {
111- log .info ("Running plugin endpoint method {}\n Request: {}" , handler .getName (), request );
121+ log .info ("Running plugin endpoint method {}\n Request: {}" , handler .getName (), request );
112122
113- EndpointResponse response = (EndpointResponse )handler .invoke (endpoint , PluginServerRequest .fromServerRequest (request ));
114- result = createServerResponse (response );
115- }
116- catch (IllegalAccessException | InvocationTargetException cause )
117- {
118- throw new BaseException ("Error running handler for [ " + endpointMeta .method () + ": " + endpointMeta .uri () + "] !" );
119- }
120- return result ;
123+ Mono <Authentication > monoAuthentication = ReactiveSecurityContextHolder .getContext ().map (SecurityContext ::getAuthentication ).cache ();
124+ Mono <AuthorizationDecision > decisionMono = monoAuthentication .flatMap (authentication -> {
125+ MethodInvocation methodInvocation = null ;
126+ try {
127+ methodInvocation = getMethodInvocation (endpointMeta , authentication );
128+ } catch (NoSuchMethodException e ) {
129+ return Mono .error (new RuntimeException (e ));
130+ }
131+ return pluginAuthorizationManager .check (monoAuthentication , methodInvocation );
132+ });
133+
134+ return decisionMono .<EndpointResponse >handle ((authorizationDecision , sink ) -> {
135+ if (!authorizationDecision .isGranted ()) sink .error (new BizException (NOT_AUTHORIZED , "NOT_AUTHORIZED" ));
136+ try {
137+ sink .next ((EndpointResponse ) handler .invoke (endpoint , PluginServerRequest .fromServerRequest (request )));
138+ } catch (IllegalAccessException | InvocationTargetException e ) {
139+ sink .error (new RuntimeException (e ));
140+ }
141+ }).flatMap (this ::createServerResponse );
121142 }
122-
123-
143+
144+ private static @ NotNull MethodInvocation getMethodInvocation (EndpointExtension endpointMeta , Authentication authentication ) throws NoSuchMethodException {
145+ Method method = Authentication .class .getMethod ("isAuthenticated" );
146+ Object [] arguments = new Object []{"someString" , endpointMeta };
147+ return new MethodInvocation () {
148+ @ NotNull
149+ @ Override
150+ public Method getMethod () {
151+ return method ;
152+ }
153+
154+ @ NotNull
155+ @ Override
156+ public Object [] getArguments () {
157+ return arguments ;
158+ }
159+
160+ @ Nullable
161+ @ Override
162+ public Object proceed () throws Throwable {
163+ return null ;
164+ }
165+
166+ @ Nullable
167+ @ Override
168+ public Object getThis () {
169+ return authentication ;
170+ }
171+
172+ @ NotNull
173+ @ Override
174+ public AccessibleObject getStaticPart () {
175+ return null ;
176+ }
177+ };
178+ }
179+
180+
124181 private void registerRouterFunctionMapping (String endpointName , RouterFunction <ServerResponse > routerFunction )
125182 {
126183 String beanName = "pluginEndpoint_" + endpointName + "_" + System .currentTimeMillis ();
0 commit comments