mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Improve API to create locations
Improve on top of sehraf work, add documentation for API token params Deprecate old version and disable it once RS 0.6.6 is released New method take relevant paramethers explicitely instead of having them incapsualted inside a RsLoginHelper::Location struct New method return a proper error_condition instead of boolean + string RsLoginHelper::attemptLogin doesn't need manual wrapper anymore
This commit is contained in:
parent
275bdba132
commit
4a34cfaf11
@ -165,6 +165,7 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
||||
RsThread::setStopTimeout(10);
|
||||
#endif
|
||||
|
||||
#if !RS_VERSION_AT_LEAST(0,6,6)
|
||||
registerHandler("/rsLoginHelper/createLocation",
|
||||
[this](const std::shared_ptr<rb::Session> session)
|
||||
{
|
||||
@ -215,8 +216,9 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
||||
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
||||
} );
|
||||
}, false);
|
||||
#endif // !RS_VERSION_AT_LEAST(0,6,6)
|
||||
|
||||
registerHandler("/rsLoginHelper/attemptLogin",
|
||||
registerHandler("/rsLoginHelper/createLocationV2",
|
||||
[this](const std::shared_ptr<rb::Session> session)
|
||||
{
|
||||
auto reqSize = session->get_request()->get_header("Content-Length", 0);
|
||||
@ -226,25 +228,51 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
||||
{
|
||||
INITIALIZE_API_CALL_JSON_CONTEXT;
|
||||
|
||||
RsPeerId account;
|
||||
RsPeerId locationId;
|
||||
RsPgpId pgpId;
|
||||
std::string locationName;
|
||||
std::string pgpName;
|
||||
std::string password;
|
||||
|
||||
// JSON API only
|
||||
std::string apiUser;
|
||||
std::string apiPass;
|
||||
|
||||
// deserialize input parameters from JSON
|
||||
{
|
||||
RsGenericSerializer::SerializeContext& ctx(cReq);
|
||||
RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON);
|
||||
RS_SERIAL_PROCESS(account);
|
||||
RS_SERIAL_PROCESS(locationId);
|
||||
RS_SERIAL_PROCESS(pgpId);
|
||||
RS_SERIAL_PROCESS(locationName);
|
||||
RS_SERIAL_PROCESS(pgpName);
|
||||
RS_SERIAL_PROCESS(password);
|
||||
|
||||
// JSON API only
|
||||
RS_SERIAL_PROCESS(apiUser);
|
||||
RS_SERIAL_PROCESS(apiPass);
|
||||
}
|
||||
|
||||
// call retroshare C++ API
|
||||
RsInit::LoadCertificateStatus retval =
|
||||
rsLoginHelper->attemptLogin(account, password);
|
||||
std::error_condition retval;
|
||||
|
||||
if(apiUser.empty())
|
||||
retval = RsJsonApiErrorNum::TOKEN_FORMAT_INVALID;
|
||||
|
||||
if(!retval)
|
||||
retval = badApiCredientalsFormat(apiUser, apiPass);
|
||||
|
||||
if(!retval) // call retroshare C++ API
|
||||
retval = rsLoginHelper->createLocationV2(
|
||||
locationId, pgpId, locationName, pgpName, password );
|
||||
|
||||
if(!retval) retval = authorizeUser(apiUser, apiPass);
|
||||
|
||||
// serialize out parameters and return value to JSON
|
||||
{
|
||||
RsGenericSerializer::SerializeContext& ctx(cAns);
|
||||
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
|
||||
RS_SERIAL_PROCESS(locationId);
|
||||
RS_SERIAL_PROCESS(pgpId);
|
||||
RS_SERIAL_PROCESS(retval);
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,7 @@
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
/// RetroShare initialization and login API
|
||||
|
||||
/// @file RetroShare initialization and login API
|
||||
|
||||
// Initialize ok, result >= 0
|
||||
#define RS_INIT_OK 0 // Initialize ok
|
||||
@ -32,11 +31,15 @@
|
||||
#define RS_INIT_NO_KEYRING -3 // Keyring is empty. Need to import it.
|
||||
#define RS_INIT_NO_EXECUTABLE -4 // executable path hasn't been set in config options
|
||||
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <retroshare/rstypes.h>
|
||||
#include <cstdint>
|
||||
#include <system_error>
|
||||
|
||||
#include "retroshare/rstypes.h"
|
||||
#include "retroshare/rsversion.h"
|
||||
|
||||
|
||||
class RsLoginHelper;
|
||||
|
||||
@ -46,6 +49,71 @@ class RsLoginHelper;
|
||||
*/
|
||||
extern RsLoginHelper* rsLoginHelper;
|
||||
|
||||
|
||||
enum class RsInitErrorNum : int32_t
|
||||
{
|
||||
ALREADY_LOGGED_IN = 6000,
|
||||
CANT_ACQUIRE_LOCK = 6001,
|
||||
INVALID_LOCATION_NAME = 6002,
|
||||
PGP_NAME_OR_ID_NEEDED = 6003,
|
||||
PGP_KEY_CREATION_FAILED = 6004,
|
||||
SSL_KEY_CREATION_FAILED = 6005,
|
||||
INVALID_SSL_ID = 6006,
|
||||
LOGIN_FAILED = 6007
|
||||
};
|
||||
|
||||
struct RsInitErrorCategory: std::error_category
|
||||
{
|
||||
const char* name() const noexcept override
|
||||
{ return "RetroShare init"; }
|
||||
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<RsInitErrorNum>(ev))
|
||||
{
|
||||
case RsInitErrorNum::ALREADY_LOGGED_IN:
|
||||
return "Already logged in";
|
||||
case RsInitErrorNum::CANT_ACQUIRE_LOCK:
|
||||
return "Cannot aquire lock on location data. Another instance is "
|
||||
"already running with this profile?";
|
||||
case RsInitErrorNum::INVALID_LOCATION_NAME:
|
||||
return "Invalid location name";
|
||||
case RsInitErrorNum::PGP_NAME_OR_ID_NEEDED:
|
||||
return "Either PGP name or PGP id is needed";
|
||||
case RsInitErrorNum::PGP_KEY_CREATION_FAILED:
|
||||
return "Failure creating PGP key";
|
||||
case RsInitErrorNum::SSL_KEY_CREATION_FAILED:
|
||||
return "Failure creating SSL key";
|
||||
case RsInitErrorNum::INVALID_SSL_ID:
|
||||
return "Invalid SSL id";
|
||||
case RsInitErrorNum::LOGIN_FAILED:
|
||||
return "Generic login failure";
|
||||
default:
|
||||
return rsErrorNotInCategory(ev, name());
|
||||
}
|
||||
}
|
||||
|
||||
const static RsInitErrorCategory instance;
|
||||
};
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
/** Register RsJsonApiErrorNum as an error condition enum, must be in std
|
||||
* namespace */
|
||||
template<> struct is_error_condition_enum<RsInitErrorNum> : true_type {};
|
||||
}
|
||||
|
||||
/** Provide RsInitErrorNum conversion to std::error_condition, must be in
|
||||
* same namespace of RsInitErrorNum */
|
||||
inline std::error_condition make_error_condition(RsInitErrorNum e) noexcept
|
||||
{
|
||||
return std::error_condition(
|
||||
static_cast<int>(e), RsInitErrorCategory::instance );
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The RsInitConfig struct
|
||||
* This class contains common configuration options, that executables using libretroshare may want to
|
||||
@ -85,7 +153,7 @@ struct RsConfigOptions
|
||||
class RsInit
|
||||
{
|
||||
public:
|
||||
enum LoadCertificateStatus : uint8_t
|
||||
enum RS_DEPRECATED_FOR(RsInitErrorNum) LoadCertificateStatus : uint8_t
|
||||
{
|
||||
OK, /// Everything go as expected, no error occurred
|
||||
ERR_ALREADY_RUNNING, /// Another istance is running already
|
||||
@ -317,7 +385,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Normal way to attempt login
|
||||
* @jsonapi{development,manualwrapper}
|
||||
* @jsonapi{development,unauthenticated}
|
||||
* @param[in] account Id of the account to which attempt login
|
||||
* @param[in] password Password for the given account
|
||||
* @return RsInit::OK if login attempt success, error code otherwhise
|
||||
@ -353,6 +421,44 @@ public:
|
||||
void getLocations(std::vector<RsLoginHelper::Location>& locations);
|
||||
|
||||
/**
|
||||
* @brief Creates a new RetroShare location, and log in once is created
|
||||
* @jsonapi{development,manualwrapper}
|
||||
* @param[out] locationId storage for generated location SSL id
|
||||
* @param[inout] pgpId specify PGP id to use to sign the location, if a null
|
||||
* id is passed the PGP key is created too and this param is used as
|
||||
* storage for its id.
|
||||
* @param[in] password to protect and unlock the associated PGP key
|
||||
* param[in] apiUser (JSON API only) string containing username for JSON API
|
||||
* so it can be later used to authenticate JSON API calls. It is passed
|
||||
* down to @see RsJsonApi::authorizeUser under the hood.
|
||||
* param[in] apiPass (JSON API only) string containing password for JSON API
|
||||
* so it can be later used to authenticate JSON API calls. It is passed
|
||||
* down to @see RsJsonApi::authorizeUser under the hood.
|
||||
* To improve security we strongly advise to not use the same as the
|
||||
* password used for the PGP key.
|
||||
* @return Success or error information
|
||||
*/
|
||||
std::error_condition createLocationV2(
|
||||
RsPeerId& locationId,
|
||||
RsPgpId& pgpId,
|
||||
const std::string& locationName,
|
||||
const std::string& pgpName,
|
||||
const std::string& password
|
||||
/* JSON API only
|
||||
* const std::string& apiUser
|
||||
* const std::string& apiPass */ );
|
||||
|
||||
/**
|
||||
* @brief Check if RetroShare is already logged in, this usually return true
|
||||
* after a successfull attemptLogin() and before closeSession()
|
||||
* @jsonapi{development,unauthenticated}
|
||||
* @return true if already logged in, false otherwise
|
||||
*/
|
||||
bool isLoggedIn();
|
||||
|
||||
#if !RS_VERSION_AT_LEAST(0,6,6)
|
||||
/**
|
||||
* @deprecated Use @see createLocationV2 instead
|
||||
* @brief Creates a new RetroShare location, and log in once is created
|
||||
* @jsonapi{development,manualwrapper}
|
||||
* @param[inout] location provide input information to generate the location
|
||||
@ -365,15 +471,9 @@ public:
|
||||
* Tor hidden location. UNTESTED!
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
RS_DEPRECATED_FOR(createLocationV2)
|
||||
bool createLocation( RsLoginHelper::Location& location,
|
||||
const std::string& password, std::string& errorMessage,
|
||||
bool makeHidden = false, bool makeAutoTor = false );
|
||||
|
||||
/**
|
||||
* @brief Check if RetroShare is already logged in, this usually return true
|
||||
* after a successfull attemptLogin() and before closeSession()
|
||||
* @jsonapi{development,unauthenticated}
|
||||
* @return true if already logged in, false otherwise
|
||||
*/
|
||||
bool isLoggedIn();
|
||||
#endif // !RS_VERSION_AT_LEAST(0,6,6)
|
||||
};
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <cstdint>
|
||||
#include <system_error>
|
||||
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rsmemory.h"
|
||||
|
||||
class RsJsonApi;
|
||||
@ -74,8 +75,7 @@ struct RsJsonApiErrorCategory: std::error_category
|
||||
case RsJsonApiErrorNum::NOT_A_MACHINE_GUN:
|
||||
return "Method must not be called in burst";
|
||||
default:
|
||||
return "Error message for error: " + std::to_string(ev) +
|
||||
" not available in category: " + name();
|
||||
return rsErrorNotInCategory(ev, name());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,8 @@ RsLoginHelper* rsLoginHelper = nullptr;
|
||||
|
||||
RsAccounts* rsAccounts = nullptr;
|
||||
|
||||
const RsInitErrorCategory RsInitErrorCategory::instance;
|
||||
|
||||
RsConfigOptions::RsConfigOptions()
|
||||
:
|
||||
autoLogin(false),
|
||||
@ -1950,6 +1952,47 @@ void RsLoginHelper::getLocations(std::vector<RsLoginHelper::Location>& store)
|
||||
}
|
||||
}
|
||||
|
||||
std::error_condition RsLoginHelper::createLocationV2(
|
||||
RsPeerId& locationId, RsPgpId& pgpId,
|
||||
const std::string& locationName, const std::string& pgpName,
|
||||
const std::string& password )
|
||||
{
|
||||
if(isLoggedIn()) return RsInitErrorNum::ALREADY_LOGGED_IN;
|
||||
if(locationName.empty()) return RsInitErrorNum::INVALID_LOCATION_NAME;
|
||||
if(pgpId.isNull() && pgpName.empty())
|
||||
return RsInitErrorNum::PGP_NAME_OR_ID_NEEDED;
|
||||
|
||||
std::string errorMessage;
|
||||
if(pgpId.isNull() && !RsAccounts::GeneratePGPCertificate(
|
||||
pgpName, "", password, pgpId, 4096, errorMessage ) )
|
||||
{
|
||||
RS_ERR("Failure creating PGP key: ", errorMessage);
|
||||
return RsInitErrorNum::PGP_KEY_CREATION_FAILED;
|
||||
}
|
||||
|
||||
std::string sslPassword =
|
||||
RsRandom::random_alphaNumericString(RsInit::getSslPwdLen());
|
||||
|
||||
rsNotify->cachePgpPassphrase(password);
|
||||
rsNotify->setDisableAskPassword(true);
|
||||
|
||||
bool ret = RsAccounts::createNewAccount(
|
||||
pgpId, "", locationName, "", false, false, sslPassword,
|
||||
locationId, errorMessage );
|
||||
if(!ret)
|
||||
{
|
||||
RS_ERR("Failure creating SSL key: ", errorMessage);
|
||||
return RsInitErrorNum::SSL_KEY_CREATION_FAILED;
|
||||
}
|
||||
|
||||
RsInit::LoadPassword(sslPassword);
|
||||
ret = (RsInit::OK == attemptLogin(locationId, password));
|
||||
rsNotify->setDisableAskPassword(false);
|
||||
|
||||
return (ret ? std::error_condition() : RsInitErrorNum::LOGIN_FAILED);
|
||||
}
|
||||
|
||||
#if !RS_VERSION_AT_LEAST(0,6,6)
|
||||
bool RsLoginHelper::createLocation(
|
||||
RsLoginHelper::Location& l, const std::string& password,
|
||||
std::string& errorMessage, bool makeHidden, bool makeAutoTor )
|
||||
@ -1991,6 +2034,7 @@ bool RsLoginHelper::createLocation(
|
||||
rsNotify->setDisableAskPassword(false);
|
||||
return ret;
|
||||
}
|
||||
#endif // !RS_VERSION_AT_LEAST(0,6,6)
|
||||
|
||||
bool RsLoginHelper::isLoggedIn()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user