Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented the delete user method #5

Merged
merged 8 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/framework/.secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
"hashed_secret": "a5c1ad5f1dc7d24152e39cb14dfa99775fa1884d",
"is_secret": false,
"is_verified": false,
"line_number": 139,
"line_number": 142,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ public enum ServletErrorMessage {
GAL5071_FAILED_TO_PARSE_YAML_INTO_JSON (5071, "E: Internal server error. Failed to convert OpenAPI specification from YAML into JSON. Report the problem to your Galasa Ecosystem owner"),

// User APIs...
GAL5081_INVALID_QUERY_PARAM_VALUE (5081, "E: A request to get the user details for a particular user failed. The query parameter provided is not valid. Supported values for the ‘loginId’ query parameter are : ‘me’. This problem is caused by the client program sending a bad request. Please report this problem to the owner of your client program."),
GAL5082_NO_LOGINID_PARAM_PROVIDED (5082, "E: A request to get the user details failed. The request did not supply a ‘loginId’ filter. A ‘loginId’ query parameter with a value of : ‘me’ was expected. This problem is caused by the client program sending a bad request. Please report this problem to the owner of your client program."),
GAL5081_INVALID_QUERY_PARAM_VALUE (5081, "E: A request to get the user details for a particular user failed. The query parameter provided is not valid. Supported values for the 'loginId' query parameter are : 'me'. This problem is caused by the client program sending a bad request. Please report this problem to the owner of your client program."),
GAL5082_NO_LOGINID_PARAM_PROVIDED (5082, "E: A request to get the user details failed. The request did not supply a 'loginId' filter. A 'loginId' query parameter with a value of : 'me' was expected. This problem is caused by the client program sending a bad request. Please report this problem to the owner of your client program."),
GAL5083_ERROR_USER_NOT_FOUND (5083, "E: Unable to retrieve a user with the given user number. No such user exists. Check your request query parameters and try again."),
GAL5084_FAILED_TO_DELETE_USER (5084, "E: Failed to delete a user with the given 'loginId' from the auth store. The auth store might be experiencing temporary issues. Report the problem to your Galasa Ecosystem owner."),
GAL5085_FAILED_TO_GET_LOGIN_ID_FROM_URL (5085, "E: Failed to retrieve a loginId from the request path. Please ensure that you have provided a valid ID representing an existing auth token in your request and try again"),

// Secrets APIs...
GAL5092_INVALID_SECRET_NAME_PROVIDED (5092, "E: Invalid secret name provided. The name of a Galasa secret cannot be empty, contain only spaces or tabs, or contain dots ('.'), and must only contain characters in the Latin-1 character set. Check your request payload and try again."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,39 @@ paths:
error_code: 5400
error_message: "E: Error occurred when trying to execute request '/users'. Please check your request parameters or report the problem to your Galasa Ecosystem owner."
summary: One or more required query parameters are missing
/users/{userNumber}:
delete:
operationId: deleteUserByNumber
summary: Deletes a user in the ecosystem
tags:
- Users API
parameters:
- name: userNumber
in: path
description: User number of the user to be deleted.
required: true
schema:
type: string
responses:
'204':
description: The delete operation worked. The user is now deleted.
'404':
description: The delete operation failed. The record was not found.
content:
application/json:
schema:
$ref: '#/components/schemas/APIError'
examples:
runiderror:
value:
error_code: 5083
error_message: "GAL5083E: Error deleting user"
summary: An Error occurred when trying to delete a user using the given user number.
'401':
$ref: "#/components/responses/Unauthorized"
'500':
$ref: '#/components/responses/InternalServerError'

##################################################################################
# CPS API
##################################################################################
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ServiceScope;

import dev.galasa.framework.api.users.internal.routes.UsersDeleteRoute;
import dev.galasa.framework.api.users.internal.routes.UsersRoute;
import dev.galasa.framework.auth.spi.AuthServiceFactory;
import dev.galasa.framework.auth.spi.IAuthService;
Expand All @@ -31,6 +32,7 @@ public class UsersServlet extends BaseServlet {
protected IFramework framework;

public static final String QUERY_PARAM_LOGIN_ID = "loginId";
public static final String QUERY_PARAMETER_LOGIN_ID_VALUE_MYSELF = "me";

private static final long serialVersionUID = 1L;

Expand All @@ -49,7 +51,8 @@ public void init() throws ServletException {
}

IAuthService authService = factory.getAuthService();
addRoute(new UsersRoute(getResponseBuilder(), env, authService.getAuthStoreService()));
addRoute(new UsersRoute(getResponseBuilder(), env, authService));
addRoute(new UsersDeleteRoute(getResponseBuilder(), env, authService));

logger.info("Galasa Users API initialised");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright contributors to the Galasa project
*
* SPDX-License-Identifier: EPL-2.0
*/
package dev.galasa.framework.api.users.internal.routes;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static dev.galasa.framework.api.common.ServletErrorMessage.*;

import dev.galasa.framework.spi.auth.IInternalAuthToken;

import dev.galasa.framework.api.common.BaseRoute;
import dev.galasa.framework.api.common.Environment;
import dev.galasa.framework.api.common.EnvironmentVariables;
import dev.galasa.framework.api.common.InternalServletException;
import dev.galasa.framework.api.common.QueryParameters;
import dev.galasa.framework.api.common.ResponseBuilder;
import dev.galasa.framework.api.common.ServletError;
import dev.galasa.framework.auth.spi.IAuthService;
import dev.galasa.framework.spi.FrameworkException;
import dev.galasa.framework.spi.auth.AuthStoreException;
import dev.galasa.framework.spi.auth.IAuthStoreService;
import dev.galasa.framework.spi.auth.IUser;

public class UsersDeleteRoute extends BaseRoute{

// Regex to match endpoint /users/{userDocumentId}
protected static final String path = "\\/([a-zA-Z0-9\\-\\_]+)\\/?";

private Environment env;
private IAuthStoreService authStoreService;
private IAuthService authService;
private BeanTransformer beanTransformer;
private Pattern pathPattern;

public UsersDeleteRoute(ResponseBuilder responseBuilder, Environment env,
IAuthService authService) {
super(responseBuilder, path);
this.env = env;
this.authService = authService;

String baseServletUrl = env.getenv(EnvironmentVariables.GALASA_EXTERNAL_API_URL);

this.beanTransformer = new BeanTransformer(baseServletUrl);
this.authStoreService = authService.getAuthStoreService();
this.pathPattern = getPathRegex();
}

@Override
public HttpServletResponse handleDeleteRequest(
String pathInfo,
QueryParameters queryParams,
HttpServletRequest request,
HttpServletResponse response
) throws FrameworkException {

logger.info("handleDeleteRequest() entered");

String userNumber = extractUserNumberFromUrl(pathInfo);
IUser user = authStoreService.getUser(userNumber);

deleteUser(user);

logger.info("handleDeleteRequest() exiting");
return getResponseBuilder().buildResponse(request, response, HttpServletResponse.SC_NO_CONTENT);
}

private String extractUserNumberFromUrl(String pathInfo) throws InternalServletException{

try {

Matcher matcher = pathPattern.matcher(pathInfo);
matcher.matches();

String userNumber = matcher.group(1);
return userNumber;

} catch(Exception ex){
ServletError error = new ServletError(GAL5085_FAILED_TO_GET_LOGIN_ID_FROM_URL);
throw new InternalServletException(error, HttpServletResponse.SC_NOT_FOUND, ex);
}

}

private void deleteUser(IUser user) throws AuthStoreException, InternalServletException{

try {

if (user == null) {
ServletError error = new ServletError(GAL5083_ERROR_USER_NOT_FOUND);
throw new InternalServletException(error, HttpServletResponse.SC_NOT_FOUND);
}

String loginId = user.getLoginId();

//Need to delete access tokens of a user if we delete the user
List<IInternalAuthToken> tokens = authStoreService.getTokensByLoginId(loginId);
for (IInternalAuthToken token : tokens) {
authService.revokeToken(token.getTokenId());
}

logger.info("A user with the given loginId was found OK");
authStoreService.deleteUser(user);
logger.info("The user with the given loginId was deleted OK");

} catch (AuthStoreException e) {
ServletError error = new ServletError(GAL5084_FAILED_TO_DELETE_USER);
throw new InternalServletException(error, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import dev.galasa.framework.api.common.Environment;
import dev.galasa.framework.api.common.EnvironmentVariables;
import dev.galasa.framework.api.users.UsersServlet;
import dev.galasa.framework.auth.spi.IAuthService;
import dev.galasa.framework.api.common.JwtWrapper;

import dev.galasa.framework.spi.FrameworkException;
Expand All @@ -35,17 +36,15 @@ public class UsersRoute extends BaseRoute {
// Regex to match endpoint /users and /users/
private static final String path = "\\/?";

public static final String QUERY_PARAMETER_LOGIN_ID_VALUE_MYSELF = "me";

private Environment env;
private IAuthStoreService authStoreService;
private BeanTransformer beanTransformer ;

public UsersRoute(ResponseBuilder responseBuilder, Environment env,
IAuthStoreService authStoreService) {
IAuthService authService) {
super(responseBuilder, path);
this.env = env;
this.authStoreService = authStoreService;
this.authStoreService = authService.getAuthStoreService();

String baseServletUrl = env.getenv(EnvironmentVariables.GALASA_EXTERNAL_API_URL);

Expand Down Expand Up @@ -88,7 +87,7 @@ private List<UserData> getUserByLoginIdList(HttpServletRequest request, String l

JwtWrapper jwtWrapper = new JwtWrapper(request, env);

if (loginId.equals("me")) {
if (loginId.equals(UsersServlet.QUERY_PARAMETER_LOGIN_ID_VALUE_MYSELF)) {
loginId = jwtWrapper.getUsername();
}

Expand Down
Loading
Loading