summaryrefslogtreecommitdiffstats
path: root/application/controllers/user.php
diff options
context:
space:
mode:
Diffstat (limited to 'application/controllers/user.php')
-rw-r--r--application/controllers/user.php511
1 files changed, 511 insertions, 0 deletions
diff --git a/application/controllers/user.php b/application/controllers/user.php
new file mode 100644
index 000000000..b4e2613ac
--- /dev/null
+++ b/application/controllers/user.php
@@ -0,0 +1,511 @@
+<?php
+/*
+ * Copyright 2012-2013 Florian "Bluewind" Pritz <bluewind@server-speed.net>
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+class User extends MY_Controller {
+ protected $json_enabled_functions = array(
+ "create_apikey",
+ "apikeys",
+ );
+
+
+ function __construct()
+ {
+ parent::__construct();
+
+ $this->var->view_dir = "user/";
+ }
+
+ function index()
+ {
+ $this->data["username"] = $this->muser->get_username();
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'index', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ function test_login()
+ {
+ $username = $this->input->post('username');
+ $password = $this->input->post('password');
+
+ if ($this->muser->login($username, $password)) {
+ $this->output->set_status_header(204);
+ } else {
+ $this->output->set_status_header(401);
+ }
+ }
+
+ function login()
+ {
+ $this->muser->require_session();
+ $this->session->keep_flashdata("uri");
+
+ if ($this->input->post('process') !== false) {
+ $username = $this->input->post('username');
+ $password = $this->input->post('password');
+
+ $result = $this->muser->login($username, $password);
+
+ if ($result !== true) {
+ $this->data['login_error'] = true;
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'login', $this->data);
+ $this->load->view('footer', $this->data);
+ } else {
+ $uri = $this->session->flashdata("uri");
+ if ($uri) {
+ redirect($uri);
+ } else {
+ redirect("/");
+ }
+ }
+ } else {
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'login', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+ }
+
+ function create_apikey()
+ {
+ $this->muser->require_access();
+
+ $userid = $this->muser->get_userid();
+ $comment = $this->input->post("comment");
+ $comment = $comment === false ? "" : $comment;
+ $access_level = $this->input->post("access_level");
+
+ if ($access_level === false) {
+ $access_level = "apikey";
+ }
+
+ $valid_levels = $this->muser->get_access_levels();
+ if (array_search($access_level, $valid_levels) === false) {
+ show_error("Invalid access levels requested.");
+ }
+
+ if (strlen($comment) > 255) {
+ show_error("Comment may only be 255 chars long.");
+ }
+
+ $key = random_alphanum(32);
+
+ $this->db->query("
+ INSERT INTO `apikeys`
+ (`key`, `user`, `comment`, `access_level`)
+ VALUES (?, ?, ?, ?)
+ ", array($key, $userid, $comment, $access_level));
+
+ if (static_storage("response_type") == "json") {
+ return send_json_reply(array("new_key" => $key));
+ }
+
+ if (is_cli_client()) {
+ echo "$key\n";
+ } else {
+ redirect("user/apikeys");
+ }
+ }
+
+ function delete_apikey()
+ {
+ $this->muser->require_access();
+
+ $userid = $this->muser->get_userid();
+ $key = $this->input->post("key");
+
+ $this->db->query("
+ DELETE FROM `apikeys`
+ WHERE `user` = ?
+ AND `key` = ?
+ ", array($userid, $key));
+
+ redirect("user/apikeys");
+ }
+
+ function apikeys()
+ {
+ $this->muser->require_access();
+
+ $userid = $this->muser->get_userid();
+
+ $query = $this->db->query("
+ SELECT `key`, UNIX_TIMESTAMP(`created`) `created`, `comment`, `access_level`
+ FROM `apikeys`
+ WHERE `user` = ? order by created desc
+ ", array($userid))->result_array();
+
+ if (static_storage("response_type") == "json") {
+ return send_json_reply($query);
+ }
+
+ $this->data["query"] = $query;
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'apikeys', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ function create_invitation_key()
+ {
+ $this->duser->require_implemented("can_register_new_users");
+ $this->muser->require_access();
+
+ $userid = $this->muser->get_userid();
+
+ $query = $this->db->query("
+ SELECT count(*) count
+ FROM `actions`
+ WHERE `user` = ?
+ AND `action` = 'invitation'
+ ", array($userid))->row_array();
+
+ if ($query["count"] + 1 > 3) {
+ show_error("You can't create more invitation keys at this time.");
+ }
+
+ $key = random_alphanum(12, 16);
+
+ $this->db->query("
+ INSERT INTO `actions`
+ (`key`, `user`, `date`, `action`)
+ VALUES (?, ?, ?, 'invitation')
+ ", array($key, $userid, time()));
+
+ redirect("user/invite");
+ }
+
+ function invite()
+ {
+ $this->duser->require_implemented("can_register_new_users");
+ $this->muser->require_access();
+
+ $userid = $this->muser->get_userid();
+
+ $query = $this->db->query("
+ SELECT `key`, `date`
+ FROM `actions`
+ WHERE `user` = ?
+ AND `action` = 'invitation'
+ ", array($userid))->result_array();
+
+ $this->data["query"] = $query;
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'invite', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ function register()
+ {
+ $this->duser->require_implemented("can_register_new_users");
+ $key = $this->uri->segment(3);
+ $process = $this->input->post("process");
+ $values = array(
+ "username" => "",
+ "email" => ""
+ );
+ $error = array();
+
+ $query = $this->muser->get_action("invitation", $key);
+
+ $referrer = $query["user"];
+
+ if ($process !== false) {
+ $username = $this->input->post("username");
+ $email = $this->input->post("email");
+ $password = $this->input->post("password");
+ $password_confirm = $this->input->post("password_confirm");
+
+ if (!$username || strlen($username) > 32 || !preg_match("/^[a-z0-9]+$/", $username)) {
+ $error[]= "Invalid username (only up to 32 chars of a-z0-9 are allowed).";
+ } else {
+ if ($this->muser->username_exists($username)) {
+ $error[] = "Username already exists.";
+ }
+ }
+
+ $this->load->helper("email");
+ if (!valid_email($email)) {
+ $error[]= "Invalid email.";
+ }
+
+ if (!$password || $password != $password_confirm) {
+ $error[]= "No password or passwords don't match.";
+ }
+
+ if (empty($error)) {
+ $this->db->query("
+ INSERT INTO users
+ (`username`, `password`, `email`, `referrer`)
+ VALUES(?, ?, ?, ?)
+ ", array(
+ $username,
+ $this->muser->hash_password($password),
+ $email,
+ $referrer
+ ));
+ $this->db->query("
+ DELETE FROM actions
+ WHERE `key` = ?
+ ", array($key));
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'registered', $this->data);
+ $this->load->view('footer', $this->data);
+ return;
+ } else {
+ $values["username"] = $username;
+ $values["email"] = $email;
+ }
+ }
+
+ $this->data["key"] = $key;
+ $this->data["values"] = $values;
+ $this->data["error"] = $error;
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'register', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ // This routes the different steps of a password reset
+ function reset_password()
+ {
+ $this->duser->require_implemented("can_reset_password");
+ $key = $this->uri->segment(3);
+
+ if ($_SERVER["REQUEST_METHOD"] == "GET" && $key === false) {
+ return $this->_reset_password_username_form();
+ }
+
+ if ($key === false) {
+ return $this->_reset_password_send_mail();
+ }
+
+ if ($key !== false) {
+ return $this->_reset_password_form();
+ }
+ }
+
+ // This simply queries the username
+ function _reset_password_username_form()
+ {
+ $this->data['username'] = $this->muser->get_username();
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'reset_password_username_form', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ // This sends a mail to the user containing the reset link
+ function _reset_password_send_mail()
+ {
+ $key = random_alphanum(12, 16);
+ $username = $this->input->post("username");
+
+ if (!$this->muser->username_exists($username)) {
+ show_error("Invalid username");
+ }
+
+ $userinfo = $this->db->query("
+ SELECT id, email, username
+ FROM users
+ WHERE username = ?
+ ", array($username))->row_array();
+
+ $this->load->library("email");
+
+ $this->db->query("
+ INSERT INTO `actions`
+ (`key`, `user`, `date`, `action`)
+ VALUES (?, ?, ?, 'passwordreset')
+ ", array($key, $userinfo["id"], time()));
+
+ $admininfo = $this->db->query("
+ SELECT email
+ FROM users
+ WHERE referrer is null
+ ORDER BY id asc
+ LIMIT 1
+ ")->row_array();
+
+ $this->email->from($admininfo["email"]);
+ $this->email->to($userinfo["email"]);
+ $this->email->subject("FileBin password reset");
+ $this->email->message(""
+ ."Someone requested a password reset for the account '${userinfo["username"]}'\n"
+ ."from the IP address '${_SERVER["REMOTE_ADDR"]}'.\n"
+ ."\n"
+ ."Please follow this link to reset your password:\n"
+ .site_url("user/reset_password/$key")
+ );
+ $this->email->send();
+
+ // don't disclose full email addresses
+ $this->data["email_domain"] = substr($userinfo["email"], strpos($userinfo["email"], "@") + 1);
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'reset_password_link_sent', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ // This displays a form and handles the reset if the form has been filled out correctly
+ function _reset_password_form()
+ {
+ $process = $this->input->post("process");
+ $key = $this->uri->segment(3);
+ $error = array();
+
+ $query = $this->muser->get_action("passwordreset", $key);
+
+ $userid = $query["user"];
+
+ if ($process !== false) {
+ $password = $this->input->post("password");
+ $password_confirm = $this->input->post("password_confirm");
+
+ if (!$password || $password != $password_confirm) {
+ $error[]= "No password or passwords don't match.";
+ }
+
+ if (empty($error)) {
+ $this->db->query("
+ UPDATE users
+ SET `password` = ?
+ WHERE `id` = ?
+ ", array($this->muser->hash_password($password), $userid));
+ $this->db->query("
+ DELETE FROM actions
+ WHERE `key` = ?
+ ", array($key));
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'reset_password_success', $this->data);
+ $this->load->view('footer', $this->data);
+ return;
+ }
+ }
+
+ $this->data["key"] = $key;
+ $this->data["error"] = $error;
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'reset_password_form', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ function profile()
+ {
+ $this->muser->require_access();
+
+ if ($this->input->post("process") !== false) {
+ $this->_save_profile();
+ }
+
+ $this->data["profile_data"] = $this->muser->get_profile_data();
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'profile', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ private function _save_profile()
+ {
+ $this->muser->require_access();
+
+ /*
+ * Key = name of the form field
+ * Value = function that sanatizes the value and returns it
+ * TODO: some kind of error handling that doesn't loose correctly filled out fields
+ */
+ $value_processor = array();
+
+ $value_processor["upload_id_limits"] = function($value) {
+ $values = explode("-", $value);
+
+ if (!is_array($values) || count($values) != 2) {
+ show_error("Invalid upload id limit value");
+ }
+
+ $lower = intval($values[0]);
+ $upper = intval($values[1]);
+
+ if ($lower > $upper) {
+ show_error("lower limit > upper limit");
+ }
+
+ if ($lower < 3 || $upper > 64) {
+ show_error("upper or lower limit out of bounds (3-64)");
+ }
+
+ return $lower."-".$upper;
+ };
+
+ $data = array();
+ foreach (array_keys($value_processor) as $field) {
+ $value = $this->input->post($field);
+
+ if ($value !== false) {
+ $data[$field] = $value_processor[$field]($value);
+ }
+ }
+
+ if (!empty($data)) {
+ $this->muser->update_profile($data);
+ }
+
+ $this->data["alerts"][] = array(
+ "type" => "success",
+ "message" => "Changes saved",
+ );
+
+ return true;
+ }
+
+ function logout()
+ {
+ $this->muser->logout();
+ redirect('/');
+ }
+
+ function hash_password()
+ {
+ $process = $this->input->post("process");
+ $password = $this->input->post("password");
+ $password_confirm = $this->input->post("password_confirm");
+ $this->data["hash"] = false;
+ $this->data["password"] = $password;
+
+ if ($process !== false) {
+ if (!$password || $password != $password_confirm) {
+ $error[]= "No password or passwords don't match.";
+ } else {
+ $this->data["hash"] = $this->muser->hash_password($password);
+ }
+ }
+
+ $this->load->view('header', $this->data);
+ $this->load->view($this->var->view_dir.'hash_password', $this->data);
+ $this->load->view('footer', $this->data);
+ }
+
+ function cron()
+ {
+ if (!$this->input->is_cli_request()) return;
+
+ if ($this->config->item('actions_max_age') == 0) return;
+
+ $oldest_time = (time() - $this->config->item('actions_max_age'));
+
+ $this->db->query("
+ DELETE FROM actions
+ WHERE date < ?
+ ", array($oldest_time));
+ }
+}