/trunk/TODO |
---|
1,4 → 1,7 |
June 2023 planned: |
- Finish REST API |
May 2023 planned: |
- Don't send "information object OIDs" (= Non-OIDs) OIDs to oid-info.com anymore |
- In re Internet access: |
/trunk/doc/config_values.md |
---|
635,6 → 635,20 |
Allow JWT tokens that were created using the RA-plugin |
"Automated AJAX calls". |
### JWT_ALLOW_REST_ADMIN |
OIDplus::baseConfig()->setValue('JWT_ALLOW_REST_ADMIN', true); |
Allow JWT tokens that were created using the admin-plugin |
"REST API". |
### JWT_ALLOW_REST_USER |
OIDplus::baseConfig()->setValue('JWT_ALLOW_REST_USER', true); |
Allow JWT tokens that were created using the RA-plugin |
"REST API". |
### JWT_ALLOW_LOGIN_ADMIN |
OIDplus::baseConfig()->setValue('JWT_ALLOW_LOGIN_ADMIN', true); |
/trunk/doc/developer_notes/feature_oids.md |
---|
108,3 → 108,7 |
- plugins/viathinksoft/adminPages/010_notifications/INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_8.class.php containing the functions: |
- getNotifications |
- plugins/viathinksoft/publicPages/002_rest_api/INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9.class.php containing the functions: |
- restApiCall |
- restApiInfo |
/trunk/includes/classes/OIDplus.class.php |
---|
2224,6 → 2224,12 |
* @throws OIDplusException |
*/ |
public static function getCurrentLang() { |
$rel_url = substr($_SERVER['REQUEST_URI'], strlen(OIDplus::webpath(null, OIDplus::PATH_RELATIVE_TO_ROOT))); |
if (str_starts_with($rel_url, 'rest/')) { // <== TODO: Find a way how to move this into the plugin, since REST does not belong to the core. (Maybe some kind of "stateless mode" that is enabled by the REST plugin) |
return self::getDefaultLang(); |
} |
if (isset($_GET['lang'])) { |
$lang = $_GET['lang']; |
} else if (isset($_POST['lang'])) { |
/trunk/includes/classes/OIDplusAuthContentStoreJWT.class.php |
---|
33,15 → 33,19 |
/** |
* "Automated AJAX" plugin |
*/ |
const JWT_GENERATOR_AJAX = 0; |
const JWT_GENERATOR_AJAX = 10; |
/** |
* "REST API" plugin |
*/ |
const JWT_GENERATOR_REST = 20; |
/** |
* "Remember me" login method |
*/ |
const JWT_GENERATOR_LOGIN = 1; |
const JWT_GENERATOR_LOGIN = 40; |
/** |
* "Manually crafted" JWT tokens |
*/ |
const JWT_GENERATOR_MANUAL = 2; |
const JWT_GENERATOR_MANUAL = 80; |
/** |
* @param int $gen OIDplusAuthContentStoreJWT::JWT_GENERATOR_... |
49,11 → 53,23 |
* @return string |
*/ |
private static function jwtGetBlacklistConfigKey(int $gen, string $sub): string { |
// Note: Needs to be <= 50 characters! |
// Note: Needs to be <= 50 characters! If $gen is 2 chars, then the config key is 49 chars long |
return 'jwt_blacklist_gen('.$gen.')_sub('.trim(base64_encode(md5($sub,true)),'=').')'; |
} |
/** |
* @param int $gen |
*/ |
private static function generatorName($gen) { |
// Note: The strings are not translated, because the name is used in config keys or logs |
if ($gen === self::JWT_GENERATOR_AJAX) return 'Automated AJAX calls'; |
if ($gen === self::JWT_GENERATOR_REST) return 'REST API'; |
if ($gen === self::JWT_GENERATOR_LOGIN) return 'Login ("Remember me")'; |
if ($gen === self::JWT_GENERATOR_MANUAL) return 'Manually created'; |
return 'Unknown generator'; |
} |
/** |
* @param int $gen OIDplusAuthContentStoreJWT::JWT_GENERATOR_... |
* @param string $sub |
* @return void |
63,10 → 79,7 |
$cfg = self::jwtGetBlacklistConfigKey($gen, $sub); |
$bl_time = time()-1; |
$gen_desc = 'Unknown'; |
if ($gen === self::JWT_GENERATOR_AJAX) $gen_desc = 'Automated AJAX calls'; |
if ($gen === self::JWT_GENERATOR_LOGIN) $gen_desc = 'Login ("Remember me")'; |
if ($gen === self::JWT_GENERATOR_MANUAL) $gen_desc = 'Manually created'; |
$gen_desc = self::generatorName($gen); |
OIDplus::config()->prepareConfigKey($cfg, 'Revoke timestamp of all JWT tokens for $sub with generator $gen ($gen_desc)', "$bl_time", OIDplusConfig::PROTECTION_HIDDEN, function($value) {}); |
OIDplus::config()->setValue($cfg, $bl_time); |
84,11 → 97,13 |
} |
/** |
* Do various checks if the token is allowed and not blacklisted |
* @param OIDplusAuthContentStore $contentProvider |
* @param int $validGenerators Bitmask which generators to allow (-1 = allow all) |
* @return void |
* @throws OIDplusException |
*/ |
private static function jwtSecurityCheck(OIDplusAuthContentStore $contentProvider) { |
private static function jwtSecurityCheck(OIDplusAuthContentStore $contentProvider, int $validGenerators=-1) { |
// Check if the token is intended for us |
if ($contentProvider->getValue('aud','') !== OIDplus::getEditionInfo()['jwtaud']) { |
throw new OIDplusException(_L('Token has wrong audience')); |
109,6 → 124,16 |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_AJAX_USER')); |
} |
} |
else if ($gen === self::JWT_GENERATOR_REST) { |
if (($has_admin) && !OIDplus::baseConfig()->getValue('JWT_ALLOW_REST_ADMIN', true)) { |
// Generator: plugins/viathinksoft/adminPages/911_rest_api/OIDplusPageAdminRestApi.class.php |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_REST_ADMIN')); |
} |
if (($has_ra) && !OIDplus::baseConfig()->getValue('JWT_ALLOW_REST_USER', true)) { |
// Generator: plugins/viathinksoft/raPages/911_rest_api/OIDplusPageRaRestApi.class.php |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_REST_USER')); |
} |
} |
else if ($gen === self::JWT_GENERATOR_LOGIN) { |
// Used for feature "Remember me" (use JWT token in a cookie as alternative to PHP session): |
// - No PHP session will be used |
156,21 → 181,13 |
} |
} |
// Checks which are dependent on the generator |
if ($gen === self::JWT_GENERATOR_LOGIN) { |
if (!isset($_COOKIE[self::COOKIE_NAME])) { |
throw new OIDplusException(_L('This kind of JWT token can only be used with the %1 request type','COOKIE')); |
// Checks if JWT are dependent on the generator |
if ($validGenerators !== -1) { |
if (($gen & $validGenerators) === 0) { |
throw new OIDplusException(_L('This kind of JWT token (%1) cannot be used in this request type', self::generatorName($gen))); |
} |
} |
if ($gen === self::JWT_GENERATOR_AJAX) { |
if (!isset($_GET[self::COOKIE_NAME]) && !isset($_POST[self::COOKIE_NAME])) { |
throw new OIDplusException(_L('This kind of JWT token can only be used with the %1 request type','GET/POST')); |
} |
if (isset($_SERVER['SCRIPT_FILENAME']) && (strtolower(basename($_SERVER['SCRIPT_FILENAME'])) !== 'ajax.php')) { |
throw new OIDplusException(_L('This kind of JWT token can only be used in ajax.php')); |
} |
} |
} |
// Override abstract functions |
250,22 → 267,54 |
*/ |
public static function getActiveProvider()/*: ?OIDplusAuthContentStore*/ { |
if (!self::$contentProvider) { |
$jwt = ''; |
if (isset($_COOKIE[self::COOKIE_NAME])) $jwt = $_COOKIE[self::COOKIE_NAME]; |
if (isset($_POST[self::COOKIE_NAME])) $jwt = $_POST[self::COOKIE_NAME]; |
if (isset($_GET[self::COOKIE_NAME])) $jwt = $_GET[self::COOKIE_NAME]; |
if (!empty($jwt)) { |
$tmp = new OIDplusAuthContentStoreJWT(); |
$tmp = null; |
$silent_error = false; |
try { |
// Decode the JWT. In this step, the signature as well as EXP/NBF times will be checked |
$tmp->loadJWT($jwt); |
// Do various checks if the token is allowed and not blacklisted |
self::jwtSecurityCheck($tmp); |
$rel_url = substr($_SERVER['REQUEST_URI'], strlen(OIDplus::webpath(null, OIDplus::PATH_RELATIVE_TO_ROOT))); |
if (str_starts_with($rel_url, 'rest/')) { // <== TODO: Find a way how to move this into the plugin, since REST does not belong to the core. |
// REST may only use Bearer Authentication |
$bearer = getBearerToken(); |
if (!is_null($bearer)) { |
$silent_error = false; |
$tmp = new OIDplusAuthContentStoreJWT(); |
$tmp->loadJWT($bearer); |
self::jwtSecurityCheck($tmp, self::JWT_GENERATOR_REST | self::JWT_GENERATOR_MANUAL); |
} |
} else { |
// A web-visitor (HTML and AJAX, but not REST) can use a JWT "remember me" Cookie |
if (isset($_COOKIE[self::COOKIE_NAME])) { |
$silent_error = true; |
$tmp = new OIDplusAuthContentStoreJWT(); |
$tmp->loadJWT($_COOKIE[self::COOKIE_NAME]); |
self::jwtSecurityCheck($tmp, self::JWT_GENERATOR_LOGIN | self::JWT_GENERATOR_MANUAL); |
} |
// AJAX may additionally use GET/POST automated AJAX (in addition to the normal JWT "remember me" Cookie) |
if (isset($_SERVER['SCRIPT_FILENAME']) && (strtolower(basename($_SERVER['SCRIPT_FILENAME'])) !== 'ajax.php')) { |
if (isset($_POST[self::COOKIE_NAME])) { |
$silent_error = false; |
$tmp = new OIDplusAuthContentStoreJWT(); |
$tmp->loadJWT($_POST[self::COOKIE_NAME]); |
self::jwtSecurityCheck($tmp, self::JWT_GENERATOR_AJAX | self::JWT_GENERATOR_MANUAL); |
} |
if (isset($_GET[self::COOKIE_NAME])) { |
$silent_error = false; |
$tmp = new OIDplusAuthContentStoreJWT(); |
$tmp->loadJWT($_GET[self::COOKIE_NAME]); |
self::jwtSecurityCheck($tmp, self::JWT_GENERATOR_AJAX | self::JWT_GENERATOR_MANUAL); |
} |
} |
} |
} catch (\Exception $e) { |
if (isset($_GET[self::COOKIE_NAME]) || isset($_POST[self::COOKIE_NAME])) { |
if (!$silent_error) { |
// Most likely an AJAX request. We can throw an Exception |
throw new OIDplusException(_L('The JWT token was rejected: %1',$e->getMessage())); |
} else { |
277,7 → 326,6 |
self::$contentProvider = $tmp; |
} |
} |
return self::$contentProvider; |
} |
297,6 → 345,7 |
$gen = $this->getValue('oidplus_generator',-1); |
switch ($gen) { |
case OIDplusAuthContentStoreJWT::JWT_GENERATOR_AJAX : |
case OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST : |
case OIDplusAuthContentStoreJWT::JWT_GENERATOR_MANUAL : |
throw new OIDplusException(_L('This kind of JWT token cannot be altered. Therefore you cannot do this action.')); |
case OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN : |
327,6 → 376,7 |
$gen = $this->getValue('oidplus_generator',-1); |
switch ($gen) { |
case OIDplusAuthContentStoreJWT::JWT_GENERATOR_AJAX : |
case OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST : |
case OIDplusAuthContentStoreJWT::JWT_GENERATOR_MANUAL : |
throw new OIDplusException(_L('This kind of JWT token cannot be altered. Therefore you cannot do this action.')); |
case OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN : |
346,6 → 396,7 |
// Individual functions |
/** |
* Decode the JWT. In this step, the signature as well as EXP/NBF times will be checked |
* @param string $jwt |
* @return void |
* @throws OIDplusException |
/trunk/includes/classes/OIDplusAuthUtils.class.php |
---|
72,15 → 72,23 |
* @throws OIDplusException |
*/ |
protected function getAuthContentStore()/*: ?OIDplusAuthContentStore*/ { |
// TODO: Should we implement these AuthContentStore as plugin type, so that there can be more than just JWT and PHP session? |
// Logged in via JWT |
$tmp = OIDplusAuthContentStoreJWT::getActiveProvider(); |
if ($tmp) return $tmp; |
// For REST, we must only allow JWT from Bearer and nothing else! So disable cookies if we are accessing the REST plugin |
$rel_url = substr($_SERVER['REQUEST_URI'], strlen(OIDplus::webpath(null, OIDplus::PATH_RELATIVE_TO_ROOT))); |
if (!str_starts_with($rel_url, 'rest/')) { // <== TODO: Find a way how to move this into the plugin, since REST does not belong to the core. (Maybe some kind of "stateless mode" that is enabled by the REST plugin) |
// Normal login via web-browser |
// Cookie will only be created once content is stored |
$tmp = OIDplusAuthContentStoreSession::getActiveProvider(); |
if ($tmp) return $tmp; |
} |
// No active session and no JWT token available. User is not logged in. |
return null; |
} |
/trunk/includes/functions.inc.php |
---|
618,3 → 618,41 |
$html = html_entity_decode($html, ENT_QUOTES, 'UTF-8'); |
return $html; |
} |
/** |
* Get header Authorization |
* @see https://stackoverflow.com/questions/40582161/how-to-properly-use-bearer-tokens |
**/ |
function getAuthorizationHeader(){ |
$headers = null; |
if (isset($_SERVER['Authorization'])) { |
$headers = trim($_SERVER["Authorization"]); |
} |
else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI |
$headers = trim($_SERVER["HTTP_AUTHORIZATION"]); |
} elseif (function_exists('apache_request_headers')) { |
$requestHeaders = apache_request_headers(); |
// Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization) |
$requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); |
//print_r($requestHeaders); |
if (isset($requestHeaders['Authorization'])) { |
$headers = trim($requestHeaders['Authorization']); |
} |
} |
return $headers; |
} |
/** |
* get access token from header |
* @see https://stackoverflow.com/questions/40582161/how-to-properly-use-bearer-tokens |
**/ |
function getBearerToken() { |
$headers = getAuthorizationHeader(); |
// HEADER: Get the access token from the header |
if (!empty($headers)) { |
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) { |
return $matches[1]; |
} |
} |
return null; |
} |
/trunk/plugins/viathinksoft/adminPages/911_rest_api/OIDplusPageAdminRestApi.class.php |
---|
0,0 → 1,156 |
<?php |
/* |
* OIDplus 2.0 |
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
// ATTENTION: If you change something, please make sure that the changes |
// are synchronous with OIDplusPageRaRestApi |
namespace ViaThinkSoft\OIDplus; |
// phpcs:disable PSR1.Files.SideEffects |
\defined('INSIDE_OIDPLUS') or die; |
// phpcs:enable PSR1.Files.SideEffects |
class OIDplusPageAdminRestApi extends OIDplusPagePluginAdmin { |
/** |
* @param string $actionID |
* @param array $params |
* @return array |
* @throws OIDplusException |
*/ |
public function action(string $actionID, array $params): array { |
if ($actionID == 'blacklistJWT') { |
if (!OIDplus::authUtils()->isAdminLoggedIn()) { |
throw new OIDplusHtmlException(_L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin'))); |
} |
if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_REST_ADMIN', true)) { |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_REST_ADMIN')); |
} |
$gen = OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST; |
$sub = 'admin'; |
OIDplusAuthContentStoreJWT::jwtBlacklist($gen, $sub); |
return array("status" => 0); |
} else { |
return parent::action($actionID, $params); |
} |
} |
/** |
* @param string $id |
* @param array $out |
* @param bool $handled |
* @return void |
* @throws OIDplusException |
*/ |
public function gui(string $id, array &$out, bool &$handled) { |
if ($id === 'oidplus:rest_api_information_admin') { |
$handled = true; |
$out['title'] = _L('REST API'); |
$out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : ''; |
if (!OIDplus::authUtils()->isAdminLoggedIn()) { |
throw new OIDplusHtmlException(_L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')), $out['title']); |
} |
if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_REST_ADMIN', true)) { |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_REST_ADMIN'), $out['title']); |
} |
$gen = OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST; |
$sub = 'admin'; |
$authSimulation = new OIDplusAuthContentStoreJWT(); |
$authSimulation->adminLogin(); |
$authSimulation->setValue('oidplus_generator', $gen); |
$token = $authSimulation->getJWTToken(); |
$out['text'] .= '<p>'._L('You can make automated calls to your OIDplus account by calling an REST API.').'</p>'; |
$out['text'] .= '<h2>'._L('Endpoints').'</h2>'; |
$endpoints = ''; |
foreach (OIDplus::getAllPlugins() as $plugin) { |
if ($plugin instanceof INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9) { |
$endpoints .= $plugin->restApiInfo('html'); |
} |
} |
if ($endpoints) { |
$out['text'] .= '<p>'._L('The following endpoints are registered by the plugins in this system:').'</p>'; |
$out['text'] .= '<p>'.$endpoints.'</p>'; |
} else { |
$out['text'] .= '<p>'._L('No installed plugin offers a REST functionality').'</p>'; |
} |
$out['text'] .= '<h2>'._L('Authentication').'</h2>'; |
$out['text'] .= '<p>'._L('The authentication is done via the following HTTP header:').'</p>'; |
$out['text'] .= '<p><pre id="oidplus_auth_jwt">'; |
$out['text'] .= 'Authentication: Bearer '.htmlentities($token)."\n"; |
$out['text'] .= '</pre></p>'; |
$out['text'] .= '<p><input type="button" value="'._L('Copy to clipboard').'" onClick="copyToClipboard(oidplus_auth_jwt)"></p>'; |
$out['text'] .= '<p>'._L('Please keep this information confidential!').'</p>'; |
$out['text'] .= '<p>'._L('The JWT-token (secret!) will automatically perform a one-time-login to fulfill the request. The other fields are the normal fields which are called during the usual operation of OIDplus.').'</p>'; |
$out['text'] .= '<h2>'._L('Blacklisted tokens').'</h2>'; |
$bl_time = OIDplusAuthContentStoreJWT::jwtGetBlacklistTime($gen, $sub); |
if ($bl_time == 0) { |
$out['text'] .= '<p>'._L('None of the previously generated JWT tokens have been blacklisted.').'</p>'; |
} else { |
$out['text'] .= '<p>'._L('All tokens generated before %1 have been blacklisted.',date('d F Y, H:i:s',$bl_time+1)).'</p>'; |
} |
$out['text'] .= '<button type="button" name="btn_blacklist_jwt" id="btn_blacklist_jwt" class="btn btn-danger btn-xs" onclick="OIDplusPageAdminRestApi.blacklistJWT()">'._L('Blacklist all previously generated tokens').'</button>'; |
} |
} |
/** |
* @param array $json |
* @param string|null $ra_email |
* @param bool $nonjs |
* @param string $req_goto |
* @return bool |
* @throws OIDplusException |
*/ |
public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool { |
if (!OIDplus::authUtils()->isAdminLoggedIn()) return false; |
if (file_exists(__DIR__.'/img/main_icon16.png')) { |
$tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
} else { |
$tree_icon = null; // default icon (folder) |
} |
$json[] = array( |
'id' => 'oidplus:rest_api_information_admin', |
'icon' => $tree_icon, |
'text' => _L('REST API') |
); |
// TODO: Make "Endpoints" (with all installed plugins) and "Authentication" as menu entries! |
return true; |
} |
/** |
* @param string $request |
* @return array|false |
*/ |
public function tree_search(string $request) { |
return false; |
} |
} |
/trunk/plugins/viathinksoft/adminPages/911_rest_api/OIDplusPageAdminRestApi.js |
---|
0,0 → 1,50 |
/* |
* OIDplus 2.0 |
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
var OIDplusPageAdminRestApi = { |
oid: "1.3.6.1.4.1.37476.2.5.2.4.3.911", |
blacklistJWT: function() { |
if(!window.confirm(_L("Are you sure that you want to blacklist all access tokens?"))) return false; |
$.ajax({ |
url:"ajax.php", |
method:"POST", |
beforeSend: function(jqXHR, settings) { |
$.xhrPool.abortAll(); |
$.xhrPool.add(jqXHR); |
}, |
complete: function(jqXHR, text) { |
$.xhrPool.remove(jqXHR); |
}, |
data: { |
csrf_token:csrf_token, |
plugin:OIDplusPageAdminRestApi.oid, |
action:"blacklistJWT" |
}, |
error: oidplus_ajax_error, |
success: function (data) { |
oidplus_ajax_success(data, function (data) { |
alertSuccess(_L("OK")); |
reloadContent(); |
}); |
} |
}); |
} |
}; |
/trunk/plugins/viathinksoft/adminPages/911_rest_api/img/index.html |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/plugins/viathinksoft/adminPages/911_rest_api/img/main_icon.png |
---|
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/plugins/viathinksoft/adminPages/911_rest_api/img/main_icon16.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/plugins/viathinksoft/adminPages/911_rest_api/index.html |
---|
--- plugins/viathinksoft/adminPages/911_rest_api/manifest.xml (nonexistent) |
+++ plugins/viathinksoft/adminPages/911_rest_api/manifest.xml (revision 1265) |
@@ -0,0 +1,29 @@ |
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> |
+<manifest |
+ xmlns="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.2.1" |
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
+ xsi:schemaLocation="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.2.1 https://oidplus.viathinksoft.com/oidplus/plugins/manifest_plugin_page.xsd"> |
+ |
+ <type>ViaThinkSoft\OIDplus\OIDplusPagePluginAdmin</type> |
+ |
+ <info> |
+ <name>REST API</name> |
+ <author>ViaThinkSoft</author> |
+ <license>Apache 2.0</license> |
+ <version /> |
+ <descriptionHTML /> |
+ <oid>1.3.6.1.4.1.37476.2.5.2.4.3.911</oid> |
+ </info> |
+ |
+ <php> |
+ <mainclass>ViaThinkSoft\OIDplus\OIDplusPageAdminRestApi</mainclass> |
+ </php> |
+ |
+ <css> |
+ </css> |
+ |
+ <js> |
+ <file>OIDplusPageAdminRestApi.js</file> |
+ </js> |
+ |
+</manifest> |
/trunk/plugins/viathinksoft/language/dede/messages.xml |
---|
718,6 → 718,14 |
</message> |
<message> |
<source><![CDATA[ |
Authentication |
]]></source> |
<target><![CDATA[ |
Authentifizierung |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
Authentication error. Please log in as admin, or as the RA of "%1" to upload an attachment. |
]]></source> |
<target><![CDATA[ |
2118,6 → 2126,14 |
</message> |
<message> |
<source><![CDATA[ |
Endpoints |
]]></source> |
<target><![CDATA[ |
Endpunkte |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
Enforce SSL (always redirect) |
]]></source> |
<target><![CDATA[ |
3350,6 → 3366,14 |
</message> |
<message> |
<source><![CDATA[ |
Invalid REST API information format |
]]></source> |
<target><![CDATA[ |
Ungültiges REST API Dokumentations-Format |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
Invalid WEID |
]]></source> |
<target><![CDATA[ |
4238,6 → 4262,14 |
</message> |
<message> |
<source><![CDATA[ |
No installed plugin offers a REST functionality |
]]></source> |
<target><![CDATA[ |
Keine installierten Plugins bieten eine REST-Funktionalität an |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
No items available |
]]></source> |
<target><![CDATA[ |
5934,6 → 5966,14 |
</message> |
<message> |
<source><![CDATA[ |
REST API |
]]></source> |
<target><![CDATA[ |
REST API |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
RFC Internet Draft |
]]></source> |
<target><![CDATA[ |
7174,6 → 7214,14 |
</message> |
<message> |
<source><![CDATA[ |
The authentication is done via the following HTTP header: |
]]></source> |
<target><![CDATA[ |
Die Authentifizierung erfolgt über die folgende HTTP-Kopfzeile: |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
The database driver has problems with "%1" |
]]></source> |
<target><![CDATA[ |
7246,6 → 7294,14 |
</message> |
<message> |
<source><![CDATA[ |
The following endpoints are registered by the plugins in this system: |
]]></source> |
<target><![CDATA[ |
Die folgenden Endpunkte werden durch Plugins in diesem System zur Verfügung gestellt: |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
The following settings need to be configured once.<br>After setup is complete, you can change all these settings through the admin login area, if necessary. |
]]></source> |
<target><![CDATA[ |
7582,22 → 7638,14 |
</message> |
<message> |
<source><![CDATA[ |
This kind of JWT token can only be used in ajax.php |
This kind of JWT token (%1) cannot be used in this request type |
]]></source> |
<target><![CDATA[ |
Dieser JWT Token kann nur in ajax.php verwendet werden |
Diese Art von JWT-Token (%1) ist nicht für diesen Aufruf-Typ bestimmt |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
This kind of JWT token can only be used with the %1 request type |
]]></source> |
<target><![CDATA[ |
Dieser JWT Token kann nur mit dem %1 Anfragetyp verwendet werden |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
This kind of JWT token cannot be altered. Therefore you cannot do this action. |
]]></source> |
<target><![CDATA[ |
8390,6 → 8438,14 |
</message> |
<message> |
<source><![CDATA[ |
You can make automated calls to your OIDplus account by calling an REST API. |
]]></source> |
<target><![CDATA[ |
Die REST API bietet die Möglichkeit, Aufgaben automatisiert über Ihr OIDplus-Konto durchzuführen. |
]]></target> |
</message> |
<message> |
<source><![CDATA[ |
You can make automated calls to your OIDplus account by calling the AJAX API. |
]]></source> |
<target><![CDATA[ |
/trunk/plugins/viathinksoft/publicPages/000_objects/OIDplusPagePublicObjects.class.php |
---|
25,7 → 25,8 |
class OIDplusPagePublicObjects extends OIDplusPagePluginPublic |
implements INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_1, /* oobeEntry, oobeRequested */ |
INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_8 /* getNotifications */ |
INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_8, /* getNotifications */ |
INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9 /* restApiCall */ |
// Important: Do NOT implement INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_7, because our getAlternativesForQuery() is the one that calls others! |
{ |
58,6 → 59,71 |
} |
/** |
* Implements INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9 |
* @param string $requestMethod |
* @param string $endpoint |
* @return array|false |
*/ |
public function restApiCall(string $requestMethod, string $endpoint) { |
if (str_starts_with($endpoint, 'objects/')) { |
$id = substr($endpoint, strlen('objects/')); |
if ($requestMethod == "GET") { |
// TODO: Implement GET (Select) |
http_response_code(501); |
return array("error" => "Not implemented"); |
} else if ($requestMethod == "PUT") { |
// TODO: Implement PUT (Replace) |
http_response_code(501); |
return array("error" => "Not implemented"); |
} else if ($requestMethod == "POST") { |
// TODO: Implement POST (Insert) |
http_response_code(501); |
return array("error" => "Not implemented"); |
} else if ($requestMethod == "PATCH") { |
// TODO: Implement PATCH (Modify) |
http_response_code(501); |
return array("error" => "Not implemented"); |
} else if ($requestMethod == "DELETE") { |
try { |
self::action('Delete', array("id" => $id)); |
http_response_code(200); |
return array("status" => "OK"); |
} catch (\Exception $e) { |
http_response_code(401); // TODO: We need some kind of Exception class to know for sure that the Exception is due to missing authentication! |
return array("error" => $e->getMessage()); |
} |
} else { |
http_response_code(400); |
return array("error" => "Unsupported request method"); |
} |
} else { |
return false; |
} |
} |
/** |
* Implements INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9 |
* Outputs information about valid endpoints |
* @param string $kind Reserved for different kind of output format (i.e. OpenAPI "TODO"). Currently only 'html' is implemented |
* @return string |
*/ |
public function restApiInfo(string $kind='html'): string { |
if ($kind === 'html') { |
// TODO: Make a good documentation..... |
$out = '<ul><li><b>Objects API</b><ul>'; |
$out .= '<li>GET objects/[id]<ul><li>Input parameters: None</li><li>Output parameters: WORK IN PROGRESS</li></ul></li>'; |
$out .= '<li>PUT objects/[id]<ul><li>Input parameters: WORK IN PROGRESS</li><li>Output parameters: WORK IN PROGRESS</li></ul></li>'; |
$out .= '<li>POST objects/[id]<ul><li>Input parameters: WORK IN PROGRESS</li><li>Output parameters: WORK IN PROGRESS</li></ul></li>'; |
$out .= '<li>PATCH objects/[id]<ul><li>Input parameters: WORK IN PROGRESS</li><li>Output parameters: WORK IN PROGRESS</li></ul></li>'; |
$out .= '<li>DELETE objects/[id]<ul><li>Input parameters: None</li><li>Output parameters: WORK IN PROGRESS</li></ul></li>'; |
$out .= '</ul></li></ul>'; |
return $out; |
} else { |
throw new OIDplusException(_L('Invalid REST API information format')); |
} |
} |
/** |
* @param string $actionID |
* @param array $params |
* @return array |
/trunk/plugins/viathinksoft/publicPages/002_rest_api/INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9.class.php |
---|
0,0 → 1,42 |
<?php |
/* |
* OIDplus 2.0 |
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
namespace ViaThinkSoft\OIDplus; |
// phpcs:disable PSR1.Files.SideEffects |
\defined('INSIDE_OIDPLUS') or die; |
// phpcs:enable PSR1.Files.SideEffects |
interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9 { |
/** |
* @param string $requestMethod |
* @param string $endpoint |
* @return array|false |
*/ |
public function restApiCall(string $requestMethod, string $endpoint); |
/** |
* Outputs information about valid endpoints |
* @param string $kind Reserved for different kind of output format (i.e. OpenAPI "TODO"). Currently only 'html' is implemented |
* @return string |
*/ |
public function restApiInfo(string $kind='html'): string; |
} |
/trunk/plugins/viathinksoft/publicPages/002_rest_api/OIDplusPagePublicRestApi.class.php |
---|
0,0 → 1,71 |
<?php |
/* |
* OIDplus 2.0 |
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
namespace ViaThinkSoft\OIDplus; |
// TODO: should this be a different plugin type? A page without gui is weird! |
// phpcs:disable PSR1.Files.SideEffects |
\defined('INSIDE_OIDPLUS') or die; |
// phpcs:enable PSR1.Files.SideEffects |
class OIDplusPagePublicRestApi extends OIDplusPagePluginPublic { |
/** |
* @param string $request |
* @return bool |
* @throws OIDplusException |
*/ |
public function handle404(string $request): bool { |
if (!isset($_SERVER['REQUEST_URI']) || !isset($_SERVER["REQUEST_METHOD"])) return false; |
$rel_url = substr($_SERVER['REQUEST_URI'], strlen(OIDplus::webpath(null, OIDplus::PATH_RELATIVE_TO_ROOT))); |
$expect = 'rest/v1/'; |
if (str_starts_with($rel_url, $expect)) { |
$rel_url = ltrim($rel_url, $expect); |
$requestMethod = $_SERVER["REQUEST_METHOD"]; |
try { |
$json_out = false; |
foreach (OIDplus::getAllPlugins() as $plugin) { |
if ($plugin instanceof INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9) { |
$json_out = $plugin->restApiCall($requestMethod, $rel_url); |
if ($json_out !== false) break; |
} |
} |
if ($json_out === false) { |
http_response_code(404); |
$json_out = array("error" => "Endpoint not found"); |
} |
} catch (\Exception $e) { |
http_response_code(500); |
$json_out = array("error" => $e->getMessage()); |
} |
OIDplus::invoke_shutdown(); |
@header('Content-Type:application/json; charset=utf-8'); |
echo json_encode($json_out); |
die(); // return true; |
} |
return false; |
} |
} |
/trunk/plugins/viathinksoft/publicPages/002_rest_api/index.html |
---|
--- plugins/viathinksoft/publicPages/002_rest_api/manifest.xml (nonexistent) |
+++ plugins/viathinksoft/publicPages/002_rest_api/manifest.xml (revision 1265) |
@@ -0,0 +1,28 @@ |
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> |
+<manifest |
+ xmlns="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.2.1" |
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
+ xsi:schemaLocation="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.2.1 https://oidplus.viathinksoft.com/oidplus/plugins/manifest_plugin_page.xsd"> |
+ |
+ <type>ViaThinkSoft\OIDplus\OIDplusPagePluginPublic</type> |
+ |
+ <info> |
+ <name>REST API</name> |
+ <author>ViaThinkSoft</author> |
+ <license>Apache 2.0</license> |
+ <version /> |
+ <descriptionHTML /> |
+ <oid>1.3.6.1.4.1.37476.2.5.2.4.1.2</oid> |
+ </info> |
+ |
+ <php> |
+ <mainclass>ViaThinkSoft\OIDplus\OIDplusPagePublicRestApi</mainclass> |
+ </php> |
+ |
+ <css> |
+ </css> |
+ |
+ <js> |
+ </js> |
+ |
+</manifest> |
/trunk/plugins/viathinksoft/raPages/910_automated_ajax_calls/OIDplusPageRaAutomatedAJAXCalls.class.php |
---|
94,7 → 94,7 |
$out['text'] .= '<p>'._L('The URL for the AJAX script is:').'</p>'; |
$out['text'] .= '<p><b>'.OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL).'ajax.php</b></p>'; |
$out['text'] .= '<p>'._L('You must at least provide following fields:').'</p>'; |
$out['text'] .= '<p><pre>'; |
$out['text'] .= '<p><pre id="oidplus_auth_jwt">'; |
$out['text'] .= htmlentities(OIDplusAuthContentStoreJWT::COOKIE_NAME).' = "'.htmlentities($token).'"'."\n"; |
$out['text'] .= '</pre></p>'; |
$out['text'] .= '<p><input type="button" value="'._L('Copy to clipboard').'" onClick="copyToClipboard(oidplus_auth_jwt)"></p>'; |
/trunk/plugins/viathinksoft/raPages/911_rest_api/OIDplusPageRaRestApi.class.php |
---|
0,0 → 1,163 |
<?php |
/* |
* OIDplus 2.0 |
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
// ATTENTION: If you change something, please make sure that the changes |
// are synchronous with OIDplusPageAdminRestApi |
namespace ViaThinkSoft\OIDplus; |
// phpcs:disable PSR1.Files.SideEffects |
\defined('INSIDE_OIDPLUS') or die; |
// phpcs:enable PSR1.Files.SideEffects |
class OIDplusPageRaRestApi extends OIDplusPagePluginRa { |
/** |
* @param string $actionID |
* @param array $params |
* @return array |
* @throws OIDplusException |
*/ |
public function action(string $actionID, array $params): array { |
if ($actionID == 'blacklistJWT') { |
if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_REST_USER', true)) { |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_REST_USER')); |
} |
_CheckParamExists($params, 'user'); |
$ra_email = $params['user']; |
if (!OIDplus::authUtils()->isRaLoggedIn($ra_email) && !OIDplus::authUtils()->isAdminLoggedIn()) { |
throw new OIDplusHtmlException(_L('You need to <a %1>log in</a> as the requested RA %2 or as admin.',OIDplus::gui()->link('oidplus:login$ra$'.$ra_email),'<b>'.htmlentities($ra_email).'</b>')); |
} |
$gen = OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST; |
$sub = $ra_email; |
OIDplusAuthContentStoreJWT::jwtBlacklist($gen, $sub); |
return array("status" => 0); |
} else { |
return parent::action($actionID, $params); |
} |
} |
/** |
* @param string $id |
* @param array $out |
* @param bool $handled |
* @return void |
* @throws OIDplusException |
*/ |
public function gui(string $id, array &$out, bool &$handled) { |
if (explode('$',$id)[0] == 'oidplus:rest_api_information_ra') { |
$handled = true; |
$ra_email = explode('$',$id)[1]; |
$out['title'] = _L('REST API'); |
$out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : ''; |
if (!OIDplus::authUtils()->isRaLoggedIn($ra_email) && !OIDplus::authUtils()->isAdminLoggedIn()) { |
throw new OIDplusHtmlException(_L('You need to <a %1>log in</a> as the requested RA %2 or as admin.',OIDplus::gui()->link('oidplus:login$ra$'.$ra_email),'<b>'.htmlentities($ra_email).'</b>'), $out['title']); |
} |
if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_REST_USER', true)) { |
throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_REST_USER'), $out['title']); |
} |
$gen = OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST; |
$sub = $ra_email; |
$authSimulation = new OIDplusAuthContentStoreJWT(); |
$authSimulation->raLogin($ra_email); |
$authSimulation->setValue('oidplus_generator', $gen); |
$token = $authSimulation->getJWTToken(); |
$out['text'] .= '<p>'._L('You can make automated calls to your OIDplus account by calling an REST API.').'</p>'; |
$out['text'] .= '<h2>'._L('Endpoints').'</h2>'; |
$endpoints = ''; |
foreach (OIDplus::getAllPlugins() as $plugin) { |
if ($plugin instanceof INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_9) { |
$endpoints .= $plugin->restApiInfo('html'); |
} |
} |
if ($endpoints) { |
$out['text'] .= '<p>'._L('The following endpoints are registered by the plugins in this system:').'</p>'; |
$out['text'] .= '<p>'.$endpoints.'</p>'; |
} else { |
$out['text'] .= '<p>'._L('No installed plugin offers a REST functionality').'</p>'; |
} |
$out['text'] .= '<h2>'._L('Authentication').'</h2>'; |
$out['text'] .= '<p>'._L('The authentication is done via the following HTTP header:').'</p>'; |
$out['text'] .= '<p><pre id="oidplus_auth_jwt">'; |
$out['text'] .= 'Authentication: Bearer '.htmlentities($token)."\n"; |
$out['text'] .= '</pre></p>'; |
$out['text'] .= '<p><input type="button" value="'._L('Copy to clipboard').'" onClick="copyToClipboard(oidplus_auth_jwt)"></p>'; |
$out['text'] .= '<p>'._L('Please keep this information confidential!').'</p>'; |
$out['text'] .= '<p>'._L('The JWT-token (secret!) will automatically perform a one-time-login to fulfill the request. The other fields are the normal fields which are called during the usual operation of OIDplus.').'</p>'; |
$out['text'] .= '<h2>'._L('Blacklisted tokens').'</h2>'; |
$bl_time = OIDplusAuthContentStoreJWT::jwtGetBlacklistTime($gen, $sub); |
if ($bl_time == 0) { |
$out['text'] .= '<p>'._L('None of the previously generated JWT tokens have been blacklisted.').'</p>'; |
} else { |
$out['text'] .= '<p>'._L('All tokens generated before %1 have been blacklisted.',date('d F Y, H:i:s',$bl_time+1)).'</p>'; |
} |
$out['text'] .= '<button type="button" name="btn_blacklist_jwt" id="btn_blacklist_jwt" class="btn btn-danger btn-xs" onclick="OIDplusPageRaRestApi.blacklistJWT('.js_escape($ra_email).')">'._L('Blacklist all previously generated tokens').'</button>'; |
} |
} |
/** |
* @param array $json |
* @param string|null $ra_email |
* @param bool $nonjs |
* @param string $req_goto |
* @return bool |
* @throws OIDplusException |
*/ |
public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool { |
if (!$ra_email) return false; |
if (!OIDplus::authUtils()->isRaLoggedIn($ra_email) && !OIDplus::authUtils()->isAdminLoggedIn()) return false; |
if (file_exists(__DIR__.'/img/main_icon16.png')) { |
$tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
} else { |
$tree_icon = null; // default icon (folder) |
} |
$json[] = array( |
'id' => 'oidplus:rest_api_information_ra$'.$ra_email, |
'icon' => $tree_icon, |
'text' => _L('REST API') |
); |
// TODO: Make "Endpoints" (with all installed plugins) and "Authentication" as menu entries! |
return true; |
} |
/** |
* @param string $request |
* @return array|false |
*/ |
public function tree_search(string $request) { |
return false; |
} |
} |
/trunk/plugins/viathinksoft/raPages/911_rest_api/OIDplusPageRaRestApi.js |
---|
0,0 → 1,51 |
/* |
* OIDplus 2.0 |
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
var OIDplusPageRaRestApi = { |
oid: "1.3.6.1.4.1.37476.2.5.2.4.2.911", |
blacklistJWT: function(user) { |
if(!window.confirm(_L("Are you sure that you want to blacklist all access tokens?"))) return false; |
$.ajax({ |
url:"ajax.php", |
method:"POST", |
beforeSend: function(jqXHR, settings) { |
$.xhrPool.abortAll(); |
$.xhrPool.add(jqXHR); |
}, |
complete: function(jqXHR, text) { |
$.xhrPool.remove(jqXHR); |
}, |
data: { |
csrf_token:csrf_token, |
plugin:OIDplusPageRaRestApi.oid, |
action:"blacklistJWT", |
user:user |
}, |
error: oidplus_ajax_error, |
success: function (data) { |
oidplus_ajax_success(data, function (data) { |
alertSuccess(_L("OK")); |
reloadContent(); |
}); |
} |
}); |
} |
}; |
/trunk/plugins/viathinksoft/raPages/911_rest_api/img/index.html |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/plugins/viathinksoft/raPages/911_rest_api/img/main_icon.png |
---|
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/plugins/viathinksoft/raPages/911_rest_api/img/main_icon16.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/plugins/viathinksoft/raPages/911_rest_api/index.html |
---|
--- plugins/viathinksoft/raPages/911_rest_api/manifest.xml (nonexistent) |
+++ plugins/viathinksoft/raPages/911_rest_api/manifest.xml (revision 1265) |
@@ -0,0 +1,29 @@ |
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> |
+<manifest |
+ xmlns="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.2.1" |
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
+ xsi:schemaLocation="urn:oid:1.3.6.1.4.1.37476.2.5.2.5.2.1 https://oidplus.viathinksoft.com/oidplus/plugins/manifest_plugin_page.xsd"> |
+ |
+ <type>ViaThinkSoft\OIDplus\OIDplusPagePluginRa</type> |
+ |
+ <info> |
+ <name>REST API</name> |
+ <author>ViaThinkSoft</author> |
+ <license>Apache 2.0</license> |
+ <version /> |
+ <descriptionHTML /> |
+ <oid>1.3.6.1.4.1.37476.2.5.2.4.2.911</oid> |
+ </info> |
+ |
+ <php> |
+ <mainclass>ViaThinkSoft\OIDplus\OIDplusPageRaRestApi</mainclass> |
+ </php> |
+ |
+ <css> |
+ </css> |
+ |
+ <js> |
+ <file>OIDplusPageRaRestApi.js</file> |
+ </js> |
+ |
+</manifest> |