Skip to content

Commit

Permalink
Separates error handling from success functions, updates error respon…
Browse files Browse the repository at this point in the history
…ses in API, adds global error handler
  • Loading branch information
cayb0rg committed Nov 14, 2023
1 parent 2243146 commit 6635291
Show file tree
Hide file tree
Showing 63 changed files with 1,561 additions and 1,197 deletions.
6 changes: 3 additions & 3 deletions fuel/app/classes/controller/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function before()
public function get_widget()
{
if ( ! \Materia\Perm_Manager::is_super_user() ) throw new \HttpNotFoundException;

Js::push_inline('var UPLOAD_ENABLED ="'.Config::get('materia.enable_admin_uploader').'";');
Js::push_inline('var HEROKU_WARNING ="'.Config::get('materia.heroku_admin_warning').'";');
Js::push_inline('var ACTION_LINK ="/admin/upload";');
Expand Down Expand Up @@ -78,8 +78,8 @@ public function post_upload()
}
}
}
if ($failed)

if ($failed)
{
throw new HttpServerErrorException;
}
Expand Down
53 changes: 51 additions & 2 deletions fuel/app/classes/controller/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,64 @@ public function before()
parent::before();
}

/**
* Recursively search for the status code in execution result
* @param Array
* @return Integer
*/
public function get_status($data)
{
if (is_array($data) || is_object($data))
{
foreach ($data as $key => $value)
{
if ($key === 'status')
{
return $value;
}
elseif (is_array($key) || is_object($key))
{
$result = $this->get_status($key);
if ($result !== null)
{
return $result;
}
}
}
}
}

public function post_call($version, $format, $method)
{
$input = json_decode(Input::post('data', []));

$result = $this->execute($version, $method, $input);

$status = $this->get_status($result);

if ( ! $status)
{
$status = 200;
}

$this->no_cache();
$this->response($result, 200);
$this->response($result, $status);
}

public function get_call($version, $format, $method)
{
$data = array_slice($this->request->route->method_params, 3);
$result = $this->execute($version, $method, $data);

$status = $this->get_status($result);

if ( ! $status)
{
$status = 200;
}

$this->no_cache();
$this->response($result, 200);
$this->response($result, $status);
}

protected function execute($version, $method, $args)
Expand All @@ -77,6 +118,14 @@ protected function execute($version, $method, $args)
{
Materia\Log::profile([get_class($e), get_class($api), $method, json_encode($args)], 'exception');
trace($e);
if ($e instanceof \HttpNotFoundException)
{
return Materia\Msg::not_found();
}
else
{
throw new HttpServerErrorException;
}
}
}
}
2 changes: 1 addition & 1 deletion fuel/app/classes/controller/api/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public function post_widget_instance_undelete(string $inst_id)
{
if ( ! \Materia\Util_Validator::is_valid_hash($inst_id)) return Msg::invalid_input($inst_id);
if (\Service_User::verify_session() !== true) return Msg::no_login();
if ( ! ($inst = \Materia\Widget_Instance_Manager::get($inst_id, false, false, true))) return new Msg(Msg::ERROR, 'Widget instance does not exist.');
if ( ! ($inst = \Materia\Widget_Instance_Manager::get($inst_id, false, false, true))) return Msg::failure('Widget instance does not exist.');
return $inst->db_undelete();
}
}
4 changes: 2 additions & 2 deletions fuel/app/classes/controller/api/asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function post_delete($asset_id)
\Log::error('Error: In the deletion process');
\Log::error($th);

return new Msg(Msg::ERROR, 'Asset could not be deleted.');
return Msg::failure('Asset could not be deleted.');
}
}

Expand All @@ -61,7 +61,7 @@ public function post_restore($asset_id)
\Log::error('Error: In the deletion process');
\Log::error($th);

return new Msg(Msg::ERROR, 'Asset could not be restored.');
return Msg::failure('Asset could not be restored.');
}
}
}
16 changes: 9 additions & 7 deletions fuel/app/classes/controller/api/instance.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class Controller_Api_Instance extends Controller_Rest
*/
public function get_history()
{
if ( ! $inst_id = Input::get('inst_id')) return $this->response('Requires an inst_id parameter!', 401);
if ( ! $inst_id = Input::get('inst_id')) return $this->response(new \Materia\Msg('Requires an inst_id parameter!', \Materia\Msg::ERROR), 401);
if ( ! \Materia\Util_Validator::is_valid_hash($inst_id) ) return $this->response(\Materia\Msg::invalid_input($inst_id), 401);
if ( ! ($inst = \Materia\Widget_Instance_Manager::get($inst_id))) return $this->response('Instance not found', 404);
if ( ! ($inst = \Materia\Widget_Instance_Manager::get($inst_id))) return $this->response(new \Materia\Msg('Instance not found', \Materia\Msg::ERROR), 404);
if ( ! \Materia\Perm_Manager::user_has_any_perm_to(\Model_User::find_current_id(), $inst_id, \Materia\Perm::INSTANCE, [\Materia\Perm::FULL])) return $this->response(\Materia\Msg::no_login(), 401);

$history = $inst->get_qset_history($inst_id);
Expand All @@ -36,13 +36,15 @@ public function post_request_access()
$inst_id = Input::json('inst_id', null);
$owner_id = Input::json('owner_id', null);

if ( ! $inst_id) return $this->response('Requires an inst_id parameter', 401);
if ( ! $owner_id) return $this->response('Requires an owner_id parameter', 401);
if ( ! $inst_id) return $this->response(new \Materia\Msg('Requires an inst_id parameter', \Materia\Msg::ERROR), 401);

if ( ! \Model_User::find_by_id($owner_id)) return $this->response('Owner not found', 404);
if ( ! ($inst = \Materia\Widget_Instance_Manager::get($inst_id))) return $this->response('Instance not found', 404);
if ( ! $owner_id) return $this->response(new \Materia\Msg('Requires an owner_id parameter', \Materia\Msg::ERROR), 401);

if ( ! Materia\Perm_Manager::user_has_any_perm_to($owner_id, $inst_id, Materia\Perm::INSTANCE, [Materia\Perm::FULL, Materia\Perm::VISIBLE])) return $this->response('Owner does not own instance', 404);
if ( ! \Model_User::find_by_id($owner_id)) return $this->response(new \Materia\Msg('Owner not found', \Materia\Msg::ERROR), 404);

if ( ! ($inst = \Materia\Widget_Instance_Manager::get($inst_id))) return $this->response(new \Materia\Msg('Instance not found', \Materia\Msg::ERROR), 404);

if ( ! Materia\Perm_Manager::user_has_any_perm_to($owner_id, $inst_id, Materia\Perm::INSTANCE, [Materia\Perm::FULL, Materia\Perm::VISIBLE])) return $this->response(new \Materia\Msg('Owner does not own instance', \Materia\Msg::ERROR), 404);

if ( ! \Materia\Util_Validator::is_valid_hash($inst_id) ) return $this->response(\Materia\Msg::invalid_input($inst_id), 401);

Expand Down
74 changes: 43 additions & 31 deletions fuel/app/classes/materia/api/v1.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ static public function widget_instances_get($inst_ids = null, bool $deleted = fa
// get all my instances - must be logged in
if (empty($inst_ids))
{
if (\Service_User::verify_session() !== true) return []; // shortcut to returning noting
if (\Service_User::verify_session() !== true) return Msg::no_login(); // shortcut to returning noting
return Widget_Instance_Manager::get_all_for_user(\Model_User::find_current_id(), $load_qset);
}

Expand Down Expand Up @@ -79,38 +79,50 @@ static public function widget_instance_delete($inst_id)
if ( ! Util_Validator::is_valid_hash($inst_id)) return Msg::invalid_input($inst_id);
if (\Service_User::verify_session() !== true) return Msg::no_login();
if ( ! static::has_perms_to_inst($inst_id, [Perm::FULL]) && ! Perm_Manager::is_support_user()) return Msg::no_perm();
if ( ! ($inst = Widget_Instance_Manager::get($inst_id))) return false;
return $inst->db_remove();
if ( ! ($inst = Widget_Instance_Manager::get($inst_id))) throw new \HttpNotFoundException;

$result = $inst->db_remove();
if ($result)
{
return $inst_id;
}
else
{
return Msg::failure('Failed to remove widget instance from database');
}
}

static public function widget_instance_access_perms_verify($inst_id)
{
if (\Service_User::verify_session() !== true) return Msg::no_login();
return static::has_perms_to_inst($inst_id, [Perm::VISIBLE, Perm::FULL]);

if ( ! Util_Validator::is_valid_hash($inst_id)) return Msg::invalid_input($inst_id);

if ( ! static::has_perms_to_inst($inst_id, [Perm::VISIBLE, Perm::FULL]))
{
return Msg::no_perm();
}
return true;
}

/**
* @return object, contains properties indicating whether the current
* user can edit the widget and a message object describing why, if not
*/
static public function widget_instance_edit_perms_verify(string $inst_id): \stdClass
static public function widget_instance_edit_perms_verify(string $inst_id)
{
$response = new \stdClass();
$response->msg = null;
$response->is_locked = true;
$response->can_publish = false;

if ( ! Util_Validator::is_valid_hash($inst_id)) $response->msg = Msg::invalid_input($inst_id);
else if (\Service_User::verify_session() !== true) $response->msg = Msg::no_login();
else if ( ! static::has_perms_to_inst($inst_id, [Perm::FULL])) $response->msg = Msg::no_perm();
else if ( ! ($inst = Widget_Instance_Manager::get($inst_id))) $response->msg = new Msg(Msg::ERROR, 'Widget instance does not exist.');
if ( ! Util_Validator::is_valid_hash($inst_id)) return Msg::invalid_input($inst_id);
else if (\Service_User::verify_session() !== true) return Msg::no_login();
else if ( ! static::has_perms_to_inst($inst_id, [Perm::FULL])) return Msg::no_perm();
else if ( ! ($inst = Widget_Instance_Manager::get($inst_id))) throw new \HttpNotFoundException;

//msg property only set if something went wrong
if ( ! $response->msg)
{
$response->is_locked = ! Widget_Instance_Manager::locked_by_current_user($inst_id);
$response->can_publish = $inst->widget->publishable_by(\Model_User::find_current_id());
}
$response->is_locked = ! Widget_Instance_Manager::locked_by_current_user($inst_id);
$response->can_publish = $inst->widget->publishable_by(\Model_User::find_current_id());

return $response;
}
Expand Down Expand Up @@ -150,7 +162,7 @@ static public function widget_instance_copy(string $inst_id, string $new_name, b
}
catch (\Exception $e)
{
return new Msg(Msg::ERROR, 'Widget instance could not be copied.');
return Msg::failure('Widget instance could not be copied.');
}
}

Expand All @@ -177,8 +189,8 @@ static public function widget_instance_new($widget_id=null, $name=null, $qset=nu

$widget = new Widget();
if ( $widget->get($widget_id) == false) return Msg::invalid_input('Invalid widget type');
if ( ! $is_draft && ! $widget->publishable_by(\Model_User::find_current_id()) ) return new Msg(Msg::ERROR, 'Widget type can not be published by students.');
if ( $is_draft && ! $widget->is_editable) return new Msg(Msg::ERROR, 'Non-editable widgets can not be saved as drafts!');
if ( ! $is_draft && ! $widget->publishable_by(\Model_User::find_current_id()) ) return Msg::no_perm('Widget type can not be published by students.');
if ( $is_draft && ! $widget->is_editable) return Msg::failure('Non-editable widgets can not be saved as drafts!');

$is_student = ! \Service_User::verify_session(['basic_author', 'super_user']);
$inst = new Widget_Instance([
Expand All @@ -203,7 +215,7 @@ static public function widget_instance_new($widget_id=null, $name=null, $qset=nu
catch (\Exception $e)
{
trace($e);
return new Msg(Msg::ERROR, 'Widget instance could not be saved.');
return Msg::failure('Widget instance could not be saved.');
}
}

Expand All @@ -226,13 +238,13 @@ static public function widget_instance_update($inst_id=null, $name=null, $qset=n
{
if (\Service_User::verify_session() !== true) return Msg::no_login();
if (\Service_User::verify_session('no_author')) return Msg::invalid_input('You are not able to create or edit widgets.');
if ( ! Util_Validator::is_valid_hash($inst_id)) return new Msg(Msg::ERROR, 'Instance id is invalid');
if ( ! Util_Validator::is_valid_hash($inst_id)) return Msg::invalid_input('Instance id is invalid');
if ( ! static::has_perms_to_inst($inst_id, [Perm::VISIBLE, Perm::FULL])) return Msg::no_perm();

$inst = Widget_Instance_Manager::get($inst_id, true);
if ( ! $inst) return new Msg(Msg::ERROR, 'Widget instance could not be found.');
if ( $is_draft && ! $inst->widget->is_editable) return new Msg(Msg::ERROR, 'Non-editable widgets can not be saved as drafts!');
if ( ! $is_draft && ! $inst->widget->publishable_by(\Model_User::find_current_id())) return new Msg(Msg::ERROR, 'Widget type can not be published by students.');
if ( ! $inst) return Msg::failure('Widget instance could not be found.');
if ( $is_draft && ! $inst->widget->is_editable) return Msg::failure('Non-editable widgets can not be saved as drafts!');
if ( ! $is_draft && ! $inst->widget->publishable_by(\Model_User::find_current_id())) return Msg::no_perm('Widget type can not be published by students.');

// student made widgets are locked forever
if ($inst->is_student_made)
Expand Down Expand Up @@ -378,7 +390,7 @@ static public function widget_instance_update($inst_id=null, $name=null, $qset=n
}
catch (\Exception $e)
{
return new Msg(Msg::ERROR, 'Widget could not be created.');
return Msg::failure('Widget could not be created.');
}
}

Expand All @@ -397,7 +409,7 @@ static public function session_play_create($inst_id, $context_id=false)
{
if ( ! ($inst = Widget_Instance_Manager::get($inst_id))) throw new \HttpNotFoundException;
if ( ! $inst->playable_by_current_user()) return Msg::no_login();
if ( $inst->is_draft == true) return new Msg(Msg::ERROR, 'Drafts Not Playable', 'Must use Preview to play a draft.');
if ( $inst->is_draft == true) return Msg::failure('Drafts Not Playable', 'Must use Preview to play a draft.');

$play = new Session_Play();
$play_id = $play->start(\Model_User::find_current_id(), $inst_id, $context_id);
Expand Down Expand Up @@ -433,7 +445,7 @@ static public function session_author_verify($role_name = null)
static public function session_play_verify($play_id)
{
// Standard session validation first
if (\Service_User::verify_session() !== true) return false;
if (\Service_User::verify_session() !== true) return Msg::no_login();

// if $play_id is null, assume it's a preview, no need for user check
if ( ! $play_id) return true;
Expand Down Expand Up @@ -481,7 +493,7 @@ static public function play_logs_save($play_id, $logs, $preview_inst_id = null)
else
{
// No user in session, just perform auth check
if (\Service_User::verify_session() !== true) return false;
if (\Service_User::verify_session() !== true) return Msg::no_login();
}

if ( $preview_inst_id === null && ! Util_Validator::is_valid_long_hash($play_id)) return Msg::invalid_input($play_id);
Expand Down Expand Up @@ -524,7 +536,7 @@ static public function play_logs_save($play_id, $logs, $preview_inst_id = null)
if ($score_mod->validate_times() == false)
{
$play->invalidate();
return new Msg(Msg::ERROR, 'Timing validation error.', true);
return Msg::failure('Timing validation error.');
}

// if widget is not scorable, check for a participation score log
Expand All @@ -548,7 +560,7 @@ static public function play_logs_save($play_id, $logs, $preview_inst_id = null)
catch (Score_Exception $e)
{
$play->invalidate();
return new Msg($e->message, $e->title, Msg::ERROR, true);
return Msg::failure($e->message, $e->title);
}

$return = [];
Expand Down Expand Up @@ -743,7 +755,7 @@ static public function score_raw_distribution_get($inst_id, $get_all = false)
}
catch (\Exception $e) {
trace("Error loading score module for {$inst_id}");
return false;
return Msg::failure("Error loading score module for {$inst_id}");
}

$result = null;
Expand Down Expand Up @@ -1155,7 +1167,7 @@ static public function notification_delete($note_id, $delete_all)
return true;
}
}
return false;
return Msg::failure('Failed to delete notification');
}
/**
* Returns all of the semesters from the semester table
Expand Down
Loading

0 comments on commit 6635291

Please sign in to comment.