Prepare settings for the API in the admin page and during the install
API settings: - api.enabled - api.secret The API settings will be initialized (and the secret generated) with an update method.
This commit is contained in:
parent
624f999fb7
commit
cbfdcff261
7 changed files with 142 additions and 2 deletions
|
@ -256,6 +256,29 @@ public function updateMethodDatastoreIds()
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize API settings:
|
||||||
|
* - api.enabled: true
|
||||||
|
* - api.secret: generated secret
|
||||||
|
*/
|
||||||
|
public function updateMethodApiSettings()
|
||||||
|
{
|
||||||
|
if ($this->conf->exists('api.secret')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->conf->set('api.enabled', true);
|
||||||
|
$this->conf->set(
|
||||||
|
'api.secret',
|
||||||
|
generate_api_secret(
|
||||||
|
$this->conf->get('credentials.login'),
|
||||||
|
$this->conf->get('credentials.salt')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->conf->write($this->isLoggedIn);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -231,3 +231,29 @@ function autoLocale($headerLocale)
|
||||||
}
|
}
|
||||||
setlocale(LC_ALL, $attempts);
|
setlocale(LC_ALL, $attempts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a default API secret.
|
||||||
|
*
|
||||||
|
* Note that the random-ish methods used in this function are predictable,
|
||||||
|
* which makes them NOT suitable for crypto.
|
||||||
|
* BUT the random string is salted with the salt and hashed with the username.
|
||||||
|
* It makes the generated API secret secured enough for Shaarli.
|
||||||
|
*
|
||||||
|
* PHP 7 provides random_int(), designed for cryptography.
|
||||||
|
* More info: http://stackoverflow.com/questions/4356289/php-random-string-generator
|
||||||
|
|
||||||
|
* @param string $username Shaarli login username
|
||||||
|
* @param string $salt Shaarli password hash salt
|
||||||
|
*
|
||||||
|
* @return string|bool Generated API secret, 12 char length.
|
||||||
|
* Or false if invalid parameters are provided (which will make the API unusable).
|
||||||
|
*/
|
||||||
|
function generate_api_secret($username, $salt)
|
||||||
|
{
|
||||||
|
if (empty($username) || empty($salt)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_shuffle(substr(hash_hmac('sha512', uniqid($salt), $username), 10, 12));
|
||||||
|
}
|
||||||
|
|
12
index.php
12
index.php
|
@ -1142,6 +1142,8 @@ function renderPage($conf, $pluginManager)
|
||||||
$conf->set('feed.rss_permalinks', !empty($_POST['enableRssPermalinks']));
|
$conf->set('feed.rss_permalinks', !empty($_POST['enableRssPermalinks']));
|
||||||
$conf->set('updates.check_updates', !empty($_POST['updateCheck']));
|
$conf->set('updates.check_updates', !empty($_POST['updateCheck']));
|
||||||
$conf->set('privacy.hide_public_links', !empty($_POST['hidePublicLinks']));
|
$conf->set('privacy.hide_public_links', !empty($_POST['hidePublicLinks']));
|
||||||
|
$conf->set('api.enabled', !empty($_POST['apiEnabled']));
|
||||||
|
$conf->set('api.secret', escape($_POST['apiSecret']));
|
||||||
try {
|
try {
|
||||||
$conf->write(isLoggedIn());
|
$conf->write(isLoggedIn());
|
||||||
}
|
}
|
||||||
|
@ -1170,6 +1172,8 @@ function renderPage($conf, $pluginManager)
|
||||||
$PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false));
|
$PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false));
|
||||||
$PAGE->assign('enable_update_check', $conf->get('updates.check_updates', true));
|
$PAGE->assign('enable_update_check', $conf->get('updates.check_updates', true));
|
||||||
$PAGE->assign('hide_public_links', $conf->get('privacy.hide_public_links', false));
|
$PAGE->assign('hide_public_links', $conf->get('privacy.hide_public_links', false));
|
||||||
|
$PAGE->assign('api_enabled', $conf->get('api.enabled', true));
|
||||||
|
$PAGE->assign('api_secret', $conf->get('api.secret'));
|
||||||
$PAGE->renderPage('configure');
|
$PAGE->renderPage('configure');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
@ -1952,6 +1956,14 @@ function install($conf)
|
||||||
$conf->set('general.title', 'Shared links on '.escape(index_url($_SERVER)));
|
$conf->set('general.title', 'Shared links on '.escape(index_url($_SERVER)));
|
||||||
}
|
}
|
||||||
$conf->set('updates.check_updates', !empty($_POST['updateCheck']));
|
$conf->set('updates.check_updates', !empty($_POST['updateCheck']));
|
||||||
|
$conf->set('api.enabled', !empty($_POST['enableApi']));
|
||||||
|
$conf->set(
|
||||||
|
'api.secret',
|
||||||
|
generate_api_secret(
|
||||||
|
$this->conf->get('credentials.login'),
|
||||||
|
$this->conf->get('credentials.salt')
|
||||||
|
)
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
// Everything is ok, let's create config file.
|
// Everything is ok, let's create config file.
|
||||||
$conf->write(isLoggedIn());
|
$conf->write(isLoggedIn());
|
||||||
|
|
|
@ -289,6 +289,42 @@ public function testEscapeConfig()
|
||||||
unlink($sandbox . '.json.php');
|
unlink($sandbox . '.json.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test updateMethodApiSettings(): create default settings for the API (enabled + secret).
|
||||||
|
*/
|
||||||
|
public function testUpdateApiSettings()
|
||||||
|
{
|
||||||
|
$confFile = 'sandbox/config';
|
||||||
|
copy(self::$configFile .'.json.php', $confFile .'.json.php');
|
||||||
|
$conf = new ConfigManager($confFile);
|
||||||
|
$updater = new Updater(array(), array(), $conf, true);
|
||||||
|
|
||||||
|
$this->assertFalse($conf->exists('api.enabled'));
|
||||||
|
$this->assertFalse($conf->exists('api.secret'));
|
||||||
|
$updater->updateMethodApiSettings();
|
||||||
|
$conf->reload();
|
||||||
|
$this->assertTrue($conf->get('api.enabled'));
|
||||||
|
$this->assertTrue($conf->exists('api.secret'));
|
||||||
|
unlink($confFile .'.json.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test updateMethodApiSettings(): already set, do nothing.
|
||||||
|
*/
|
||||||
|
public function testUpdateApiSettingsNothingToDo()
|
||||||
|
{
|
||||||
|
$confFile = 'sandbox/config';
|
||||||
|
copy(self::$configFile .'.json.php', $confFile .'.json.php');
|
||||||
|
$conf = new ConfigManager($confFile);
|
||||||
|
$conf->set('api.enabled', false);
|
||||||
|
$conf->set('api.secret', '');
|
||||||
|
$updater = new Updater(array(), array(), $conf, true);
|
||||||
|
$updater->updateMethodApiSettings();
|
||||||
|
$this->assertFalse($conf->get('api.enabled'));
|
||||||
|
$this->assertEmpty($conf->get('api.secret'));
|
||||||
|
unlink($confFile .'.json.php');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test updateMethodDatastoreIds().
|
* Test updateMethodDatastoreIds().
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -253,4 +253,21 @@ public function testIsSessionIdInvalid()
|
||||||
is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=')
|
is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test generateSecretApi.
|
||||||
|
*/
|
||||||
|
public function testGenerateSecretApi()
|
||||||
|
{
|
||||||
|
$this->assertEquals(12, strlen(generate_api_secret('foo', 'bar')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test generateSecretApi with invalid parameters.
|
||||||
|
*/
|
||||||
|
public function testGenerateSecretApiInvalid()
|
||||||
|
{
|
||||||
|
$this->assertFalse(generate_api_secret('', ''));
|
||||||
|
$this->assertFalse(generate_api_secret(false, false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,20 @@
|
||||||
<label for="updateCheck"> Notify me when a new release is ready</label>
|
<label for="updateCheck"> Notify me when a new release is ready</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><b>Enable API</b></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="apiEnabled" id="apiEnabled"
|
||||||
|
{if="$api_enabled"}checked{/if}/>
|
||||||
|
<label for="apiEnabled"> Allow third party software to use Shaarli such as mobile application.</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><b>API secret</b></td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="apiSecret" id="apiSecret" size="50" value="{$api_secret}" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
|
|
@ -14,6 +14,18 @@ <h1>Shaarli</h1>
|
||||||
<tr><td valign="top"><b>Update:</b></td><td>
|
<tr><td valign="top"><b>Update:</b></td><td>
|
||||||
<input type="checkbox" name="updateCheck" id="updateCheck" checked="checked"><label for="updateCheck"> Notify me when a new release is ready</label></td>
|
<input type="checkbox" name="updateCheck" id="updateCheck" checked="checked"><label for="updateCheck"> Notify me when a new release is ready</label></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<b>API:</b>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="enableApi" id="enableApi" checked="checked">
|
||||||
|
<label for="enableApi">
|
||||||
|
Enable Shaarli's API.
|
||||||
|
Allow third party software to use Shaarli such as mobile application.
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr><td colspan="2"><input type="submit" name="Save" value="Save config" class="bigbutton"></td></tr>
|
<tr><td colspan="2"><input type="submit" name="Save" value="Save config" class="bigbutton"></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
|
|
Loading…
Reference in a new issue