From eef6142fa9e06dce9b79712a71eb62156524ed11 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 4 Mar 2018 15:35:52 +0000 Subject: Sign-ups Improves the handling of sign-up requests when an existing unverified user already exists and authentication for that user succeeds with the newly provided credentials. In this case, resend the verification email to the original address and return the original user model. --- gentoobrowse-api/api/users.ice | 1 + gentoobrowse-api/service/sql/users/get.sql | 1 + gentoobrowse-api/service/sql/users/getNew.sql | 6 +++ gentoobrowse-api/service/usersimpl.cpp | 26 ++++++++++-- gentoobrowse-api/service/usersimpl.h | 4 ++ gentoobrowse-api/unittests/testUsers.cpp | 61 ++++++++++++++++++++++++--- 6 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 gentoobrowse-api/service/sql/users/getNew.sql diff --git a/gentoobrowse-api/api/users.ice b/gentoobrowse-api/api/users.ice index f9d66df..ef9de92 100644 --- a/gentoobrowse-api/api/users.ice +++ b/gentoobrowse-api/api/users.ice @@ -12,6 +12,7 @@ module Gentoo { User verify(string username, string verifyguid) throws Slicer::NoRowsReturned; User get(int id) throws Slicer::NoRowsReturned; + NewUser getNew(string username, string password) throws Slicer::NoRowsReturned; User find(string username) throws Slicer::NoRowsReturned; NewUser create(string username, string password, string realname, string email) throws DuplicateDetails; void mailshotsent(int id); diff --git a/gentoobrowse-api/service/sql/users/get.sql b/gentoobrowse-api/service/sql/users/get.sql index c6a66a1..32f1d1a 100644 --- a/gentoobrowse-api/service/sql/users/get.sql +++ b/gentoobrowse-api/service/sql/users/get.sql @@ -2,3 +2,4 @@ SELECT userid, username, userrealname, useremail, signedup, lastmailshot FROM gentoobrowse.users WHERE userid = ? +AND verifyguid IS NULL diff --git a/gentoobrowse-api/service/sql/users/getNew.sql b/gentoobrowse-api/service/sql/users/getNew.sql new file mode 100644 index 0000000..375b4f3 --- /dev/null +++ b/gentoobrowse-api/service/sql/users/getNew.sql @@ -0,0 +1,6 @@ +-- libdbpp:no-cursor +SELECT userid, username, userrealname, useremail, signedup, lastmailshot, verifyguid +FROM gentoobrowse.users +WHERE username = ? +AND userpassword = ? +AND verifyguid IS NOT NULL diff --git a/gentoobrowse-api/service/usersimpl.cpp b/gentoobrowse-api/service/usersimpl.cpp index f5fb111..8071bf9 100644 --- a/gentoobrowse-api/service/usersimpl.cpp +++ b/gentoobrowse-api/service/usersimpl.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -39,23 +40,42 @@ Users::get(Ice::Int id, const Ice::Current &) return fetch(sql::users::get, id); } +Gentoo::NewUserPtr +Users::getNew(const std::string & username, const std::string & password, const Ice::Current &) +{ + return fetch(sql::users::getNew, username, password); +} + Gentoo::UserPtr Users::find(const std::string & username, const Ice::Current &) { return fetch(sql::users::find, username); } +Gentoo::NewUserPtr +Users::authOrCreate(const std::string & username, const std::string & password, const std::string & realname, const std::string & email) +{ + auto existing = fetch>(sql::users::getNew, username, password); + if (existing && *existing) { + return *existing; + } + return fetch(sql::users::create, username, password, realname, email); +} + Gentoo::NewUserPtr Users::create(const std::string & username, const std::string & password, const std::string & realname, const std::string & email, const Ice::Current & current) { auto notifications = NotificationsPrx::checkedCast(current.adapter->getCommunicator()->stringToProxy("notifications")); - notifications->ice_ping(); + BOOST_ASSERT(notifications); + BOOST_ASSERT((notifications->ice_ping(), true)); auto mailServer = MailServerPrx::checkedCast(current.adapter->getCommunicator()->stringToProxy("mailserver")); - mailServer->ice_ping(); + BOOST_ASSERT(mailServer); + BOOST_ASSERT((mailServer->ice_ping(), true)); auto dbc = db->get(); DB::TransactionScope tx(dbc.get()); - auto newUser = fetch(sql::users::create, username, password, realname, email); + + auto newUser = authOrCreate(username, password, realname, email); auto mail = notifications->getSignup(newUser); mailServer->sendEmail(mail); diff --git a/gentoobrowse-api/service/usersimpl.h b/gentoobrowse-api/service/usersimpl.h index 84cf970..ac2a62b 100644 --- a/gentoobrowse-api/service/usersimpl.h +++ b/gentoobrowse-api/service/usersimpl.h @@ -15,6 +15,7 @@ class DLL_PUBLIC Users : public Gentoo::Users, IceTray::AbstractCachingDatabaseC Gentoo::UserPtr verify(const std::string &, const std::string &, const Ice::Current &) override; Gentoo::UserPtr get(Ice::Int id, const Ice::Current &) override; + Gentoo::NewUserPtr getNew(const std::string &, const std::string &, const Ice::Current &) override; Gentoo::UserPtr find(const std::string & username, const Ice::Current &) override; Gentoo::NewUserPtr create(const std::string &, const std::string &, const std::string &, const std::string &, const Ice::Current &) override; void mailshotsent(Ice::Int id, const Ice::Current &) override; @@ -23,6 +24,9 @@ class DLL_PUBLIC Users : public Gentoo::Users, IceTray::AbstractCachingDatabaseC void track(Ice::Int, Ice::Int, const Ice::Current &) override; void untrack(Ice::Int, Ice::Int, const Ice::Current &) override; Gentoo::PackageIds tracked(Ice::Int, const Ice::Current &) override; + + private: + DLL_PRIVATE Gentoo::NewUserPtr authOrCreate(const std::string &, const std::string &, const std::string &, const std::string &); }; } } diff --git a/gentoobrowse-api/unittests/testUsers.cpp b/gentoobrowse-api/unittests/testUsers.cpp index 7f9eaee..a894e95 100644 --- a/gentoobrowse-api/unittests/testUsers.cpp +++ b/gentoobrowse-api/unittests/testUsers.cpp @@ -54,24 +54,75 @@ BOOST_AUTO_TEST_CASE( create ) BOOST_REQUIRE_EQUAL("testuser", user->username); BOOST_REQUIRE_EQUAL("Test User", user->userrealname); BOOST_REQUIRE_EQUAL("test@user.com", user->useremail); - BOOST_REQUIRE(user->signedup.length() > 19); + BOOST_REQUIRE_GE(user->signedup.length(), 19); BOOST_REQUIRE(!user->lastmailshot); BOOST_REQUIRE_EQUAL(36, user->verifyguid.length()); - auto verified = u->verify(user->username, user->verifyguid); - BOOST_REQUIRE(verified); } BOOST_AUTO_TEST_CASE( get ) { - auto user = u->get(3); + auto user = u->get(1); + BOOST_REQUIRE(user); + BOOST_REQUIRE_EQUAL(1, user->userid); + BOOST_REQUIRE_EQUAL("randomdan", user->username); + BOOST_REQUIRE_EQUAL("Dan Goodliffe", user->userrealname); + BOOST_REQUIRE_EQUAL("dan@randomdan.homeip.net", user->useremail); + BOOST_REQUIRE_EQUAL("2015-10-01T12:13:14", user->signedup); + BOOST_REQUIRE(!user->lastmailshot); +} + +BOOST_AUTO_TEST_CASE( getNotVerified ) +{ + // Is not verified, doesn't exist + BOOST_REQUIRE_THROW(u->get(3), Slicer::NoRowsReturned); +} + +BOOST_AUTO_TEST_CASE( getNew ) +{ + auto user = u->getNew("testuser", "testpass"); + BOOST_REQUIRE(user); BOOST_REQUIRE_EQUAL(3, user->userid); BOOST_REQUIRE_EQUAL("testuser", user->username); BOOST_REQUIRE_EQUAL("Test User", user->userrealname); BOOST_REQUIRE_EQUAL("test@user.com", user->useremail); - BOOST_REQUIRE(user->signedup.length() > 19); + BOOST_REQUIRE_GE(user->signedup.length(), 19); + BOOST_REQUIRE_EQUAL(36, user->verifyguid.length()); BOOST_REQUIRE(!user->lastmailshot); } +BOOST_AUTO_TEST_CASE( getNewVerified ) +{ + // Is verified, not new + BOOST_REQUIRE_THROW(u->getNew("randomdan", "p@55w0rd"), Slicer::NoRowsReturned); +} + +BOOST_AUTO_TEST_CASE( createAgain ) +{ + /* + * Should (unverified): + * * return original user + * * resend verification + */ + auto ms = getProxy("mailserver"); + BOOST_REQUIRE(ms); + auto user = u->create("testuser", "testpass", "Test User", "recreate@user.com"); + BOOST_REQUIRE_EQUAL(2, ms->getSentEmails().size()); + BOOST_REQUIRE_EQUAL("Gentoo Browse: Welcome", ms->getSentEmails()[1]->subject); + BOOST_REQUIRE_EQUAL("test@user.com", ms->getSentEmails()[1]->to.address); + BOOST_REQUIRE_EQUAL(3, user->userid); + BOOST_REQUIRE_EQUAL(36, user->verifyguid.length()); +} + +BOOST_AUTO_TEST_CASE( verify ) +{ + auto user = u->getNew("testuser", "testpass"); + BOOST_REQUIRE(user); + auto verified = u->verify(user->username, user->verifyguid); + BOOST_REQUIRE(verified); + BOOST_REQUIRE_THROW(u->getNew("testuser", "testpass"), Slicer::NoRowsReturned); + BOOST_REQUIRE(u->get(3)); +} + BOOST_AUTO_TEST_CASE( sendmailshot ) { auto user = u->get(3); -- cgit v1.2.3