/** * Comments */ public function action_comment() { $this->template = ""; if (!$this->admin) { throw new HTTP_Exception_403(); } if ($this->request->method() != "POST") { throw HTTP_Exception::factory(405)->allowed('POST'); } // Get the POST data $data = json_decode($this->request->body(), TRUE); $user = Model_User::get_user_by_email($data['from_email']); $drop_id = intval($this->request->param('id', 0)); if (!$user->loaded()) { throw HTTP_Exception::factory(404); } $comment = Model_Droplet_Comment::create_new($data['comment_text'], $drop_id, $user->id); $context_obj = ORM::factory(ucfirst($data['context']), $data['context_obj_id']); if ($context_obj->loaded()) { Swiftriver_Mail::notify_new_drop_comment($comment, $context_obj); } Kohana::$log->add(Log::DEBUG, "New comment for drop id :id from :email", array(':id' => $drop_id, ':email' => $data['from_email'])); }
/** * Password reset for ORM auth. * */ private static function password_reset_orm($email) { $ret = array(); $auth_token = Model_Auth_Token::create_token('password_reset', array('email' => $email)); if ($auth_token->loaded()) { //Send an email with a secret token URL $mail_body = View::factory('emails/resetpassword')->bind('secret_url', $secret_url); $secret_url = url::site('login/reset/' . urlencode($email) . '/' . $auth_token->token, TRUE, TRUE); $mail_subject = __(':sitename: Password Reset', array(':sitename' => Model_Setting::get_setting('site_name'))); Swiftriver_Mail::send($email, $mail_subject, $mail_body); $ret['messages'] = array(__('An email has been sent with instructions to complete the password reset process.')); } else { $ret['errors'] = array(__('Error')); } return $ret; }
/** * REST endpoint for sharing droplets via email */ public function action_share() { $this->template = ''; $this->auto_render = FALSE; if ($this->request->method() != "POST") { throw HTTP_Exception::factory(405)->allowed('POST'); } // Extract the input data to be used for sending the email $post = Arr::extract($_POST, array('recipient', 'drop_title', 'drop_url', 'security_code')); $csrf_token = $this->request->headers('x-csrf-token'); // Setup validation $validation = Validation::factory($post)->rule('recipient', 'not_empty')->rule('recipient', 'email')->rule('security_code', 'Captcha::valid')->rule('drop_title', 'not_empty')->rule('drop_url', 'url'); // Validate if (!CSRF::valid($csrf_token) or !$validation->check()) { Kohana::$log->add(Log::DEBUG, "CSRF token or form validation failure"); throw HTTP_Exception::factory(400); } else { list($recipient, $subject) = array($post['recipient'], $post['drop_title']); // Modify the mail body to include the email address of the // use sharing content $mail_body = __(":user has shared a drop with you via SwiftRiver\n\n:url", array(':user' => $this->user['owner']['username'], ':url' => $post['drop_url'])); // Send the email Swiftriver_Mail::send($recipient, $subject, $mail_body); } }
/** * @return void */ private function notify_new_follower($user_orm) { // Send email notification after successful save $html = View::factory('emails/html/new_follower'); $text = View::factory('emails/text/new_follower'); $html->from_name = $text->from_name = $this->user->name; $html->avatar = Swiftriver_Users::gravatar($this->user->email, 80); $html->from_link = $text->from_link = URL::site($this->user->account->account_path, TRUE); $html->nickname = $text->nickname = $user_orm->account->account_path; $subject = __(':who if now following you of SwiftRiver!', array(":who" => $this->user->name)); Swiftriver_Mail::send($user_orm->email, $subject, $text->render(), $html->render()); }
private function _update_settings() { // Validate current password $validated = FALSE; $current_password = $_POST['current_password']; if ($this->riverid_auth) { $response = RiverID_API::instance()->signin($this->user->email, $_POST['current_password']); $validated = ($response and $response['status']); } else { $validated = Auth::instance()->hash($current_password) == $this->user->password; } if (!$validated) { $this->errors = __('Current password is incorrect'); return; } $messages = array(); // Password is changing and we are using RiverID authentication if (!empty($_POST['password']) or !empty($_POST['password_confirm'])) { $post = Model_Auth_User::get_password_validation($_POST); if (!$post->check()) { $this->errors = $post->errors('user'); return; } // Are we using RiverID? if ($this->riverid_auth) { $resp = RiverID_API::instance()->change_password($this->user->email, $_POST['current_password'], $_POST['password']); if (!$resp['status']) { $this->errors = $resp['error']; return; } // For API calls below, use this new password $current_password = $_POST['password']; unset($_POST['password'], $_POST['password_confirm']); } } // Email address is changing if ($_POST['email'] != $this->user->email) { $new_email = $_POST['email']; if (!Valid::email($new_email)) { $this->errors = __('Invalid email address'); return; } if ($this->riverid_auth) { // RiverID email change process $mail_body = View::factory('emails/changeemail')->bind('secret_url', $secret_url); $secret_url = url::site('login/changeemail/' . urlencode($this->user->email) . '/' . urlencode($new_email) . '/%token%', TRUE, TRUE); $site_email = Kohana::$config->load('useradmin.email_address'); $mail_subject = __(':sitename: Email Change', array(':sitename' => Model_Setting::get_setting('site_name'))); $resp = RiverID_API::instance()->change_email($this->user->email, $new_email, $current_password, $mail_body, $mail_subject, $site_email); if (!$resp['status']) { $this->errors = $resp['error']; return; } } else { // Make sure the new email address is not yet registered $user = ORM::factory('user', array('email' => $new_email)); if ($user->loaded()) { $this->errors = __('The new email address has already been registered'); return; } $auth_token = Model_Auth_Token::create_token('change_email', array('new_email' => $new_email, 'old_email' => $this->user->email)); if ($auth_token->loaded()) { // Send an email with a secret token URL $mail_body = View::factory('emails/changeemail')->bind('secret_url', $secret_url); $secret_url = URL::site('login/changeemail/' . urlencode($this->user->email) . '/' . urlencode($new_email) . '/' . $auth_token->token, TRUE, TRUE); // Send email to the user using the new address $mail_subject = __(':sitename: Email Change', array(':sitename' => Model_Setting::get_setting('site_name'))); Swiftriver_Mail::send($new_email, $mail_subject, $mail_body); } else { $this->errors = __('Error'); return; } $messages[] = __("A confirmation email has been sent to :email", array(':email' => $new_email)); } // Don't change email address immediately. // Only do so after the tokens sent above are validated unset($_POST['email']); } // END if - email address change // Nickname is changing if ($_POST['nickname'] != $this->user->account->account_path) { $nickname = $_POST['nickname']; // Make sure the account path is not already taken $account = ORM::factory('account', array('account_path' => $nickname)); if ($account->loaded()) { $this->errors = __('Nickname is already taken'); return; } // Update $this->user->account->account_path = $nickname; $this->user->account->save(); } $this->user->update_user($_POST, array('name', 'password', 'email')); $messages[] = __("Account settings were saved successfully."); Session::instance()->set("messages", $messages); $this->request->redirect(URL::site($this->user->account->account_path . '/settings')); }
/** * REST endpoint for sharing droplets via email */ public function action_share() { $this->template = ''; $this->auto_render = FALSE; if ($_POST) { // Extract the input data $post = Arr::extract($_POST, array('recipient', 'subject', 'body')); $csrf_token = $this->request->headers('x-csrf-token'); // Setup validation $validation = Validation::factory($post)->rule('recipient', 'not_empty')->rule('recipient', 'email')->rule('subject', 'not_empty')->rule('body', 'not_empty')->rule('body', 'max_length', array(':value', 300)); // Validate if (!CSRF::valid($csrf_token) and !$validation->check()) { $this->response->status(400); } else { // Modify the mail body to include the email address of the // use sharing content $mail_body = __(":body \n\nShared by :sender", array(':body' => $post['body'], ':sender' => $this->user->username)); // Send the email Swiftriver_Mail::send($post['recipient'], $post['subject'], $mail_body); } } else { throw new HTTP_Exception_405("Only HTTP POST requests are allowed"); } }
/** * Notify bucket owners and followers of a new comment * * @return void */ public static function notify_new_bucket_comment($comment, $bucket) { $html = View::factory('emails/html/comment'); $text = View::factory('emails/text/comment'); $html->is_drop = $text->is_drop = FALSE; $html->from_name = $text->from_name = $comment->user->name; $html->avatar = Swiftriver_Users::gravatar($comment->user->email, 80); $html->from_link = URL::site($comment->user->account->account_path, TRUE); $html->asset = $text->asset = 'bucket'; $html->asset_name = $text->asset_name = $bucket->bucket_name; $html->asset_link = $text->asset_link = URL::site($bucket->get_base_url(), TRUE); $html->link = $text->link = URL::site($bucket->get_base_url() . '/discussion#comment-' . $comment->id, TRUE); $text->comment = $comment->comment_content; $html->comment = Markdown::instance()->transform($comment->comment_content); $subject = __(':from commented on the ":name" bucket.', array(":from" => $comment->user->name, ":name" => $bucket->bucket_name)); // Add owner of the bucket first $emails = array($bucket->user->email); // Then collaborators foreach ($bucket->get_collaborators(TRUE) as $collaborator) { $emails[] = $collaborator['email']; } // Then followers foreach ($bucket->subscriptions->find_all() as $follower) { $emails[] = $follower->email; } $text_body = $text->render(); $html_body = $html->render(); $site_email = Swiftriver_Mail::get_default_address(); $from = '"' . $comment->user->name . '" <notifications@' . Swiftriver_Mail::get_email_domain() . '>'; $token_data = array('bucket_id' => $comment->bucket_id); $token = Model_Auth_Token::create_token('bucket-comment', $token_data); $reply_to = 'bucket-comment-' . $token->token . '@' . Swiftriver_Mail::get_comments_email_domain(); foreach ($emails as $email) { if ($email != $comment->user->email) { Swiftriver_Mail::send($email, $subject, $text_body, $html_body, $from, array('Reply-To' => $reply_to)); } } }
/** * Perform the maintenance */ public function action_run() { if (php_sapi_name() !== 'cli') { Kohana::$log->add(Log::ERROR, __("Maintenance must be run in CLI mode")); exit; } Kohana::$log->add(Log::INFO, __("Running river maintenance schedule")); // Get settings $settings = Model_Setting::get_settings(array('river_active_duration', 'river_expiry_notice_period', 'site_url')); $notice_period = $settings['river_expiry_notice_period']; $site_url = $settings['site_url']; // Templates for the notifications $warning_template = View::factory('emails/expiry_warning'); $notice_template = View::factory('emails/expiry_notice'); // Fix the current date to the time when the maintenance // is being run $current_date_timestamp = time(); $current_date = date("Y-m-d H:i:s", $current_date_timestamp); // Compute the filter date $filter_date_timestamp = strtotime(sprintf("+%s day", $notice_period), $current_date_timestamp); $filter_date = date("Y-m-d H:i:s", $filter_date_timestamp); // Get the rivers that have expired or are about to expire $candidates = ORM::factory('river')->where('river_expired', '=', 0)->where('river_date_expiry', '<=', $filter_date)->find_all(); $to_be_expired = array(); $to_be_flagged = array(); $rivers = array(); foreach ($candidates as $river) { $days_to_expiry = $river->get_days_to_expiry($current_date); $river_url = $site_url . $river->get_base_url(); // Generate extension token and modify the URL if ($days_to_expiry === 0) { $token = hash("sha256", Text::random('alnum', 32)); $river_url .= '/extend?token=' . $token; $to_be_expired[$river->id] = $token; } else { // Is the river to be flagged for expiry if ($days_to_expiry > 0 and $river->expiry_candidate == 0) { $to_be_flagged[] = $river->id; } else { continue; } } $rivers[$river->id] = array('river_name' => $river->river_name, 'river_url' => $river_url, 'days_to_expiry' => $days_to_expiry); } // If no rivers found, terminate if (count($rivers) == 0) { Kohana::$log->add(Log::INFO, __("No rivers found. Exiting...")); return; } // Get the owners for each of the rivers $river_owners = $this->_get_river_owners(array_keys($rivers)); // Expire rivers if (count($to_be_expired) > 0) { $this->_expire_rivers($to_be_expired); } // Switch on the expiry flag if (count($to_be_flagged) > 0) { DB::update('rivers')->set(array('expiry_candidate' => 1))->where('id', 'IN', $to_be_flagged)->execute(); } // Send out notifications Kohana::$log->add(Log::INFO, __("Sending out notifications")); foreach ($river_owners as $river_id => $owners) { $data = $rivers[$river_id]; // Mail subject $subject = __("Your :river_name river will shutdown in :days_to_expiry day(s)!", array(":river_name" => $data['river_name'], ":days_to_expiry" => $data['days_to_expiry'])); // Mail body - expiry warning is the default $mail_body = $warning_template->set(array('river_name' => $data['river_name'], 'days_to_expiry' => $data['days_to_expiry'], 'active_duration' => $settings['river_active_duration'], 'river_url' => $data['river_url'])); if ($data['days_to_expiry'] === 0) { $subject = __("Your :river_name has shutdown!", array(":river_name" => $data['river_name'])); // Expiry notice message $mail_body = $notice_template->set(array('river_name' => $data['river_name'], 'active_duration' => $settings['river_active_duration'], 'activation_url' => $data['river_url'])); } // Construct the mail body foreach ($owners as $owner) { $mail_body->recipient_name = $owner['name']; Swiftriver_Mail::send($owner['email'], $subject, $mail_body); } } Kohana::$log->add(Log::INFO, "Completed maintenance schedule"); }