initial
This commit is contained in:
		
						commit
						dc9c7e5ded
					
				
							
								
								
									
										22
									
								
								autologin.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								autologin.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "usermgr.php";
 | 
			
		||||
 | 
			
		||||
// attempt to auto-login
 | 
			
		||||
$autologin_user_data = [];
 | 
			
		||||
$auto_logged_in = false;
 | 
			
		||||
if ((session_status() === PHP_SESSION_ACTIVE) && isset($_SESSION["nickname"])) {
 | 
			
		||||
    $autologin_user_data = get_user($_SESSION["nickname"]);
 | 
			
		||||
    $auto_logged_in = count($autologin_user_data) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_autologin_state() : bool {
 | 
			
		||||
    global $auto_logged_in;
 | 
			
		||||
    return $auto_logged_in;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_autologin_user_data() : array {
 | 
			
		||||
    global $autologin_user_data;
 | 
			
		||||
    return $autologin_user_data;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								common_func.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								common_func.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
function explode_list(string $str) : array {
 | 
			
		||||
    return explode(",", str_replace(" ", "", $str));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function alter_array_contents(array &$a, $add, $remove) {
 | 
			
		||||
    if (($add !== null) && !array_search($add, $a)) { // if user was not assigned to the corresponding group
 | 
			
		||||
        $a[] = $add;
 | 
			
		||||
    }
 | 
			
		||||
    if (($remove !== null) && (($i = array_search($remove, $a)) !== false)) { // only perform deleting if user is assigned to the passed group
 | 
			
		||||
        array_splice($a, $i, 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  "require": {
 | 
			
		||||
    "rakibtg/sleekdb": "2.15",
 | 
			
		||||
    "ext-http": "*",
 | 
			
		||||
    "ext-json": "*"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								default_frame.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								default_frame.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "autologin.php";
 | 
			
		||||
 | 
			
		||||
$user_data = get_autologin_user_data();
 | 
			
		||||
if (!get_autologin_state()) {
 | 
			
		||||
    exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>SpreadQuiz</title>
 | 
			
		||||
    <script src="js/spreadquiz.js"></script>
 | 
			
		||||
    <script src="js/req.js"></script>
 | 
			
		||||
    <script src="js/o.js"></script>
 | 
			
		||||
    <script src="js/default_frame.js"></script>
 | 
			
		||||
    <link rel="stylesheet" href="style/spreadquiz.css">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<section id="game_list_panel">
 | 
			
		||||
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
    list_available_games();
 | 
			
		||||
</script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								examples/minta_quiz_táblázat.xlsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								examples/minta_quiz_táblázat.xlsx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										66
									
								
								game_manager_frame.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								game_manager_frame.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "autologin.php";
 | 
			
		||||
 | 
			
		||||
$user_data = get_autologin_user_data();
 | 
			
		||||
if (!get_autologin_state() || (($user_data["privilege"] !== PRIVILEGE_CREATOR) && ($user_data["privilege"] !== PRIVILEGE_QUIZMASTER))) {
 | 
			
		||||
    exit(); // this page is only available for quizmasters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>SpreadQuiz</title>
 | 
			
		||||
    <script src="js/req.js"></script>
 | 
			
		||||
    <script src="js/spreadquiz.js"></script>
 | 
			
		||||
    <script src="js/o.js"></script>
 | 
			
		||||
    <script src="js/hintbox.js"></script>
 | 
			
		||||
    <script src="js/usermgr.js"></script>
 | 
			
		||||
    <script src="js/gamemgr.js"></script>
 | 
			
		||||
    <link rel="stylesheet" href="style/spreadquiz.css"/>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<section id="table_section">
 | 
			
		||||
    <table class="management">
 | 
			
		||||
        <thead>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <th></th>
 | 
			
		||||
            <th>Név</th>
 | 
			
		||||
            <th>Leírás</th>
 | 
			
		||||
            <th>Tulajdonos</th>
 | 
			
		||||
        </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tbody id="game_manager_table">
 | 
			
		||||
        </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
</section>
 | 
			
		||||
<section>
 | 
			
		||||
    <input type="button" value="Új játék" onclick="create_edit_game();">
 | 
			
		||||
    <input type="button" value="Játék(ok) törlése" onclick="delete_games()">
 | 
			
		||||
</section>
 | 
			
		||||
<section class="window" shown="false" id="game_editor_window">
 | 
			
		||||
    <section class="window-inner">
 | 
			
		||||
        <section style="text-align: right">
 | 
			
		||||
            <span>Név: <input type="text" id="game_name"></span><br>
 | 
			
		||||
            <span>Leírás: <input type="text" id="game_description"></span><br>
 | 
			
		||||
            <span>Tulajdonos: <input type="text" id="game_owner" readonly></span><br>
 | 
			
		||||
            <span>Szerkesztők: <input type="text" id="game_contributors"></span><br>
 | 
			
		||||
            <span>Kérdés-fájl: <input type="button" id="download_challenges_btn" value="Letöltés CSV-ként" shown="false" onclick="download_challenges()">
 | 
			
		||||
                <input type="button" value="Új feltöltése" id="show_game_file_upload" onclick="show_hide_gamefile_upload(true)">
 | 
			
		||||
                <input type="file" id="game_file" shown="false">
 | 
			
		||||
                <input type="button" value="Mégse" id="cancel_game_file_upload" shown="false" onclick="show_hide_gamefile_upload(false);"></span><br>
 | 
			
		||||
            <span>Csoportok:   <input type="text" id="game_groups"></span><br>
 | 
			
		||||
        </section>
 | 
			
		||||
        <span><input type="button" value="" id="game_editor_submit_btn"><input type="button" value="Mégse" onclick="hide('game_editor_window')"></span>
 | 
			
		||||
    </section>
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
    list_all_games();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										186
									
								
								gamemgr.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								gamemgr.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,186 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "common_func.php";
 | 
			
		||||
 | 
			
		||||
$gamedb = new \SleekDB\Store(GAMEDB, DATADIR, ["timeout" => false]);
 | 
			
		||||
 | 
			
		||||
const DEFAULT_GAME_PROPERTIES = [
 | 
			
		||||
    "forward_only" => false, // player may traverse back and forth between challenges
 | 
			
		||||
    "time_limit" => -1, // no time limit; otherwise, this field indicates time limit in seconds
 | 
			
		||||
    "repeatable" => false // this test can be taken multiple times
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
function create_game(string $name, string $owner, string $description = "", array $properties = DEFAULT_GAME_PROPERTIES, array $contributors = [], array $challenges = []): bool
 | 
			
		||||
{
 | 
			
		||||
    global $testdb;
 | 
			
		||||
    $game_data = [
 | 
			
		||||
        "name" => $name,
 | 
			
		||||
        "owner" => $owner,
 | 
			
		||||
        "contributors" => $contributors,
 | 
			
		||||
        "description" => $description,
 | 
			
		||||
        "game_file_present" => false,
 | 
			
		||||
        "properties" => $properties,
 | 
			
		||||
        "groups" => [],
 | 
			
		||||
    ];
 | 
			
		||||
    $game_data = $testdb->insert($game_data);
 | 
			
		||||
 | 
			
		||||
    // prepare game context
 | 
			
		||||
    $id = $game_data["_id"];
 | 
			
		||||
    $current_game_media_dir = GAMEMEDIA_DIR . DIRECTORY_SEPARATOR . $id;
 | 
			
		||||
    mkdir($current_game_media_dir);
 | 
			
		||||
    save_challenges($id, []);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_game(string $gameid): array
 | 
			
		||||
{
 | 
			
		||||
    global $testdb;
 | 
			
		||||
    return $testdb->findById($gameid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_game(array $game_data)
 | 
			
		||||
{
 | 
			
		||||
    global $testdb;
 | 
			
		||||
    $testdb->update($game_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function delete_game(string $gameid)
 | 
			
		||||
{
 | 
			
		||||
    global $testdb;
 | 
			
		||||
    $game_data = get_game($gameid);
 | 
			
		||||
    if (count($game_data) != 0) {
 | 
			
		||||
        foreach ($game_data["groups"] as $groupid) {
 | 
			
		||||
            change_group_game_assignments($groupid, null, $gameid);
 | 
			
		||||
        }
 | 
			
		||||
        $testdb->deleteById($gameid);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function change_game_group_assignments(string $gid, $groupname_add, $groupname_remove)
 | 
			
		||||
{
 | 
			
		||||
    $game_data = get_game($gid);
 | 
			
		||||
    if (count($game_data) != 0) {
 | 
			
		||||
        alter_array_contents($game_data["groups"], $groupname_add, $groupname_remove);
 | 
			
		||||
        update_game($game_data); // update user
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_all_games()
 | 
			
		||||
{
 | 
			
		||||
    global $testdb;
 | 
			
		||||
    return $testdb->findAll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_all_game_data_by_contributor_nickname(string $nickname): array
 | 
			
		||||
{
 | 
			
		||||
    global $testdb;
 | 
			
		||||
    $game_headers = [];
 | 
			
		||||
    if ($nickname !== "*") {
 | 
			
		||||
        $game_data_array = $testdb->findBy([["owner", "=", $nickname], "OR", ["contributors", "CONTAINS", $nickname]]);
 | 
			
		||||
    } else {
 | 
			
		||||
        $game_data_array = $testdb->findAll();
 | 
			
		||||
    }
 | 
			
		||||
    foreach ($game_data_array as $game_data) {
 | 
			
		||||
        $game_headers[] = $game_data;
 | 
			
		||||
    }
 | 
			
		||||
    return $game_headers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function import_challenges_from_csv(string $csv_path, string $gameid)
 | 
			
		||||
{
 | 
			
		||||
    $game_data = get_game($gameid);
 | 
			
		||||
    if (count($game_data) === []) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $challenges = [];
 | 
			
		||||
 | 
			
		||||
    // load filled CSV file
 | 
			
		||||
    $f = fopen($csv_path, "r");
 | 
			
		||||
    if (!$f) { // failed to open file
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    while ($csvline = fgetcsv($f)) {
 | 
			
		||||
        if (count($csvline) >= 3) {
 | 
			
		||||
            $ch = [
 | 
			
		||||
                "question" => $csvline[0],
 | 
			
		||||
                "image_url" => $csvline[1],
 | 
			
		||||
                "correct_answer" => $csvline[2],
 | 
			
		||||
                "answers" => array_filter(array_slice($csvline, 2), function ($v) {
 | 
			
		||||
                    return trim($v) !== "";
 | 
			
		||||
                })
 | 
			
		||||
            ];
 | 
			
		||||
            $challenges[] = $ch;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    fclose($f);
 | 
			
		||||
 | 
			
		||||
    // save challenges
 | 
			
		||||
    save_challenges($gameid, $challenges);
 | 
			
		||||
 | 
			
		||||
    // update game with game file present
 | 
			
		||||
    $game_data["game_file_present"] = true;
 | 
			
		||||
    update_game($game_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function is_user_contributor_to_game(string $gameid, string $nickname): bool
 | 
			
		||||
{
 | 
			
		||||
    $game_data = get_game($gameid);
 | 
			
		||||
    if (count($game_data) === 0) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return in_array($nickname, $game_data["contributors"]) || ($game_data["owner"] === $nickname);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function is_user_owner_of_the_game(string $gameid, string $nickname): bool
 | 
			
		||||
{
 | 
			
		||||
    $game_data = get_game($gameid);
 | 
			
		||||
    if (count($game_data) === 0) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return $game_data["owner"] === $nickname;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function save_challenges(string $gameid, array $challenges)
 | 
			
		||||
{
 | 
			
		||||
    file_put_contents(get_game_file_by_gameid($gameid), json_encode($challenges));     // store challenges in JSON-format
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function load_challenges(string $gameid)
 | 
			
		||||
{
 | 
			
		||||
    return json_decode(file_get_contents(get_game_file_by_gameid($gameid)), true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function export_challenges_to_csv($f, string $gameid)
 | 
			
		||||
{
 | 
			
		||||
    $game_data = get_game($gameid);
 | 
			
		||||
    if ((count($game_data) === []) || (!$game_data["game_file_present"])) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // load challenges
 | 
			
		||||
    $challenges = load_challenges($gameid);
 | 
			
		||||
 | 
			
		||||
    // populate CSV file
 | 
			
		||||
    foreach ($challenges as $ch) {
 | 
			
		||||
        $csvline = [
 | 
			
		||||
            $ch["question"],
 | 
			
		||||
            $ch["image_url"],
 | 
			
		||||
        ];
 | 
			
		||||
        $csvline = array_merge($csvline, $ch["answers"]);
 | 
			
		||||
        fputcsv($f, $csvline);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_contributors(string $gameid): array
 | 
			
		||||
{
 | 
			
		||||
    $game_data = get_game($gameid);
 | 
			
		||||
    return $game_data["contributors"];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_game_file_by_gameid(string $gameid)
 | 
			
		||||
{
 | 
			
		||||
    return GAMEMEDIA_DIR . DIRECTORY_SEPARATOR . $gameid . DIRECTORY_SEPARATOR . GAME_FILE;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								globals.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								globals.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "vendor/autoload.php";
 | 
			
		||||
 | 
			
		||||
const DATADIR = "appdata";
 | 
			
		||||
const GAMEMEDIA_DIR = DATADIR . DIRECTORY_SEPARATOR . "game_media";
 | 
			
		||||
const GAME_FILE = "challenges.json";
 | 
			
		||||
const USERDB = "users";
 | 
			
		||||
const GROUPDB = "groups";
 | 
			
		||||
const GAMEDB = "games";
 | 
			
		||||
const TESTDB = "tests";
 | 
			
		||||
const INSTALL_INDICATOR = "INSTALLED";
 | 
			
		||||
const QUIZMASTER_NICKNAME = "quizmaster";
 | 
			
		||||
const LOGIN_URL = "login.php";
 | 
			
		||||
const MAIN_URL = "main.php";
 | 
			
		||||
const SESSION_NAME = "spreadquiz_sid";
 | 
			
		||||
 | 
			
		||||
session_name(SESSION_NAME);
 | 
			
		||||
 | 
			
		||||
// autoload session
 | 
			
		||||
if ((session_status() === PHP_SESSION_NONE) && isset($_COOKIE[SESSION_NAME])) {
 | 
			
		||||
    session_start();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------
 | 
			
		||||
 | 
			
		||||
// initialize data directory
 | 
			
		||||
function init_datadir() {
 | 
			
		||||
    if (!file_exists(DATADIR)) {
 | 
			
		||||
        mkdir(DATADIR);
 | 
			
		||||
        mkdir(GAMEMEDIA_DIR);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								group_manager_frame.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								group_manager_frame.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "autologin.php";
 | 
			
		||||
 | 
			
		||||
$user_data = get_autologin_user_data();
 | 
			
		||||
if (!get_autologin_state() || ($user_data["privilege"] !== PRIVILEGE_QUIZMASTER)) {
 | 
			
		||||
    exit(); // this page is only available for quizmasters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>SpreadQuiz</title>
 | 
			
		||||
    <script src="js/req.js"></script>
 | 
			
		||||
    <script src="js/spreadquiz.js"></script>
 | 
			
		||||
    <script src="js/o.js"></script>
 | 
			
		||||
    <script src="js/groupmgr.js"></script>
 | 
			
		||||
    <link rel="stylesheet" href="style/spreadquiz.css"/>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<section id="table_section">
 | 
			
		||||
    <table class="management">
 | 
			
		||||
        <thead>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <th></th>
 | 
			
		||||
            <th>Név</th>
 | 
			
		||||
            <th>Leírás</th>
 | 
			
		||||
            <th>Tulajdonos</th>
 | 
			
		||||
        </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tbody id="group_manager_table">
 | 
			
		||||
        </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
</section>
 | 
			
		||||
<section>
 | 
			
		||||
    <input type="button" value="Új csoport" onclick="create_edit_group();">
 | 
			
		||||
    <input type="button" value="Csoport(ok) törlése" onclick="delete_groups();">
 | 
			
		||||
</section>
 | 
			
		||||
<section class="window" shown="false" id="group_editor_window">
 | 
			
		||||
    <section class="window-inner">
 | 
			
		||||
        <section style="text-align: right">
 | 
			
		||||
            <span>Név: <input type="text" id="groupname"></span><br>
 | 
			
		||||
            <span>Leírás: <input type="text" id="group_description"></span><br>
 | 
			
		||||
            <span>Tulajdonos: <input type="text" id="group_owner" readonly></span><br>
 | 
			
		||||
            <span>Szerkesztők: <input type="text" id="group_editors"></span><br>
 | 
			
		||||
            <span>Tagok: <textarea id="group_members" readonly></textarea></span>
 | 
			
		||||
        </section>
 | 
			
		||||
        <span><input type="button" value="" id="group_editor_submit_btn"><input type="button" value="Mégse" onclick="hide('group_editor_window')"></span>
 | 
			
		||||
    </section>
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
    list_all_groups();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										192
									
								
								groupmgr.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								groupmgr.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,192 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "common_func.php";
 | 
			
		||||
require_once "usermgr.php";
 | 
			
		||||
 | 
			
		||||
$groupdb = new \SleekDB\Store(GROUPDB, DATADIR, ["timeout" => false]);
 | 
			
		||||
 | 
			
		||||
function create_group(string $groupname, string $owner, string $description = "", array $editors = []): bool
 | 
			
		||||
{
 | 
			
		||||
    global $groupdb;
 | 
			
		||||
 | 
			
		||||
    // test name uniqueness
 | 
			
		||||
    $unique = clear_unique_in_siblings($groupname);
 | 
			
		||||
 | 
			
		||||
    // initialize group data
 | 
			
		||||
    $group_data = [
 | 
			
		||||
        "groupname" => $groupname,
 | 
			
		||||
        "unique" => $unique,
 | 
			
		||||
        "owner" => $owner,
 | 
			
		||||
        "description" => $description,
 | 
			
		||||
        "editors" => $editors,
 | 
			
		||||
        "users" => [],
 | 
			
		||||
        "games" => []
 | 
			
		||||
    ];
 | 
			
		||||
    $groupdb->insert($group_data); // insert group
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_group(string $groupid): array
 | 
			
		||||
{
 | 
			
		||||
    global $groupdb;
 | 
			
		||||
    return $groupdb->findById($groupid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_group(array $group_data)
 | 
			
		||||
{
 | 
			
		||||
    global $groupdb;
 | 
			
		||||
    $groupdb->update($group_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function delete_group(string $groupid)
 | 
			
		||||
{
 | 
			
		||||
    global $groupdb;
 | 
			
		||||
    $group_data = get_group($groupid);
 | 
			
		||||
    if (count($group_data) !== 0) {
 | 
			
		||||
        foreach ($group_data["users"] as $nickname) { // remove all references to this group
 | 
			
		||||
            change_user_group_assignments($nickname, null, $groupid);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    $groupdb->deleteById($groupid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_all_groups()
 | 
			
		||||
{
 | 
			
		||||
    global $groupdb;
 | 
			
		||||
    return $groupdb->findAll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function change_group_user_assignments(string $groupid, $nickname_add, $nickname_remove)
 | 
			
		||||
{
 | 
			
		||||
    $group_data = get_group($groupid);
 | 
			
		||||
    if (count($group_data) != 0) {
 | 
			
		||||
        // --------- UPDATE group assignments (DEV ONLY!)------
 | 
			
		||||
 | 
			
		||||
        $group_data["editors"] = $group_data["editors"] ?: [];
 | 
			
		||||
 | 
			
		||||
        // ---------
 | 
			
		||||
 | 
			
		||||
        alter_array_contents($group_data["users"], $nickname_add, $nickname_remove); // add to local storage
 | 
			
		||||
        alter_array_contents($group_data["editors"], null, $nickname_remove); // removed users must be excluded from the editors' list as well
 | 
			
		||||
        update_group($group_data); // update user
 | 
			
		||||
        if ($nickname_add !== null) {
 | 
			
		||||
            change_user_group_assignments($nickname_add, $groupid, null); // add to user's storage remote
 | 
			
		||||
        }
 | 
			
		||||
        if ($nickname_remove !== null) {
 | 
			
		||||
            change_user_group_assignments($nickname_remove, null, $groupid); // remove from user's storage
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function change_group_game_assignments(string $groupid, $gameid_add, $gameid_remove)
 | 
			
		||||
{
 | 
			
		||||
    $group_data = get_group($groupid);
 | 
			
		||||
    if (count($group_data) != 0) {
 | 
			
		||||
        alter_array_contents($group_data["games"], $gameid_add, $gameid_remove); // add to local storage
 | 
			
		||||
        update_group($group_data); // update user
 | 
			
		||||
        if ($gameid_add !== null) {
 | 
			
		||||
            change_game_group_assignments($gameid_add, $groupid, null); // add to user's storage remote
 | 
			
		||||
        }
 | 
			
		||||
        if ($gameid_remove !== null) {
 | 
			
		||||
            change_game_group_assignments($gameid_remove, null, $groupid); // remove from user's storage
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function search_groups(string $needle): array
 | 
			
		||||
{
 | 
			
		||||
    if (strlen($needle) < 3) {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    global $groupdb;
 | 
			
		||||
    $parts = explode("#", $needle, 2);
 | 
			
		||||
    $groupname = $parts[0];
 | 
			
		||||
    $group_data_array = [];
 | 
			
		||||
    if (count($parts) === 1) {
 | 
			
		||||
        $group_data_array = $groupdb->findBy(["groupname", "LIKE", "%$groupname%"]);
 | 
			
		||||
    } else if (count($parts) > 1) {
 | 
			
		||||
        $groupid = $parts[1];
 | 
			
		||||
        $group_data_array = $groupdb->findBy([["groupname", "LIKE", "%$groupname%"], "AND", ["_id", "LIKE", "%$groupid%"]]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $results = [];
 | 
			
		||||
    foreach ($group_data_array as $group_data) {
 | 
			
		||||
        $results[] = [
 | 
			
		||||
            "groupname" => $group_data["groupname"],
 | 
			
		||||
            "_id" => $group_data["_id"],
 | 
			
		||||
            "unique" => $group_data["unique"]
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
    return $results;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function clear_unique_in_siblings($groupname): bool
 | 
			
		||||
{
 | 
			
		||||
    // make test on name uniqueness
 | 
			
		||||
    global $groupdb;
 | 
			
		||||
    $twins = $groupdb->findBy(["groupname", "=", "$groupname"]);
 | 
			
		||||
    $unique = count($twins) == 0;
 | 
			
		||||
    if (count($twins) === 1) { // if fails, then also indicate in the original group that its name is no longer unique
 | 
			
		||||
        $twins[0]["unique"] = false;
 | 
			
		||||
        update_group($twins[0]);
 | 
			
		||||
    }
 | 
			
		||||
    return $unique;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_groupids_by_compounds(array $compounds): array
 | 
			
		||||
{
 | 
			
		||||
    global $groupdb;
 | 
			
		||||
    $groupids = [];
 | 
			
		||||
    foreach ($compounds as $compound) {
 | 
			
		||||
        if (trim($compound) === "") { // skip empty entries
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // fetch the group
 | 
			
		||||
        $parts = explode("#", $compound);
 | 
			
		||||
        $group_data = [];
 | 
			
		||||
        if (count($parts) === 1) {
 | 
			
		||||
            $fetch_cmd = ["groupname", "=", $parts[0]];
 | 
			
		||||
            $group_data = $groupdb->findBy($fetch_cmd);
 | 
			
		||||
            if (count($group_data) == 1) { // too many hits
 | 
			
		||||
                $group_data = $group_data[0];
 | 
			
		||||
            } else {
 | 
			
		||||
                $group_data = [];
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            $group_data = $groupdb->findById($parts[1]);
 | 
			
		||||
        }
 | 
			
		||||
        if ($group_data !== []) {
 | 
			
		||||
            $groupids[] = $group_data["_id"];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return $groupids;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function is_user_editor_to_group(string $groupid, string $nickname): bool
 | 
			
		||||
{
 | 
			
		||||
    $group_data = get_group($groupid);
 | 
			
		||||
    if (count($group_data) === 0) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return in_array($nickname, $group_data["editors"]) || ($group_data["owner"] === $nickname);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_group_unique_name(string $groupid): string
 | 
			
		||||
{
 | 
			
		||||
    $group_data = get_group($groupid);
 | 
			
		||||
    if (count($group_data) !== 0) {
 | 
			
		||||
        return $group_data["groupname"] . (!$group_data["unique"] ? "#" . $groupid : "");
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function resolve_groupids(array &$groups): void
 | 
			
		||||
{
 | 
			
		||||
    for ($i = 0; $i < count($groups); $i++) {
 | 
			
		||||
        $groups[$i] = get_group_unique_name($groups[$i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								index.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								index.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="hu">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>SpreadQuiz</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <?="asd" ?>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										24
									
								
								install.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								install.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
 | 
			
		||||
if (file_exists(INSTALL_INDICATOR)) {
 | 
			
		||||
    echo "SpreadQuiz already installed!";
 | 
			
		||||
    exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
init_datadir(); // create data directory
 | 
			
		||||
 | 
			
		||||
// auto-create databases
 | 
			
		||||
require_once "usermgr.php";
 | 
			
		||||
require_once "groupmgr.php";
 | 
			
		||||
require_once "gamemgr.php";
 | 
			
		||||
 | 
			
		||||
// create "quizmaster" (admin) user
 | 
			
		||||
$pw = uniqid();
 | 
			
		||||
add_user(QUIZMASTER_NICKNAME, $pw, "");
 | 
			
		||||
change_privilege_level(QUIZMASTER_NICKNAME, PRIVILEGE_QUIZMASTER);
 | 
			
		||||
echo "Quizmaster account: quizmaster, $pw\n";
 | 
			
		||||
 | 
			
		||||
// deploy install indicator
 | 
			
		||||
touch(INSTALL_INDICATOR);
 | 
			
		||||
							
								
								
									
										324
									
								
								interface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								interface.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,324 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
 | 
			
		||||
if (!file_exists(INSTALL_INDICATOR)) {
 | 
			
		||||
    exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (!isset($_REQUEST["action"])) {
 | 
			
		||||
    exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
require_once "common_func.php";
 | 
			
		||||
 | 
			
		||||
// load databases only if something meaningful have arrived
 | 
			
		||||
require_once "usermgr.php";
 | 
			
		||||
require_once "groupmgr.php";
 | 
			
		||||
require_once "gamemgr.php";
 | 
			
		||||
 | 
			
		||||
$action = $_REQUEST["action"];
 | 
			
		||||
 | 
			
		||||
$result = "";
 | 
			
		||||
 | 
			
		||||
// no-login accessible actions
 | 
			
		||||
switch ($action) {
 | 
			
		||||
    case "login":
 | 
			
		||||
        {
 | 
			
		||||
            $nickname = $_REQUEST["nickname"];
 | 
			
		||||
            $password = $_REQUEST["password"];
 | 
			
		||||
            if (check_user_credentials($nickname, $password)) {
 | 
			
		||||
                session_start();
 | 
			
		||||
                $_SESSION["nickname"] = $nickname;
 | 
			
		||||
                $result = "OK";
 | 
			
		||||
            } else {
 | 
			
		||||
                $result = "FAIL";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// exit script if there's no live session or nickname is missing or the referenced user is non-existent
 | 
			
		||||
if ((session_status() != PHP_SESSION_ACTIVE) || (!isset($_SESSION["nickname"])) || (count(get_user($_SESSION["nickname"])) == 0)) {
 | 
			
		||||
    goto print_result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$user_data = get_user($_SESSION["nickname"]);
 | 
			
		||||
$nickname = $user_data["nickname"];
 | 
			
		||||
$privilege = $user_data["privilege"];
 | 
			
		||||
 | 
			
		||||
// login-requiring actions
 | 
			
		||||
switch ($action) {
 | 
			
		||||
    case "logout":
 | 
			
		||||
        {
 | 
			
		||||
            $_SESSION = []; // clean up session data
 | 
			
		||||
            setcookie(SESSION_NAME, "", -1); // invalidate cookie
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "get_user_info":
 | 
			
		||||
        {
 | 
			
		||||
            $user_data_filtered = $user_data;
 | 
			
		||||
            unset($user_data_filtered["password"]);
 | 
			
		||||
            $result = json_encode($user_data_filtered);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "get_available_games":
 | 
			
		||||
        {
 | 
			
		||||
            $games_by_groups = [];
 | 
			
		||||
            $groupids = $user_data["groups"];
 | 
			
		||||
            foreach ($groupids as $groupid) {
 | 
			
		||||
                $group_data = get_group($groupid);
 | 
			
		||||
                $game_collection = [
 | 
			
		||||
                    "groupname" => $group_data["groupname"],
 | 
			
		||||
                    "description" => $group_data["description"],
 | 
			
		||||
                    "games" => []
 | 
			
		||||
                ];
 | 
			
		||||
                $gameids = $group_data["games"];
 | 
			
		||||
                foreach ($gameids as $gameid) {
 | 
			
		||||
                    $game = get_game($gameid);
 | 
			
		||||
                    $game_collection["games"][] = $game;
 | 
			
		||||
                }
 | 
			
		||||
                $games_by_groups[] = $game_collection;
 | 
			
		||||
            }
 | 
			
		||||
            $result = json_encode($games_by_groups);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// creator or quizmaster actions
 | 
			
		||||
if (($privilege !== PRIVILEGE_CREATOR) && ($privilege !== PRIVILEGE_QUIZMASTER)) {
 | 
			
		||||
    goto print_result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
switch ($action) {
 | 
			
		||||
    case "create_game":
 | 
			
		||||
    case "update_game":
 | 
			
		||||
        {
 | 
			
		||||
            $update = $action === "update_game";
 | 
			
		||||
            $data = json_decode($_REQUEST["data"], true) ?: [];
 | 
			
		||||
            if (($data === []) || (trim($data["name"] ?: "") === "")) { // no further processing
 | 
			
		||||
                goto print_result; // ~exit...
 | 
			
		||||
            }
 | 
			
		||||
            $gameid = $data["_id"];
 | 
			
		||||
            $name = $data["name"];
 | 
			
		||||
            $description = $data["description"];
 | 
			
		||||
            $contributors = explode_list($data["contributors"] ?: "");
 | 
			
		||||
            $owner = $update ? trim($data["owner"] ?: $nickname) : $nickname;
 | 
			
		||||
            $groups = explode_list($data["groups"] ?: "");
 | 
			
		||||
 | 
			
		||||
            $groupids = get_groupids_by_compounds($groups); // convert group compounds to _ids
 | 
			
		||||
 | 
			
		||||
            // remove group ID's this user cannot edit
 | 
			
		||||
            $groupids_with_editor_access = [];
 | 
			
		||||
            foreach ($groupids as $groupid) {
 | 
			
		||||
                if (is_user_editor_to_group($groupid, $nickname)) {
 | 
			
		||||
                    $groupids_with_editor_access[] = $groupid;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $groupids_with_editor_access = $groupid;
 | 
			
		||||
 | 
			
		||||
            if (!$update) {
 | 
			
		||||
                create_game($name, $owner, $description);
 | 
			
		||||
            } else if (is_user_contributor_to_game($gameid, $nickname)) {
 | 
			
		||||
                $game_data = get_game($gameid);
 | 
			
		||||
                if (count($game_data) !== 0) {
 | 
			
		||||
                    // group management
 | 
			
		||||
                    $old_groupids = $game_data["groups"]; // retain old groupids
 | 
			
		||||
                    $new_groupids = $groupids; // get new groupids
 | 
			
		||||
                    $groupids_add = array_diff($new_groupids, $old_groupids); // groups this user needs to be added to
 | 
			
		||||
                    $groupids_remove = array_diff($old_groupids, $new_groupids); // groups this user need to be removed from
 | 
			
		||||
                    foreach ($groupids_add as $groupid) { // execute insertion and removal
 | 
			
		||||
                        change_group_game_assignments($groupid, $gameid, null);
 | 
			
		||||
                    }
 | 
			
		||||
                    foreach ($groupids_remove as $groupid) {
 | 
			
		||||
                        change_group_game_assignments($groupid, null, $gameid);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // re-fetch game data
 | 
			
		||||
                    $game_data = get_game($gameid);
 | 
			
		||||
 | 
			
		||||
                    // update game header data
 | 
			
		||||
                    $game_data["name"] = $name;
 | 
			
		||||
                    $game_data["description"] = $description;
 | 
			
		||||
                    if (($game_data["owner"] === $nickname) || ($privilege === PRIVILEGE_QUIZMASTER)) {
 | 
			
		||||
                        $game_data["owner"] = $owner;
 | 
			
		||||
                    }
 | 
			
		||||
                    $game_data["contributors"] = array_intersect($contributors, get_all_nicknames());
 | 
			
		||||
                    update_game($game_data);
 | 
			
		||||
 | 
			
		||||
                    // update game file if supplied
 | 
			
		||||
                    if (isset($_FILES["game_file"])) {
 | 
			
		||||
                        import_challenges_from_csv($_FILES["game_file"]["tmp_name"], $data["_id"]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "get_all_game_headers":
 | 
			
		||||
        {
 | 
			
		||||
            $requester_nickname = ($privilege === PRIVILEGE_QUIZMASTER) ? "*" : $nickname; // "*" means every game
 | 
			
		||||
            $game_headers = get_all_game_data_by_contributor_nickname($requester_nickname);
 | 
			
		||||
            foreach ($game_headers as &$game_header) {
 | 
			
		||||
                resolve_groupids($game_header["groups"]);
 | 
			
		||||
            }
 | 
			
		||||
            $result = json_encode($game_headers);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "delete_games":
 | 
			
		||||
        {
 | 
			
		||||
            $gameids = explode_list(trim($_REQUEST["ids"] ?: ""));
 | 
			
		||||
            foreach ($gameids as $gameid) {
 | 
			
		||||
                if (($gameid !== "") && (is_user_owner_of_the_game($gameid, $nickname))) { // only the owner may delete a game
 | 
			
		||||
                    delete_game($gameid);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "export_game_file_csv":
 | 
			
		||||
        {
 | 
			
		||||
            $gameid = trim($_REQUEST["gameid"] ?: "");
 | 
			
		||||
            if (($gameid !== "") && is_user_contributor_to_game($gameid, $nickname)) {
 | 
			
		||||
                $f = tmpfile();
 | 
			
		||||
                header("Content-Type: text/csv");
 | 
			
		||||
                header("Content-Disposition: attachment; filename=\"challenges_$gameid.csv\"\r\n");
 | 
			
		||||
                export_challenges_to_csv($f, $gameid);
 | 
			
		||||
                fseek($f, 0);
 | 
			
		||||
                fpassthru($f);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// quizmaster actions
 | 
			
		||||
if ($privilege !== PRIVILEGE_QUIZMASTER) {
 | 
			
		||||
    goto print_result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
switch ($action) {
 | 
			
		||||
    case "create_group":
 | 
			
		||||
    case "update_group":
 | 
			
		||||
        {
 | 
			
		||||
            $update = $action === "update_group";
 | 
			
		||||
            $groupname = trim($_REQUEST["groupname"] ?: "");
 | 
			
		||||
            $description = trim($_REQUEST["description"] ?: "");
 | 
			
		||||
            $editors = explode_list(trim($_REQUEST["editors"] ?: ""));
 | 
			
		||||
            $owner = (!$update) ? $user_data["nickname"] : trim($_REQUEST["owner"]);
 | 
			
		||||
            if ($owner === "") {
 | 
			
		||||
                $owner = $user_data["nickname"];
 | 
			
		||||
            }
 | 
			
		||||
            if ($groupname != "") {
 | 
			
		||||
                switch ($action) {
 | 
			
		||||
                    case "create_group":
 | 
			
		||||
                        create_group($groupname, $owner, $description, $editors);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case "update_group":
 | 
			
		||||
                        {
 | 
			
		||||
                            $gid = $_REQUEST["id"];
 | 
			
		||||
                            $group = get_group($gid);
 | 
			
		||||
                            if (count($group) !== 0) {
 | 
			
		||||
                                $group["unique"] = clear_unique_in_siblings($groupname); // manage unique flag in case of renaming
 | 
			
		||||
                                $group["groupname"] = $groupname;
 | 
			
		||||
                                $group["description"] = $description;
 | 
			
		||||
                                $group["editors"] = array_intersect($editors, $group["users"]); // a user cannot be an editor if not part of the group
 | 
			
		||||
                                $group["owner"] = $owner;
 | 
			
		||||
                                update_group($group);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "delete_groups":
 | 
			
		||||
        {
 | 
			
		||||
            $groups = explode_list($_REQUEST["ids"] ?: "");
 | 
			
		||||
            foreach ($groups as $g) {
 | 
			
		||||
                delete_group($g);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "get_all_groups":
 | 
			
		||||
        $result = json_encode(get_all_groups());
 | 
			
		||||
        break;
 | 
			
		||||
    case "search_groups":
 | 
			
		||||
        {
 | 
			
		||||
            $needle = $_REQUEST["needle"] ?: "";
 | 
			
		||||
            $result = json_encode(search_groups($needle));
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "create_user":
 | 
			
		||||
    case "update_user":
 | 
			
		||||
        {
 | 
			
		||||
            $update = $action === "update_user";
 | 
			
		||||
            $target_nickname = trim($_REQUEST["nickname"] ?: "");
 | 
			
		||||
            $password = trim($_REQUEST["password"] ?: "");
 | 
			
		||||
            $groups = explode_list($_REQUEST["groups"] ?: "");
 | 
			
		||||
            $realname = trim($_REQUEST["realname"] ?: "");
 | 
			
		||||
            $privilege = trim($_REQUEST["privilege"] ?: PRIVILEGE_PLAYER);
 | 
			
		||||
 | 
			
		||||
            $groupids = get_groupids_by_compounds($groups); // convert group compounds to _ids
 | 
			
		||||
 | 
			
		||||
            if (($target_nickname !== "")) {
 | 
			
		||||
                if ((!$update) && ($password !== "")) { // CREATE
 | 
			
		||||
                    add_user($target_nickname, $password, $realname, $groupids, $privilege);
 | 
			
		||||
                } else if ($update) { // UPDATE
 | 
			
		||||
                    $user_data = get_user($target_nickname); // load user data
 | 
			
		||||
 | 
			
		||||
                    // group management
 | 
			
		||||
                    $old_groupids = $user_data["groups"]; // retain old groupids
 | 
			
		||||
                    $new_groupids = $groupids; // get new groupids
 | 
			
		||||
                    $groupids_add = array_diff($new_groupids, $old_groupids); // groups this user needs to be added to
 | 
			
		||||
                    $groupids_remove = array_diff($old_groupids, $new_groupids); // groups this user need to be removed from
 | 
			
		||||
                    foreach ($groupids_add as $groupid) { // execute insertion and removal
 | 
			
		||||
                        change_group_user_assignments($groupid, $target_nickname, null);
 | 
			
		||||
                    }
 | 
			
		||||
                    foreach ($groupids_remove as $groupid) {
 | 
			
		||||
                        change_group_user_assignments($groupid, null, $target_nickname);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // re-fetch user
 | 
			
		||||
                    $user_data = get_user($target_nickname); // load user data
 | 
			
		||||
 | 
			
		||||
                    // further field update
 | 
			
		||||
                    $user_data["realname"] = $realname;
 | 
			
		||||
                    $user_data["privilege"] = $privilege;
 | 
			
		||||
 | 
			
		||||
                    // password replacement, if requested
 | 
			
		||||
                    if ($password !== "") {
 | 
			
		||||
                        $user_data["password"] = password_hash($password, PASSWORD_DEFAULT);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    update_user($user_data);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "delete_users":
 | 
			
		||||
        {
 | 
			
		||||
            $users = explode_list($_REQUEST["users"] ?: "");
 | 
			
		||||
            foreach ($users as $g) {
 | 
			
		||||
                delete_user($g);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case "get_all_users":
 | 
			
		||||
        {
 | 
			
		||||
            $user_data_filtered = get_all_users();
 | 
			
		||||
            for ($i = 0; $i < count($user_data_filtered); $i++) {
 | 
			
		||||
                unset($user_data_filtered[$i]["password"]); // remove password from records
 | 
			
		||||
                resolve_groupids($user_data_filtered[$i]["groups"]);  // resolve group IDs
 | 
			
		||||
            }
 | 
			
		||||
            $result = json_encode($user_data_filtered);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------
 | 
			
		||||
 | 
			
		||||
print_result:
 | 
			
		||||
 | 
			
		||||
if ($result !== "") {
 | 
			
		||||
    echo $result;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								js/default_frame.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								js/default_frame.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
function list_available_games() {
 | 
			
		||||
    let game_list_panel = document.getElementById("game_list_panel");
 | 
			
		||||
 | 
			
		||||
    let req = {
 | 
			
		||||
        action: "get_available_games"
 | 
			
		||||
    }
 | 
			
		||||
    request(req).then(resp => {
 | 
			
		||||
        let games_by_groups = JSON.parse(resp);
 | 
			
		||||
        games_by_groups.forEach((game_collection) => {
 | 
			
		||||
            let group_box = document.createElement("section");
 | 
			
		||||
            group_box.classList.add("group-box");
 | 
			
		||||
            let group_box_caption = document.createElement("span");
 | 
			
		||||
            group_box_caption.classList.add("group-box-caption");
 | 
			
		||||
            group_box_caption.innerHTML = game_collection["groupname"];
 | 
			
		||||
            let group_box_inner = document.createElement("section");
 | 
			
		||||
            group_box_inner.classList.add("group-box-inner");
 | 
			
		||||
            group_box.append(group_box_caption, group_box_inner);
 | 
			
		||||
 | 
			
		||||
            game_collection["games"].forEach((game) => {
 | 
			
		||||
               let game_box = document.createElement("section");
 | 
			
		||||
               game_box.classList.add("game-box");
 | 
			
		||||
               game_box.innerHTML = game["name"];
 | 
			
		||||
               group_box_inner.appendChild(game_box);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            game_list_panel.appendChild(group_box);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										175
									
								
								js/gamemgr.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								js/gamemgr.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,175 @@
 | 
			
		||||
function list_all_games() {
 | 
			
		||||
    let req = {action: "get_all_game_headers"};
 | 
			
		||||
    let tbody = document.getElementById("game_manager_table");
 | 
			
		||||
    tbody.innerHTML = "";
 | 
			
		||||
    request(req).then(resp => {
 | 
			
		||||
        let games = JSON.parse(resp);
 | 
			
		||||
        for (let i = 0; i < games.length; i++) {
 | 
			
		||||
            let g = games[i];
 | 
			
		||||
            let row = document.createElement("tr");
 | 
			
		||||
            let chkbox = document.createElement("input");
 | 
			
		||||
            chkbox.type = "checkbox";
 | 
			
		||||
            chkbox.name = "game_chkbox";
 | 
			
		||||
            chkbox.game = g;
 | 
			
		||||
            let tdChkBox = document.createElement("td");
 | 
			
		||||
            tdChkBox.appendChild(chkbox);
 | 
			
		||||
            tdChkBox.classList.add("checkbox");
 | 
			
		||||
            let tdGameName = create_table_cell(g["name"]);
 | 
			
		||||
            let tdGameDescription = create_table_cell(g["description"]);
 | 
			
		||||
            let tdOwner = create_table_cell(g["owner"]);
 | 
			
		||||
            row.append(tdChkBox, tdGameName, tdGameDescription, tdOwner);
 | 
			
		||||
            tbody.appendChild(row);
 | 
			
		||||
 | 
			
		||||
            let edit_group_action = () => {
 | 
			
		||||
                create_edit_game(g);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            tdGameName.addEventListener("click", edit_group_action);
 | 
			
		||||
            tdGameDescription.addEventListener("click", edit_group_action);
 | 
			
		||||
            tdOwner.addEventListener("click", edit_group_action);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var EDITED_GAME = null;
 | 
			
		||||
 | 
			
		||||
function create_edit_game(game = null) {
 | 
			
		||||
    EDITED_GAME = game;
 | 
			
		||||
    let updating = game !== null;
 | 
			
		||||
 | 
			
		||||
    let nameF = document.getElementById("game_name");
 | 
			
		||||
    let descriptionF = document.getElementById("game_description");
 | 
			
		||||
    let submit_btn = document.getElementById("game_editor_submit_btn");
 | 
			
		||||
    let ownerF = document.getElementById("game_owner");
 | 
			
		||||
    let contributorsF = document.getElementById("game_contributors");
 | 
			
		||||
    let gameFileF = document.getElementById("game_file");
 | 
			
		||||
    let download_challenges_btn = document.getElementById("download_challenges_btn");
 | 
			
		||||
    let show_game_file_upload_btn = document.getElementById("show_game_file_upload");
 | 
			
		||||
    let cancel_game_file_upload_btn = document.getElementById("cancel_game_file_upload");
 | 
			
		||||
    let groupF = document.getElementById("game_groups");
 | 
			
		||||
 | 
			
		||||
    if (!updating) { // creating a new game
 | 
			
		||||
        nameF.value = "";
 | 
			
		||||
        descriptionF.value = "";
 | 
			
		||||
        submit_btn.value = "Létrehozás"
 | 
			
		||||
        ownerF.value = USERDATA["nickname"];
 | 
			
		||||
        ownerF.readOnly = true;
 | 
			
		||||
        contributorsF.value = "";
 | 
			
		||||
        groupF.value = "";
 | 
			
		||||
    } else { // editing an existing one
 | 
			
		||||
        nameF.value = game["name"];
 | 
			
		||||
        descriptionF.value = game["description"];
 | 
			
		||||
        submit_btn.value = "Mentés"
 | 
			
		||||
        ownerF.value = game["owner"];
 | 
			
		||||
        ownerF.readOnly = false;
 | 
			
		||||
        contributorsF.value = game["contributors"].join(", ");
 | 
			
		||||
        groupF.value = game["groups"].join(", ");
 | 
			
		||||
    }
 | 
			
		||||
    gameFileF.value = "";
 | 
			
		||||
 | 
			
		||||
    let game_file_present = updating && game["game_file_present"];
 | 
			
		||||
    if (game_file_present) {
 | 
			
		||||
        show(download_challenges_btn);
 | 
			
		||||
    }
 | 
			
		||||
    show_hide_gamefile_upload(false);
 | 
			
		||||
 | 
			
		||||
    submit_btn.onclick = () => {
 | 
			
		||||
        let game_name = document.getElementById("game_name").value.trim();
 | 
			
		||||
        if (game_name !== "") {
 | 
			
		||||
            let reqData = {
 | 
			
		||||
                name: game_name,
 | 
			
		||||
                description: descriptionF.value.trim(),
 | 
			
		||||
                owner: updating ? ownerF.value.trim() : USERDATA["nickname"],
 | 
			
		||||
                contributors: contributorsF.value.trim(),
 | 
			
		||||
                groups: groupF.value.trim()
 | 
			
		||||
            };
 | 
			
		||||
            if (updating) {
 | 
			
		||||
                reqData["_id"] = game["_id"];
 | 
			
		||||
            }
 | 
			
		||||
            let req = {
 | 
			
		||||
                action: updating ? "update_game" : "create_game",
 | 
			
		||||
                data: JSON.stringify(reqData)
 | 
			
		||||
            };
 | 
			
		||||
            if (gameFileF.files.length > 0) { // append game file if selected
 | 
			
		||||
                req["game_file"] = gameFileF.files[0];
 | 
			
		||||
            }
 | 
			
		||||
            request(req).then(resp => {
 | 
			
		||||
                list_all_games();
 | 
			
		||||
            });
 | 
			
		||||
            hide("game_editor_window");
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    show("game_editor_window");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function show_hide_gamefile_upload(en) {
 | 
			
		||||
    if (en) {
 | 
			
		||||
        // hide("download_challenges_btn");
 | 
			
		||||
        hide("show_game_file_upload");
 | 
			
		||||
        show("game_file");
 | 
			
		||||
        show("cancel_game_file_upload");
 | 
			
		||||
    } else {
 | 
			
		||||
        // show("download_challenges_btn");
 | 
			
		||||
        show("show_game_file_upload");
 | 
			
		||||
        hide("game_file");
 | 
			
		||||
        hide("cancel_game_file_upload");
 | 
			
		||||
        document.getElementById("game_file").value = "";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function download_challenges() {
 | 
			
		||||
    let action = "export_game_file_csv";
 | 
			
		||||
    let gameid = EDITED_GAME["_id"];
 | 
			
		||||
    window.open(`interface.php?action=${action}&gameid=${gameid}`, "_blank");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_selected_games() {
 | 
			
		||||
    let selected_chkboxes = document.getElementsByName("game_chkbox");
 | 
			
		||||
    let selected_games = [];
 | 
			
		||||
    selected_chkboxes.forEach((chkbox) => {
 | 
			
		||||
        if (chkbox.checked) {
 | 
			
		||||
            selected_games.push(chkbox.game);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    return selected_games;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function delete_games() {
 | 
			
		||||
    let games = get_selected_games();
 | 
			
		||||
    if (games.length === 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let game_names = [];
 | 
			
		||||
    let game_ids = [];
 | 
			
		||||
    games.forEach((g) => {
 | 
			
		||||
        game_names.push(g["name"]);
 | 
			
		||||
        game_ids.push(g["_id"]);
 | 
			
		||||
    });
 | 
			
		||||
    let msg = "Biztosan törölni kívánja a következő játéko(ka)t?\n\n" + game_names.join(", ") + "\n\n"
 | 
			
		||||
        + "A törlés nem vonható vissza!";
 | 
			
		||||
    if (confirm(msg)) {
 | 
			
		||||
        let req = {action: "delete_games", ids: game_ids.join(",")};
 | 
			
		||||
        request(req).then(resp => {
 | 
			
		||||
            list_all_games();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// function hint_all_groups(target_element_id) {
 | 
			
		||||
//     const hintbox_insert_fn = (record) => {
 | 
			
		||||
//         let targetF = document.getElementById(target_element_id);
 | 
			
		||||
//         let groups = explode_sanitize_string_list(targetF.value);
 | 
			
		||||
//         groups.pop();
 | 
			
		||||
//         groups.push(record);
 | 
			
		||||
//         targetF.value = groups.join(", ");
 | 
			
		||||
//         close_hintbox(true);
 | 
			
		||||
//     }
 | 
			
		||||
//
 | 
			
		||||
//     let req = {
 | 
			
		||||
//         action: "search_groups",
 | 
			
		||||
//     }
 | 
			
		||||
//
 | 
			
		||||
//     open_hintbox_at(target_element_id, req, print_group_name, hintbox_insert_fn);
 | 
			
		||||
// }
 | 
			
		||||
							
								
								
									
										123
									
								
								js/groupmgr.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								js/groupmgr.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,123 @@
 | 
			
		||||
function list_all_groups() {
 | 
			
		||||
    let req = {action: "get_all_groups"};
 | 
			
		||||
    let tbody = document.getElementById("group_manager_table");
 | 
			
		||||
    tbody.innerHTML = "";
 | 
			
		||||
    request(req).then(resp => {
 | 
			
		||||
        let groups = JSON.parse(resp);
 | 
			
		||||
        for (let i = 0; i < groups.length; i++) {
 | 
			
		||||
            let g = groups[i];
 | 
			
		||||
            let row = document.createElement("tr");
 | 
			
		||||
            let chkbox = document.createElement("input");
 | 
			
		||||
            chkbox.type = "checkbox";
 | 
			
		||||
            chkbox.name = "group_chkbox";
 | 
			
		||||
            chkbox.group = g;
 | 
			
		||||
            let tdChkBox = document.createElement("td");
 | 
			
		||||
            tdChkBox.appendChild(chkbox);
 | 
			
		||||
            tdChkBox.classList.add("checkbox");
 | 
			
		||||
            let tdGroupName = create_table_cell(print_group_name(g));
 | 
			
		||||
            let tdGroupDescription = create_table_cell(g["description"]);
 | 
			
		||||
            let tdOwner = create_table_cell(g["owner"]);
 | 
			
		||||
            row.append(tdChkBox, tdGroupName, tdGroupDescription, tdOwner);
 | 
			
		||||
            tbody.appendChild(row);
 | 
			
		||||
 | 
			
		||||
            let edit_group_action = () => {
 | 
			
		||||
                create_edit_group(g);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            tdGroupName.addEventListener("click", edit_group_action);
 | 
			
		||||
            tdGroupDescription.addEventListener("click", edit_group_action);
 | 
			
		||||
            tdOwner.addEventListener("click", edit_group_action);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function create_edit_group(group = null) {
 | 
			
		||||
    let update = group !== null;
 | 
			
		||||
 | 
			
		||||
    let groupnameF = document.getElementById("groupname");
 | 
			
		||||
    let group_descriptionF = document.getElementById("group_description");
 | 
			
		||||
    let submit_btn = document.getElementById("group_editor_submit_btn");
 | 
			
		||||
    let group_ownerF = document.getElementById("group_owner");
 | 
			
		||||
    let group_editorsF = document.getElementById("group_editors");
 | 
			
		||||
    let group_membersF = document.getElementById("group_members");
 | 
			
		||||
 | 
			
		||||
    if (!update) { // create a new group
 | 
			
		||||
        groupnameF.value = "";
 | 
			
		||||
        group_descriptionF.value = "";
 | 
			
		||||
        submit_btn.value = "Létrehozás"
 | 
			
		||||
        group_ownerF.value = USERDATA["nickname"];
 | 
			
		||||
        group_ownerF.readOnly = true;
 | 
			
		||||
        group_editorsF.value = "";
 | 
			
		||||
        group_membersF.value = "";
 | 
			
		||||
    } else { // update and existing one
 | 
			
		||||
        groupnameF.value = group["groupname"];
 | 
			
		||||
        group_descriptionF.value = group["description"];
 | 
			
		||||
        submit_btn.value = "Mentés"
 | 
			
		||||
        group_ownerF.value = group["owner"];
 | 
			
		||||
        group_ownerF.readOnly = false;
 | 
			
		||||
        group_editorsF.value = group["editors"].join(", ");
 | 
			
		||||
        group_membersF.value = group["users"].join(", ");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    submit_btn.onclick = () => {
 | 
			
		||||
        let groupname = document.getElementById("groupname").value.trim();
 | 
			
		||||
        if (groupname !== "") {
 | 
			
		||||
            let req = {
 | 
			
		||||
                action: update ? "update_group" : "create_group",
 | 
			
		||||
                groupname: groupname,
 | 
			
		||||
                description: group_descriptionF.value.trim(),
 | 
			
		||||
                editors: group_editorsF.value.trim()
 | 
			
		||||
            };
 | 
			
		||||
            if (update) {
 | 
			
		||||
                req["id"] = group["_id"];
 | 
			
		||||
            }
 | 
			
		||||
            request(req).then(resp => {
 | 
			
		||||
                list_all_groups();
 | 
			
		||||
            });
 | 
			
		||||
            hide("group_editor_window");
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    show("group_editor_window");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_selected_groups() {
 | 
			
		||||
    let selected_chkboxes = document.getElementsByName("group_chkbox");
 | 
			
		||||
    let selected_groups = [];
 | 
			
		||||
    selected_chkboxes.forEach((chkbox) => {
 | 
			
		||||
        if (chkbox.checked) {
 | 
			
		||||
            selected_groups.push(chkbox.group);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    return selected_groups;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function delete_groups() {
 | 
			
		||||
    let groups = get_selected_groups();
 | 
			
		||||
    if (groups.length === 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let group_names = [];
 | 
			
		||||
    let group_ids = [];
 | 
			
		||||
    groups.forEach((g) => {
 | 
			
		||||
       group_names.push(g["groupname"]);
 | 
			
		||||
       group_ids.push(g["_id"]);
 | 
			
		||||
    });
 | 
			
		||||
    let msg = "Biztosan törölni kívánja a következő csoporto(ka)t?\n\n" + group_names.join(", ") + "\n\n"
 | 
			
		||||
        + "A törlés nem vonható vissza!";
 | 
			
		||||
    if (confirm(msg)) {
 | 
			
		||||
        let req = {action: "delete_groups", ids: group_ids.join(",")};
 | 
			
		||||
        request(req).then(resp => {
 | 
			
		||||
            list_all_groups();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function print_group_name(group_data) {
 | 
			
		||||
    let record = group_data["groupname"];
 | 
			
		||||
    if (!group_data["unique"]) {
 | 
			
		||||
        record += "#" + group_data["_id"];
 | 
			
		||||
    }
 | 
			
		||||
    return record;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								js/hintbox.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								js/hintbox.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
function explode_sanitize_string_list(list, explodeAt = ",") {
 | 
			
		||||
    let elements = list.split(explodeAt);
 | 
			
		||||
    let sanitized = [];
 | 
			
		||||
    elements.forEach((e) => {
 | 
			
		||||
        if (e.trim() !== "") {
 | 
			
		||||
            sanitized.push(e);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    return sanitized;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const HINTBOX_ID = "HINTBOX";
 | 
			
		||||
 | 
			
		||||
function close_hintbox(close_if_focused = false) {
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
        if (close_if_focused || (document.getElementById(HINTBOX_ID).firstChild !== document.activeElement)) {
 | 
			
		||||
            hide(HINTBOX_ID);
 | 
			
		||||
        }
 | 
			
		||||
    }, 20);
 | 
			
		||||
}
 | 
			
		||||
function open_hintbox(x, y, contents, print_fun, insert_fun) {
 | 
			
		||||
    let hbw = document.getElementById(HINTBOX_ID);
 | 
			
		||||
    if (hbw === null) {
 | 
			
		||||
        hbw = document.createElement("section");
 | 
			
		||||
        hbw.id = HINTBOX_ID;
 | 
			
		||||
        hbw.classList.add("hintbox-window");
 | 
			
		||||
        let lb = document.createElement("select");
 | 
			
		||||
        lb.size = 5;
 | 
			
		||||
        lb.style.width = "100%";
 | 
			
		||||
        hbw.appendChild(lb);
 | 
			
		||||
        document.body.appendChild(hbw);
 | 
			
		||||
    }
 | 
			
		||||
    let lb = hbw.firstChild;
 | 
			
		||||
 | 
			
		||||
    hbw.style.left = `${x}px`;
 | 
			
		||||
    hbw.style.top = `${y}px`;
 | 
			
		||||
 | 
			
		||||
    lb.innerHTML = "";
 | 
			
		||||
    contents.forEach((record) => {
 | 
			
		||||
        let line = print_fun(record);
 | 
			
		||||
        let opt = document.createElement("option");
 | 
			
		||||
        opt.value = line;
 | 
			
		||||
        opt.innerText = line;
 | 
			
		||||
        lb.appendChild(opt);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    lb.ondblclick = () => {
 | 
			
		||||
        insert_fun(lb.value);
 | 
			
		||||
    };
 | 
			
		||||
    show(HINTBOX_ID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function open_hintbox_at(target_element_id, req_data, print_fn, insert_fn) {
 | 
			
		||||
    let targetF = document.getElementById(target_element_id);
 | 
			
		||||
 | 
			
		||||
    let bbox = targetF.getBoundingClientRect();
 | 
			
		||||
    let list_str = targetF.value.trim().split(",");
 | 
			
		||||
    if (list_str.length > 0) {
 | 
			
		||||
        let last_le_str = list_str[list_str.length - 1].trim();
 | 
			
		||||
        if (last_le_str.length > 2) {
 | 
			
		||||
            req_data["needle"] = last_le_str; // auto-insert needle
 | 
			
		||||
            request(req_data).then(resp => {
 | 
			
		||||
                let groups = JSON.parse(resp);
 | 
			
		||||
                let x = bbox.x + bbox.width;
 | 
			
		||||
                let y = bbox.y;
 | 
			
		||||
                open_hintbox(x, y, groups, print_fn, insert_fn);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								js/o.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								js/o.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
function o(input) {
 | 
			
		||||
    var o;
 | 
			
		||||
    if (typeof input === "string")
 | 
			
		||||
        o = document.getElementById(input);
 | 
			
		||||
    else if (typeof input === "object")
 | 
			
		||||
        o = input;
 | 
			
		||||
    return o;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// megjelenítés / eltüntetés
 | 
			
		||||
function show(obj) {
 | 
			
		||||
    o(obj).setAttribute("shown", "true");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function hide(obj) {
 | 
			
		||||
    o(obj).setAttribute("shown", "false");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function toggle_show(obj) {
 | 
			
		||||
    o(obj).setAttribute("shown", o(obj).getAttribute("shown") === "false");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								js/req.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								js/req.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
// kérés indítása a szerver felé (eredeti: KL.)
 | 
			
		||||
function request(data, url = "interface.php", method = "POST") {
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        var fd;
 | 
			
		||||
 | 
			
		||||
        // ha van adat megadva...
 | 
			
		||||
        if (data != null) {
 | 
			
		||||
            fd = new FormData();
 | 
			
		||||
 | 
			
		||||
            // mezők hozzáfűzése a kéréshez
 | 
			
		||||
            for (let prop in data) {
 | 
			
		||||
                if (Object.prototype.hasOwnProperty.call(data, prop)) {
 | 
			
		||||
                    fd.append(prop, data[prop]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // kérés feladása
 | 
			
		||||
        fetch(url, {
 | 
			
		||||
            method: method,
 | 
			
		||||
            body: fd,
 | 
			
		||||
        })
 | 
			
		||||
            .then(response => response.text())
 | 
			
		||||
            .then(data => resolve(data))
 | 
			
		||||
            .catch((error) => {
 | 
			
		||||
                console.error('Error: ', error);
 | 
			
		||||
                reject(error);
 | 
			
		||||
            });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								js/spreadquiz.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								js/spreadquiz.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
function login() {
 | 
			
		||||
    let nicknameF = document.getElementById("nickname"); // fetch fields
 | 
			
		||||
    let pwF = document.getElementById("password");
 | 
			
		||||
    let nickname = nicknameF.value; // extract values
 | 
			
		||||
    let pw = pwF.value;
 | 
			
		||||
 | 
			
		||||
    let loginReq = {
 | 
			
		||||
        action: "login",
 | 
			
		||||
        nickname: nickname,
 | 
			
		||||
        password: pw
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    request(loginReq).then(resp => {
 | 
			
		||||
        if (resp === "OK") {
 | 
			
		||||
            location.href = "main.php"
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function open_in_content_frame(url) {
 | 
			
		||||
    document.getElementById("content_frame").src = url;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var USERDATA = {};
 | 
			
		||||
function load_userdata() {
 | 
			
		||||
    let req = {action: "get_user_info"};
 | 
			
		||||
    request(req).then(resp => {
 | 
			
		||||
        USERDATA = JSON.parse(resp);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
load_userdata();
 | 
			
		||||
 | 
			
		||||
function create_table_cell(content, styleClass = "") {
 | 
			
		||||
    if (content.trim() === "") {
 | 
			
		||||
        content = "<i>(üres)</i>";
 | 
			
		||||
    }
 | 
			
		||||
    let td = document.createElement("td");
 | 
			
		||||
    td.innerHTML = content;
 | 
			
		||||
    if (styleClass !== "") {
 | 
			
		||||
        td.classList.add(styleClass);
 | 
			
		||||
    }
 | 
			
		||||
    return td;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ---------------
 | 
			
		||||
 | 
			
		||||
function highlight_row(nickname) {
 | 
			
		||||
    let hl_on = document.getElementById("user_chk_" + nickname).checked;
 | 
			
		||||
    let row = document.getElementById("row_" + nickname);
 | 
			
		||||
    row.setAttribute("highlight", hl_on ? "true" : "false");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								js/testground.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								js/testground.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
function populate_test(test_id) {
 | 
			
		||||
    let test_display = document.getElementById("test_display");
 | 
			
		||||
 | 
			
		||||
    let req = {
 | 
			
		||||
        action: "get_test",
 | 
			
		||||
        id: test_id
 | 
			
		||||
    }
 | 
			
		||||
    request(req).then(resp => {
 | 
			
		||||
        let test_data = JSON.parse(resp);
 | 
			
		||||
        test_data["challenges"].forEach((challenge) => {
 | 
			
		||||
            let challenge_box = document.createElement("section");
 | 
			
		||||
            challenge_box.classList.add("challenge");
 | 
			
		||||
            let question = document.createElement("span");
 | 
			
		||||
            question.classList.add("question");
 | 
			
		||||
            question.innerHTML = challenge["question"];
 | 
			
		||||
            let answer_container = document.createElement("section");
 | 
			
		||||
            answer_container.classList.add("answer-container");
 | 
			
		||||
            challenge_box.append(question, answer_container);
 | 
			
		||||
 | 
			
		||||
            challenge["answers"].forEach((answer) => {
 | 
			
		||||
                let answer_section = document.createElement("section");
 | 
			
		||||
                answer_section.classList.add("answer");
 | 
			
		||||
                answer_section.innerHTML = answer;
 | 
			
		||||
                answer_container.appendChild(answer_section);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            test_display.appendChild(challenge_box);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										164
									
								
								js/usermgr.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								js/usermgr.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,164 @@
 | 
			
		||||
function list_all_users() {
 | 
			
		||||
    let tbody = document.getElementById("user_manager_table_body");
 | 
			
		||||
    tbody.innerHTML = "";
 | 
			
		||||
    let req = {action: "get_all_users"};
 | 
			
		||||
    request(req).then(resp => {
 | 
			
		||||
        let users = JSON.parse(resp);
 | 
			
		||||
        for (let i = 0; i < users.length; i++) {
 | 
			
		||||
            let u = users[i];
 | 
			
		||||
            let row = document.createElement("tr");
 | 
			
		||||
            let chkbox = document.createElement("input");
 | 
			
		||||
            chkbox.type = "checkbox";
 | 
			
		||||
            chkbox.name = "user_chkbox";
 | 
			
		||||
            chkbox.user = u;
 | 
			
		||||
            let tdChkBox = document.createElement("td");
 | 
			
		||||
            tdChkBox.appendChild(chkbox);
 | 
			
		||||
            tdChkBox.classList.add("checkbox");
 | 
			
		||||
            let tdNickName = create_table_cell(u["nickname"]);
 | 
			
		||||
            let tdRealName = create_table_cell(u["realname"]);
 | 
			
		||||
            let tdGroups = create_table_cell(u["groups"].join(", "));
 | 
			
		||||
            let tdPrivilege = create_table_cell(u["privilege"]);
 | 
			
		||||
            row.append(tdChkBox, tdNickName, tdRealName, tdGroups, tdPrivilege);
 | 
			
		||||
            tbody.appendChild(row);
 | 
			
		||||
 | 
			
		||||
            let edit_user_action = () => {
 | 
			
		||||
                if (get_selected_users().length === 0) {
 | 
			
		||||
                    edit_user(u);
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            tdNickName.addEventListener("click", edit_user_action);
 | 
			
		||||
            tdRealName.addEventListener("click", edit_user_action);
 | 
			
		||||
            tdGroups.addEventListener("click", edit_user_action);
 | 
			
		||||
            tdPrivilege.addEventListener("click", edit_user_action)
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function create_new_user() {
 | 
			
		||||
    const generateRandomString = () => {
 | 
			
		||||
        return Math.floor(Math.random() * Date.now()).toString(36);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let nicknameF = document.getElementById("nickname");
 | 
			
		||||
    let realnameF = document.getElementById("realname");
 | 
			
		||||
    let passwordF = document.getElementById("password");
 | 
			
		||||
    let groupsF = document.getElementById("groups");
 | 
			
		||||
    let privilegeF = document.getElementById("privilege");
 | 
			
		||||
    let submit_btn = document.getElementById("user_editor_submit_btn");
 | 
			
		||||
 | 
			
		||||
    nicknameF.value = "";
 | 
			
		||||
    nicknameF.readOnly = false;
 | 
			
		||||
    realnameF.value = "";
 | 
			
		||||
    passwordF.type = "text";
 | 
			
		||||
    passwordF.value = generateRandomString();
 | 
			
		||||
    passwordF.readOnly = true;
 | 
			
		||||
    groupsF.value = "";
 | 
			
		||||
    submit_btn.value = "Létrehozás"
 | 
			
		||||
 | 
			
		||||
    submit_btn.onclick = () => {
 | 
			
		||||
        let nickname = nicknameF.value.trim();
 | 
			
		||||
        if (nickname !== "") {
 | 
			
		||||
            let req = {
 | 
			
		||||
                action: "create_user",
 | 
			
		||||
                nickname: nickname,
 | 
			
		||||
                realname: realnameF.value.trim(),
 | 
			
		||||
                password: passwordF.value,
 | 
			
		||||
                groups: groupsF.value.trim(),
 | 
			
		||||
                privilege: privilegeF.value
 | 
			
		||||
            };
 | 
			
		||||
            request(req).then(resp => {
 | 
			
		||||
                list_all_users();
 | 
			
		||||
            });
 | 
			
		||||
            hide("user_editor_window");
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    show("user_editor_window");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function edit_user(user) {
 | 
			
		||||
    let nicknameF = document.getElementById("nickname");
 | 
			
		||||
    let realnameF = document.getElementById("realname");
 | 
			
		||||
    let passwordF = document.getElementById("password");
 | 
			
		||||
    let groupsF = document.getElementById("groups");
 | 
			
		||||
    let privilegeF = document.getElementById("privilege");
 | 
			
		||||
    let submit_btn = document.getElementById("user_editor_submit_btn");
 | 
			
		||||
 | 
			
		||||
    nicknameF.value = user["nickname"];
 | 
			
		||||
    nicknameF.readOnly = true;
 | 
			
		||||
    realnameF.value = user["realname"];
 | 
			
		||||
    passwordF.type = "password";
 | 
			
		||||
    passwordF.value = "";
 | 
			
		||||
    passwordF.readOnly = false;
 | 
			
		||||
    groupsF.value = user["groups"].join(", ");
 | 
			
		||||
    privilegeF.value = user["privilege"];
 | 
			
		||||
    submit_btn.value = "Mentés"
 | 
			
		||||
 | 
			
		||||
    submit_btn.onclick = () => {
 | 
			
		||||
        let nickname = nicknameF.value.trim();
 | 
			
		||||
        if (nickname !== "") {
 | 
			
		||||
            let req = {
 | 
			
		||||
                action: "update_user",
 | 
			
		||||
                nickname: nickname,
 | 
			
		||||
                realname: realnameF.value.trim(),
 | 
			
		||||
                password: passwordF.value,
 | 
			
		||||
                groups: groupsF.value.trim(),
 | 
			
		||||
                privilege: privilegeF.value
 | 
			
		||||
            };
 | 
			
		||||
            request(req).then(resp => {
 | 
			
		||||
                list_all_users();
 | 
			
		||||
            });
 | 
			
		||||
            hide("user_editor_window");
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    show("user_editor_window");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_selected_users() {
 | 
			
		||||
    let selected_chkboxes = document.getElementsByName("user_chkbox");
 | 
			
		||||
    let selected_users = [];
 | 
			
		||||
    selected_chkboxes.forEach((chkbox) => {
 | 
			
		||||
        if (chkbox.checked) {
 | 
			
		||||
            selected_users.push(chkbox.user);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    return selected_users;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function delete_users() {
 | 
			
		||||
    let users = get_selected_users();
 | 
			
		||||
    if (users.length === 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    let user_nicknames = [];
 | 
			
		||||
    users.forEach((u) => {
 | 
			
		||||
        user_nicknames.push(u["nickname"]);
 | 
			
		||||
    });
 | 
			
		||||
    let msg = "Biztosan törölni kívánja a következő felhasználó(ka)t?\n\n" + user_nicknames.join(", ") + "\n\n"
 | 
			
		||||
        + "A törlés nem vonható vissza!";
 | 
			
		||||
    if (confirm(msg)) {
 | 
			
		||||
        let req = {action: "delete_users", users: user_nicknames.join(",")};
 | 
			
		||||
        request(req).then(resp => {
 | 
			
		||||
            list_all_users();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function hint_all_groups(target_element_id) {
 | 
			
		||||
    const hintbox_insert_fn = (record) => {
 | 
			
		||||
        let targetF = document.getElementById(target_element_id);
 | 
			
		||||
        let groups = explode_sanitize_string_list(targetF.value);
 | 
			
		||||
        groups.pop();
 | 
			
		||||
        groups.push(record);
 | 
			
		||||
        targetF.value = groups.join(", ");
 | 
			
		||||
        close_hintbox(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let req = {
 | 
			
		||||
        action: "search_groups",
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open_hintbox_at(target_element_id, req, print_group_name, hintbox_insert_fn);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								login.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								login.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
<?php
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "autologin.php";
 | 
			
		||||
 | 
			
		||||
if (get_autologin_state()) {
 | 
			
		||||
    header("Location: " . MAIN_URL);
 | 
			
		||||
    exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>SpreadQuiz :: Bejelentkezés</title>
 | 
			
		||||
    <script src="js/req.js"></script>
 | 
			
		||||
    <script src="js/spreadquiz.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<input type="text" placeholder="Felhasználónév" id="nickname">
 | 
			
		||||
<input type="password" placeholder="Jelszó" id="password">
 | 
			
		||||
<input type="button" value="Belépés" onclick="login()">
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										50
									
								
								main.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								main.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
			
		||||
<?php
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "usermgr.php";
 | 
			
		||||
 | 
			
		||||
require_once "autologin.php";
 | 
			
		||||
 | 
			
		||||
// if not logged in, then redirect to login page
 | 
			
		||||
$logged_in = get_autologin_state();
 | 
			
		||||
if (!$logged_in) {
 | 
			
		||||
    header("Location: " . LOGIN_URL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$user_data = get_autologin_user_data();
 | 
			
		||||
$privilege = $user_data["privilege"];
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
 | 
			
		||||
<?php if ($logged_in) { ?>
 | 
			
		||||
    <!DOCTYPE html>
 | 
			
		||||
    <html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="UTF-8">
 | 
			
		||||
        <title>SpreadQuiz</title>
 | 
			
		||||
        <script src="js/req.js"></script>
 | 
			
		||||
        <script src="js/spreadquiz.js"></script>
 | 
			
		||||
        <link rel="stylesheet" href="style/spreadquiz.css"/>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
    <section id="screen_panel">
 | 
			
		||||
        <section id="content_pane">
 | 
			
		||||
            <iframe id="content_frame" src="default_frame.php"></iframe>
 | 
			
		||||
        </section>
 | 
			
		||||
        <section id="info_pane">
 | 
			
		||||
            <section id="user_info" class="info-pane-element"><?= $user_data["nickname"]; ?></section>
 | 
			
		||||
            <?php if ($privilege != PRIVILEGE_PLAYER) { ?>
 | 
			
		||||
                <section id="action_panel" class="info-pane-element">
 | 
			
		||||
                    <?php if (($privilege === PRIVILEGE_CREATOR) || ($privilege === PRIVILEGE_QUIZMASTER)) { ?>
 | 
			
		||||
                        <input type="button" value="Tartalmak kezelése" onclick="open_in_content_frame('game_manager_frame.php')">
 | 
			
		||||
                    <?php } ?>
 | 
			
		||||
                    <?php if ($privilege === PRIVILEGE_QUIZMASTER) { ?>
 | 
			
		||||
                        <input type="button" value="Felhasználók kezelése" onclick="open_in_content_frame('user_manager_frame.php')">
 | 
			
		||||
                        <input type="button" value="Csoportok kezelése" onclick="open_in_content_frame('group_manager_frame.php')">
 | 
			
		||||
                    <?php } ?>
 | 
			
		||||
                </section>
 | 
			
		||||
            <?php } ?>
 | 
			
		||||
        </section>
 | 
			
		||||
    </section>
 | 
			
		||||
    </body>
 | 
			
		||||
    </html>
 | 
			
		||||
<?php } ?>
 | 
			
		||||
							
								
								
									
										197
									
								
								style/spreadquiz.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								style/spreadquiz.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,197 @@
 | 
			
		||||
*[shown="false"] {
 | 
			
		||||
    visibility: hidden;
 | 
			
		||||
    display: none;
 | 
			
		||||
    opacity: 0;
 | 
			
		||||
    width: 0;
 | 
			
		||||
    height: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*[shown="true"] {
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ----------------- */
 | 
			
		||||
 | 
			
		||||
section#screen_panel {
 | 
			
		||||
    display: block;
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section#content_pane, section#info_pane {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    display: block;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section#content_pane {
 | 
			
		||||
    left: 0;
 | 
			
		||||
    width: 80vw;
 | 
			
		||||
    background-color: lightcyan;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section#info_pane {
 | 
			
		||||
    right: 0;
 | 
			
		||||
    width: 20vw;
 | 
			
		||||
    background-color: beige;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.info-pane-element {
 | 
			
		||||
    display: block;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    padding: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section#user_info {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    background-color: aquamarine;
 | 
			
		||||
    font-size: 18pt;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section#action_panel {
 | 
			
		||||
    background-color: antiquewhite;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
iframe#content_frame {
 | 
			
		||||
    display: block;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    border: 0 transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section#table_section {
 | 
			
		||||
    position: sticky;
 | 
			
		||||
    height: calc(100vh - 4em);
 | 
			
		||||
    overflow-y: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.management {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.management thead th {
 | 
			
		||||
    padding: 0.5em 0;
 | 
			
		||||
    position: sticky;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    background-color: darkgray;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.management tbody td {
 | 
			
		||||
    border: 1pt lightgrey solid;
 | 
			
		||||
    padding: 0.3em 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.management tbody tr[highlight="true"] {
 | 
			
		||||
    background-color: antiquewhite;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.management tbody tr[highlight="false"] td input {
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section#user_manager_action_bar {
 | 
			
		||||
    margin-top: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section.window {
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    display: block;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    background-color: rgba(128, 128, 128, 0.7);
 | 
			
		||||
    padding: 4em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section.window-inner {
 | 
			
		||||
    margin: 0 auto;
 | 
			
		||||
    display: block;
 | 
			
		||||
    border: 2pt solid darkslategray;
 | 
			
		||||
    background-color: whitesmoke;
 | 
			
		||||
    padding: 1em;
 | 
			
		||||
    width: fit-content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
td.checkbox {
 | 
			
		||||
    width: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hintbox-window {
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    display: block;
 | 
			
		||||
    width: 15em;
 | 
			
		||||
    height: 8em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ----- */
 | 
			
		||||
 | 
			
		||||
section#game_list_panel {
 | 
			
		||||
    display: block;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section.group-box {
 | 
			
		||||
    margin: 1em;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    background-color: beige;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
span.group-box-caption {
 | 
			
		||||
    display: block;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    padding: 1em;
 | 
			
		||||
    background-color: chartreuse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section.group-box-inner {
 | 
			
		||||
    display: inline-table;
 | 
			
		||||
    padding: 1em;
 | 
			
		||||
    collapse: 1em;
 | 
			
		||||
    border-spacing: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section.game-box {
 | 
			
		||||
    display: table-cell;
 | 
			
		||||
    width: 8em;
 | 
			
		||||
    height: 8em;
 | 
			
		||||
    border: 2pt dashed gray;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section#test_area {
 | 
			
		||||
    display: block;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section.challenge {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
span.question {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section.answer-container {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
section.answer {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								testground.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								testground.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "autologin.php";
 | 
			
		||||
 | 
			
		||||
$user_data = get_autologin_user_data();
 | 
			
		||||
if (!get_autologin_state() || !isset($_REQUEST["testid"])) {
 | 
			
		||||
    exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$testid = $_REQUEST["testid"];
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>SpreadQuiz</title>
 | 
			
		||||
    <script src="js/spreadquiz.js"></script>
 | 
			
		||||
    <script src="js/req.js"></script>
 | 
			
		||||
    <script src="js/o.js"></script>
 | 
			
		||||
    <script src="js/testground.js"></script>
 | 
			
		||||
    <link rel="stylesheet" href="style/spreadquiz.css">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <section id="test_display">
 | 
			
		||||
 | 
			
		||||
    </section>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										93
									
								
								testmgr.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								testmgr.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,93 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "common_func.php";
 | 
			
		||||
 | 
			
		||||
require_once "gamemgr.php";
 | 
			
		||||
require_once "usermgr.php";
 | 
			
		||||
 | 
			
		||||
$testdb = new \SleekDB\Store(TESTDB, DATADIR, ["timeout" => false]);
 | 
			
		||||
 | 
			
		||||
const TEST_ONGOING = "ongoing";
 | 
			
		||||
const TEST_CONCLUDED = "concluded";
 | 
			
		||||
 | 
			
		||||
function create_or_continue_test(string $gameid, string $nickname): string
 | 
			
		||||
{
 | 
			
		||||
    global $testdb;
 | 
			
		||||
 | 
			
		||||
    // get game and user data
 | 
			
		||||
    $game_data = get_game($gameid);
 | 
			
		||||
    $user_data = get_user($nickname);
 | 
			
		||||
    if ((count($game_data) === 0) || (count($user_data) === 0)) {
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // check if this user has permission to take this test
 | 
			
		||||
    // if the intersection of user's groups and game's assigned groups is zero, then the user has no access to this game
 | 
			
		||||
    if (count(array_intersect($game_data["groups"], $user_data["groups"])) === 0) {
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // check if the user had taken this test before
 | 
			
		||||
    $fetch_criteria = [["gameid", "=", $gameid], "AND", ["nickname", "=", $nickname]];
 | 
			
		||||
    $previous_tests = $testdb->findBy($fetch_criteria);
 | 
			
		||||
    if (count($previous_tests) > 0) { // if there are previous attempts, then...
 | 
			
		||||
        // update timed tests to see if they had expired
 | 
			
		||||
        update_timed_tests($previous_tests);
 | 
			
		||||
 | 
			
		||||
        // re-fetch tests, look only for ongoing
 | 
			
		||||
        $ongoing_tests = $testdb->findBy([$fetch_criteria, "AND", ["state", "=", TEST_ONGOING]]);
 | 
			
		||||
        if (count($ongoing_tests) !== 0) { // if there's an ongoing test
 | 
			
		||||
            return $ongoing_tests[0]["_id"];
 | 
			
		||||
        } else { // there's no ongoing test
 | 
			
		||||
            if ($game_data["properties"]["repeatable"]) { // test is repeatable...
 | 
			
		||||
                return create_test($game_data, $user_data);
 | 
			
		||||
            } else { // test is non-repeatable, cannot be attempted more times
 | 
			
		||||
                return "";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else { // there were no previous attempts
 | 
			
		||||
        return create_test($game_data, $user_data);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function create_test(array $game_data, array $user_data) : string
 | 
			
		||||
{
 | 
			
		||||
    $gameid = $game_data["_id"];
 | 
			
		||||
 | 
			
		||||
    // fill basic data
 | 
			
		||||
    $game_data = [
 | 
			
		||||
        "gameid" => $gameid,
 | 
			
		||||
        "nickname" => $user_data["nickname"],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    // fill challenges
 | 
			
		||||
    $challenges = load_challenges($gameid);
 | 
			
		||||
 | 
			
		||||
    // shuffle answers
 | 
			
		||||
    foreach ($challenges as &$ch) {
 | 
			
		||||
        shuffle($ch["answers"]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $game_data["challenges"] = $challenges;
 | 
			
		||||
 | 
			
		||||
    // involve properties
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_timed_tests(array $test_data_array)
 | 
			
		||||
{
 | 
			
		||||
    $now = time();
 | 
			
		||||
    foreach ($test_data_array as $test_data) {
 | 
			
		||||
        // look for unprocessed expired tests
 | 
			
		||||
        if (($test_data["state"] === TEST_ONGOING) && ($test_data["end_limit_time"] < $now)) {
 | 
			
		||||
            $test_data["state"] = TEST_CONCLUDED;
 | 
			
		||||
            update_test($test_data);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_test(array $test_data)
 | 
			
		||||
{
 | 
			
		||||
    global $testdb;
 | 
			
		||||
    $testdb->update($test_data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										104
									
								
								user_manager_frame.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								user_manager_frame.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,104 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "autologin.php";
 | 
			
		||||
 | 
			
		||||
$user_data = get_autologin_user_data();
 | 
			
		||||
if (!get_autologin_state() || ($user_data["privilege"] !== PRIVILEGE_QUIZMASTER)) {
 | 
			
		||||
    exit(); // this page is only available for quizmasters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>SpreadQuiz</title>
 | 
			
		||||
    <script src="js/req.js"></script>
 | 
			
		||||
    <script src="js/spreadquiz.js"></script>
 | 
			
		||||
    <script src="js/o.js"></script>
 | 
			
		||||
    <script src="js/groupmgr.js"></script>
 | 
			
		||||
    <script src="js/hintbox.js"></script>
 | 
			
		||||
    <script src="js/usermgr.js"></script>
 | 
			
		||||
    <link rel="stylesheet" href="style/spreadquiz.css"/>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<section id="table_section">
 | 
			
		||||
    <table id="user_manager_table" class="management">
 | 
			
		||||
        <thead>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <th></th>
 | 
			
		||||
            <th>Felhasználónév</th>
 | 
			
		||||
            <th>Név</th>
 | 
			
		||||
            <th>Csoportok</th>
 | 
			
		||||
            <th>Jogosultság</th>
 | 
			
		||||
        </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tbody id="user_manager_table_body">
 | 
			
		||||
        <!--        --><?php
 | 
			
		||||
        //        function create_cell(string $content, string $class = "")
 | 
			
		||||
        //        {
 | 
			
		||||
        //            if (trim($content) === "") {
 | 
			
		||||
        //                $content = "<i>(üres)</i>";
 | 
			
		||||
        //            }
 | 
			
		||||
        //            return "<td class='$class'>$content</td>";
 | 
			
		||||
        //        }
 | 
			
		||||
        //
 | 
			
		||||
        //        function create_table_row(array $keys, array $record)
 | 
			
		||||
        //        {
 | 
			
		||||
        //            $tr = "<tr>";
 | 
			
		||||
        //            foreach ($keys as $k) {
 | 
			
		||||
        //                $tr .= "<td>${record[$k]}</td>";
 | 
			
		||||
        //            }
 | 
			
		||||
        //            $tr .= "</tr>";
 | 
			
		||||
        //            return $tr;
 | 
			
		||||
        //        }
 | 
			
		||||
        //
 | 
			
		||||
        //        $users = get_all_users();
 | 
			
		||||
        //        foreach ($users as $u) {
 | 
			
		||||
        //            $nickname = $u["nickname"];
 | 
			
		||||
        //            $tr = "<tr id='row_$nickname'>";
 | 
			
		||||
        //            $tr .= create_cell("<input type='checkbox' id='user_chk_$nickname' onchange='highlight_row(\"$nickname\")'>", "checkbox");
 | 
			
		||||
        //            $tr .= create_cell($u["nickname"]);
 | 
			
		||||
        //            $tr .= create_cell($u["realname"]);
 | 
			
		||||
        //            $tr .= create_cell(implode(",", $u["groups"]));
 | 
			
		||||
        //            $tr .= create_cell($u["privilege"]);
 | 
			
		||||
        //            $tr .= "</tr>";
 | 
			
		||||
        //            echo $tr;
 | 
			
		||||
        //        }
 | 
			
		||||
        //        ?>
 | 
			
		||||
        </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
</section>
 | 
			
		||||
<section>
 | 
			
		||||
    <input type="button" value="Új felhasználó" onclick="create_new_user()">
 | 
			
		||||
    <input type="button" value="Felhasználó(k) törlése" onclick="delete_users()">
 | 
			
		||||
    <input type="button" value="Felhasználók importálása CSV-ből">
 | 
			
		||||
</section>
 | 
			
		||||
<section class="window" shown="false" id="user_editor_window">
 | 
			
		||||
    <section class="window-inner">
 | 
			
		||||
        <section style="text-align: right">
 | 
			
		||||
            <span>Felhasználónév: <input type="text" id="nickname"></span><br>
 | 
			
		||||
            <span>Teljes név: <input type="text" id="realname"></span><br>
 | 
			
		||||
            <span>Jelszó: <input type="text" id="password" readonly></span><br>
 | 
			
		||||
            <span>Csoportok: <input type="text" id="groups" oninput="hint_all_groups('groups')" onblur="close_hintbox()"></span><br>
 | 
			
		||||
            <span>Jogosultság:
 | 
			
		||||
                <select id="privilege">
 | 
			
		||||
                    <option value="player">játékos</option>
 | 
			
		||||
                    <option value="creator">szerkesztő</option>
 | 
			
		||||
                    <option value="admin">kvízmester</option>
 | 
			
		||||
                </select>
 | 
			
		||||
            </span>
 | 
			
		||||
        </section>
 | 
			
		||||
        <span><input type="button" value="" id="user_editor_submit_btn"><input type="button" value="Mégse" onclick="hide('user_editor_window')"></span>
 | 
			
		||||
    </section>
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
    list_all_users();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										113
									
								
								usermgr.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								usermgr.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "globals.php";
 | 
			
		||||
require_once "common_func.php";
 | 
			
		||||
 | 
			
		||||
$userdb = new \SleekDB\Store(USERDB, DATADIR, ["timeout" => false]);
 | 
			
		||||
 | 
			
		||||
const PRIVILEGE_PLAYER = "player";
 | 
			
		||||
const PRIVILEGE_CREATOR = "creator";
 | 
			
		||||
const PRIVILEGE_QUIZMASTER = "admin"; // TODO: refactor!
 | 
			
		||||
 | 
			
		||||
function add_user(string $nickname, string $password, string $realname, array $groups = [], string $privilege = PRIVILEGE_PLAYER): bool
 | 
			
		||||
{
 | 
			
		||||
    global $userdb;
 | 
			
		||||
    if (count(get_user($nickname)) != 0) { // user exists
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $user_data = [
 | 
			
		||||
        "nickname" => $nickname,
 | 
			
		||||
        "password" => password_hash($password, PASSWORD_DEFAULT),
 | 
			
		||||
        "realname" => $realname,
 | 
			
		||||
        "groups" => $groups,
 | 
			
		||||
        "privilege" => $privilege
 | 
			
		||||
    ];
 | 
			
		||||
    $userdb->insert($user_data);
 | 
			
		||||
    return true; // user registration successful
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function delete_user(string $nickname)
 | 
			
		||||
{
 | 
			
		||||
    global $userdb;
 | 
			
		||||
    if ($nickname == QUIZMASTER_NICKNAME) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $user_data = get_user($nickname);
 | 
			
		||||
    if (count($user_data) !== 0) {
 | 
			
		||||
        foreach ($user_data["groups"] as $groupid) {
 | 
			
		||||
            change_group_user_assignments($groupid, null, $nickname);
 | 
			
		||||
        }
 | 
			
		||||
        $userdb->deleteBy(["nickname", "=", $nickname]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_user(string $nickname): array
 | 
			
		||||
{
 | 
			
		||||
    global $userdb;
 | 
			
		||||
    $user_data_array = $userdb->findBy(["nickname", "=", $nickname]);
 | 
			
		||||
    return count($user_data_array) != 0 ? $user_data_array[0] : [];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_user(array $user_data)
 | 
			
		||||
{
 | 
			
		||||
    global $userdb;
 | 
			
		||||
    return $userdb->update($user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function change_password(string $nickname, string $old, string $new): bool
 | 
			
		||||
{
 | 
			
		||||
    $user_data = get_user($nickname);
 | 
			
		||||
    if (count($user_data) != 0) {
 | 
			
		||||
        if (password_verify($old, $user_data["password"])) {
 | 
			
		||||
            $user_data["password"] = password_hash($new, PASSWORD_DEFAULT);
 | 
			
		||||
            update_user($user_data);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function change_user_group_assignments(string $nickname, $groupname_add, $groupname_remove)
 | 
			
		||||
{
 | 
			
		||||
    $user_data = get_user($nickname);
 | 
			
		||||
    if (count($user_data) != 0) {
 | 
			
		||||
        alter_array_contents($user_data["groups"], $groupname_add, $groupname_remove);
 | 
			
		||||
        update_user($user_data); // update user
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function change_privilege_level(string $nickname, string $privilege)
 | 
			
		||||
{
 | 
			
		||||
    $user_data = get_user($nickname);
 | 
			
		||||
    if (count($user_data) != 0) {
 | 
			
		||||
        $user_data["privilege"] = $privilege;
 | 
			
		||||
        update_user($user_data);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function check_user_credentials(string $nickname, string $password): bool
 | 
			
		||||
{
 | 
			
		||||
    $user_data = get_user($nickname);
 | 
			
		||||
    if (count($user_data) != 0) {
 | 
			
		||||
        return password_verify($password, $user_data["password"]);
 | 
			
		||||
    } else {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_all_users(): array
 | 
			
		||||
{
 | 
			
		||||
    global $userdb;
 | 
			
		||||
    return $userdb->findAll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_all_nicknames() : array {
 | 
			
		||||
    $nicknames = [];
 | 
			
		||||
    $user_data_array = get_all_users();
 | 
			
		||||
    foreach ($user_data_array as $user_data) {
 | 
			
		||||
        $nicknames[] = $user_data["nickname"];
 | 
			
		||||
    }
 | 
			
		||||
    return $nicknames;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user