Function Authentication_API(@API) /*********************************************************************************************************************** This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written permission from SRP Computer Solutions, Inc. Name : Authentication_API Description : API logic for the Authentication resource. Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables: HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.) APIURL - The URL for the API entry point (e.g., api.mysite.com/v1). FullEndpointURL - The URL submitted by the client, including query params. FullEndpointURLNoQuery - The URL submitted by the client, excluding query params. EndpointSegment - The URL endpoint segment. ParentURL - The URL path preceeding the current endpoint. CurrentAPI - The name of this stored procedure. Parameters : API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]: - APIPattern must follow this structure Authentication[.ID.[]] - HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc. Examples: - Authentication.POST - Authentication.ID.PUT - Authentication.ID.firstName.GET Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API services do not rely upon anything being returned in the response. This is what the various services like SetResponseBody and SetResponseStatus services are for. A response value is only helpful if the developers want to use it for debug purposes. History : (Date, Initials, Notes) 07/17/24 djs Original programmer. ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler $insert APP_INSERTS $insert API_SETUP $insert HTTP_INSERTS $insert LSL_USERS_EQUATES Equ USERNAME$ To 1 Equ GROUP$ To 2 Equ PASSWORD$ To 3 Equ CONTEXT$ To 4 Declare function Database_Services, MemberOf GoToAPI else // The specific resource endpoint doesn't have a API handler yet. HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.') end Return Response OR '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Endpoint Handlers //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// API authentication.POST Body = HTTP_Services('GetHTTPPostString') If Body NE '' then // The POST string will have been encoded so use percent (URL) decoding AuthJson = HTTP_Services('DecodePercentString', Body) hAuthJson = '' ParseResponse = SRP_JSON(hAuthJson, 'PARSE', AuthJson) If (ParseResponse EQ '') then Username = SRP_JSON(hAuthJson, 'GetValue', 'Username') Password = SRP_JSON(hAuthJson, 'GetValue', 'Password') Groups = '' hGroups = SRP_JSON(hAuthJson, 'get', 'Groups') If hGroups then ElementHandles = SRP_JSON(hGroups, 'GetElements', @VM) If ElementHandles NE '' then For each ElementHandle in ElementHandles using @VM Groups<0, -1> = SRP_JSON(ElementHandle, 'GetValue') SRP_JSON(ElementHandle, 'Release') Next ElementHandle end SRP_JSON(hGroups, 'Release') end SRP_JSON(hAuthJson, 'Release') // Validate Credentials UserRec = Database_Services('ReadDataRow', 'LSL_USERS', Username) If Error_Services('NoError') then Credentials = '' Credentials = Username Credentials = UserRec Credentials = UserRec Member = False$ Group = '' If Groups NE '' then For each Group in Groups using @VM Member = MemberOf(Credentials, Group) Until Member EQ True$ Next Group end else Member = True$ end Begin Case Case (Password EQ Credentials) AND (Member EQ True$) // Return 200, authentication successful StatusCode = 200 Message = 'Authentication successful' HTTP_Services('SetResponseStatus', 200, Message) Case (Password EQ Credentials) AND (Member EQ False$) // Return 401, not a member of required groups NumGroups = DCount(Groups, @VM) If NumGroups GT 1 then Swap @VM with ' or ' in Groups Message = 'User is not a member of the ' : Groups : ' groups.' end else Message = 'User is not a member of the ' : Group : ' group.' end HTTP_Services('SetResponseStatus', 401, 'Authentication failed. ':Message) Case Password NE Credentials // Return 401, unable to validate password Message = 'Unable to validate username. Please re-enter.' HTTP_Services('SetResponseStatus', 401, 'Authentication failed. ':Message) Case Otherwise$ HTTP_Services('SetResponseStatus', 500, 'Error in the ' : CurrentAPI : ' API. Unhandled case.') End Case end else // Error reading user record ErrorMsg = Error_Services('GetMessage') HTTP_Services('SetResponseStatus', 500, 'Error in the ' : CurrentAPI : ' API. Message: ': ErrorMsg) end end else HTTP_Services('SetResponseStatus', 400, 'Error in the ' : CurrentAPI : ' API. Error parsing JSON.') end end else HTTP_Services('SetResponseStatus', 400, 'Error in the ' : CurrentAPI : ' API. Empty request.') end end api //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////