summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gentoobrowse-api/api/users.ice2
-rw-r--r--gentoobrowse-api/domain/user-models.ice1
-rw-r--r--gentoobrowse-api/service/usersimpl.cpp15
-rw-r--r--gentoobrowse-api/unittests/testUsers.cpp40
4 files changed, 57 insertions, 1 deletions
diff --git a/gentoobrowse-api/api/users.ice b/gentoobrowse-api/api/users.ice
index f6a444e..cde2ae0 100644
--- a/gentoobrowse-api/api/users.ice
+++ b/gentoobrowse-api/api/users.ice
@@ -14,7 +14,7 @@ module Gentoo {
User get(int id) throws Slicer::NoRowsReturned;
NewUser getNew(stringview username, stringview password) throws Slicer::NoRowsReturned;
User find(stringview username) throws Slicer::NoRowsReturned;
- NewUser create(stringview username, stringview password, stringview realname, stringview email) throws DuplicateDetails;
+ NewUser create(stringview username, stringview password, stringview realname, stringview email) throws DuplicateDetails, Rejected;
void mailshotsent(int id);
void remove(int id, stringview password) throws Slicer::NoRowsReturned;
void prune();
diff --git a/gentoobrowse-api/domain/user-models.ice b/gentoobrowse-api/domain/user-models.ice
index 7e2d4f2..0cc00a1 100644
--- a/gentoobrowse-api/domain/user-models.ice
+++ b/gentoobrowse-api/domain/user-models.ice
@@ -20,6 +20,7 @@ module Gentoo {
exception InvalidCredentials { };
exception DuplicateDetails { };
+ exception Rejected { };
};
#endif
diff --git a/gentoobrowse-api/service/usersimpl.cpp b/gentoobrowse-api/service/usersimpl.cpp
index 082f802..76d1eea 100644
--- a/gentoobrowse-api/service/usersimpl.cpp
+++ b/gentoobrowse-api/service/usersimpl.cpp
@@ -13,6 +13,7 @@
#include <memory>
#include <modifycommand.h>
#include <notifications.h>
+#include <regex>
#include <resourcePool.h> // IWYU pragma: keep
#include <sql/users/authenticate.sql.h>
#include <sql/users/create.sql.h>
@@ -77,9 +78,23 @@ namespace Gentoo::Service {
Users::create(const std::string_view username, const std::string_view password, const std::string_view realname,
const std::string_view email, const Ice::Current &)
{
+ static const std::regex invalid {".*://.*"};
+ static const std::regex validUsername {".+"};
+ static const std::regex validRealname {".+"};
+ static const std::regex validEmail {"[^ ]+@[^ ]+(\\.[^ ]+)+"};
+
auto notifications = IceTray::Cube::get<Notifications>();
auto mailServer = IceTray::Cube::get<IceTray::Mail::MailServer>();
+ const auto check = [](const auto in, const auto & valid, const auto & invalid) {
+ if (!std::regex_match(in.begin(), in.end(), valid) || std::regex_match(in.begin(), in.end(), invalid)) {
+ throw Rejected {};
+ }
+ };
+ check(username, validUsername, invalid);
+ check(realname, validRealname, invalid);
+ check(email, validEmail, invalid);
+
auto dbc = db->get();
DB::TransactionScope tx(*dbc.get());
diff --git a/gentoobrowse-api/unittests/testUsers.cpp b/gentoobrowse-api/unittests/testUsers.cpp
index 4af063b..6d1ce02 100644
--- a/gentoobrowse-api/unittests/testUsers.cpp
+++ b/gentoobrowse-api/unittests/testUsers.cpp
@@ -1,10 +1,12 @@
#define BOOST_TEST_MODULE TestUsers
+#include <boost/test/data/test_case.hpp>
#include <boost/test/unit_test.hpp>
#include "mockDefs.h"
#include "user-models.h"
#include "users.h"
#include <Ice/Optional.h>
+#include <compileTimeFormatter.h>
#include <ext/alloc_traits.h>
#include <icecube.h>
#include <mail.h>
@@ -71,6 +73,44 @@ BOOST_AUTO_TEST_CASE(create)
BOOST_REQUIRE_EQUAL(36, user->verifyguid.length());
}
+auto genUsername = [n = 0]() mutable {
+ return AdHoc::scprintf<"genUsername%?">(n++);
+};
+auto genEmail = [n = 0]() mutable {
+ return AdHoc::scprintf<"email%?@test.com">(n++);
+};
+
+const auto EMPTY = boost::unit_test::data::make({""});
+const auto URLS = boost::unit_test::data::make(
+ {"before https://something", "before https://something after", "https://something after", "http://something"});
+const auto EMAILS = boost::unit_test::data::make({"something@something.com"});
+const auto BAD_EMAILS = boost::unit_test::data::make(
+ {"@something.com", "something@", "something", "some thing@something.com", "something@some thing.com"});
+
+BOOST_DATA_TEST_CASE(create_reject_username, EMPTY + URLS, username)
+{
+ auto ms = std::dynamic_pointer_cast<IceTray::Mail::MockMailServer>(IceTray::Cube::get<IceTray::Mail::MailServer>());
+ BOOST_CHECK_THROW(u->create(username, "testpass", "Test User", genEmail()), Gentoo::Rejected);
+ BOOST_REQUIRE(ms);
+ BOOST_CHECK(ms->getSentEmails().empty());
+}
+
+BOOST_DATA_TEST_CASE(create_reject_realname, EMPTY + URLS, realname)
+{
+ auto ms = std::dynamic_pointer_cast<IceTray::Mail::MockMailServer>(IceTray::Cube::get<IceTray::Mail::MailServer>());
+ BOOST_CHECK_THROW(u->create(genUsername(), "testpass", realname, genEmail()), Gentoo::Rejected);
+ BOOST_REQUIRE(ms);
+ BOOST_CHECK(ms->getSentEmails().empty());
+}
+
+BOOST_DATA_TEST_CASE(create_reject_email, EMPTY + URLS + BAD_EMAILS, email)
+{
+ auto ms = std::dynamic_pointer_cast<IceTray::Mail::MockMailServer>(IceTray::Cube::get<IceTray::Mail::MailServer>());
+ BOOST_CHECK_THROW(u->create(genUsername(), "testpass", "Test User", email), Gentoo::Rejected);
+ BOOST_REQUIRE(ms);
+ BOOST_CHECK(ms->getSentEmails().empty());
+}
+
BOOST_AUTO_TEST_CASE(get)
{
auto user = u->get(1);