diff options
| -rw-r--r-- | gentoobrowse-api/api/users.ice | 2 | ||||
| -rw-r--r-- | gentoobrowse-api/domain/user-models.ice | 1 | ||||
| -rw-r--r-- | gentoobrowse-api/service/usersimpl.cpp | 15 | ||||
| -rw-r--r-- | gentoobrowse-api/unittests/testUsers.cpp | 40 | 
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);  | 
