add new API Call checkUsername

with that it is possible
- to check if username exist already in a given Group
- if a group_id exist in db
- which group_id a group_alias has
This commit is contained in:
einhornimmond 2021-06-04 17:20:48 +02:00
parent 42bca07bf7
commit 0489ab0746
6 changed files with 209 additions and 1 deletions

View File

@ -89,6 +89,56 @@ In case of success returns:
nginx was wrong configured.
- `session_id`: can be also negative
## Check username
### Request
`GET http://localhost/login_api/checkUsername?username=<username>&group_id=<group_id>`
`POST http://localhost/login_api/checkUsername`
with
```json
{
"username": "Maxilein",
"group_id": 1,
"group_alias": "gdd1"
}
```
group_id or group_alias, one of both is enough.
group_id is better, because one db request less
### Response
If username is not already taken
```json
{
"state":"success"
}
```
If username is already taken
```json
{
"state":"warning",
"msg":"username already in use"
}
```
If only group_alias was given and group with that alias was found in db
```json
{
"state":"success",
"group_id": 1
}
```
If group_id or group_alias unknown
```json
{
"state":"error",
"msg": "unknown group"
}
```
## Create user
Register a new User

View File

@ -0,0 +1,93 @@
#include "JsonCheckUsername.h"
#include "Poco/URI.h"
#include "controller/User.h"
#include "lib/DataTypeConverter.h"
Poco::JSON::Object* JsonCheckUsername::handle(Poco::Dynamic::Var params)
{
std::string username;
int group_id = 0;
std::string group_alias;
// if is json object
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
auto username_obj = paramJsonObject->get("username");
auto group_id_obj = paramJsonObject->get("group_id");
auto group_alias_obj = paramJsonObject->get("group_alias");
try {
paramJsonObject->get("username").convert(username);
if (!username_obj.isEmpty()) {
username_obj.convert(username);
}
if (!group_id_obj.isEmpty()) {
group_id_obj.convert(group_id);
}
if (!group_alias_obj.isEmpty()) {
group_alias_obj.convert(group_alias);
}
}
catch (Poco::Exception& ex) {
return stateError("username not found or invalid");
}
}
else if (params.isVector()) {
const Poco::URI::QueryParameters queryParams = params.extract<Poco::URI::QueryParameters>();
for (auto it = queryParams.begin(); it != queryParams.end(); it++) {
if (it->first == "username") {
username = it->second;
}
else if (it->first == "group_id") {
DataTypeConverter::strToInt(it->second, group_id);
}
else if (it->first == "group_alias") {
group_alias = it->second;
}
}
}
else {
return stateError("format not implemented", std::string(params.type().name()));
}
if (!group_id && group_alias == "") {
return stateError("no group given");
}
if (!group_id) {
auto groups = controller::Group::load(group_alias);
if (groups.size() > 1) {
return stateError("group is ambiguous");
}
if (!groups.size()) {
return stateError("unknown group");
}
group_id = groups[0]->getModel()->getID();
}
auto group = controller::Group::load(group_id);
if (group.isNull()) {
return stateError("unknown group");
}
auto user = controller::User::create();
user->getModel()->setGroupId(group_id);
if (username == "") {
Poco::JSON::Object* result = new Poco::JSON::Object;
result->set("state", "success");
result->set("group_id", group_id);
return result;
}
if (user->isUsernameAlreadyUsed(username)) {
return stateWarning("username already in use");
}
return stateSuccess();
}

View File

@ -0,0 +1,16 @@
#ifndef __JSON_INTERFACE_JSON_CHECK_USERNAME_
#define __JSON_INTERFACE_JSON_CHECK_USERNAME_
#include "JsonRequestHandler.h"
class JsonCheckUsername : public JsonRequestHandler
{
public:
Poco::JSON::Object* handle(Poco::Dynamic::Var params);
protected:
};
#endif // __JSON_INTERFACE_JSON_CHECK_USERNAME_

View File

@ -7,6 +7,7 @@
#include "JsonAdminEmailVerificationResend.h"
#include "JsonCheckSessionState.h"
#include "JsonCheckUsername.h"
#include "JsonAppLogin.h"
#include "JsonAquireAccessToken.h"
#include "JsonCreateTransaction.h"
@ -74,6 +75,9 @@ Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(c
else if (url_first_part == "/checkSessionState") {
return new JsonCheckSessionState;
}
else if (url_first_part == "/checkUsername") {
return new JsonCheckUsername;
}
else if (url_first_part == "/createTransaction") {
return new JsonCreateTransaction;
}

View File

@ -108,7 +108,9 @@ namespace controller {
bool User::isUsernameAlreadyUsed(const std::string& username)
{
auto db = getModel();
return db->loadFromDB({ "username", "group_id" }, username, db->getGroupId(), model::table::MYSQL_CONDITION_AND) > 0;
auto results = db->loadMultipleFromDB<model::table::UserTuple>({ "username", "group_id" }, username, db->getGroupId(), model::table::MYSQL_CONDITION_AND);
return results.size() > 0;
}
int User::load(const unsigned char* pubkey_array)

View File

@ -61,6 +61,12 @@ namespace model {
template<class T1, class T2>
size_t loadFromDB(const std::vector<std::string>& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
template<class Tuple, class T1, class T2>
std::vector<Tuple> loadMultipleFromDB(
const std::vector<std::string>& fieldNames,
const T1& field1Value, const T2& field2Value,
MysqlConditionType conditionType = MYSQL_CONDITION_AND);
template<class Tuple, class T1, class T2, class T3, class T4>
std::vector<Tuple> loadMultipleFromDB(
const std::vector<std::string>& fieldNames,
@ -290,6 +296,43 @@ namespace model {
return resultCount;
}
template<class Tuple, class T1, class T2>
std::vector<Tuple> ModelBase::loadMultipleFromDB(
const std::vector<std::string>& fieldNames,
const T1& field1Value, const T2& field2Value,
MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/)
{
auto cm = ConnectionManager::getInstance();
std::vector<Tuple> results;
if (fieldNames.size() != 2) {
addError(new Error(getTableName(), "error in loadFromDB with 2 different field values, fieldNames count isn't 2"));
return results;
}
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
Poco::Data::Statement select = _loadMultipleFromDB(session, fieldNames, conditionType);
select, Poco::Data::Keywords::into(results),
Poco::Data::Keywords::useRef(field1Value), Poco::Data::Keywords::useRef(field2Value);
size_t resultCount = 0;
try {
resultCount = select.execute();
}
catch (Poco::Exception& ex) {
lock();
addError(new ParamError(getTableName(), "mysql error by selecting with 2 different field types", ex.displayText()));
int count = 0;
for (auto it = fieldNames.begin(); it != fieldNames.end(); it++) {
addError(new ParamError(getTableName(), "field name for select: ", *it));
}
//addError(new ParamError(getTableName(), "field name for select: ", fieldName.data()));
unlock();
}
return results;
}
template<class Tuple, class T1, class T2, class T3, class T4>
std::vector<Tuple> ModelBase::loadMultipleFromDB(
const std::vector<std::string>& fieldNames,