summaryrefslogtreecommitdiff
path: root/manager
diff options
context:
space:
mode:
authorMichael Tänzer <neo@nhng.de>2011-06-20 13:41:52 +0200
committerMichael Tänzer <neo@nhng.de>2011-06-20 13:41:52 +0200
commitf4d471baacad50526b8ee722a810998379f8c414 (patch)
treefa541052704cf9ef6cfbbc3f77829fe1298895e9 /manager
parent1996e4f0a9231344031b6e189f955f371b11d3a8 (diff)
downloadcacert-mgr-f4d471baacad50526b8ee722a810998379f8c414.tar.gz
cacert-mgr-f4d471baacad50526b8ee722a810998379f8c414.tar.xz
cacert-mgr-f4d471baacad50526b8ee722a810998379f8c414.zip
Factor out functionality into a model so the controllers get more lightweight
Signed-off-by: Michael Tänzer <neo@nhng.de>
Diffstat (limited to 'manager')
-rw-r--r--manager/application/controllers/ManageAccountController.php125
-rw-r--r--manager/application/models/User.php310
2 files changed, 317 insertions, 118 deletions
diff --git a/manager/application/controllers/ManageAccountController.php b/manager/application/controllers/ManageAccountController.php
index b07285b..f0701b4 100644
--- a/manager/application/controllers/ManageAccountController.php
+++ b/manager/application/controllers/ManageAccountController.php
@@ -6,7 +6,6 @@
class ManageAccountController extends Zend_Controller_Action
{
const MAX_POINTS_PER_ASSURANCE = 35;
- const MAX_ASSURANCE_POINTS = 100;
const MAX_POINTS_TOTAL = 150;
const ADMIN_INCREASE_FRAGMENT_SIZE = 2;
@@ -57,55 +56,28 @@ class ManageAccountController extends Zend_Controller_Action
// Form is valid -> get values for processing
$values = $form->getValues();
- // Get user data
- $user['id'] = $this->getUserId();
- $user['points'] = $this->getPoints($user['id']);
+ // Get the current user
+ $user = Application_Model_User::findCurrentUser();
-
- // Do the actual assurances
- $assurance = array(); // Make sure the array is empty
- $assurance['to'] = $user['id'];
- $assurance['location'] = $values['location'];
- $assurance['date'] = $values['date'];
- $assurance['when'] = new Zend_Db_Expr('now()');
$this->view->assurancesDone = array();
-
$quantity = $values['quantity'];
do {
// split up into multiple assurances
if ($quantity > self::MAX_POINTS_PER_ASSURANCE) {
- $assurance['awarded'] = self::MAX_POINTS_PER_ASSURANCE;
+ $points = self::MAX_POINTS_PER_ASSURANCE;
$quantity -= self::MAX_POINTS_PER_ASSURANCE;
} else {
- $assurance['awarded'] = $quantity;
+ $points = $quantity;
$quantity = 0;
}
// Get the assurer for this assurance
- $assurance['from'] = $this->getNewAssurer($user['id']);
-
- // only assign points whithin the limit
- if ($user['points'] + $assurance['awarded'] > self::MAX_ASSURANCE_POINTS){
- $assurance['points'] = self::MAX_ASSURANCE_POINTS - $user['points'];
- } else {
- $assurance['points'] = $assurance['awarded'];
- }
-
- // Only assign positive amounts
- if ($assurance['points'] < 0){
- $assurance['points'] = 0;
- }
-
- $this->db->insert('notary', $assurance);
+ $issued = $user->findNewAssurer()
+ ->assure($user, $points, $values['location'], $values['date']);
- $user['points'] += $assurance['points'];
- $this->view->assurancesDone[] = $assurance['points'];
+ $this->view->assurancesDone[] = $issued;
} while ($quantity > 0);
-
- // Maybe user is now assurer
- $this->fixAssurerFlag($user['id']);
-
return;
}
@@ -229,89 +201,6 @@ class ManageAccountController extends Zend_Controller_Action
return;
}
- /**
- * Get and check the user ID of the current user
- *
- * @return int The ID of the current user
- */
- protected function getUserId()
- {
- $session = Zend_Registry::get('session');
- if ($session->authdata['authed'] !== true) {
- throw new Exception(__METHOD__ . ': you need to log in to use this feature');
- }
-
- // Check if the ID is present on the test server
- $query = 'select `id` from `users` where `id` = :user';
- $query_params['user'] = $session->authdata['authed_id'];
- $result = $this->db->query($query, $query_params);
- if ($result->rowCount() !== 1) {
- throw new Exception(__METHOD__ . ': user ID not found in the data base');
- }
- $row = $result->fetch();
-
- return $row['id'];
- }
-
- /**
- * Get current points of the user
- *
- * @param int $user_id ID of the user
- * @return int the amount of points the user currently has
- */
- protected function getPoints($user_id)
- {
- $query = 'select sum(`points`) as `total` from `notary` where `to` = :user';
- $query_params['user'] = $user_id;
- $row = $this->db->query($query, $query_params)->fetch();
- if ($row['total'] === NULL) $row['total'] = 0;
-
- return $row['total'];
- }
-
- /**
- * Get the first assurer who didn't already assure the user
- *
- * @param int $user_id The ID of the user who should get assured
- * @return int The ID of the selected assurer
- */
- protected function getNewAssurer($user_id)
- {
- $query = 'select min(`id`) as `assurer` from `users` ' .
- 'where `email` like \'john.doe-___@example.com\' and ' .
- '`id` not in (select `from` from `notary` where `to` = :user)';
- $query_params['user'] = $user_id;
- $row = $this->db->query($query, $query_params)->fetch();
-
- if ($row['assurer'] === NULL) {
- throw new Exception(__METHOD__ . ': no more assurers that haven\'t '.
- 'already assured this account');
- }
-
- return $row['assurer'];
- }
-
- /**
- * Fix the assurer flag for the given user
- *
- * @param $user_id ID of the user
- */
- protected function fixAssurerFlag($user_id)
- {
- // TODO: unset flag if requirements are not met
-
- $query = 'UPDATE `users` SET `assurer` = 1 WHERE `users`.`id` = :user AND '.
-
- 'EXISTS(SELECT * FROM `cats_passed` AS `cp`, `cats_variant` AS `cv` '.
- 'WHERE `cp`.`variant_id` = `cv`.`id` AND `cv`.`type_id` = 1 AND '.
- '`cp`.`user_id` = :user) AND '.
-
- '(SELECT SUM(`points`) FROM `notary` WHERE `to` = :user AND '.
- '`expire` < now()) >= 100';
- $query_params['user'] = $user_id;
- $this->db->query($query, $query_params);
- }
-
protected function getAssuranceForm()
{
$form = new Zend_Form();
diff --git a/manager/application/models/User.php b/manager/application/models/User.php
new file mode 100644
index 0000000..29bd1e7
--- /dev/null
+++ b/manager/application/models/User.php
@@ -0,0 +1,310 @@
+<?php
+/**
+ * @author Michael Tänzer
+ */
+
+class Application_Model_User {
+ protected $db;
+
+ protected $id;
+ protected $points = null;
+
+ protected function __construct(Zend_Db_Adapter_Abstract $db, $id) {
+ // Not allowed to create new users from within the manager
+
+ $this->db = $db;
+ $this->id = $id;
+ }
+
+ /**
+ * Get an user object for the given ID
+ *
+ * @param $id int
+ * @return Application_Model_User
+ */
+ public static function findById($id) {
+ // Get database connection
+ $config = new Zend_Config_Ini(
+ APPLICATION_PATH . '/configs/application.ini',
+ APPLICATION_ENV);
+ $db = Zend_Db::factory($config->ca_mgr->db->auth->pdo,
+ $config->ca_mgr->db->auth);
+
+ // Check if the ID is present on the test server
+ $query = 'select `id` from `users` where `id` = :user';
+ $query_params['user'] = $id;
+ $result = $db->query($query, $query_params);
+ if ($result->rowCount() !== 1) {
+ throw new Exception(
+ __METHOD__ . ': user ID not found in the data base');
+ }
+ $row = $result->fetch();
+
+ return new Application_Model_User($db, $row['id']);
+ }
+
+ /**
+ * Get an user object for the currently logged in user
+ *
+ * @return Application_Model_User
+ */
+ public static function findCurrentUser() {
+ $session = Zend_Registry::get('session');
+ if ($session->authdata['authed'] !== true) {
+ throw new Exception(
+ __METHOD__ . ': you need to log in to use this feature');
+ }
+
+ return self::findById($session->authdata['authed_id']);
+ }
+
+ /**
+ * Get the first assurer who didn't already assure the user
+ *
+ * @return Application_Model_User
+ */
+ public function findNewAssurer()
+ {
+ $query = 'select min(`id`) as `assurer` from `users` ' .
+ 'where `email` like \'john.doe-___@example.com\' and ' .
+ '`id` not in (select `from` from `notary` where `to` = :user)';
+ $query_params['user'] = $this->id;
+ $row = $this->db->query($query, $query_params)->fetch();
+
+ if ($row['assurer'] === NULL) {
+ throw new Exception(
+ __METHOD__ . ': no more assurers that haven\'t already '.
+ 'assured this account');
+ }
+
+ return new Application_Model_User($this->db, $row['assurer']);
+ }
+
+ /**
+ * Refresh the current value of points from the test server
+ *
+ * Needed if operations outside this class are made, that might affect the
+ * user's points
+ */
+ public function refreshPoints() {
+ $query = 'select sum(`points`) as `total` from `notary` '.
+ 'where `to` = :user';
+ $query_params['user'] = $this->id;
+ $row = $this->db->query($query, $query_params)->fetch();
+ if ($row['total'] === null) $row['total'] = 0;
+
+ $this->points = $row['total'];
+ }
+
+ /**
+ * Get points of the user
+ *
+ * @return int
+ * The amount of points the user has
+ */
+ public function getPoints()
+ {
+ if ($this->points === null) {
+ $this->refreshPoints();
+ }
+
+ return $this->points;
+ }
+
+ /**
+ * Fix the assurer flag for the user
+ */
+ public function fixAssurerFlag()
+ {
+ // TODO: unset flag if requirements are not met
+
+ $query = 'UPDATE `users` SET `assurer` = 1 WHERE `users`.`id` = :user AND '.
+
+ 'EXISTS(SELECT * FROM `cats_passed` AS `cp`, `cats_variant` AS `cv` '.
+ 'WHERE `cp`.`variant_id` = `cv`.`id` AND `cv`.`type_id` = 1 AND '.
+ '`cp`.`user_id` = :user) AND '.
+
+ '(SELECT SUM(`points`) FROM `notary` WHERE `to` = :user AND '.
+ '`expire` < now()) >= 100';
+ $query_params['user'] = $this->id;
+ $this->db->query($query, $query_params);
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getAssurerStatus() {
+ $query = 'SELECT 1 FROM `users` WHERE `users`.`id` = :user AND '.
+ '`assurer_blocked` = 0 AND'.
+
+ 'EXISTS(SELECT * FROM `cats_passed` AS `cp`, `cats_variant` AS `cv` '.
+ 'WHERE `cp`.`variant_id` = `cv`.`id` AND `cv`.`type_id` = 1 AND '.
+ '`cp`.`user_id` = :user) AND '.
+
+ '(SELECT SUM(`points`) FROM `notary` WHERE `to` = :user AND '.
+ '`expire` < now()) >= 100';
+ $query_params['user'] = $this->id;
+ $result = $this->db->query($query, $query_params);
+ if ($result->rowCount() === 1) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @return Zend_Date
+ */
+ public function getDob() {
+ $query = 'select `dob` from `users` where `id` = :user';
+ $query_params['user'] = $this->id;
+ $row = $this->db->query($query, $query_params)->fetch();
+
+ return new Zend_Date($row['dob'], Zend_Date::ISO_8601);
+ }
+
+ /**
+ * @return int
+ */
+ public function getAge() {
+ $now = new Zend_Date();
+ return $now->sub($this->getDob())->toValue(Zend_Date::YEAR);
+ }
+
+ /**
+ * Assure another user. Usual restrictions apply
+ *
+ * @param $assuree Application_Model_User
+ * @param $points int
+ * @param $location string
+ * @param $date string
+ * @throws Exception
+ *
+ * @return int
+ * The amount of points that have been issued (might be less than
+ * $points)
+ */
+ public function assure(Application_Model_User $assuree, $points, $location,
+ $date) {
+ // Sanitize inputs
+ $points = intval($points);
+ $location = stripslashes($location);
+ $date = stripslashes($date);
+
+ if (!$this->getAssurerStatus()) {
+ throw new Exception(
+ __METHOD__ . ': '.$this->id.' needs to be an assurer to do '.
+ 'assurances');
+ }
+
+ if ($this->id === $assuree->id) {
+ throw new Exception(
+ __METHOD__ . ': '.$this->id.' is not allowed to assure '.
+ 'himself');
+ }
+
+ $query = 'select * from `notary` where `from`= :assurer and '.
+ '`to`= :assuree';
+ $query_params['assurer'] = $this->id;
+ $query_params['assuree'] = $assuree->id;
+ $result = $this->db->query($query, $query_params);
+ if ($result->rowCount() > 0 && $this->getPoints() < 200) {
+ throw new Exception(
+ __METHOD__ . ': '.$this->id.' is not allowed to assure '.
+ $assuree->id .' more than once');
+ }
+
+ // Respect the maximum points
+ $max = $this->maxpoints();
+ $points = min($points, $max);
+
+ $rounddown = $points;
+ if ($max < 100) {
+ if ($assuree->getPoints() + $points > 100)
+ $rounddown = 100 - $assuree->getPoints();
+ } else {
+ if ($assuree->getPoints() + $points > $max)
+ $rounddown = $max - $assuree->getPoints();
+ }
+ if ($rounddown < 0) $rounddown = 0;
+
+ $query = 'select * from `notary` where `from` = :assurer and '.
+ '`to` = :assuree and `awarded` = :points and '.
+ '`location` = :location and `date` = :date';
+ $query_params['assurer'] = $this->id;
+ $query_params['assuree'] = $assuree->id;
+ $query_params['points'] = $points;
+ $query_params['location'] = $location;
+ $query_params['date'] = $date;
+ $result = $this->db->query($query, $query_params);
+ if ($result->rowCount() > 0) {
+ throw new Exception(
+ __METHOD__ . ': '.$this->id.' is not allowed to do the same '.
+ 'assurance to '.$assuree->id.' more than once');
+ }
+
+ // Make sure it is empty
+ $assurance = array();
+ $assurance['from'] = $this->id;
+ $assurance['to'] = $assuree->id;
+ $assurance['points'] = $rounddown;
+ $assurance['awarded'] = $points;
+ $assurance['location'] = $location;
+ $assurance['date'] = $date;
+ $assurance['when'] = new Zend_Db_Expr('now()');
+
+ $this->db->insert('notary', $assurance);
+ $assuree->points += $rounddown;
+ $assuree->fixAssurerFlag();
+
+ if ($this->getPoints() < 150) {
+ $addpoints = 0;
+ if ($this->getPoints() < 149 && $this->getPoints() >= 100) {
+ $addpoints = 2;
+ } elseif ($this->getPoints() === 149) {
+ $addpoints = 1;
+ }
+
+ $increase = array();
+ $increase['from'] = $this->id;
+ $increase['to'] = $this->id;
+ $increase['points'] = $addpoints;
+ $increase['awarded'] = $addpoints;
+ $increase['location'] = $location;
+ $increase['date'] = $date;
+ $increase['method'] = 'Administrative Increase';
+ $increase['when'] = new Zend_Db_Expr('now()');
+
+ $this->db->insert('notary', $increase);
+ $this->points += $addpoints;
+ // No need to fix assurer flag here
+ }
+
+ return $rounddown;
+ }
+
+ /**
+ * Maximum number of points the user may issue
+ *
+ * @return int
+ */
+ private function maxpoints() {
+ if (!$this->getAssurerStatus()) return 0;
+
+ if ($this->getAge() < 18) return 10;
+
+ $points = $this->getPoints();
+ if ($points >= 300) return 200;
+ if ($points >= 200) return 150;
+ if ($points >= 150) return 35;
+ if ($points >= 140) return 30;
+ if ($points >= 130) return 25;
+ if ($points >= 120) return 20;
+ if ($points >= 110) return 15;
+ if ($points >= 100) return 10;
+
+ // Should not get here
+ throw new Exception(
+ __METHOD__ . ': '.$this->id.' We have reached unreachable code');
+ }
+} \ No newline at end of file