admin.patch
| new/src/com/goldencode/p2j/admin/server/AdminRestHandler.java 2025-04-14 10:25:32 +0000 | ||
|---|---|---|
| 94 | 94 |
* </ul> |
| 95 | 95 |
*/ |
| 96 | 96 |
public class AdminRestHandler |
| 97 |
extends HandlerCollection
|
|
| 97 |
extends ContextHandler
|
|
| 98 | 98 |
{
|
| 99 | 99 |
/** Logger */ |
| 100 | 100 |
private static final CentralLogger LOG = CentralLogger.get(AdminRestHandler.class); |
| ... | ... | |
| 102 | 102 |
/** The handler used for authentication and authorization. */ |
| 103 | 103 |
protected final WebAuthHandler authHandler; |
| 104 | 104 |
|
| 105 |
/** The context handler. */ |
|
| 106 |
private final ContextHandler handler; |
|
| 107 |
|
|
| 108 | 105 |
/** The singleton which handles tenant REST requests. */ |
| 109 | 106 |
private static AdminRestHandler instance; |
| 110 | 107 |
|
| ... | ... | |
| 116 | 113 |
// authHandler is used to authenticate all calls to specialized BaseAdminRestHandler classes |
| 117 | 114 |
authHandler = new WebAuthHandler("admin", "basic", "/admin/login", "/admin/logout", timeout);
|
| 118 | 115 |
|
| 119 |
handler = new ContextHandler(CONTEXT_PREFIX); |
|
| 120 |
handler.setAllowNullPathInfo(true); |
|
| 121 |
handler.setHandler(this); |
|
| 116 |
this.setContextPath(CONTEXT_PREFIX); |
|
| 117 |
this.setAllowNullPathInfo(true); |
|
| 122 | 118 |
} |
| 123 | 119 |
|
| 124 | 120 |
/** |
| ... | ... | |
| 128 | 124 |
* @return An instance of {@link AdminRestHandler} on success or {@code null} if the directory is not
|
| 129 | 125 |
* configured with a REST handler for tenant administration. |
| 130 | 126 |
*/ |
| 131 |
public static AdminRestHandler initialize()
|
|
| 127 |
public static HandlerCollection initialize()
|
|
| 132 | 128 |
{
|
| 133 | 129 |
if (!Utils.getDirectoryNodeBoolean(null, "admin-rest/enabled", false, false)) |
| 134 | 130 |
{
|
| ... | ... | |
| 137 | 133 |
|
| 138 | 134 |
synchronized (AdminRestHandler.class) |
| 139 | 135 |
{
|
| 136 |
HandlerCollection res = null; |
|
| 140 | 137 |
if (instance == null) |
| 141 | 138 |
{
|
| 142 | 139 |
instance = new AdminRestHandler( |
| 143 | 140 |
Utils.getDirectoryNodeInt(null, "admin-rest/timeout", 3600, false)); |
| 141 | ||
| 142 |
res = new HandlerCollection(); |
|
| 143 |
res.addHandler(instance); |
|
| 144 | 144 |
|
| 145 | 145 |
String crtPackage = AdminRestHandler.class.getPackage().getName(); |
| 146 | 146 |
Reflections reflections = new Reflections( |
| ... | ... | |
| 183 | 183 |
continue; |
| 184 | 184 |
} |
| 185 | 185 |
|
| 186 |
instance.addHandler((BaseAdminRestHandler) result);
|
|
| 186 |
res.addHandler((BaseAdminRestHandler) result);
|
|
| 187 | 187 |
} |
| 188 | 188 |
} |
| 189 | 189 |
|
| 190 |
return instance.getHandlers().length == 0 ? null : instance;
|
|
| 190 |
return res.getHandlers().length == 0 ? null : res;
|
|
| 191 | 191 |
} |
| 192 | 192 |
} |
| 193 |
|
|
| 194 |
/** |
|
| 195 |
* Obtain the {@link ContextHandler}, if one was created by the initialization process.
|
|
| 196 |
* |
|
| 197 |
* @return the current the {@link ContextHandler}.
|
|
| 198 |
*/ |
|
| 199 |
public org.eclipse.jetty.server.Handler getHandler() |
|
| 200 |
{
|
|
| 201 |
return handler; |
|
| 202 |
} |
|
| 203 |
|
|
| 193 | ||
| 204 | 194 |
/** |
| 205 | 195 |
* Method for handling the requests. Will perform checking, authentication and authorization before |
| 206 | 196 |
* dispatching the execution to proper method/verb. |
| ... | ... | |
| 215 | 205 |
* The response as the {@link Response} object or a wrapper of that request.
|
| 216 | 206 |
*/ |
| 217 | 207 |
@Override |
| 218 |
public void handle(String target,
|
|
| 219 |
Request baseRequest, |
|
| 220 |
HttpServletRequest request, |
|
| 221 |
HttpServletResponse response) |
|
| 208 |
public void doHandle(String target,
|
|
| 209 |
Request baseRequest,
|
|
| 210 |
HttpServletRequest request,
|
|
| 211 |
HttpServletResponse response)
|
|
| 222 | 212 |
throws IOException, ServletException |
| 223 | 213 |
{
|
| 224 | 214 |
// quick validation |
| ... | ... | |
| 239 | 229 |
target = target.substring(0, target.length() - 1); |
| 240 | 230 |
} |
| 241 | 231 |
|
| 242 |
// process only the know context subtree
|
|
| 243 |
if (!target.startsWith(CONTEXT_PREFIX))
|
|
| 232 |
// /admin is processing only /login and /logout in this handler
|
|
| 233 |
if (!(target.equals("/login") || target.equals("/logout")))
|
|
| 244 | 234 |
{
|
| 245 | 235 |
return; |
| 246 | 236 |
} |
| 247 | 237 |
|
| 248 | 238 |
// authentication. The authorization will be done by each AdminRestHandler child: |
| 249 |
authHandler.handle(target, baseRequest, request, response); |
|
| 239 |
authHandler.handle(getContextPath() + target, baseRequest, request, response);
|
|
| 250 | 240 |
if (baseRequest.isHandled()) |
| 251 | 241 |
{
|
| 252 | 242 |
return; // authentication done, nothing else to do |
| new/src/com/goldencode/p2j/admin/server/BaseAdminRestHandler.java 2025-04-14 10:28:18 +0000 | ||
|---|---|---|
| 89 | 89 |
* {@code handleDelete()}.
|
| 90 | 90 |
*/ |
| 91 | 91 |
public abstract class BaseAdminRestHandler |
| 92 |
extends AbstractHandler
|
|
| 92 |
extends ContextHandler
|
|
| 93 | 93 |
{
|
| 94 | 94 |
/** Logger */ |
| 95 | 95 |
private static final CentralLogger LOG = CentralLogger.get(BaseAdminRestHandler.class); |
| 96 | 96 |
|
| 97 |
/** The URL path it will handle.*/ |
|
| 98 |
protected final String contextPath; |
|
| 99 |
|
|
| 100 | 97 |
/** The handler used for authentication and authorization. */ |
| 101 | 98 |
protected final WebAuthHandler authenticationHandler; |
| 102 | 99 |
|
| ... | ... | |
| 118 | 115 |
{
|
| 119 | 116 |
this.wsm = SecurityManager.getInstance().legacyWebSm; |
| 120 | 117 |
this.authenticationHandler = authenticationHandler; |
| 121 |
this.contextPath = contextPath;
|
|
| 118 |
this.setContextPath(contextPath);
|
|
| 122 | 119 |
} |
| 123 | 120 |
|
| 124 | 121 |
/** |
| ... | ... | |
| 135 | 132 |
* The response as the {@link Response} object or a wrapper of that request.
|
| 136 | 133 |
*/ |
| 137 | 134 |
@Override |
| 138 |
public void handle(String target, |
|
| 139 |
Request baseRequest, |
|
| 140 |
HttpServletRequest request, |
|
| 141 |
HttpServletResponse response) |
|
| 142 |
throws IOException, ServletException |
|
| 135 |
public void doHandle(String target, |
|
| 136 |
Request baseRequest, |
|
| 137 |
HttpServletRequest request, |
|
| 138 |
HttpServletResponse response) |
|
| 139 |
throws IOException, |
|
| 140 |
ServletException |
|
| 143 | 141 |
{
|
| 144 | 142 |
// quick validation |
| 145 | 143 |
if (baseRequest.isHandled()) // already handled by other handler? |
| ... | ... | |
| 152 | 150 |
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); |
| 153 | 151 |
return; |
| 154 | 152 |
} |
| 155 |
else if (!target.startsWith(contextPath)) |
|
| 156 |
{
|
|
| 157 |
return; // not my business |
|
| 158 |
} |
|
| 159 | 153 |
|
| 160 | 154 |
baseRequest.setHandled(true); |
| 161 | 155 |
response.setContentType("application/json");
|
| 162 | 156 |
|
| 157 |
if (target.endsWith("/"))
|
|
| 158 |
{
|
|
| 159 |
target = target.substring(0, target.length() - 1); |
|
| 160 |
} |
|
| 163 | 161 |
// check authorization: |
| 164 |
String token = authenticationHandler.authorize(target, request, response); |
|
| 162 |
String cpath = getContextPath(); |
|
| 163 |
String token = authenticationHandler.authorize(cpath + target, request, response); |
|
| 165 | 164 |
if (token == null) |
| 166 | 165 |
{
|
| 167 | 166 |
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); |
| ... | ... | |
| 169 | 168 |
} |
| 170 | 169 |
|
| 171 | 170 |
String body = request.getReader().lines().collect(Collectors.joining()); |
| 172 |
target = trimContextPrefix(target); |
|
| 173 |
|
|
| 174 | 171 |
switch (baseRequest.getMethod()) |
| 175 | 172 |
{
|
| 176 | 173 |
case "GET": |
| ... | ... | |
| 360 | 357 |
return false; |
| 361 | 358 |
} |
| 362 | 359 |
} |
| 363 |
|
|
| 364 |
/** |
|
| 365 |
* Cleaning up the target by removing the context path. This information is not useful since all requests |
|
| 366 |
* dispatched to this handler are filtered to match this prefix. |
|
| 367 |
*/ |
|
| 368 |
private String trimContextPrefix(String originalTarget) |
|
| 369 |
{
|
|
| 370 |
if (!originalTarget.startsWith(contextPath)) |
|
| 371 |
{
|
|
| 372 |
LOG.warning( |
|
| 373 |
"Invalid context received '" + originalTarget + "'. Was expecting '" + contextPath + "'."); |
|
| 374 |
return originalTarget; |
|
| 375 |
} |
|
| 376 |
|
|
| 377 |
String newTarget = originalTarget.substring(contextPath.length()); |
|
| 378 |
|
|
| 379 |
// drop the starting "/" if any: |
|
| 380 |
if (newTarget.startsWith("/"))
|
|
| 381 |
{
|
|
| 382 |
newTarget = newTarget.substring(1); |
|
| 383 |
} |
|
| 384 |
return newTarget; |
|
| 385 |
} |
|
| 386 |
|
|
| 360 | ||
| 387 | 361 |
/** |
| 388 | 362 |
* Parse a JSON and extract the value (String, int or boolean for the moment) of a given field. |
| 389 | 363 |
* |
| new/src/com/goldencode/p2j/main/StandardServer.java 2025-04-14 10:17:36 +0000 | ||
|---|---|---|
| 1710 | 1710 |
boolean virtualDesktop = false; |
| 1711 | 1711 |
boolean ssoEnabled = SecurityManager.getInstance().ssoSm.isSsoEnabled(); |
| 1712 | 1712 |
boolean embedded = false; |
| 1713 |
AdminRestHandler adminHandle;
|
|
| 1713 |
HandlerCollection adminHandle;
|
|
| 1714 | 1714 |
|
| 1715 | 1715 |
if (ssoEnabled && ConfigItem.EMBEDDED.read(false)) |
| 1716 | 1716 |
{
|