Пример #1
0
 /**
  * Initiates the password reset process on behalf of the user
  * Generates a unique hash and an expiration time that the hash is valid up until (defaults to 15 minutes)
  * This key will internally expire (but not be expunged) after that time
  */
 public function initPasswordResetProcess()
 {
     if (!$this->validate()) {
         return false;
     }
     $hash = Cii::generateSafeHash();
     $expires = strtotime("+15 minutes");
     $meta = UserMetadata::model()->findByAttributes(array('user_id' => $this->_user->id, 'key' => 'passwordResetCode'));
     if ($meta === NULL) {
         $meta = new UserMetadata();
     }
     $meta->user_id = $this->_user->id;
     $meta->key = 'passwordResetCode';
     $meta->value = $hash;
     $meta->save();
     $meta = UserMetadata::model()->findByAttributes(array('user_id' => $this->_user->id, 'key' => 'passwordResetExpires'));
     if ($meta === NULL) {
         $meta = new UserMetadata();
     }
     $meta->user_id = $this->_user->id;
     $meta->key = 'passwordResetExpires';
     $meta->value = $expires;
     $meta->save();
     $emailSettings = new EmailSettings();
     $emailSettings->send($this->_user, Yii::t('ciims.email', 'Your Password Reset Information'), 'webroot.themes.' . Cii::getConfig('theme', 'default') . '.views.email.forgot', array('user' => $this->_user, 'hash' => $hash), true, true);
     // Set success flash
     Yii::app()->user->setFlash('success', Yii::t('ciims.controllers.Site', 'An email has been sent to {{email}} with further instructions on how to reset your password', array('{{email}}' => $this->email)));
     return true;
 }
Пример #2
0
 /**
  * Creates a new Dashboard card with the $id dashboard_card_{ID_HERE}
  * $id is a randomly generated hash based upon the unique data of the card.json + name, and contains 2 key pieces of information
  *     1) The class name
  *     2) The path in.dot.format
  *
  * Once created, the unique instance is added to the user's specific dashboard. This is an Ajax specific request
  * @param  string  $id  The unique id of the card as defined on creation of said card type
  * @return bool
  */
 public function actionAdd($id)
 {
     if ($id == NULL) {
         throw new CHttpException(400, Yii::t('Dashboard.main', 'An ID must be specified'));
     }
     $config = Configuration::model()->findByAttributes(array('key' => $id));
     if ($config == NULL) {
         throw new CHttpException(400, Yii::t('Dashboard.main', 'No card type exists with that ID'));
     }
     $name = CJSON::decode($config->value);
     Yii::import($name['path'] . '.*');
     $card = new $name['class']();
     $card->create($id, $name['path']);
     $data = CJSON::decode($card->getJSON($name['path']));
     $data['id'] = $card->id;
     // Update the user's card information
     $meta = UserMetadata::model()->findByAttributes(array('user_id' => Yii::app()->user->id, 'key' => 'dashboard'));
     if ($meta == NULL) {
         $meta = new UserMetadata();
         $meta->key = 'dashboard';
         $meta->user_id = Yii::app()->user->id;
         $meta->value = array();
     }
     if (!is_array($meta->value)) {
         $order = CJSON::decode($meta->value);
     } else {
         $order = $meta->value;
     }
     $order[] = $card->id;
     $meta->value = CJSON::encode($order);
     $meta->save();
     return $card->render();
 }
Пример #3
0
 /**
  * Sends an invite to a new user
  * @return boolean
  */
 public function invite()
 {
     if (!$this->validate()) {
         return false;
     }
     $user = new Users();
     $user->attributes = array('email' => $this->email, 'firstName' => null, 'lastName' => null, 'displayName' => null, 'password' => null, 'user_role' => 5, 'status' => Users::PENDING_INVITATION);
     // Create a new user, but bypass validation
     if ($user->save(false)) {
         $meta = new UserMetadata();
         $meta->attributes = array('user_id' => $user->id, 'key' => 'invitationKey', 'value' => Cii::generateSafeHash());
         // If the key was savedm send the email out
         if ($meta->save()) {
             $emailSettings = new EmailSettings();
             $emailSettings->send($user, Yii::t('ciims.models.InvitationForm', "You've Been Invited..."), 'webroot.themes.' . Cii::getConfig('theme', 'default') . '.views.email.invite', array('user' => $user, 'hash' => $meta->value), true, true);
             return true;
         }
         $user->delete();
     }
     return false;
 }
Пример #4
0
 /**
  * Generates a new change key
  * @return boolean
  */
 public function setNewEmailChangeKey()
 {
     $metadata = UserMetadata::model()->findByAttributes(array('user_id' => $this->_user->id, 'key' => 'newEmailAddressChangeKey'));
     if ($metadata == NULL) {
         $metadata = new UserMetadata();
         $metadata->attributes = array('user_id' => $this->_user->id, 'key' => 'newEmailAddressChangeKey');
     }
     // Generate a new key
     $metadata->value = Cii::generateSafeHash();
     // Save the record
     if ($metadata->save()) {
         return $metadata->value;
     }
     throw new CHttpException(500, Yii::t('ciims.ProfileForm', 'Unable to save change key'));
 }
Пример #5
0
 /**
  * Creates a new user, and sends the appropriate messaging out
  * @return boolean
  */
 public function save($sendEmail = true)
 {
     if (!$this->validate()) {
         return false;
     }
     $this->_user = new Users();
     // Set the model attributes
     $this->_user->attributes = array('email' => $this->email, 'password' => $this->password, 'username' => $this->username, 'user_role' => 1, 'status' => $sendEmail ? Users::PENDING_INVITATION : Users::ACTIVE);
     // If we saved the user model, return true
     if ($this->_user->save()) {
         // This class my be extended by other modules, in which case we don't need to send an activation form if we don't want need it to.
         if ($sendEmail) {
             $meta = new UserMetadata();
             $meta->attributes = array('user_id' => $this->_user->id, 'key' => 'activationKey', 'value' => Cii::generateSafeHash());
             $meta->save();
             // Send the registration email
             $emailSettings = new EmailSettings();
             $emailSettings->send($this->_user, Yii::t('ciims.email', 'Activate Your Account'), 'base.themes.' . Cii::getConfig('theme', 'default') . '.views.email.register', array('user' => $this->_user, 'hash' => $meta->value), true, true);
         }
         return true;
     }
     return false;
 }
Пример #6
0
 /**
  * Retrieves all comments that the user has flagged
  * @return array
  */
 public function getFlaggedComments($model = false)
 {
     $flags = UserMetadata::model()->findByAttributes(array('user_id' => $this->id, 'key' => 'flaggedComments'));
     if ($flags === NULL) {
         $flags = new UserMetadata();
         $flags->attributes = array('user_id' => $this->id, 'key' => 'flaggedComments', 'value' => CJSON::encode(array()));
         $flags->save();
         if ($model == true) {
             return $flags;
         }
         return array();
     }
     if ($model == true) {
         return $flags;
     }
     return CJSON::decode($flags->value);
 }
Пример #7
0
 /**
  * Provides functionality for "liking and un-liking" a post
  * @param int $id		The Content ID
  */
 public function actionLike($id = NULL)
 {
     $this->layout = false;
     header('Content-type: application/json');
     // Load the content
     $content = ContentMetadata::model()->findByAttributes(array('content_id' => $id, 'key' => 'likes'));
     if ($content === NULL) {
         $content = new ContentMetadata();
         $content->content_id = $id;
         $content->key = 'likes';
         $content->value = 0;
     }
     if ($id === NULL || $content === NULL) {
         echo CJavaScript::jsonEncode(array('status' => 'error', 'message' => Yii::t('ciims.controllers.Content', 'Unable to access post')));
         return Yii::app()->end();
     }
     // Load the user likes, create one if it does not exist
     $user = UserMetadata::model()->findByAttributes(array('user_id' => Yii::app()->user->id, 'key' => 'likes'));
     if ($user === NULL) {
         $user = new UserMetadata();
         $user->user_id = Yii::app()->user->id;
         $user->key = 'likes';
         $user->value = json_encode(array());
     }
     $type = "inc";
     $likes = json_decode($user->value, true);
     if (in_array($id, array_values($likes))) {
         $type = "dec";
         $content->value -= 1;
         if ($content->value <= 0) {
             $content->value = 0;
         }
         $element = array_search($id, $likes);
         unset($likes[$element]);
     } else {
         $content->value += 1;
         array_push($likes, $id);
     }
     $user->value = json_encode($likes);
     if (!$user->save()) {
         echo CJavaScript::jsonEncode(array('status' => 'error', 'message' => Yii::t('ciims.controllers.Content', 'Unable to save user like')));
         return Yii::app()->end();
     }
     if (!$content->save()) {
         echo CJavaScript::jsonEncode(array('status' => 'error', 'message' => Yii::t('ciims.controllers.Content', 'Unable to save like')));
         return Yii::app()->end();
     }
     echo CJavaScript::jsonEncode(array('status' => 'success', 'type' => $type, 'message' => Yii::t('ciims.controllers.Content', 'Liked saved')));
     return Yii::app()->end();
 }
Пример #8
0
 /**
  * Registration page
  *
  **/
 public function actionRegister()
 {
     $this->setPageTitle(Yii::t('ciims.controllers.Site', '{{app_name}} | {{label}}', array('{{app_name}}' => Cii::getConfig('name', Yii::app()->name), '{{label}}' => Yii::t('ciims.controllers.Site', 'Sign Up'))));
     $this->layout = '//layouts/main';
     $model = new RegisterForm();
     $user = new Users();
     $error = '';
     if (isset($_POST) && !empty($_POST)) {
         $model->attributes = $_POST['RegisterForm'];
         if ($model->validate()) {
             if (!function_exists('password_hash')) {
                 require_once YiiBase::getPathOfAlias('ext.bcrypt.bcrypt') . '.php';
             }
             // Bcrypt the initial password instead of just using the basic hashing mechanism
             $hash = Users::model()->encryptHash(Cii::get($_POST['RegisterForm'], 'email'), Cii::get($_POST['RegisterForm'], 'password'), Yii::app()->params['encryptionKey']);
             $cost = Cii::getBcryptCost();
             $password = password_hash($hash, PASSWORD_BCRYPT, array('cost' => $cost));
             $user->attributes = array('email' => Cii::get($_POST['RegisterForm'], 'email'), 'password' => $password, 'firstName' => NULL, 'lastName' => NULL, 'displayName' => Cii::get($_POST['RegisterForm'], 'displayName'), 'user_role' => 1, 'status' => Users::INACTIVE);
             try {
                 if ($user->save()) {
                     $hash = mb_strimwidth(hash("sha256", md5(time() . md5(hash("sha512", time())))), 0, 16);
                     $meta = new UserMetadata();
                     $meta->user_id = $user->id;
                     $meta->key = 'activationKey';
                     $meta->value = $hash;
                     $meta->save();
                     // Send the registration email
                     $this->sendEmail($user, Yii::t('ciims.email', 'Activate Your Account'), '//email/register', array('user' => $user, 'hash' => $hash), true, true);
                     $this->redirect($this->createUrl('/register-success'));
                     return;
                 }
             } catch (CDbException $e) {
                 $model->addError(null, Yii::t('ciims.controllers.Site', 'The email address has already been associated to an account. Do you want to login instead?'));
             }
         }
     }
     $this->render('register', array('model' => $model, 'error' => $error, 'user' => $user));
 }
Пример #9
0
 /**
  * Internal API endpoint for inviting new users to join the site
  *
  **/
 public function actionCreate()
 {
     $validator = new CEmailValidator();
     if (!$validator->validateValue(Cii::get($_POST, 'email', NULL))) {
         throw new CHttpException(400, Yii::t('Dashboard.main', 'The email address you provided is invalid.'));
     }
     if (Users::model()->countByAttributes(array('email' => Cii::get($_POST, 'email', NULL)))) {
         throw new CHttpException(400, Yii::t('Dashboard.main', 'A user with that email address already exists.'));
     }
     $user = new Users();
     $user->attributes = array('status' => Users::PENDING_INVITATION, 'email' => Cii::get($_POST, 'email', NULL), 'user_role' => 5, 'about' => '', 'password' => '', 'displayName' => '', 'firstName' => '', 'lastName' => '');
     $user->created = new CDbExpression('UTC_TIMESTAMP()');
     $user->updated = new CDbExpression('UTC_TIMESTAMP()');
     // Save the user, and ignore all validation
     if ($user->save(false)) {
         $hash = mb_strimwidth(hash("sha256", md5(time() . md5(hash("sha512", time())))), 0, 16);
         $meta = new UserMetadata();
         $meta->user_id = $user->id;
         $meta->key = 'activationKey';
         $meta->value = $hash;
         $meta->save();
         // Send an invitation email
         $this->sendEmail($user, Yii::t('Dashboard.email', "You've Been Invited To Join a Blog!"), '/email/invite', array('user' => $user, 'hash' => $hash), true, true);
         // End the request
         return $this->renderPartial('/users/userList', array('data' => $user));
     }
     throw new CHttpException(400, Yii::t('Dashboard.main', 'An unexpected error occured fulfilling your request.'));
 }
Пример #10
0
 /**
  * Main mehod to handle login attempts.  If the user passes authentication with their
  * chosen provider then it displays a form for them to choose their username and email.
  * The email address they choose is *not* verified.
  * 
  * @throws Exception if a provider isn't supplied, or it has non-alpha characters
  */
 private function hybridAuth($provider = NULL)
 {
     if ($provider == NULL) {
         throw new CException(Yii::t('Hybridauth.main', "You haven't supplied a provider"));
     }
     if (!function_exists('password_hash')) {
         require_once YiiBase::getPathOfAlias('ext.bcrypt.bcrypt') . '.php';
     }
     $identity = new RemoteUserIdentity();
     if ($identity->authenticate($provider)) {
         // If we found a user and authenticated them, bind this data to the user if it does not already exist
         $user = UserMetadata::model()->findByAttributes(array('key' => $provider . 'Provider', 'value' => $identity->userData['id']));
         if ($user === NULL) {
             $user = new UserMetadata();
             $user->user_id = Users::model()->findByAttributes(array('email' => $identity->userData['email']))->id;
             $user->key = $provider . 'Provider';
             $user->value = $identity->userData['id'];
             $user->save();
         }
         $user = Users::model()->findByPk($user->user_id);
         // Log the user in with just their email address
         $model = new LoginForm(true);
         // CiiMS 1.7 provided authentication schemes against md5 hashes. If we have any users in the system who still have md5 hashes
         // as their password, allow authentication, but immediatly upgrade their password to something more secure.
         $model->attributes = array('username' => isset($user->email) ? $user->email : $identity->userData['email'], 'password' => md5('PUBUSER'));
         // validate user input and redirect to the previous page if valid
         if ($model->validate() && $model->login()) {
             // Upgradee the user's password to bcrypt so they don't stick out in database dumps
             if ($user->password == md5('PUBUSER')) {
                 $user->password = password_hash($identity->userData['email'], PASSWORD_BCRYPT, array('cost' => 13));
                 $user->save();
             }
             $this->redirect(Yii::app()->user->returnUrl);
         }
         // If the prevvious authentication failed, then the user has been upgraded, and we should attempt to use the bcrypt hash isntead of the md5 one
         $model->attributes = array('username' => isset($user->email) ? $user->email : $identity->userData['email'], 'password' => password_hash($identity->userData['email'], PASSWORD_BCRYPT, array('cost' => 13)));
         // validate user input and redirect to the previous page if valid
         if ($model->validate() && $model->login()) {
             $this->redirect(Yii::app()->user->returnUrl);
         }
         throw new CException(Yii::t('Hybridauth.main', 'Unable to bind to local user'));
     } else {
         if ($identity->errorCode == RemoteUserIdentity::ERROR_USERNAME_INVALID) {
             // If the user authenticatd against the remote network, but we didn't find them locally
             // Create a local account, and bind this information to it.
             $user = new Users();
             $user->attributes = array('email' => $identity->userData['email'], 'password' => password_hash($identity->userData['email'], PASSWORD_BCRYPT, array('cost' => 13)), 'firstName' => Cii::get($identity->userData, 'firstName', 'UNKNOWN'), 'lastName' => Cii::get($identity->userData, 'lastName', 'UNKNOWN'), 'displayName' => $provider == 'twitter' ? $identity->userData['firstName'] : $identity->userData['displayName'], 'user_role' => 1, 'status' => 1);
             $user->save();
             $meta = new UserMetadata();
             $meta->user_id = $user->id;
             $meta->key = $provider . 'Provider';
             $meta->value = $identity->userData['id'];
             $meta->save();
             // Log the user in with just their email address
             $model = new LoginForm(true);
             $model->attributes = array('username' => $identity->userData['email'], 'password' => password_hash($identity->userData['email'], PASSWORD_BCRYPT, array('cost' => 13)));
             // validate user input and redirect to the previous page if valid
             if ($model->validate() && $model->login()) {
                 $this->redirect(Yii::app()->user->returnUrl);
             }
             throw new CException(Yii::t('Hybridauth.main', 'Unable to bind new user locally'));
         } else {
             // Panic?
             throw new CException(Yii::t('Hybridauth.main', 'We were able to authenticate you against the remote network, but could not sign you in locally.'));
         }
     }
 }
Пример #11
0
 /**
  * Bind behaviors for changing the user's email, and allow them to make the appropriate changes on their end.
  * The intention behind this, is that the user has to first, verify that they requested the change, and second
  * verify that they own both email addresses.
  *
  * The intention behind this is to protect the user from changes to their account, either by an administrator or a malicious user.
  * This doesn't protect from database attacks, it only protects from malicious attacks from within CiiMS.
  * 
  * @return parent::afterSave();
  */
 public function beforeSave()
 {
     // If the user's email address is about to change
     if (isset($this->_oldAttributes['email']) && $this->_oldAttributes['email'] != $this->email) {
         // Store the new email address
         $newEmail = $this->email;
         // Reset the email addres and block the change internally
         $this->email = $this->_oldAttributes['email'];
         // Save the NEW email address in the database as a metadata record
         $meta = UserMetadata::model()->findByAttributes(array('user_id' => $this->id, 'key' => 'newEmailAddress'));
         if ($meta === NULL) {
             $meta = new UserMetadata();
         }
         $meta->user_id = $this->id;
         $meta->key = 'newEmailAddress';
         $meta->value = $newEmail;
         $meta->save();
         $meta = UserMetadata::model()->findByAttributes(array('user_id' => $this->id, 'key' => 'newEmailAddressChangeKey'));
         if ($meta === NULL) {
             $meta = new UserMetadata();
         }
         $meta->user_id = $this->id;
         $meta->key = 'newEmailAddressChangeKey';
         $key = $meta->value = md5(md5($newEmail . time()) . Yii::app()->params['encryptionKey']);
         $meta->save();
         // Delete all API tokens associated to this account
         $response = Yii::app()->db->createCommand('DELETE FROM user_metadata WHERE `key` LIKE "api_key%" AND user_id = :id')->bindParam(':id', $this->id)->execute();
         // Fire off an email to the OLD email address asking them VERIFY the change
         $response = Yii::app()->controller->sendEmail($this, Yii::t('Dashboard.email', 'CiiMS Email Change Notification'), 'application.modules.dashboard.views.email.email-change', array('key' => $key));
     }
     return parent::beforeSave();
 }
Пример #12
0
 /** 
  * Provides functionality to create a new user. This method will create a new user if the user does not already exist.
  * And then it will send an email invitation to the user so that they can join the blog.
  * @return array
  */
 private function createUser()
 {
     $validator = new CEmailValidator();
     if (!$validator->validateValue(Cii::get($_POST, 'email', NULL))) {
         throw new CHttpException(400, Yii::t('Api.user', 'The email address you provided is invalid.'));
     }
     if (Users::model()->countByAttributes(array('email' => Cii::get($_POST, 'email', NULL)))) {
         throw new CHttpException(400, Yii::t('Api.user', 'A user with that email address already exists.'));
     }
     // Passowrds cannot be set through the API
     unset($_POST['password']);
     // Relational data cannot be set through this API
     unset($_POST['comments']);
     unset($_POST['content']);
     unset($_POST['tags']);
     unset($_POST['metadata']);
     unset($_POST['role']);
     $user = new Users();
     $user->attributes = array('status' => Users::PENDING_INVITATION, 'email' => Cii::get($_POST, 'email', NULL), 'user_role' => 1, 'about' => '', 'password' => '', 'displayName' => '', 'firstName' => '', 'lastName' => '');
     $user->attributes = $_POST;
     $user->created = new CDbExpression('UTC_TIMESTAMP()');
     $user->updated = new CDbExpression('UTC_TIMESTAMP()');
     // Save the user, and ignore all validation
     if ($user->save(false)) {
         $hash = mb_strimwidth(hash("sha256", md5(time() . md5(hash("sha512", time())))), 0, 16);
         $meta = new UserMetadata();
         $meta->user_id = $user->id;
         $meta->key = 'activationKey';
         $meta->value = $hash;
         $meta->save();
         // Send an invitation email
         $this->sendEmail($user, Yii::t('Api.user', "You've Been Invited To Join a Blog!"), 'application.modules.dashboard.views.email.invite', array('user' => $user, 'hash' => $hash), true, true);
         // End the request
         return $user->getAPIAttributes(array('password', 'activation_key'));
     }
     throw new CHttpException(400, Yii::t('Api.user', 'An unexpected error occured fulfilling your request.'));
 }
Пример #13
0
 /**
  * 
  * @param unknown $slug
  */
 public function actionEdit($slug)
 {
     $user = User::model()->findbyAttributes(array('slug' => $slug, 'status' => User::STATUS_ACTIVE));
     if (isset($user)) {
         // save the current mail
         $oldMail = $user->email;
         // if there isn't an instance of UserPersonalInfo we have to create it.
         if (!isset($user->personalInfo)) {
             $user->personalInfo = new UserPersonalInfo();
         }
         if (isset($_POST['User']) && isset($_POST['UserPersonalInfo'])) {
             $user->attributes = $_POST['User'];
             // check if at least one of these field is setted
             if (!empty($_POST['UserPersonalInfo']['first_name']) || !empty($_POST['UserPersonalInfo']['last_name']) || !empty($_POST['UserPersonalInfo']['gender']) || !empty($_POST['UserPersonalInfo']['birthdate'])) {
                 $user->personalInfo->attributes = $_POST['UserPersonalInfo'];
                 $user->personalInfo->user_id = $user->id;
             }
             // used to check if the user has already changed his own mail
             if ($oldMail != $user->email) {
                 $user->setScenario('editProfile');
             }
             // validation of the models
             $this->performAjaxValidationProfileForm($user);
             //verify if the mail was changed
             if ($oldMail != $user->email) {
                 $usersMetadata = new UserMetadata();
                 $usersMetadata->user_id = $user->id;
                 $usersMetadata->key = User::METADATA_KEY_EMAIL_CHANGE_NEW_ADDRESS;
                 $usersMetadata->value = $user->email;
                 $usersMetadata->save();
                 $usersMetadata2 = new UserMetadata();
                 $usersMetadata2->user_id = $user->id;
                 $usersMetadata2->key = User::METADATA_KEY_EMAIL_CHANGE_TOKEN;
                 $usersMetadata2->value = UserHelper::generateActivationToken();
                 $usersMetadata2->save();
                 //confirmation mail
                 $activation_link = Yii::app()->createAbsoluteUrl('profile/email?token=' . $usersMetadata2->value);
                 BasicNotifier::sendTemplatedEmail($oldMail, Yii::t('ProfileModule.edit', 'email.subject.changeEmail'), 'profile/change_email_confirmation', array('{CHANGE_EMAIL_ADDRESS}' => $user->email, '{CHANGE_EMAIL_CONFIRMATION_LINK}' => $activation_link), Yii::app()->session['lang']);
                 /* set flash messages */
                 Yii::app()->user->setFlash('pending', 'email');
                 //assign to as mail of the user his old mail. The new mail before to replace the old one have to be confirmed
                 $user->email = $oldMail;
             }
             /* save user and related models */
             $user->withRelated->save(true, array('personalInfo'));
             /* set flash messages */
             Yii::app()->user->setFlash('success', true);
             /* back to profile */
             $this->redirect(Yii::app()->createUrl('profile'));
         }
         $this->render('edit', array('user' => $user, 'userPersonalInfo' => $user->personalInfo, 'slug' => $slug));
     }
 }