diff options
| -rw-r--r-- | gentoobrowse-api/api/maintenance.ice | 5 | ||||
| -rw-r--r-- | gentoobrowse-api/domain/news-models.ice | 26 | ||||
| -rw-r--r-- | gentoobrowse-api/service/maintenanceCommon.cpp | 54 | ||||
| -rw-r--r-- | gentoobrowse-api/service/maintenanceimpl.h | 2 | ||||
| -rw-r--r-- | gentoobrowse-api/service/notifications/notifications.ice | 8 | ||||
| -rw-r--r-- | gentoobrowse-api/service/sql/maintenance/getNotificationEbuildLists.sql | 11 | ||||
| -rw-r--r-- | gentoobrowse-api/service/usersimpl.cpp | 18 | ||||
| -rw-r--r-- | gentoobrowse-api/unittests/Jamfile.jam | 9 | ||||
| -rw-r--r-- | gentoobrowse-api/unittests/testNotificationsTriggers.cpp | 50 | ||||
| -rw-r--r-- | gentoobrowse-api/unittests/testUsers.cpp | 6 | 
10 files changed, 177 insertions, 12 deletions
| diff --git a/gentoobrowse-api/api/maintenance.ice b/gentoobrowse-api/api/maintenance.ice index 013acb3..736b913 100644 --- a/gentoobrowse-api/api/maintenance.ice +++ b/gentoobrowse-api/api/maintenance.ice @@ -1,3 +1,5 @@ +#include <news-models.ice> +  module Gentoo {  	["cpp:ice_print"]  	exception GitError { @@ -5,10 +7,13 @@ module Gentoo {  		int errorClass;  		string message;  	}; +  	interface Maintenance {  		idempotent void refreshPackageTree();  		idempotent void refreshBugs();  		idempotent void refreshChangeLogs() throws GitError; +		UserNews getUserNews(); +		void sendNotifications();  	};  }; diff --git a/gentoobrowse-api/domain/news-models.ice b/gentoobrowse-api/domain/news-models.ice new file mode 100644 index 0000000..0b7021f --- /dev/null +++ b/gentoobrowse-api/domain/news-models.ice @@ -0,0 +1,26 @@ +#ifndef GENTOO_NEWS_MODELS +#define GENTOO_NEWS_MODELS + +#include <portage-models.ice> + +module Gentoo { +	struct NewsContentTrigger { +		int userid; +		IntList ebuildids; +		IntList packageids; +		IntList categoryids; +	}; + +	sequence<NewsContentTrigger> NewsContentTriggers; + +	struct NewsContent { +		Categories categories; +		Packages packages; +		Ebuilds ebuilds; +	}; + +	dictionary<int, NewsContent> UserNews; +}; + +#endif + diff --git a/gentoobrowse-api/service/maintenanceCommon.cpp b/gentoobrowse-api/service/maintenanceCommon.cpp index 49101ee..8a55087 100644 --- a/gentoobrowse-api/service/maintenanceCommon.cpp +++ b/gentoobrowse-api/service/maintenanceCommon.cpp @@ -1,9 +1,11 @@  #include "maintenanceimpl.h"  #include <Ice/ObjectAdapter.h>  #include <Ice/Communicator.h> -#include <tablepatch.h> -#include "utils/dbUtils.h" -#include "sql/maintenance/bugAssociate.sql.h" +#include <notifications.h> +#include <portage.h> +#include <users.h> +#include <safeMapFind.h> +#include "sql/maintenance/getNotificationEbuildLists.sql.h"  namespace Gentoo {  	namespace Service { @@ -12,6 +14,52 @@ namespace Gentoo {  		{  			return c.adapter->getCommunicator()->getProperties();  		} + +		Gentoo::UserNews +		Maintenance::getUserNews(const Ice::Current & current) +		{ +			auto portage = PortagePrx::checkedCast(current.adapter->getCommunicator()->stringToProxy("portage")); +			portage->ice_ping(); +			auto categories = portage->getAllCategories(); + +			UserNews un; +			auto t = fetch<NewsContentTriggers>(sql::maintenance::getNotificationEbuildLists); +			std::transform(t.begin(), t.end(), std::inserter(un, un.end()), [&categories,&portage](const NewsContentTriggers::value_type & t) { +				NewsContent nc; +				std::copy_if(categories.begin(), categories.end(), std::back_inserter(nc.categories), [&t](const Gentoo::CategoryPtr & c) { +					return AdHoc::containerContains(t.categoryids, c->categoryid); +				}); +				for (auto pid : t.packageids) { +					auto par = portage->begin_getPackage(pid); +					auto vsar = portage->begin_getPackageVersions(pid); +					nc.packages.push_back(portage->end_getPackage(par)); +					auto vs = portage->end_getPackageVersions(vsar); +					std::copy_if(vs.begin(), vs.end(), std::back_inserter(nc.ebuilds), [&t](const Gentoo::EbuildPtr & v) { +						return AdHoc::containerContains(t.ebuildids, v->ebuildid); +					}); +				} +				return UserNews::value_type(t.userid, nc); +			}); +			return un; +		} + +		void +		Maintenance::sendNotifications(const Ice::Current & current) +		{ +			auto notifications = NotificationsPrx::checkedCast(current.adapter->getCommunicator()->stringToProxy("notifications")); +			notifications->ice_ping(); +			auto mailServer = MailServerPrx::checkedCast(current.adapter->getCommunicator()->stringToProxy("mailserver")); +			mailServer->ice_ping(); +			auto users = UsersPrx::checkedCast(current.adapter->getCommunicator()->stringToProxy("users")); +			users->ice_ping(); + +			for (const auto & trigger : getUserNews(current)) { +				auto user = users->get(trigger.first); +				auto email = notifications->getNews(user, trigger.second); +				mailServer->sendEmail(email); +				users->mailshotsent(user->userid); +			} +		}  	}  } diff --git a/gentoobrowse-api/service/maintenanceimpl.h b/gentoobrowse-api/service/maintenanceimpl.h index c150043..dc6cbbf 100644 --- a/gentoobrowse-api/service/maintenanceimpl.h +++ b/gentoobrowse-api/service/maintenanceimpl.h @@ -38,6 +38,8 @@ namespace Gentoo {  				void refreshPackageTree(const Ice::Current &) override;  				void refreshBugs(const Ice::Current &) override;  				void refreshChangeLogs(const Ice::Current &) override; +				Gentoo::UserNews getUserNews(const Ice::Current &) override; +				void sendNotifications(const Ice::Current &) override;  			private:  				void updateFileTypes(DB::Connection *) const; diff --git a/gentoobrowse-api/service/notifications/notifications.ice b/gentoobrowse-api/service/notifications/notifications.ice index a60fa28..4a2673f 100644 --- a/gentoobrowse-api/service/notifications/notifications.ice +++ b/gentoobrowse-api/service/notifications/notifications.ice @@ -2,7 +2,7 @@  #define GENTOO_NOTIFICATIONS  #include <user-models.ice> -#include <portage-models.ice> +#include <news-models.ice>  module Gentoo {  	class MimePart { @@ -29,12 +29,6 @@ module Gentoo {  		string message;  	}; -	struct NewsContent { -		Categories categories; -		Packages packages; -		Ebuilds ebuilds; -	}; -  	interface Notifications {  		Email getSignup(NewUser user);  		Email getNews(User user, NewsContent nc); diff --git a/gentoobrowse-api/service/sql/maintenance/getNotificationEbuildLists.sql b/gentoobrowse-api/service/sql/maintenance/getNotificationEbuildLists.sql new file mode 100644 index 0000000..35453fc --- /dev/null +++ b/gentoobrowse-api/service/sql/maintenance/getNotificationEbuildLists.sql @@ -0,0 +1,11 @@ +SELECT u.userid, +	array_agg(DISTINCT e.ebuildid) ebuildids, +	array_agg(DISTINCT p.packageid) packageids, +	array_agg(DISTINCT p.categoryid) categoryids +FROM gentoobrowse.users u, gentoobrowse.user_packages up, gentoobrowse.ebuilds e, gentoobrowse.packages p +WHERE u.userid = up.userid +AND p.packageid = e.packageid +AND up.trackedsince < e.firstseen +AND up.packageid = e.packageid +AND coalesce(u.lastmailshot, u.signedup) < e.firstseen +GROUP BY u.userid diff --git a/gentoobrowse-api/service/usersimpl.cpp b/gentoobrowse-api/service/usersimpl.cpp index c2f45a7..60d0b64 100644 --- a/gentoobrowse-api/service/usersimpl.cpp +++ b/gentoobrowse-api/service/usersimpl.cpp @@ -1,4 +1,6 @@  #include "usersimpl.h" +#include <Ice/ObjectAdapter.h> +#include <Ice/Communicator.h>  #include <modifycommand.h>  #include <sql/users/authenticate.sql.h>  #include <sql/users/verify.sql.h> @@ -10,6 +12,7 @@  #include <sql/users/untrack.sql.h>  #include <sql/users/tracked.sql.h>  #include <sql/users/mailshotsent.sql.h> +#include <notifications.h>  namespace Gentoo {  namespace Service { @@ -43,9 +46,20 @@ Users::find(const std::string & username, const Ice::Current &)  }  Gentoo::NewUserPtr -Users::create(const std::string & username, const std::string & password, const std::string & realname, const std::string & email, const Ice::Current &) +Users::create(const std::string & username, const std::string & password, const std::string & realname, const std::string & email, const Ice::Current & current)  { -	return fetch<Gentoo::NewUserPtr>(sql::users::create, username, password, realname, email); +	auto notifications = NotificationsPrx::checkedCast(current.adapter->getCommunicator()->stringToProxy("notifications")); +	notifications->ice_ping(); +	auto mailServer = MailServerPrx::checkedCast(current.adapter->getCommunicator()->stringToProxy("mailserver")); +	mailServer->ice_ping(); + +	auto dbc = db->get(); +	DB::TransactionScope tx(dbc.get()); +	auto newUser = fetch<Gentoo::NewUserPtr>(sql::users::create, username, password, realname, email); +	auto mail = notifications->getSignup(newUser); +	mailServer->sendEmail(mail); + +	return newUser;  }  void diff --git a/gentoobrowse-api/unittests/Jamfile.jam b/gentoobrowse-api/unittests/Jamfile.jam index 60ee5e6..ba030eb 100644 --- a/gentoobrowse-api/unittests/Jamfile.jam +++ b/gentoobrowse-api/unittests/Jamfile.jam @@ -112,6 +112,15 @@ run  	: testNotifications ;  run +	testNotificationsTriggers.cpp +	: : : +	<dependency>../db/schema.sql +	<define>BOOST_TEST_DYN_LINK +	<library>testCommon +	<implicit-dependency>testCommon +	: testNotificationsTriggers ; + +run  	testBugs.cpp  	: : :  	<dependency>../db/schema.sql diff --git a/gentoobrowse-api/unittests/testNotificationsTriggers.cpp b/gentoobrowse-api/unittests/testNotificationsTriggers.cpp new file mode 100644 index 0000000..6455627 --- /dev/null +++ b/gentoobrowse-api/unittests/testNotificationsTriggers.cpp @@ -0,0 +1,50 @@ +#define BOOST_TEST_MODULE TestNotificationsTriggers +#include <boost/test/unit_test.hpp> + +#include "mockDefs.h" + +BOOST_GLOBAL_FIXTURE( Service ); + +BOOST_FIXTURE_TEST_SUITE(tp, TestClient); + +BOOST_AUTO_TEST_CASE( triggers ) +{ +	auto t = m->getUserNews(); +	BOOST_REQUIRE_EQUAL(1, t.size()); +	BOOST_REQUIRE_EQUAL(1, t.begin()->first); +	BOOST_REQUIRE_EQUAL(2, t.begin()->second.categories.size()); +	std::sort(t.begin()->second.categories.begin(), t.begin()->second.categories.end(), [](auto a, auto b) { return a->categoryid < b->categoryid; }); +	BOOST_REQUIRE_EQUAL(311, t.begin()->second.categories[0]->categoryid); +	BOOST_REQUIRE_EQUAL(313, t.begin()->second.categories[1]->categoryid); +	BOOST_REQUIRE_EQUAL(2, t.begin()->second.packages.size()); +	std::sort(t.begin()->second.packages.begin(), t.begin()->second.packages.end(), [](auto a, auto b) { return a->packageid < b->packageid; }); +	BOOST_REQUIRE_EQUAL(49517, t.begin()->second.packages[0]->packageid); +	BOOST_REQUIRE_EQUAL(54144, t.begin()->second.packages[1]->packageid); +	BOOST_REQUIRE_EQUAL(7, t.begin()->second.ebuilds.size()); +	std::sort(t.begin()->second.ebuilds.begin(), t.begin()->second.ebuilds.end(), [](auto a, auto b) { return a->ebuildid < b->ebuildid; }); +	BOOST_REQUIRE_EQUAL(657508, t.begin()->second.ebuilds[0]->ebuildid); +	BOOST_REQUIRE_EQUAL(657509, t.begin()->second.ebuilds[1]->ebuildid); +	BOOST_REQUIRE_EQUAL(658228, t.begin()->second.ebuilds[2]->ebuildid); +	BOOST_REQUIRE_EQUAL(658511, t.begin()->second.ebuilds[3]->ebuildid); +	BOOST_REQUIRE_EQUAL(659908, t.begin()->second.ebuilds[4]->ebuildid); +	BOOST_REQUIRE_EQUAL(660220, t.begin()->second.ebuilds[5]->ebuildid); +	BOOST_REQUIRE_EQUAL(680613, t.begin()->second.ebuilds[6]->ebuildid); +} + +BOOST_AUTO_TEST_CASE( send ) +{ +	auto ms = getProxy<Gentoo::MockMailServerPrx>("mailserver"); +	BOOST_REQUIRE(ms); + +	BOOST_REQUIRE(!u->get(1)->lastmailshot); +	m->sendNotifications(); +	BOOST_REQUIRE(u->get(1)->lastmailshot); +	const auto & es = ms->getSentEmails(); +	BOOST_REQUIRE_EQUAL(1, es.size()); +	BOOST_REQUIRE_EQUAL("Gentoo Browse: Latest updates", es[0]->subject); +	BOOST_REQUIRE_EQUAL("Dan Goodliffe", es[0]->to.name); +	BOOST_REQUIRE_EQUAL("Gentoo Browse", es[0]->from.name); +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/gentoobrowse-api/unittests/testUsers.cpp b/gentoobrowse-api/unittests/testUsers.cpp index e515b77..7f9eaee 100644 --- a/gentoobrowse-api/unittests/testUsers.cpp +++ b/gentoobrowse-api/unittests/testUsers.cpp @@ -43,7 +43,13 @@ BOOST_AUTO_TEST_CASE( authenticateVerify )  BOOST_AUTO_TEST_CASE( create )  { +	auto ms = getProxy<Gentoo::MockMailServerPrx>("mailserver"); +	BOOST_REQUIRE(ms);  	auto user = u->create("testuser", "testpass", "Test User", "test@user.com"); +	BOOST_REQUIRE_EQUAL(1, ms->getSentEmails().size()); +	BOOST_REQUIRE_EQUAL("Gentoo Browse: Welcome", ms->getSentEmails().front()->subject); +	BOOST_REQUIRE_EQUAL("test@user.com", ms->getSentEmails().front()->to.address); +	BOOST_REQUIRE_EQUAL("Test User", ms->getSentEmails().front()->to.name);  	BOOST_REQUIRE_EQUAL(3, user->userid);  	BOOST_REQUIRE_EQUAL("testuser", user->username);  	BOOST_REQUIRE_EQUAL("Test User", user->userrealname); | 
