-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #88 from AndrewPoppe/83-api-methods
Add API Methods - address #83
- Loading branch information
Showing
10 changed files
with
675 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
|
||
namespace YaleREDCap\REDCapPRO; | ||
|
||
/** @var REDCapPRO $module */ | ||
|
||
// This is an API endpoint that can be used to register and enroll participants | ||
// It is NOAUTH and No CSRF, so API token is required | ||
try { | ||
|
||
$action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS); | ||
if ( $action == "register" ) { | ||
$apiHandler = new APIParticipantRegister($module, $_POST); | ||
} elseif ( $action == "enroll" ) { | ||
$apiHandler = new APIParticipantEnroll($module, $_POST); | ||
} else { | ||
throw new \Error("Invalid API action"); | ||
} | ||
|
||
$projectSettings = new ProjectSettings($module); | ||
if ( !$projectSettings->apiEnabled($apiHandler->project->getProjectId()) ) { | ||
throw new \Error("API is not enabled for this project"); | ||
} | ||
|
||
if ( !$apiHandler->valid ) { | ||
echo json_encode($apiHandler->errorMessages, JSON_PRETTY_PRINT); | ||
throw new \Error("Invalid API payload"); | ||
} | ||
} catch ( \Throwable $e ) { | ||
$module->logError("Error using API", $e); | ||
echo json_encode([ | ||
"error" => $e->getMessage(), | ||
], JSON_PRETTY_PRINT); | ||
return; | ||
} | ||
|
||
// Only allow Normal Users and above to use the API | ||
if ( ((int) $apiHandler->getRole()) < 2 ) { | ||
echo json_encode([ | ||
"error" => "You do not have permission to use the REDCapPRO API", | ||
], JSON_PRETTY_PRINT); | ||
return; | ||
} | ||
|
||
// Try to enroll/register the participants | ||
try { | ||
$result = $apiHandler->takeAction(); | ||
} catch ( \Throwable $e ) { | ||
$module->logError("Error using the REDCapPRO API", $e); | ||
echo json_encode([ | ||
"error" => $e->getMessage(), | ||
], JSON_PRETTY_PRINT); | ||
return; | ||
} | ||
|
||
echo json_encode($result, JSON_PRETTY_PRINT); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
<?php | ||
namespace YaleREDCap\REDCapPRO; | ||
|
||
use \ExternalModules\User; | ||
|
||
class APIHandler | ||
{ | ||
public $token; | ||
public REDCapPRO $module; | ||
private array $payload; | ||
public User $user; | ||
public array $rights = []; | ||
public \ExternalModules\Project $project; | ||
private array $data = []; | ||
public array $actionData = []; | ||
|
||
public function __construct(REDCapPRO $module, array $payload) | ||
{ | ||
define("API", true); | ||
|
||
$this->module = $module; | ||
$this->payload = $payload; | ||
$this->data = $this->parsePayload(); | ||
$this->token = $this->module->framework->sanitizeAPIToken($this->data['token']) ?? 'X'; | ||
$this->rights = $this->extractRights(); | ||
$this->user = $this->extractUser(); | ||
$this->project = $this->extractProject(); | ||
$this->actionData = $this->extractActionData(); | ||
|
||
define('USERID', $this->user->getUsername()); | ||
define('PROJECT_ID', $this->rights['project_id']); | ||
$_GET['pid'] = $this->rights['project_id']; | ||
$GLOBALS['Proj'] = new \Project($this->rights['project_id']); | ||
} | ||
|
||
public function extractUser() | ||
{ | ||
$username = $this->rights['username']; | ||
if ( empty($username) ) { | ||
throw new \Error("Invalid API token"); | ||
} | ||
return $this->module->framework->getUser($username); | ||
} | ||
|
||
public function extractProject() | ||
{ | ||
$project_id = $this->rights['project_id']; | ||
if ( empty($project_id) ) { | ||
throw new \Error("Invalid API token"); | ||
} | ||
return $this->module->framework->getProject($project_id); | ||
} | ||
|
||
public function extractRights() | ||
{ | ||
$rights = $this->getUserRightsFromToken(); | ||
if ( empty($rights) ) { | ||
throw new \Error('Invalid API token'); | ||
} | ||
return $rights; | ||
} | ||
|
||
public function extractActionData() | ||
{ | ||
$actionDataString = $this->data['data']; | ||
try { | ||
$actionData = json_decode($actionDataString, true); | ||
} catch ( \Throwable $e ) { | ||
$this->module->logError('Error decoding action data', $e); | ||
} | ||
if ( empty($actionData) ) { | ||
throw new \Error('No import data provided'); | ||
} | ||
return $this->module->framework->escape($actionData); | ||
} | ||
|
||
private function getUserRightsFromToken() : array | ||
{ | ||
$sql = "SELECT * FROM redcap_user_rights WHERE api_token = ?"; | ||
$rights = []; | ||
try { | ||
$result = $this->module->framework->query($sql, [ $this->token ]); | ||
$rights = $result->fetch_assoc() ?? []; | ||
} catch ( \Throwable $e ) { | ||
$this->module->logError('Error getting user rights from API token', $e); | ||
} finally { | ||
return $this->module->framework->escape($rights); | ||
} | ||
} | ||
|
||
private function parsePayload() | ||
{ | ||
try { | ||
$actionDataString = $this->payload['data'] ?? '{}'; // This will be sanitized later | ||
$this->data = $this->module->framework->escape($this->payload); | ||
$this->data['data'] = $actionDataString; | ||
} catch ( \Throwable $e ) { | ||
$this->module->logError('Error parsing payload', $e); | ||
} finally { | ||
return $this->data; | ||
} | ||
} | ||
|
||
public function getRole() | ||
{ | ||
return $this->module->getUserRole($this->user->getUsername()); | ||
} | ||
|
||
public function getApiData() | ||
{ | ||
return [ | ||
'token' => $this->token, | ||
'rights' => $this->rights, | ||
'user' => $this->user->getUsername(), | ||
'project' => $this->project->getProjectId(), | ||
'role' => $this->module->getUserRole($this->user->getUsername()), | ||
'actionData' => $this->actionData | ||
]; | ||
} | ||
} |
Oops, something went wrong.