/**
  * Test whether splitting an recurring event saves the new event under a new UID.
  * See http://jira.opensource.mayflower.de/jira/browse/PHPROJEKT-298 for the ratio behind this.
  */
 public function testSplittingRecurrenceGivesNewUidAndUri()
 {
     $this->setRequestUrl('Calendar2/index/jsonSave/nodeId/1/id/0');
     $this->request->setParam('comments', '');
     $this->request->setParam('confirmationStatus', '2');
     $this->request->setParam('description', '');
     $this->request->setParam('end', '2011-12-01 09:00');
     $this->request->setParam('location', '');
     $this->request->setParam('ownerId', '2');
     $this->request->setParam('participants', '2');
     $this->request->setParam('rrule', 'FREQ=DAILY;INTERVAL=1;BYDAY=');
     $this->request->setParam('sendNotification', '0');
     $this->request->setParam('start', '2011-12-01 08:00');
     $this->request->setParam('summary', 'test');
     $this->request->setParam('visibility', '1');
     $response = $this->getResponse();
     $this->assertContains(IndexController::ADD_TRUE_TEXT, $response);
     $response = Zend_Json::decode(substr($response, 5, -1));
     $this->assertArrayHasKey('id', $response);
     $firstId = $response['id'];
     $this->_reset();
     $tzOffset = (int) Phprojekt_Auth_Proxy::getEffectiveUser()->getSetting('timeZone', '0');
     $hour = 8 - $tzOffset;
     $hour = sprintf('%02d', $hour);
     $this->setRequestUrl("Calendar2/index/jsonSave/nodeId/1/id/{$firstId}/occurrence/2011-12-03%20{$hour}:00:00");
     $this->request->setParam('comments', '');
     $this->request->setParam('confirmationStatus', '2');
     $this->request->setParam('description', '');
     $this->request->setParam('end', '2011-12-03 09:00:00');
     $this->request->setParam('location', '');
     $this->request->setParam('multipleEvents', 'true');
     $this->request->setParam('occurrence', '2011-12-03 08:00:00');
     $this->request->setParam('ownerId', '2');
     $this->request->setParam('participants', '2');
     $this->request->setParam('rrule', 'FREQ=DAILY;INTERVAL=1;BYDAY=');
     $this->request->setParam('sendNotification', '0');
     $this->request->setParam('start', '2011-12-03 08:00:00');
     $this->request->setParam('summary', 'something else');
     $this->request->setParam('visibility', '1');
     $response = $this->getResponse();
     $this->assertContains(IndexController::EDIT_TRUE_TEXT, $response);
     $response = Zend_Json::decode(substr($response, 5, -1));
     $this->assertArrayHasKey('id', $response);
     $secondId = $response['id'];
     $first = new Calendar2_Models_Calendar2();
     $first->find($firstId);
     $second = new Calendar2_Models_Calendar2();
     $second->find($secondId);
     $this->assertNotEquals($first->uid, $second->uid);
     $this->assertNotEquals($first->uri, $second->uri);
 }
Beispiel #2
0
 /**
  * Convert a UTC time to user or user to UTC and return the timestamp.
  *
  * @param string  $value Date value to convert.
  * @param integer $side  1 for utc to user, -1 for user to utc.
  *
  * @return integer Unix timestamp value.
  */
 public static function convert($value, $side)
 {
     $timeZone = Phprojekt_Auth_Proxy::getEffectiveUser()->getSetting("timeZone", 'UTC');
     if (strstr($timeZone, "_")) {
         list($hours, $minutes) = explode("_", $timeZone);
     } else {
         $hours = (int) $timeZone;
         $minutes = 0;
     }
     $hoursComplement = $hours * $side;
     $minutesComplement = $minutes * $side;
     $u = strtotime($value);
     return mktime(date("H", $u) + $hoursComplement, date("i", $u) + $minutesComplement, date("s", $u), date("m", $u), date("d", $u), date("Y", $u));
 }
Beispiel #3
0
 /**
  * Returns the rights merged with the role for the current user.
  *
  * @return array Array of rights per user.
  */
 public function getRights($userId = null)
 {
     // backward compatbility
     if (null === $userId) {
         $userId = Phprojekt_Auth_Proxy::getEffectiveUserId();
     }
     $moduleId = Phprojekt_Module::getId($this->getModelName());
     return Phprojekt_Right::getRightsForItems($moduleId, $this->projectId, $userId, array($this->id));
 }
Beispiel #4
0
 /**
  * Checks that the user has permission for modifying the item, in this case for uploading or deleting files.
  *
  * @param Phprojekt_Model_Interface $model  Current module.
  * @param integer                   $itemId Current item id.
  *
  * @throws Exception On no write access.
  *
  * @return void
  */
 private static function _checkWritePermission($model, $itemId)
 {
     if ($itemId != 0) {
         $model->find($itemId);
     }
     if (!$model->hasRight(Phprojekt_Auth_Proxy::getEffectiveUserId(), Phprojekt_Acl::WRITE)) {
         $error = Phprojekt::getInstance()->translate('You don\'t have permission for modifying this item.');
         self::_logError("Error: trying to Delete or Upload a file without write access.", array(get_class($model), $itemId));
         throw new Exception($error);
     }
 }
 /**
  * Returns a list of all the users the current user has proxy rights on
  *
  * Returns a list of all the users with:
  * <pre>
  *  - id      => id of user.
  *  - display => Display for the user.
  *  - current => True or false if is the current user.
  * </pre>
  *
  * The return is in JSON format.
  *
  * @return void
  */
 public function jsonGetProxyableUsersAction()
 {
     $current = Phprojekt_Auth_Proxy::getEffectiveUserId();
     $proxyTable = new Phprojekt_Auth_ProxyTable();
     $proxyUserIds = $proxyTable->getProxyableUsersForUserId();
     $data = array();
     foreach ($proxyUserIds as $user) {
         $data['data'][] = array('id' => (int) $user->id, 'display' => $user->displayName, 'current' => $current == $user->id);
     }
     Phprojekt_Converter_Json::echoConvert($data, Phprojekt_ModelInformation_Default::ORDERING_LIST);
 }
Beispiel #6
0
 /**
  * Get a participant's confirmation status.
  *
  * If no id is given, the currently logged in user's status
  * will be returned.
  *
  * @param int $id The id of the participant.
  *
  * @return int
  */
 public function getConfirmationStatus($id = null)
 {
     if (is_null($id)) {
         $id = Phprojekt_Auth_Proxy::getEffectiveUserId();
     }
     $this->_fetchParticipantData();
     if (!$this->hasParticipant($id)) {
         // We can not throw an exception here because if a user edits a new
         // entry, a empty model object will be requested and serialized.
         // Returning null here will yield the default value as configured
         // in the database_manager table.
         return null;
     }
     return $this->_participantData[$id];
 }
 /**
  * As defined in Sabre_CalDAV_Backend_Abstract
  *
  * Alters a calendar object. This is currently not supported if the event is recurring and any occurrences have been
  * modified in PHProjekt or if this operation would modify any speficic occurrences.
  *
  * @param string $calendarId   The id of the calendar. Equals to the id of the user it belongs to.
  * @param string $objectUri    The uri of the object.
  * @param string $calendarData The vobject data that the object should be modified to.
  *
  * @return void
  */
 public function updateCalendarObject($calendarId, $objectUri, $calendarData)
 {
     $vcalendar = Sabre_VObject_Reader::read($calendarData);
     $timecard = new Timecard_Models_Timecard();
     $timecard = $timecard->findByUri($objectUri);
     if (!$timecard) {
         throw new Sabre_DAV_Exception_NotFound("Timecard entry with uri {$objectUri} not found");
     }
     if ($timecard->ownerId != Phprojekt_Auth_Proxy::getEffectiveUserId()) {
         throw new Sabre_DAV_Exception_Forbidden("You are not allowed to modify this entry");
     }
     $timecard = Timecard_Models_VObjectReader::readBasedOnExistingTimecard($timecard, $vcalendar->vevent);
     $timecard->save();
 }
Beispiel #8
0
 /**
  * Check if the user has delete access to the item if is not a global module.
  *
  * @param Phprojekt_ActiveRecord_Abstract $model      The model to save.
  * @param string                          $moduleName The current module.
  *
  * @return boolean True for a valid right.
  */
 private static function _checkItemRights(Phprojekt_ActiveRecord_Abstract $model, $moduleName)
 {
     $canDelete = false;
     if ($moduleName == 'Core') {
         return Phprojekt_Auth::isAdminUser();
     } else {
         if (Phprojekt_Module::saveTypeIsNormal(Phprojekt_Module::getId($moduleName)) && method_exists($model, 'hasRight')) {
             return $model->hasRight(Phprojekt_Auth_Proxy::getEffectiveUserId(), Phprojekt_Acl::DELETE);
         } else {
             return true;
         }
     }
 }
Beispiel #9
0
 /**
  * Help to save a model by setting the models properties.
  * Validation is based on the ModelInformation implementation.
  *
  * @param Phprojekt_Model_Interface $model  The model
  * @param array                     $params The parameters used to feed the model.
  *
  * @throws Exception If validation of parameters fails.
  *
  * @return boolean True for a sucessful save.
  */
 protected static function _saveModel(Phprojekt_Model_Interface $model, array $params)
 {
     $newItem = empty($params['id']);
     $model = self::parameterToModel($model, $params, $newItem);
     $projectId = $model->hasField('projectId') ? $model->projectId : 0;
     $userId = Phprojekt_Auth_Proxy::getEffectiveUserId();
     $moduleName = Phprojekt_Loader::getModuleFromObject($model);
     $moduleId = Phprojekt_Module::getId($moduleName);
     if (!$model->recordValidate()) {
         $errors = $model->getError();
         $error = array_pop($errors);
         throw new Zend_Controller_Action_Exception($error['label'] . ': ' . $error['message'], 400);
     }
     if (!self::_checkModule($moduleId, $projectId)) {
         throw new Zend_Controller_Action_Exception('The parent project do not have enabled this module', 400);
     }
     $rights = Default_Helpers_Right::getRights($params);
     if ($model instanceof Phprojekt_Item_Abstract) {
         if ($newItem && !Phprojekt_Module::saveTypeIsGlobal($moduleId)) {
             $project = new Project_Models_Project();
             $project->find($projectId);
             if (!$project->hasRight($userId, Phprojekt_Acl::CREATE)) {
                 throw new Zend_Controller_Action_Exception('You do not have the necessary create right', 403);
             }
             $rights[$userId] = Phprojekt_Acl::ALL;
         } else {
             if (!$model->hasRight($userId, Phprojekt_Acl::WRITE)) {
                 throw new Zend_Controller_Action_Exception('You do not have the necessary write right', 403);
             }
         }
         // Set the projectId to 1 for global modules
         // @TODO Remove the Timecard limitation
         if ($model->hasField('projectId') && Phprojekt_Module::saveTypeIsGlobal($moduleId) && Phprojekt_Module::getModuleName($moduleId) != 'Timecard') {
             $model->projectId = 1;
         }
         $model->save();
         // Save access only if the user have "admin" right
         if ($newItem || $model->hasRight(Phprojekt_Auth_Proxy::getEffectiveUserId(), Phprojekt_Acl::ADMIN)) {
             if (!Phprojekt_Auth_Proxy::isAdminUser() && count($rights) <= 0) {
                 throw new Zend_Controller_Action_Exception('At least one person must have access to this item', 400);
             }
             $model->saveRights($rights);
         }
     } else {
         $model->save();
         $model->saveRights($rights);
     }
     return $model;
 }
Beispiel #10
0
 /**
  * This function wraps around the phprojekt setting for the user timezone
  * to return a DateTimeZone object.
  *
  * @return DateTimeZone The timezone of the user.
  */
 public static function getUserDateTimeZone()
 {
     $tz = Phprojekt_Auth_Proxy::getEffectiveUser()->getSetting('timezone', '0');
     $tz = explode('_', $tz);
     $hours = (int) $tz[0];
     if ($hours >= 0) {
         $hours = '+' . $hours;
     }
     $minutes = '00';
     if (array_key_exists(1, $tz)) {
         // We don't need the minus sign
         $minutes = abs($tz[1]);
     }
     $datetime = new Datetime($hours . ':' . $minutes);
     return $datetime->getTimezone();
 }
 /**
  * Renders the upload.phtml template for display an upload field.
  *
  * This function draws the upload field in the form.
  * All the uploaded files are displayed with a cross for delete it and a link for download it.
  *
  * @param integer $itemId Current item id.
  * @param string  $field  Name of the field in the module.
  * @param string  $value  Value of the field.
  *
  * @return void
  */
 private function _fileRenderView($itemId, $field, $files)
 {
     $this->getResponse()->clearHeaders();
     $this->getResponse()->clearBody();
     $sessionName = 'Phprojekt_CsrfToken';
     $csrfNamespace = new Zend_Session_Namespace($sessionName);
     $config = Phprojekt::getInstance()->getConfig();
     $linkBegin = 'index.php/' . $this->getModuleName() . '/index/';
     $fieldId = $this->getRequest()->getParam('fieldId', '');
     // Add all the extra parameters that have the original URL
     $linkData = '';
     $removeParams = array('module', 'controller', 'field', 'id', 'csrfToken', 'action', 'MAX_FILE_SIZE', 'order');
     foreach ($this->getRequest()->getParams() as $paramName => $paramValue) {
         if (!in_array($paramName, $removeParams)) {
             $linkData .= $paramName . '/' . $paramValue . '/';
         }
     }
     $this->view->compressedDojo = (bool) $config->compressedDojo;
     $this->view->formPath = $linkBegin . 'fileUpload/' . $linkData;
     $this->view->downloadLink = '';
     $this->view->fileName = null;
     $this->view->itemId = $itemId;
     $this->view->field = $field;
     $this->view->fieldId = $fieldId;
     $this->view->csrfToken = $csrfNamespace->token;
     $this->view->maxUploadSize = isset($config->maxUploadSize) ? (int) $config->maxUploadSize : Phprojekt::DEFAULT_MAX_UPLOAD_SIZE;
     $model = $this->getModelObject();
     $model->find($itemId);
     $filesForView = array();
     $hasDownloadRight = $model->hasRight(Phprojekt_Auth_Proxy::getEffectiveUserId(), Phprojekt_Acl::DOWNLOAD);
     $hasWriteRight = $model->hasRight(Phprojekt_Auth_Proxy::getEffectiveUserId(), Phprojekt_Acl::WRITE);
     $this->view->disabled = !$hasWriteRight;
     // Is there any file?
     if (!empty($files)) {
         $i = 0;
         foreach ($files as $file) {
             $fileName = $file['name'];
             $fileHash = $file['md5'];
             $fileData = 'id/' . $itemId . '/field/' . $field . '/hash/' . $fileHash . '/csrfToken/' . $csrfNamespace->token;
             $filesForView[$i] = array('fileName' => $fileName, 'hash' => $fileHash);
             if ($hasDownloadRight) {
                 $filesForView[$i]['downloadLink'] = $linkBegin . 'fileDownload/' . $linkData . $fileData;
             }
             $fileinfo = Default_Helpers_Upload::getInfosFromFile($file);
             $filesForView[$i]['size'] = $fileinfo['size'];
             $filesForView[$i]['ctime'] = $fileinfo['ctime'];
             $i++;
         }
     }
     if (isset($this->view->errorMessage) && !empty($this->view->errorMessage)) {
         $filesForView[] = array();
     }
     $this->view->files = $filesForView;
     $this->render('upload');
 }
Beispiel #12
0
 /**
  * Delete only the own records
  *
  * @return boolean
  */
 public function delete()
 {
     if ($this->ownerId == Phprojekt_Auth_Proxy::getEffectiveUserId()) {
         return parent::delete();
     } else {
         return false;
     }
 }
Beispiel #13
0
 /**
  * Convert a model or a model information into a json stream.
  *
  * @param Phprojekt_Interface_Model | array $models The model(s) to convert.
  * @param integer                           $order  A Phprojekt_ModelInformation_Default::ORDERING_* const that
  *                                                  defines the ordering for the convert.
  *
  * @return string Data in JSON format.
  */
 private static function _convertModel($models, $order = Phprojekt_ModelInformation_Default::ORDERING_DEFAULT)
 {
     if (empty($models)) {
         throw new Exception('Called with empty value');
     }
     // TODO: Are we sure every model is of the same type and have the same
     // parent?
     if (!is_array($models)) {
         $models = array($models);
     }
     $information = $models[0]->getInformation($order);
     $fieldDefinition = $information->getFieldDefinition($order);
     $datas = array();
     $itemIds = array();
     foreach ($models as $model) {
         if (!$model instanceof Phprojekt_Model_Interface) {
             throw new Exception("A given model does not implement the\n                    model interface.");
         }
         $data = array();
         $data['id'] = (int) $model->id;
         $itemIds[] = $data['id'];
         foreach ($fieldDefinition as $field) {
             $key = $field['key'];
             $value = $model->{$key};
             $data[$key] = self::_convertModelValue($value, $field);
         }
         $data['rights'] = array();
         $datas[] = $data;
     }
     $userId = (int) Phprojekt_Auth_Proxy::getEffectiveUserId();
     $moduleId = Phprojekt_Module::getId($models[0]->getModelName());
     // Okay we got real models and stuff that pretends to be a model
     // so we try to guess if we the model has rights that we can access
     if ($models[0] instanceof Phprojekt_Item_Abstract) {
         if ($models[0] instanceof Project_Models_Project) {
             $projectId = $models[0]->id;
         } else {
             $projectId = $models[0]->projectId;
         }
         // TODO: we still asume that the getModelName call works
         $rights = Phprojekt_Right::getRightsForItems($moduleId, $projectId, $userId, $itemIds);
         // We need the $idx to modify the $datas elements instead of just copies.
         foreach ($datas as $index => $data) {
             $datas[$index]['rights'][$userId] = Phprojekt_Acl::convertBitmaskToArray($rights[$datas[$index]['id']]);
         }
     }
     $data = array('metadata' => $fieldDefinition, 'data' => $datas, 'numRows' => (int) count($datas));
     return self::_makeJsonString($data);
 }
 /**
  * Updates the current user's confirmation status on the given event.
  *
  * @param Calendar2_Models_Calendar2 $model  The model to update.
  * @param Array                      $params The Request's parameters. All
  *                                           values taken from this array
  *                                           will be validated.
  *
  * @return int The id of the (new) model object.
  *
  * @throws Zend_Controller_Action_Exception On malformed $params content.
  */
 private function _updateConfirmationStatusAction($model, $params)
 {
     $status = $params['confirmationStatus'];
     $multiple = array_key_exists('multipleEvents', $params) ? $params['multipleEvents'] : 'true';
     if (!Cleaner::validate('int', $status) || !Calendar2_Models_Calendar2::isValidStatus((int) $status)) {
         throw new Zend_Controller_Action_Exception("Invalid confirmationStatus '{$status}'", 400);
     }
     if (!Cleaner::validate('boolean', $multiple)) {
         throw new Zend_Controller_Action_Exception("Invalid multiple '{$multiple}'", 400);
     }
     $status = (int) $status;
     $multiple = 'true' == strtolower($multiple);
     $model->setConfirmationStatus(Phprojekt_Auth_Proxy::getEffectiveUserId(), $status);
     if ($multiple) {
         $model->save();
     } else {
         $model->saveSingleEvent();
     }
     return $model->id;
 }
Beispiel #15
0
 protected static function _getProxyTable()
 {
     if (is_null(self::$_proxyTable)) {
         self::$_proxyTable = new Phprojekt_Auth_ProxyTable();
     }
     return self::$_proxyTable;
 }
Beispiel #16
0
 /**
  * Return the value of one setting.
  *
  * @param string  $settingName The name of the setting.
  * @param integer $userId      The user ID, if is not setted, the current user is used.
  *
  * @return mix Value of the setting.
  */
 public function getSetting($settingName, $userId = 0)
 {
     $toReturn = null;
     if (!$userId) {
         $userId = Phprojekt_Auth_Proxy::getEffectiveUserId();
     }
     $namespace = new Zend_Session_Namespace(self::IDENTIFIER . $userId);
     if (!isset($namespace->{$settingName})) {
         $where = sprintf('user_id = %d AND key_value = %s AND module_id = %d', (int) $userId, $this->_db->quote($settingName), (int) $this->_moduleId);
         $record = $this->fetchAll($where);
         if (!empty($record)) {
             $toReturn = $record[0]->value;
         }
         $namespace->{$settingName} = $toReturn;
     } else {
         $toReturn = $namespace->{$settingName};
     }
     return $toReturn;
 }