#include "user_service.h"
#include <utility>
#include "username.h"
UserService::UserService(DataSourceInterface& data_source)
: data_source_(data_source)
{}
mw::E<User> UserService::setUsername(
std::int64_t user_id, const std::string& submitted_username)
{
auto normalized = normalizeUsername(submitted_username);
if(!normalized)
{
return std::unexpected(mw::httpError(400, "Invalid username"));
}
auto transaction = data_source_.beginTransaction();
if(!transaction)
{
return std::unexpected(std::move(transaction.error()));
}
auto user = (*transaction)->getUserForUpdate(user_id);
if(!user)
{
return std::unexpected(std::move(user.error()));
}
if(!*user)
{
return std::unexpected(mw::httpError(404, "User not found"));
}
auto updated = (*transaction)->updateUsername(
user_id, normalized->username, normalized->key);
if(!updated)
{
return std::unexpected(mw::httpError(
409, "Username is already in use"));
}
if(!*updated)
{
return std::unexpected(mw::httpError(404, "User not found"));
}
auto committed = (*transaction)->commit();
if(!committed)
{
return std::unexpected(std::move(committed.error()));
}
(**user).username = std::move(normalized->username);
return std::move(**user);
}
mw::E<User> UserService::promote(
std::int64_t administrator_user_id,
std::int64_t target_user_id)
{
auto transaction = data_source_.beginTransaction();
if(!transaction)
{
return std::unexpected(std::move(transaction.error()));
}
auto administrator = (*transaction)->getUserForUpdate(
administrator_user_id);
if(!administrator)
{
return std::unexpected(std::move(administrator.error()));
}
if(!*administrator ||
(**administrator).role != UserRole::ADMINISTRATOR)
{
return std::unexpected(mw::httpError(403, "Forbidden"));
}
auto target = (*transaction)->getUserForUpdate(target_user_id);
if(!target)
{
return std::unexpected(std::move(target.error()));
}
if(!*target)
{
return std::unexpected(mw::httpError(404, "User not found"));
}
if((**target).role == UserRole::ADMINISTRATOR)
{
return std::unexpected(mw::httpError(409, "Role cannot be changed"));
}
if((**target).role == UserRole::PLAYER)
{
auto promoted = (*transaction)->promoteUser(target_user_id);
if(!promoted)
{
return std::unexpected(std::move(promoted.error()));
}
if(!*promoted)
{
return std::unexpected(mw::httpError(
409, "User role changed in another request"));
}
(**target).role = UserRole::CREATOR;
}
auto committed = (*transaction)->commit();
if(!committed)
{
return std::unexpected(std::move(committed.error()));
}
return std::move(**target);
}