190 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php declare(strict_types=1);
 | 
						|
 | 
						|
/** @var Config */
 | 
						|
global $user_config;
 | 
						|
 | 
						|
 | 
						|
// The user object doesn't exist until after database setup operations and the first wave of InitExtEvents,
 | 
						|
// so we can't reliably access this data until then. This event is triggered by the system after all of that is done.
 | 
						|
class InitUserConfigEvent extends Event
 | 
						|
{
 | 
						|
    public User $user;
 | 
						|
    public Config $user_config;
 | 
						|
 | 
						|
    public function __construct(User $user, Config $user_config)
 | 
						|
    {
 | 
						|
        parent::__construct();
 | 
						|
        $this->user = $user;
 | 
						|
        $this->user_config = $user_config;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
class UserOptionsBuildingEvent extends Event
 | 
						|
{
 | 
						|
    protected SetupTheme $theme;
 | 
						|
    public SetupPanel $panel;
 | 
						|
    public User $user;
 | 
						|
 | 
						|
 | 
						|
    public function __construct(User $user, SetupPanel $panel)
 | 
						|
    {
 | 
						|
        parent::__construct();
 | 
						|
        $this->user = $user;
 | 
						|
        $this->panel = $panel;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class UserConfig extends Extension
 | 
						|
{
 | 
						|
    /** @var UserConfigTheme */
 | 
						|
    protected ?Themelet $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)
 | 
						|
    {
 | 
						|
        global $user_config;
 | 
						|
 | 
						|
        $user_config = self::get_for_user($event->user->id);
 | 
						|
    }
 | 
						|
 | 
						|
    public static function get_for_user(int $id): BaseConfig
 | 
						|
    {
 | 
						|
        global $database;
 | 
						|
 | 
						|
        $user = User::by_id($id);
 | 
						|
 | 
						|
        $user_config = new DatabaseConfig($database, "user_config", "user_id", "$id");
 | 
						|
        send_event(new InitUserConfigEvent($user, $user_config));
 | 
						|
        return $user_config;
 | 
						|
    }
 | 
						|
 | 
						|
    public function onDatabaseUpgrade(DatabaseUpgradeEvent $event): void
 | 
						|
    {
 | 
						|
        global $database;
 | 
						|
 | 
						|
        if ($this->get_version(self::VERSION) < 1) {
 | 
						|
            $database->create_table("user_config", "
 | 
						|
                user_id INTEGER NOT NULL,
 | 
						|
                name VARCHAR(128) NOT NULL,
 | 
						|
                value TEXT,
 | 
						|
                PRIMARY KEY (user_id, name),
 | 
						|
			    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
 | 
						|
		    ");
 | 
						|
            $database->execute("CREATE INDEX user_config_user_id_idx ON user_config(user_id)");
 | 
						|
 | 
						|
            $this->set_version(self::VERSION, 1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
 | 
						|
    {
 | 
						|
        global $user;
 | 
						|
        if ($event->parent==="user" && !$user->is_anonymous()) {
 | 
						|
            $event->add_nav_link("user_config", new Link('user_config'), "User Options", false, 40);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public function onPageRequest(PageRequestEvent $event)
 | 
						|
    {
 | 
						|
        global $user, $database, $config, $page, $user_config;
 | 
						|
 | 
						|
        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));
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            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;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if ($event->page_matches("user_config")) {
 | 
						|
            if (!$user->can(Permissions::CHANGE_USER_SETTING)) {
 | 
						|
                $this->theme->display_permission_denied();
 | 
						|
            } else {
 | 
						|
                if ($event->count_args() == 0) {
 | 
						|
                    $display_user = ($event->count_args() == 0) ? $user : User::by_name($event->get_arg(0));
 | 
						|
 | 
						|
                    if ($user->id!=$display_user->id && !$user->can(Permissions::CHANGE_OTHER_USER_SETTING)) {
 | 
						|
                        $this->theme->display_permission_denied();
 | 
						|
                        return;
 | 
						|
                    }
 | 
						|
 | 
						|
                    $uobe = new UserOptionsBuildingEvent($display_user, new SetupPanel($user_config));
 | 
						|
                    send_event($uobe);
 | 
						|
 | 
						|
                    $this->theme->display_user_config_page($page, $uobe->user, $uobe->panel);
 | 
						|
                } elseif ($event->get_arg(0) == "save" && $user->check_auth_token()) {
 | 
						|
                    $input = validate_input([
 | 
						|
                        'id' => 'user_id,exists'
 | 
						|
                    ]);
 | 
						|
                    $duser = User::by_id($input['id']);
 | 
						|
 | 
						|
                    if ($user->id!=$duser->id && !$user->can(Permissions::CHANGE_OTHER_USER_SETTING)) {
 | 
						|
                        $this->theme->display_permission_denied();
 | 
						|
                        return;
 | 
						|
                    }
 | 
						|
 | 
						|
                    $target_config = UserConfig::get_for_user($duser->id);
 | 
						|
                    send_event(new ConfigSaveEvent($target_config));
 | 
						|
                    $target_config->save();
 | 
						|
                    $page->flash("Config saved");
 | 
						|
                    $page->set_mode(PageMode::REDIRECT);
 | 
						|
                    $page->set_redirect(make_link("user_config"));
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public function onUserOperationsBuilding(UserOperationsBuildingEvent $event)
 | 
						|
    {
 | 
						|
        global $config;
 | 
						|
 | 
						|
        if ($config->get_bool(self::ENABLE_API_KEYS)) {
 | 
						|
            $key = $event->user_config->get_string(self::API_KEY, "");
 | 
						|
            if (empty($key)) {
 | 
						|
                $key = generate_key();
 | 
						|
                $event->user_config->set_string(self::API_KEY, $key);
 | 
						|
            }
 | 
						|
            $event->add_html($this->theme->get_user_operations($key));
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // This needs to happen before any other events, but after db upgrade
 | 
						|
    public function get_priority(): int
 | 
						|
    {
 | 
						|
        return 6;
 | 
						|
    }
 | 
						|
}
 |