diff options
-rw-r--r-- | application/config/migration.php | 2 | ||||
-rw-r--r-- | application/controllers/file.php | 10 | ||||
-rw-r--r-- | application/controllers/user.php | 65 | ||||
-rw-r--r-- | application/helpers/filebin_helper.php | 6 | ||||
-rw-r--r-- | application/libraries/Duser/Duser.php | 1 | ||||
-rw-r--r-- | application/migrations/009_add_apikeys.php | 24 | ||||
-rw-r--r-- | application/models/mfile.php | 2 | ||||
-rw-r--r-- | application/models/muser.php | 64 | ||||
-rw-r--r-- | application/views/file/client.php | 8 | ||||
-rw-r--r-- | application/views/file/upload_form.php | 2 | ||||
-rw-r--r-- | application/views/header.php | 4 | ||||
-rw-r--r-- | application/views/user/apikeys.php | 36 | ||||
-rw-r--r-- | application/views/user/nav.php | 1 |
13 files changed, 206 insertions, 19 deletions
diff --git a/application/config/migration.php b/application/config/migration.php index 943ff0880..5fef0ad40 100644 --- a/application/config/migration.php +++ b/application/config/migration.php @@ -21,7 +21,7 @@ $config['migration_enabled'] = true; | be upgraded / downgraded to. | */ -$config['migration_version'] = 8; +$config['migration_version'] = 9; /* diff --git a/application/controllers/file.php b/application/controllers/file.php index c133539f7..7629b809b 100644 --- a/application/controllers/file.php +++ b/application/controllers/file.php @@ -282,7 +282,7 @@ class File extends CI_Controller { "lexer" => $lexer )); $this->session->set_flashdata("uri", "file/claim_id"); - $this->muser->require_access(); + $this->muser->require_access("apikey"); } foreach ($ids as $id) { @@ -444,7 +444,7 @@ class File extends CI_Controller { function upload_history() { - $this->muser->require_access(); + $this->muser->require_access("apikey"); $user = $this->muser->get_userid(); @@ -523,7 +523,7 @@ class File extends CI_Controller { function do_delete() { - $this->muser->require_access(); + $this->muser->require_access("apikey"); $ids = $this->input->post("ids"); $errors = array(); @@ -563,7 +563,7 @@ class File extends CI_Controller { function delete() { - $this->muser->require_access(); + $this->muser->require_access("apikey"); if (!is_cli_client()) { echo "Not a listed cli client, please use the history to delete uploads.\n"; @@ -634,7 +634,7 @@ class File extends CI_Controller { { // desktop clients get a cookie to claim the ID later if (is_cli_client()) { - $this->muser->require_access(); + $this->muser->require_access("apikey"); } $ids = array(); diff --git a/application/controllers/user.php b/application/controllers/user.php index 21b58cf93..f1dbe5c31 100644 --- a/application/controllers/user.php +++ b/application/controllers/user.php @@ -84,6 +84,71 @@ class User extends CI_Controller { } } + function create_apikey() + { + $this->muser->require_access(); + + $userid = $this->muser->get_userid(); + $comment = $this->input->post("comment"); + + + if (strlen($comment) > 255 || !preg_match("/^[a-zA-Z0-9 -@,]*$/", $comment)) { + // display better error for + show_error("Comment invalid. Only 255 chars of a-zA-Z0-9, @, -, space and comma allowed"); + } + + $key = random_alphanum(32); + + $this->db->query(" + INSERT INTO `apikeys` + (`key`, `user`, `comment`) + VALUES (?, ?, ?) + ", array($key, $userid, $comment)); + + 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"); + + var_dump($userid, $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` + FROM `apikeys` + WHERE `user` = ? order by created desc + ", array($userid))->result_array(); + + $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"); diff --git a/application/helpers/filebin_helper.php b/application/helpers/filebin_helper.php index 88bb290c4..4af106a14 100644 --- a/application/helpers/filebin_helper.php +++ b/application/helpers/filebin_helper.php @@ -323,6 +323,12 @@ function auth_driver_function_implemented($function) return $result[$function]; } +function user_logged_in() +{ + $CI =& get_instance(); + return $CI->muser->logged_in(); +} + function send_json_reply($array) { $CI =& get_instance(); diff --git a/application/libraries/Duser/Duser.php b/application/libraries/Duser/Duser.php index 19d1bfa09..733616b40 100644 --- a/application/libraries/Duser/Duser.php +++ b/application/libraries/Duser/Duser.php @@ -78,6 +78,7 @@ class Duser extends CI_Driver_Library { $CI->session->set_userdata('logged_in', true); $CI->session->set_userdata('username', $login_info["username"]); $CI->session->set_userdata('userid', $login_info["userid"]); + $CI->session->set_userdata('access_level', 'full'); return true; } diff --git a/application/migrations/009_add_apikeys.php b/application/migrations/009_add_apikeys.php new file mode 100644 index 000000000..8e88260a8 --- /dev/null +++ b/application/migrations/009_add_apikeys.php @@ -0,0 +1,24 @@ +<?php +defined('BASEPATH') OR exit('No direct script access allowed'); + +class Migration_Add_apikeys extends CI_Migration { + + public function up() + { + $this->db->query(" + CREATE TABLE `apikeys` ( + `key` varchar(64) COLLATE utf8_bin NOT NULL, + `user` int(8) unsigned NOT NULL, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `comment` varchar(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, + PRIMARY KEY (`key`), + KEY `user` (`user`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin + "); + } + + public function down() + { + $this->dbforge->drop_table('apikeys'); + } +} diff --git a/application/models/mfile.php b/application/models/mfile.php index a7bab5d51..aaeebccaf 100644 --- a/application/models/mfile.php +++ b/application/models/mfile.php @@ -310,7 +310,7 @@ class Mfile extends CI_Model { function delete_id($id) { - $this->muser->require_access(); + $this->muser->require_access("apikey"); $filedata = $this->get_filedata($id); $userid = $this->muser->get_userid(); diff --git a/application/models/muser.php b/application/models/muser.php index 639b5ee3a..843b7cad6 100644 --- a/application/models/muser.php +++ b/application/models/muser.php @@ -67,6 +67,14 @@ class Muser extends CI_Model { { $username = $this->input->post("username"); $password = $this->input->post("password"); + $apikey = $this->input->post("apikey"); + + if ($apikey !== false) { + if ($this->apilogin(trim($apikey))) { + return true; + } + show_error("API key login failed", 401); + } // prefer post parameters if either (username or password) is set if ($username === false && $password === false) { @@ -76,18 +84,36 @@ class Muser extends CI_Model { } } - if ($username !== false && $password !== false) { + if ($apikey === false && $username !== false && $password !== false) { if ($this->login($username, $password)) { return true; } else { - // TODO: better message - $this->output->set_status_header(401); - echo "login failed.\n"; - exit; + show_error("Login failed", 401); } } } + function apilogin($apikey) + { + $this->require_session(); + + $query = $this->db->query(" + SELECT a.user userid + FROM apikeys a + WHERE a.key = ? + ", array($apikey))->row_array(); + + if (isset($query["userid"])) { + $this->session->set_userdata('logged_in', true); + $this->session->set_userdata('username', ""); + $this->session->set_userdata('userid', $query["userid"]); + $this->session->set_userdata('access_level', 'apikey'); + return true; + } + + return false; + } + function logout() { $this->require_session(); @@ -124,16 +150,36 @@ class Muser extends CI_Model { return $this->duser->get_email($userid); } - function require_access() + private function check_access_level($wanted_level) { - if ($this->logged_in()) { + $session_level = $this->session->userdata("access_level"); + + // last level has the most access + $levels = array("apikey", "full"); + + $wanted = array_search($wanted_level, $levels); + $have = array_search($session_level, $levels); + + if ($wanted === false || $have === false) { + show_error("Failed to determine access level"); + } + + if ($have >= $wanted) { return true; } - // handle cli clients + show_error("Access denied", 403); + } + + function require_access($wanted_level = "full") + { + if ($this->logged_in()) { + return $this->check_access_level($wanted_level); + } + if (is_cli_client()) { if ($this->login_cli_client()) { - return true; + return $this->check_access_level($wanted_level); } echo "FileBin requires you to have an account, please go to the homepage for more information.\n"; diff --git a/application/views/file/client.php b/application/views/file/client.php index 19e6a01fb..5e141f141 100644 --- a/application/views/file/client.php +++ b/application/views/file/client.php @@ -13,6 +13,14 @@ machine <?php echo $domain; ?> login my_username password my_secret_password </pre> <p> + If you are using fb-client ≥1.2 you can + <a href="<?php echo site_url("user/apikeys"); ?>">create an API key</a>, + save it in <code>~/.config/fb-client/apikey</code> and remove + your password from <code>.netrc</code>. Please refer to <code>man + 1 fb</code> for further details. +</p> + +<p> If you are using fb-client ≥1.1 you can use <code>~/.config/fb-client/config</code> to upload to a different pastebin URL (https or you own installation). Please refer to diff --git a/application/views/file/upload_form.php b/application/views/file/upload_form.php index 99c1d9e42..841ac3746 100644 --- a/application/views/file/upload_form.php +++ b/application/views/file/upload_form.php @@ -1,4 +1,4 @@ -<?php if (isset($username) && $username) { ?> +<?php if (user_logged_in()) { ?> <div class="well"> <div class="row-fluid"> <div class="span12 text-upload-form"> diff --git a/application/views/header.php b/application/views/header.php index e85463735..ba6d6ae9d 100644 --- a/application/views/header.php +++ b/application/views/header.php @@ -45,7 +45,7 @@ if (is_cli_client() && !isset($force_full_html)) { </a> <?php if(!isset($GLOBALS["is_error_page"])) { ?> <ul class="nav pull-right"> - <?php if(isset($username) && $username) { ?> + <?php if(user_logged_in()) { ?> <li><a href="<?php echo site_url("/user/logout"); ?>">Logout</a></li> <?php } else { ?> <li class="dropdown"> @@ -65,7 +65,7 @@ if (is_cli_client() && !isset($force_full_html)) { </ul> <?php }; ?> <ul class="nav"> - <?php if(isset($username) && $username) { ?> + <?php if(user_logged_in()) { ?> <li><a href="<?php echo site_url("file/index") ?>"><i class="icon-pencil icon-white"></i> New</a></li> <li><a href="<?php echo site_url("file/upload_history") ?>"><i class="icon-book icon-white"></i> History</a></li> <li class="dropdown"> diff --git a/application/views/user/apikeys.php b/application/views/user/apikeys.php new file mode 100644 index 000000000..14d829ffa --- /dev/null +++ b/application/views/user/apikeys.php @@ -0,0 +1,36 @@ +<h2>API keys</h2> +<table class="table table-striped"> + <thead> + <tr> + <th>#</th> + <th>Key</th> + <th style="width: 30%;">Comment</th> + <th>Created on</th> + <th></th> + </tr> + </thead> + <tbody> + <?php $i = 1; ?> + <?php foreach($query as $key => $item): ?> + <tr> + <td><?php echo $i++; ?></td> + <td><?php echo $item["key"]; ?></td> + <td><?php echo $item["comment"]; ?></td> + <td><?php echo date("Y/m/d H:i", $item["created"]); ?></td> + <td> + <?php echo form_open("user/delete_apikey", array("style" => "margin-bottom: 0")); ?> + <?php echo form_hidden("key", $item["key"]); ?> + <button class="btn btn-danger btn-mini" type="submit">Delete</input> + </form> + </td> + </tr> + <?php endforeach; ?> + </tbody> +</table> + +<p> + <?php echo form_open('user/create_apikey', array("class" => "form-horizontal")); ?> + <input type="text" name="comment" placeholder="Comment" /> + <input class="btn btn-primary" type="submit" value="Create a new key" name="process" /> + </form> +</p> diff --git a/application/views/user/nav.php b/application/views/user/nav.php index 26898fde8..90f76e05e 100644 --- a/application/views/user/nav.php +++ b/application/views/user/nav.php @@ -3,6 +3,7 @@ <?php } ?> <li><a href="<?php echo site_url("user/profile") ?>"><i class="icon-user icon-black"></i> Profile</a></li> +<li><a href="<?php echo site_url("user/apikeys") ?>"><i class="icon-tags icon-black"></i> API keys</a></li> <?php if(auth_driver_function_implemented("can_reset_password")) { ?> <li><a href="<?php echo site_url("user/reset_password") ?>"><i class="icon-lock icon-black"></i> Change password</a></li> |