Sequenzia/app/controllers/UserController.php
2014-01-26 15:43:12 -05:00

497 lines
17 KiB
PHP
Executable File

<?php
class UserController extends ApplicationController
{
protected function filters()
{
return [
'before' => [
'blocked_only' => ['only' => ['authenticate', 'update', 'edit', 'modifyBlacklist']],
'janitor_only' => ['only' => ['invites']],
'mod_only' => ['only' => ['block', 'unblock', 'showBlockedUsers']],
'post_member_only' => ['only' => ['setAvatar']],
'no_anonymous' => ['only' => ['changePassword', 'changeEmail']],
'set_settings_layout' => ['only' => ['changePassword', 'changeEmail', 'edit']]
]
];
}
protected function set_settings_layout()
{
$this->setLayout('settings');
}
public function autocompleteName()
{
$keyword = $this->params()->term;
if (strlen($keyword) >= 2) {
$this->users = User::where('name LIKE ?', '%' . $keyword . '%')->pluck('name');
if (!$this->users)
$this->users = [];
} else
$this->users = [];
$this->respondTo([
'json' => function() {
$this->render(['json' => ($this->users)]);
}
]);
}
# FIXME: this method is crap and only function as temporary workaround
# until I convert the controllers to resourceful version which is
# planned for 3.2 branch (at least 3.2.1).
public function removeAvatar()
{
# When removing other user's avatar, ensure current user is mod or higher.
if (current_user()->id != $this->params()->id and !current_user()->is_mod_or_higher()) {
$this->access_denied();
return;
}
$this->user = User::find($this->params()->id);
$this->user->avatar_post_id = null;
if ($this->user->save()) {
$this->notice('Avatar removed');
} else {
$this->notice('Failed removing avatar');
}
$this->redirectTo(['#show', 'id' => $this->params()->id]);
}
public function changePassword()
{
$this->title = 'Change Password';
$this->setLayout('settings');
}
public function changeEmail()
{
$this->title = 'Change Email';
current_user()->current_email = current_user()->email;
$this->user = current_user();
$this->setLayout('settings');
}
public function show()
{
if ($this->params()->name) {
$this->user = User::where(['name' => $this->params()->name])->first();
} else {
$this->user = User::find($this->params()->id);
}
if (!$this->user) {
$this->redirectTo("/404");
} else {
if ($this->user->id == current_user()->id)
$this->set_title('My profile');
else
$this->set_title($this->user->name . "'s profile");
}
if (current_user()->is_mod_or_higher()) {
# RP: Missing feature.
// $this->user_ips = $this->user->user_logs->order('created_at DESC').pluck('ip_addr').uniq
$this->user_ips = array_unique(UserLog::where(['user_id' => $this->user->id])->order('created_at DESC')->take()->getAttributes('ip_addr'));
}
$tag_types = CONFIG()->tag_types;
foreach (array_keys($tag_types) as $k) {
if (!preg_match('/^[A-Z]/', $k) || $k == 'General' || $k == 'Faults')
unset($tag_types[$k]);
}
$this->tag_types = $tag_types;
$this->respondTo(array(
'html'
));
}
public function invites()
{
if ($this->request()->isPost()) {
if ($this->params()->member) {
try {
current_user()->invite($this->params()->member['name'], $this->params()->member['level']);
$this->notice("User was invited");
} catch (Rails\ActiveRecord\Exception\RecordNotFoundException $e) {
$this->notice("Account not found");
} catch (User_NoInvites $e) {
$this->notice("You have no invites for use");
} catch (User_HasNegativeRecord $e) {
$this->notice("This use has a negative record and must be invited by an admin");
}
}
$this->redirectTo('#invites');
} else {
$this->invited_users = User::where("invited_by = ?", current_user()->id)->order("lower(name)")->take();
}
}
public function home()
{
$this->set_title('My Account');
}
public function index()
{
$this->set_title('Users');
$this->users = User::generate_sql($this->params()->all())->paginate($this->page_number(), 20);
$this->respond_to_list("users");
}
public function authenticate()
{
$this->_save_cookies(current_user());
$path = $this->params()->url ?: '#home';
$this->respond_to_success("You are now logged in", $path);
}
public function check()
{
if (!$this->request()->isPost()) {
$this->redirectTo('root');
return;
}
$user = User::where(['name' => $this->params()->username])->first();
$ret['exists'] = false;
$ret['name'] = $this->params()->username;
if (!$user) {
$ret['response'] = "unknown-user";
$this->respond_to_success("User does not exist", array(), array('api' => $ret));
return;
}
# Return some basic information about the user even if the password isn't given, for
# UI cosmetics.
$ret['exists'] = true;
$ret['id'] = $user->id;
$ret['name'] = $user->name;
$ret['no_email'] = !((bool)$user->email);
$pass = $this->params()->password ?: "";
$user = User::authenticate($this->params()->username, $pass);
if (!$user) {
$ret['response'] = "wrong-password";
$this->respond_to_success("Wrong password", array(), array('api' => $ret));
return;
}
$ret['pass_hash'] = $user->password_hash;
$ret['user_info'] = $user->user_info_cookie();
$ret['response'] = 'success';
$this->respond_to_success("Successful", array(), array('api' => $ret));
}
public function login()
{
$this->set_title('Login');
}
public function create()
{
$user = User::create($this->params()->user);
if ($user->errors()->blank()) {
$this->_save_cookies($user);
$ret = [
'exists' => false,
'name' => $user->name,
'id' => $user->id,
'pass_hash' => $user->password_hash,
'user_info' => $user->user_info_cookie()
];
$this->respond_to_success("New account created", '#home', ['api' => array_merge(['response' => "success"], $ret)]);
} else {
$error = $user->errors()->fullMessages(", ");
$this->respond_to_success("Error: " . $error, '#signup', ['api' => ['response' => "error", 'errors' => $user->errors()->fullMessages()]]);
}
}
public function signup()
{
$this->set_title('Signup');
$this->user = new User();
}
public function logout()
{
$this->set_title('Logout');
$this->session()->delete('user_id');
$this->cookies()->delete('login');
$this->cookies()->delete('pass_hash');
$dest = $this->params()->from ?: '#home';
$this->respond_to_success("You are now logged out", $dest);
}
public function update()
{
if ($this->params()->commit == "Cancel") {
$this->redirectTo('#home');
return;
}
if (current_user()->updateAttributes($this->params()->user)) {
$this->respond_to_success("Account settings saved", '#edit');
} else {
if ($this->params()->render and $this->params()->render['view']) {
$this->render(['action' => $this->_get_view_name_for_edit($this->params()->render['view'])]);
} else {
$this->respond_to_error(current_user(), '#edit');
}
}
}
public function modifyBlacklist()
{
$added_tags = $this->params()->add ?: [];
$removed_tags = $this->params()->remove ?: [];
$tags = current_user()->blacklisted_tags_array();
foreach ($added_tags as $tag) {
if (!in_array($tag, $tags))
$tags[] = $tag;
}
$tags = array_diff($tags, $removed_tags);
if (current_user()->user_blacklisted_tag->updateAttribute('tags', implode("\n", $tags))) {
$this->respond_to_success("Tag blacklist updated", '#home', ['api' => ['result' => current_user()->blacklisted_tags_array()]]);
} else {
$this->respond_to_error(current_user(), '#edit');
}
}
public function removeFromBlacklist()
{
}
public function edit()
{
$this->set_title('Edit Account');
$this->user = current_user();
}
public function resetPassword()
{
$this->set_title('Reset Password');
if ($this->request()->isPost()) {
$this->user = User::where(['name' => $this->params()->user['name']])->first();
if (!$this->user) {
$this->respond_to_error("That account does not exist", '#reset_password', ['api' => ['result' => "unknown-user"]]);
return;
}
if (!$this->user->email) {
$this->respond_to_error("You never supplied an email address, therefore you cannot have your password automatically reset",
'#login', ['api' => ['result' => "no-email"]]);
return;
}
if ($this->user->email != $this->params()->user['email']) {
$this->respond_to_error("That is not the email address you supplied",
'#login', ['api' => ['result' => "wrong-email"]]);
return;
}
# iTODO:
try {
// User.transaction do
# If the email is invalid, abort the password reset
$new_password = $this->user->reset_password();
UserMailer::mail('new_password', [$this->user, $new_password])->deliver();
$this->respond_to_success("Password reset. Check your email in a few minutes.",
'#login', ['api' => ['result' => "success"]]);
return;
// end
} catch (Exception $e) { // rescue Net::SMTPSyntaxError, Net::SMTPFatalError
$this->respond_to_success("Your email address was invalid",
'#login', ['api' => ['result' => "invalid-email"]]);
return;
}
} else {
$this->user = new User();
if ($this->params()->format and $this->params()->format != 'html')
$this->redirectTo('root');
}
}
public function block()
{
$this->user = User::find($this->params()->id);
if ($this->request()->isPost()) {
if ($this->user->is_mod_or_higher()) {
$this->notice("You can not ban other moderators or administrators");
$this->redirectTo(['#block', 'id' => $this->params()->id]);
return;
}
!is_array($this->params()->ban) && $this->params()->ban = [];
$attrs = array_merge($this->params()->ban, ['banned_by' => current_user()->id, 'user_id' => $this->params()->id]);
Ban::create($attrs);
$this->redirectTo('#show_blocked_users');
} else {
$this->ban = new Ban(['user_id' => $this->user->id, 'duration' => "1"]);
}
}
public function unblock()
{
foreach (array_keys($this->params()->user) as $user_id)
Ban::destroyAll("user_id = ?", $user_id);
$this->redirectTo('#show_blocked_users');
}
public function showBlockedUsers()
{
$this->set_title('Blocked Users');
#$this->users = User.find(:all, 'select' => "users.*", 'joins' => "JOIN bans ON bans.user_id = users.id", 'conditions' => ["bans.banned_by = ?", current_user()->id])
$this->users = User::order("expires_at ASC")->select("users.*")->joins("JOIN bans ON bans.user_id = users.id")->take();
$this->ip_bans = IpBans::all();
}
/**
* MyImouto:
* MyImouto:
* Moebooru doesn't use email activation,
* so these 2 following methods aren't used.
* Also, User::confirmation_hash() method is missing.
*/
// public function resendConfirmation()
// {
// if (!CONFIG()->enable_account_email_activation) {
// $this->access_denied();
// return;
// }
// if ($this->request()->isPost()) {
// $user = User::find_by_email($this->params()->email);
// if (!$user) {
// $this->notice("No account exists with that email");
// $this->redirectTo('#home')
// return;
// }
// if ($user->is_blocked_or_higher()) {
// $this->notice("Your account is already activated");
// $this->redirectTo('#home');
// return;
// }
// UserMailer::deliver_confirmation_email($user);
// $this->notice("Confirmation email sent");
// $this->redirectTo('#home');
// }
// }
// public function activateUser()
// {
// if (!CONFIG()->enable_account_email_activation) {
// $this->access_denied();
// return;
// }
// $this->notice("Invalid confirmation code");
// $users = User::find_all(['conditions' => ["level = ?", CONFIG()->user_levels["Unactivated"]]]);
// foreach ($users as $user) {
// if (User::confirmation_hash($user->name) == $this->params()->hash) {
// $user->updateAttribute('level', CONFIG()->starting_level);
// $this->notice("Account has been activated");
// break;
// }
// }
// $this->redirectTo('#home');
// }
public function setAvatar()
{
$this->user = current_user();
if ($this->params()->user_id) {
$this->user = User::find($this->params()->user_id);
if (!$this->user)
$this->respond_to_error("Not found", '#index', ['status' => 404]);
}
if (!$this->user->is_anonymous() && !current_user()->has_permission($this->user, 'id')) {
$this->access_denied();
return;
}
if ($this->request()->isPost()) {
if ($this->user->set_avatar($this->params()->all())) {
$this->redirectTo(['#show', 'id' => $this->user->id]);
} else {
$this->respond_to_error($this->user, '#home');
}
}
if (!$this->user->is_anonymous() && $this->params()->id == $this->user->avatar_post_id) {
$this->old = $this->params();
}
$this->params = $this->params();
$this->post = Post::find($this->params()->id);
}
public function error()
{
$report = $this->params()->report;
$file = Rails::root() . "/log/user_errors.log";
if (!is_file($file)) {
$fh = fopen($file, 'a');
fclose($fh);
}
file_put_contents($file, $report . "\n\n\n-------------------------------------------\n\n\n", FILE_APPEND);
$this->render(array('json' => array('success' => true)));
}
protected function init()
{
$this->helper('Post', 'TagSubscription', 'Avatar');
}
protected function _save_cookies($user)
{
$this->cookies()->login = ['value' => $user->name, 'expires' => strtotime('+1 year')];
$this->cookies()->pass_hash = ['value' => $user->password_hash, 'expires' => strtotime('+1 year')];
$this->cookies()->user_id = ['value' => $user->id, 'expires' => strtotime('+1 year')];
$this->session()->user_id = $user->id;
}
protected function _get_view_name_for_edit($param)
{
switch ($param) {
case 'change_email':
return 'change_email';
case 'change_password':
return 'change_password';
default:
return 'edit';
}
}
}