Skip to content

Commit

Permalink
Merge pull request #377 from mudhoney/feature/save_state
Browse files Browse the repository at this point in the history
client_state database table and endpoints to create and read them
  • Loading branch information
mudhoney authored May 17, 2024
2 parents 821aad9 + f67fce5 commit 25918c7
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 9 deletions.
2 changes: 2 additions & 0 deletions docroot/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ function loadModule($params) {
'updateDataCoverage' => 'WebClient', // Deprecated, remove in V3, replaced by management scripts
'shortenURL' => 'WebClient',
'goto' => 'WebClient',
'saveWebClientState' => 'WebClient',
'getWebClientState' => 'WebClient',
'takeScreenshot' => 'WebClient',
'getRandomSeed' => 'WebClient',
'getJP2Image' => 'JHelioviewer',
Expand Down
4 changes: 2 additions & 2 deletions docroot/statistics/statistics.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var heirarchy = {
"Movies":["buildMovie","getMovieStatus","queueMovie","reQueueMovie","playMovie","downloadMovie","getUserVideos","getObservationDateVideos","uploadMovieToYouTube","checkYouTubeAuth","getYouTubeAuth"],
"Events":["getEventGlossary", "events", "getEvents","getFRMs","getEvent","getEventFRMs","getDefaultEventTypes","getEventsByEventLayers","importEvents"],
"Data":["getRandomSeed","getDataSources","getJP2Header","getDataCoverage","getStatus","getNewsFeed","getDataCoverageTimeline","getClosestData","getSolarBodiesGlossary","getSolarBodies","getTrajectoryTime","sciScript-SSWIDL","sciScript-SunPy","getSciDataScript","updateDataCoverage","getEclipseImage"],
"Other":["shortenURL", "goto", "getUsageStatistics","movie-notifications-granted","movie-notifications-denied","logNotificationStatistics","launchJHelioviewer"],
"Other":["shortenURL", "goto", "getUsageStatistics","movie-notifications-granted","movie-notifications-denied","logNotificationStatistics","launchJHelioviewer", "saveWebClientState", "getWebClientState"],
"WebGL":["getTexture","getGeometryServiceData"]
};

Expand Down Expand Up @@ -644,4 +644,4 @@ function createDeviceChart(id, deviceSummary, size) {

chart = new google.visualization.PieChart(document.getElementById(id));
chart.draw(data, {width: size, height: size*pieHeightScale, colors: colors, title: "Client Devices"});
};
};
6 changes: 6 additions & 0 deletions install/database/2024_05_16_create_client_states_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS `client_states` (
`id` CHAR(64) PRIMARY KEY,
`state` JSON NOT NULL DEFAULT '{}',
`created` DATETIME DEFAULT CURRENT_TIMESTAMP,
`updated` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
14 changes: 14 additions & 0 deletions install/helioviewer/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ def setup_database_schema(adminuser, adminpass, dbhost, dbname, dbuser, dbpass,
create_flare_prediction_dataset_table(cursor)
print("Creating flare prediction table")
create_flare_prediction_table(cursor)
print("Creating client_states table")
create_client_states_table(cursor)

return db, cursor

Expand Down Expand Up @@ -888,6 +890,18 @@ def create_rate_limit_table(cursor):
PRIMARY KEY (`datetime`, `identifier`)
) DEFAULT CHARSET=utf8;""")

def create_client_states_table(cursor):
"""
Create table for client states
"""
cursor.execute("""
CREATE TABLE IF NOT EXISTS `client_states` (
`id` CHAR(64) PRIMARY KEY,
`state` JSON NOT NULL DEFAULT '{}',
`created` DATETIME DEFAULT CURRENT_TIMESTAMP,
`updated` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;""")

def create_flare_prediction_table(cursor):
"""
Create table for storing CCMC Flare Predictions
Expand Down
2 changes: 1 addition & 1 deletion scripts/hv_stats/hv_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -2274,7 +2274,7 @@ def add_harea_if_timestamp_in_range(start_time, end_time, color, alpha, label):
"Movies":["buildMovie","getMovieStatus","queueMovie","reQueueMovie","playMovie","downloadMovie","getUserVideos","getObservationDateVideos","uploadMovieToYouTube","checkYouTubeAuth","getYouTubeAuth"],
"Events":["getEventGlossary","getEvents","getFRMs","getEvent","getEventFRMs","getDefaultEventTypes","getEventsByEventLayers","importEvents"],
"Data":["getRandomSeed","getDataSources","getJP2Header","getDataCoverage","getStatus","getNewsFeed","getDataCoverageTimeline","getClosestData","getSolarBodiesGlossary","getSolarBodies","getTrajectoryTime","sciScript-SSWIDL","sciScript-SunPy","getSciDataScript","updateDataCoverage","getEclipseImage"],
"Other":["shortenURL","getUsageStatistics","movie-notifications-granted","movie-notifications-denied","logNotificationStatistics","launchJHelioviewer"],
"Other":["shortenURL","getUsageStatistics","movie-notifications-granted","movie-notifications-denied","logNotificationStatistics","launchJHelioviewer", "saveWebClientState", "getWebClientState"],
"WebGL":["getTexture","getGeometryServiceData"]
};

Expand Down
61 changes: 61 additions & 0 deletions src/Database/ClientState.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Client State class for managing client_states table
*
* @category Database
* @package Helioviewer
* @author Kasim Necdet Percinel <[email protected]>
* @license http://www.mozilla.org/MPL/MPL-1.1.html Mozilla Public License 1.1
* @link https://github.com/Helioviewer-Project/
*/

require_once HV_ROOT_DIR.'/../src/Database/DbConnection.php';

class ClientState extends Database_DbConnection
{
/**
* This function creates or updates the state in database.
*
* @return string
*/
public function upsert(array $state): string
{
$state_json = json_encode($state);
$state_key = hash('sha256',$state_json);

$create_sql = "REPLACE INTO client_states(id, state) VALUES ('%s','%s')";
$create_state_sql = sprintf($create_sql, $state_key, $this->link->real_escape_string($state_json));

// intentionally let exception thrown
$result = $this->query($create_state_sql);

return $state_key;
}

/**
* This function finds the client state in db, with our given id
* @param string, state_key is the id of the client state in database
* @return array?
*/
public function find(string $state_key): ?array
{
$find_sql = "SELECT * FROM client_states WHERE id = '%s' LIMIT 1";

$find_state_sql = sprintf($find_sql, $this->link->real_escape_string($state_key));

$query_result = $this->query($find_state_sql);

$res = null;

while ($row = $query_result->fetch_array(MYSQLI_ASSOC)) {
$res = json_decode($row['state'], true);
}

$query_result->close();

return $res;

}

}
14 changes: 13 additions & 1 deletion src/Database/DbConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,17 @@ public function query($query) {
public function setEncoding($encoding) {
mysqli_set_charset($this->link, $encoding);
}

/**
* Deconstructor should be executed when this class instance is not referenced
*
* @return void
*/
public function __destruct() {
if ($this->link) {
mysqli_close($this->link);
}
}

}
?>
?>
4 changes: 4 additions & 0 deletions src/Database/Statistics.php
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,8 @@ private function _createCountsArray(){
'getDataCoverage' => array(),
'updateDataCoverage' => array(),
'shortenURL' => array(),
'saveWebClientState' => array(),
'getWebClientState' => array(),
'goto' => array(),
'takeScreenshot' => array(),
'getRandomSeed' => array(),
Expand Down Expand Up @@ -890,6 +892,8 @@ private function _createSummaryArray(){
'getDataCoverage' => 0,
'updateDataCoverage' => 0,
'shortenURL' => 0,
'saveWebClientState' => 0,
'getWebClientState' => 0,
'goto' => 0,
'takeScreenshot' => 0,
'getRandomSeed' => 0,
Expand Down
93 changes: 88 additions & 5 deletions src/Module/WebClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -619,14 +619,13 @@ public function getNewsFeed() {
}

private static function GetClientUrl(): string {
$base = self::GetApiUrl();
return str_replace('api.', '', $base);
// i.e. http://helioviewer.org
return HV_CLIENT_URL;
}

private static function GetApiUrl(): string {
$http = ($_SERVER['HTTPS'] ?? false) ? 'https' : 'http';
$baseUrl = "$http://".$_SERVER['SERVER_NAME'];
return $baseUrl;
// i.e. http://api.helioviewer.org
return HV_WEB_ROOT_URL;
}

public function goto() {
Expand All @@ -641,6 +640,58 @@ public function goto() {
}
}

/**
* This function saves event state into our database
*
* It saves the event and returns the identifier
*/
public function saveWebClientState() {

require_once HV_ROOT_DIR.'/../src/Database/ClientState.php';

$client_state = new ClientState();

try {

$state_key = $client_state->upsert($this->_params['state']);

return $this->_sendResponse(200, 'OK', $state_key);

} catch (\Exception $e) {
return $this->_sendResponse(500, 'Server Error', '');
}


}

/**
* This function returns the event state for the given id
*/
public function getWebClientState()
{
require_once HV_ROOT_DIR.'/../src/Database/ClientState.php';

$client_state = new ClientState();

try {

$state = $client_state->find($this->_params['state_id']);

if(is_null($state)) {
return $this->_sendResponse(404, 'Not Found', '');
}

return $this->_sendResponse(200, 'OK', $state);

} catch (\Exception $e) {

return $this->_sendResponse(500, 'Server Error', '');

}


}

/**
* Uses bit.ly to generate a shortened URL
*
Expand Down Expand Up @@ -1341,6 +1392,26 @@ private function _getTileCacheFilename($directory, $filename, $scale, $x, $y, $d
);
}

/**
* Helper function to handle response code and response message with
* output result as either JSON or JSONP
*
* @param int $code HTTP response code to return
* @param string $message Message for the response code,
* @param mixed $data Data can be anything
*
* @return void
*/
private function _sendResponse(int $code, string $message, mixed $data) : void
{
http_response_code($code);
$this->_printJSON(json_encode([
'status_code' => $code,
'status_txt' => $message,
'data' => $data,
]));
}

/**
* Helper function to output result as either JSON or JSONP
*
Expand Down Expand Up @@ -1435,6 +1506,18 @@ public function validate() {

switch( $this->_params['action'] ) {

case 'saveWebClientState':
$expected = array(
'required' => array('state'),
);
break;

case 'getWebClientState':
$expected = array(
'required' => array('state_id'),
);
break;

case 'downloadScreenshot':
$expected = array(
'required' => array('id'),
Expand Down
Loading

0 comments on commit 25918c7

Please sign in to comment.