Added user API key system

This commit is contained in:
Matthew Barbour 2020-06-16 19:03:03 -05:00 committed by Shish
parent ea34d9b756
commit 919a3039c4
6 changed files with 160 additions and 39 deletions

View file

@ -805,3 +805,18 @@ function human_filesize(int $bytes, $decimals = 2)
$factor = floor((strlen(strval($bytes)) - 1) / 3); $factor = floor((strlen(strval($bytes)) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @BYTE_DENOMINATIONS[$factor]; return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @BYTE_DENOMINATIONS[$factor];
} }
/*
* Generates a unique key for the website to prevent unauthorized access.
*/
function generate_key(int $length = 20)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters [rand(0, strlen($characters) - 1)];
}
return $randomString;
}

View file

@ -21,7 +21,7 @@ abstract class CronUploaderConfig
$config->set_default_int(self::LOG_LEVEL, SCORE_LOG_INFO); $config->set_default_int(self::LOG_LEVEL, SCORE_LOG_INFO);
$upload_key = $config->get_string(self::KEY, ""); $upload_key = $config->get_string(self::KEY, "");
if (empty($upload_key)) { if (empty($upload_key)) {
$upload_key = self::generate_key(); $upload_key = generate_key();
$config->set_string(self::KEY, $upload_key); $config->set_string(self::KEY, $upload_key);
} }
@ -67,21 +67,4 @@ abstract class CronUploaderConfig
global $config; global $config;
$config->set_string(self::DIR, $value); $config->set_string(self::DIR, $value);
} }
/*
* Generates a unique key for the website to prevent unauthorized access.
*/
private static function generate_key()
{
$length = 20;
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters [rand(0, strlen($characters) - 1)];
}
return $randomString;
}
} }

View file

@ -111,9 +111,9 @@ class SetupBlock extends Block
$this->body .= $content; $this->body .= $content;
$this->end_table_cell(); $this->end_table_cell();
} }
public function start_table_header_cell(int $colspan = 1) public function start_table_header_cell(int $colspan = 1, string $align = 'right')
{ {
$this->body .= "<th colspan='$colspan'>"; $this->body .= "<th colspan='$colspan' style='text-align: $align'>";
} }
public function end_table_header_cell() public function end_table_header_cell()
{ {
@ -126,23 +126,34 @@ class SetupBlock extends Block
$this->end_table_header_cell(); $this->end_table_header_cell();
} }
private function format_option(string $name, $html, ?string $label, bool $table_row) private function format_option(
{ string $name,
$html,
?string $label,
bool $table_row,
bool $label_row = false
) {
if ($table_row) { if ($table_row) {
$this->start_table_row(); $this->start_table_row();
} }
if ($table_row) { if ($table_row) {
$this->start_table_header_cell(); $this->start_table_header_cell($label_row ? 2 : 1, $label_row ? 'center' : 'right');
} }
if (!is_null($label)) { if (!is_null($label)) {
$this->body .= "<label for='{$name}'>{$label}</label>"; $this->body .= "<label for='{$name}'>{$label}</label>";
} }
if ($table_row) { if ($table_row) {
$this->end_table_header_cell(); $this->end_table_header_cell();
} }
if ($table_row && $label_row) {
$this->end_table_row();
$this->start_table_row();
}
if ($table_row) { if ($table_row) {
$this->start_table_cell(); $this->start_table_cell($label_row ? 2 : 1);
} }
$this->body .= $html; $this->body .= $html;
if ($table_row) { if ($table_row) {
@ -173,7 +184,7 @@ class SetupBlock extends Block
$html = "<textarea rows='$rows' id='$name' name='_config_$name'>$val</textarea>\n"; $html = "<textarea rows='$rows' id='$name' name='_config_$name'>$val</textarea>\n";
$html .= "<input type='hidden' name='_type_$name' value='string'>\n"; $html .= "<input type='hidden' name='_type_$name' value='string'>\n";
$this->format_option($name, $html, $label, $table_row); $this->format_option($name, $html, $label, $table_row, true);
} }
public function add_bool_option(string $name, string $label=null, bool $table_row = false) public function add_bool_option(string $name, string $label=null, bool $table_row = false)

View file

@ -276,12 +276,27 @@ class UserPage extends Extension
]; ];
$sb = new SetupBlock("User Options"); $sb = new SetupBlock("User Options");
$sb->add_bool_option("login_signup_enabled", "Allow new signups: "); $sb->start_table();
$sb->add_longtext_option("login_tac", "<br>Terms &amp; Conditions:<br>"); $sb->add_bool_option(UserConfig::ENABLE_API_KEYS, "Enable user API keys", true);
$sb->add_choice_option("avatar_host", $hosts, "<br>Avatars: "); $sb->add_bool_option("login_signup_enabled", "Allow new signups", true);
$sb->add_longtext_option("login_tac", "Terms &amp; Conditions", true);
$sb->add_choice_option(
"user_loginshowprofile",
[
"return to previous page" => 0, // 0 is default
"send to user profile" => 1],
"On log in/out",
true
);
$sb->add_choice_option("avatar_host", $hosts, "Avatars", true);
if ($config->get_string("avatar_host") == "gravatar") { if ($config->get_string("avatar_host") == "gravatar") {
$sb->add_label("<br>&nbsp;<br><b>Gravatar Options</b>"); $sb->start_table_row();
$sb->start_table_cell(2);
$sb->add_label("<div style='text-align: center'><b>Gravatar Options</b></div>", );
$sb->end_table_cell();
$sb->end_table_row();
$sb->add_choice_option( $sb->add_choice_option(
"avatar_gravatar_type", "avatar_gravatar_type",
[ [
@ -290,22 +305,19 @@ class UserPage extends Extension
'Monster ID'=>'monsterid', 'Monster ID'=>'monsterid',
'Identicon'=>'identicon' 'Identicon'=>'identicon'
], ],
"<br>Type: " "Type",
true
); );
$sb->add_choice_option( $sb->add_choice_option(
"avatar_gravatar_rating", "avatar_gravatar_rating",
['G'=>'g', 'PG'=>'pg', 'R'=>'r', 'X'=>'x'], ['G'=>'g', 'PG'=>'pg', 'R'=>'r', 'X'=>'x'],
"<br>Rating: " "Rating",
true
); );
$sb->end_table();
} }
$sb->add_choice_option(
"user_loginshowprofile",
[
"return to previous page" => 0, // 0 is default
"send to user profile" => 1],
"<br>When user logs in/out"
);
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }

View file

@ -21,7 +21,18 @@ class InitUserConfigEvent extends Event
class UserConfig extends Extension class UserConfig extends Extension
{ {
private const VERSION = "ext_user_config_version"; /** @var UserConfigTheme */
protected $theme;
public const VERSION = "ext_user_config_version";
public const ENABLE_API_KEYS = "ext_user_config_enable_api_keys";
public const API_KEY = "api_key";
public function onInitExt(InitExtEvent $event)
{
global $config;
$config->set_default_bool(self::ENABLE_API_KEYS, false);
}
public function onUserLogin(UserLoginEvent $event) public function onUserLogin(UserLoginEvent $event)
{ {
@ -49,6 +60,66 @@ class UserConfig extends Extension
} }
} }
public function onPageRequest(PageRequestEvent $event)
{
global $user, $database, $config, $page;
if ($config->get_bool(self::ENABLE_API_KEYS)) {
if (!empty($_GET["api_key"]) && $user->is_anonymous()) {
$user_id = $database->get_one(
"SELECT user_id FROM user_config WHERE value=:value AND name=:name",
["value" => $_GET["api_key"], "name" => self::API_KEY]
);
if (!empty($user_id)) {
$user = User::by_id($user_id);
if ($user !== null) {
send_event(new UserLoginEvent($user));
}
}
}
global $user_config;
if ($event->page_matches("user_admin")) {
if (!$user->check_auth_token()) {
return;
}
switch ($event->get_arg(0)) {
case "reset_api_key":
$user_config->set_string(self::API_KEY, "");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user"));
break;
}
}
}
}
public function onUserOptionsBuilding(UserOptionsBuildingEvent $event)
{
global $config, $user_config;
if ($config->get_bool(self::ENABLE_API_KEYS)) {
$key = $user_config->get_string(self::API_KEY, "");
if (empty($key)) {
$key = generate_key();
$user_config->set_string(self::API_KEY, $key);
}
$event->add_html($this->theme->get_user_options($key));
}
}
public function onSetupBuilding(SetupBuildingEvent $event)
{
$sb = new SetupBlock("User Options");
$sb->start_table();
$sb->end_table();
$event->panel->add_block($sb);
}
// This needs to happen before any other events, but after db upgrade // This needs to happen before any other events, but after db upgrade
public function get_priority(): int public function get_priority(): int

29
ext/user_config/theme.php Normal file
View file

@ -0,0 +1,29 @@
<?php declare(strict_types=1);
use function MicroHTML\BR;
use function MicroHTML\BUTTON;
use function MicroHTML\INPUT;
class UserConfigTheme extends Themelet
{
public function get_user_options(string $key): string
{
$html = "
<p>".make_form(make_link("user_admin/reset_api_key"))."
<table style='width: 300px;'>
<tbody>
<tr><th colspan='2'>API Key</th></tr>
<tr>
<td>
$key
</td>
</tbody>
<tfoot>
<tr><td><input type='submit' value='Reset Key'></td></tr>
</tfoot>
</table>
</form>
";
return $html;
}
}