From 8199198816cddd25106850c1d8ed22db06597473 Mon Sep 17 00:00:00 2001 From: Tony Yang Date: Sun, 2 Jun 2019 03:31:28 +0800 Subject: [PATCH] Finished user component --- admin/ajax/user.php | 41 ++++++- admin/component/user.js | 262 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 290 insertions(+), 13 deletions(-) diff --git a/admin/ajax/user.php b/admin/ajax/user.php index 4dfe44b..8b6b383 100644 --- a/admin/ajax/user.php +++ b/admin/ajax/user.php @@ -13,11 +13,15 @@ if (!$user->valid) { send_error(403, "nopermission"); } -if ($_SERVER["REQUEST_METHOD"] == "POST") { - // modify account data +if ($_SERVER["REQUEST_METHOD"] == "PATCH" || $_SERVER["REQUEST_METHOD"] == "POST") { + // patch: modify; post: create if (!validate_csrf()) { send_error(403, "csrf"); } + if ($_SERVER["REQUEST_METHOD"] == "PATCH") { + parse_str(file_get_contents('php://input'), $_POST); + // hack + } if (isset($_POST['username']) && (isset($_POST['name']) || isset($_POST['password']))) { // modify account data @@ -25,8 +29,18 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { try { $target_user = new User($username); + if ($_SERVER["REQUEST_METHOD"] == "POST") { + // create new user, but user exists + send_error(409, "userexists"); + } } catch (NoUserException $e) { - send_error(404, "nouser"); + if ($_SERVER["REQUEST_METHOD"] == "PATCH") { + // modify one that not exist -> error + send_error(404, "nouser"); + } else if ($_SERVER["REQUEST_METHOD"] == "POST") { + // create new user + $SQL->query("INSERT INTO `user` (`username`) VALUES ('%s')", array($username)); + } } if (trim($_POST['password']) != '') { @@ -48,8 +62,21 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { } else { send_error(400, "noemail"); } - - $SQL->query("UPDATE `user` SET `muted`='%d' WHERE `username`='%s'", array($_POST['muted'], $username)); + + if (isset($_POST["muted"])) { + $muted = 1; + } else { + $muted = 0; + } + + $level = intval($_POST['role']); + if ($level > 9) { + $level = 9; + } else if ($level < 0) { + $level = 0; + } + + $SQL->query("UPDATE `user` SET `muted`='%d' AND `level`='%d' WHERE `username`='%s'", array($muted, $level, $username)); header("Content-Type: application/json"); echo json_encode(array("status" => TRUE, "modified" => $username)); @@ -69,7 +96,9 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { "username" => $data['username'], "name" => $data['name'], "email" => $data['email'], - "role" => cavern_level_to_role($data['level']) + "level" => intval($data['level']), + "role" => cavern_level_to_role($data['level']), + "muted" => (($data["muted"] == 1) ? TRUE : FALSE) ); } while ($user_query['row'] = $user_query['query']->fetch_assoc()); } diff --git a/admin/component/user.js b/admin/component/user.js index 332bf30..ec22ea4 100644 --- a/admin/component/user.js +++ b/admin/component/user.js @@ -1,16 +1,264 @@ (() => { - function create(tag) { - return document.createElement(tag); + async function fetchUser(mode, data="") { + try { + switch (mode) { + case "list": + pageManager.setHeader("使用者列表"); + var res = await axios.request({ + url: "ajax/user.php", + method: "GET" + }); + renderList(res.data); + break; + case "username": + pageManager.setHeader("修改資料"); + var res = await axios.request({ + url: "../ajax/user.php?username=" + data, + method: "GET" + }); + renderForm(mode, res.data) + break; + case "add": + pageManager.setHeader("新增使用者"); + renderForm(mode); + break; + } + } catch (e) { + console.error(e); + } + bindListener(mode); + setTimeout(() => { + pageManager.setLoaderState(false) + }, 1000); + } + + function renderList(data) { + let doc = pageManager.document; + doc.innerHTML = ""; + + var wrapper = create('div', "table wrapper"); + var table = create('table', "ts sortable celled striped table"); + + let thead = create('thead'); + (["帳號", "暱稱", "信箱", "權限", "禁言", "管理"]).forEach((e, _i) => { + let th = create('th'); th.textContent = e; + thead.appendChild(th); + }) + table.appendChild(thead); + + var tbody = create('tbody'); + for (user of data["list"]) { + let tr = create("tr"); + (["username", "name", "email", "role", "muted"]).forEach((e, _i) => { + let td = create('td'); + if (e != "name") td.classList.add("collapsing"); + + if (e == "muted") { + td.classList.add("center", "aligned"); + if (user[e]) td.innerHTML = ``; + } else if (e == "email") { + td.innerHTML = `${user[e]}`; + } else { + td.textContent = user[e]; + } + tr.appendChild(td); + }); + + let action = `` + + ``; + if (user.level != 9) { + action += ``; + } + action += ``; + tr.insertAdjacentHTML("beforeend", action); + + tbody.appendChild(tr); + } + + table.appendChild(tbody); + wrapper.appendChild(table); + doc.appendChild(wrapper); + } + + function renderForm(mode, data={}) { + let doc = pageManager.document; + doc.innerHTML = ""; + + let fieldName = { + "username": "帳號", + "name": "暱稱", + "email": "信箱", + "password": "密碼", + "role": "權限", + "muted": "禁言" + }; + + let levelRole = { + 0: "會員", + 1: "作者", + 8: "管理員", + 9: "站長" + }; + + let formContainer = create('div'); formContainer.className = "ts form"; + let form = create('form'); form.method = "POST"; form.action = "ajax/user.php"; form.name = "config"; form.id = "config"; form.className = "clearfix"; + form.autocomplete = "new-password"; + + if (mode == "username") { + var avatarSrc = `https://www.gravatar.com/avatar/${data["hash"]}?d=https%3A%2F%2Ftocas-ui.com%2Fassets%2Fimg%2F5e5e3a6.png&s=500`; + form.insertAdjacentHTML("beforeend", `
` + + `
` + + `
` + ); + } + + Object.keys(fieldName).forEach((e, _i) => { + let field = create('div', "field"); + let label = create('label'); + label.textContent = fieldName[e]; + + if (e == "role") { + var input = create('select'); input.name = e; + [0, 1, 8, 9].forEach((opt, _i) => { + let option = create('option'); + option.value = opt; + option.textContent = levelRole[opt]; + if (data["level"] == opt) { + option.selected = "selected"; + } + input.appendChild(option); + }); + } else if (e == "password") { + var input = create('input'); input.name = e; input.type = "password"; + } else if (e == "muted") { + var input = create('div', "ts toggle checkbox"); + let checkbox = create('input'); checkbox.id = "muted"; checkbox.type = "checkbox"; + checkbox.value = "on"; + let label = create('label'); label.setAttribute("for", "muted"); + if (data[e]) { + checkbox.checked = "checked"; + } + input.appendChild(checkbox); + input.appendChild(label); + } else { + var input = create('input'); input.name = e; input.type = "text"; + if (mode == "username") { + input.value = data[e]; + } + } + + if (e == "username" && mode == "username") { + input.disabled = "disabled"; + } + + field.appendChild(label); + field.appendChild(input); + form.appendChild(field); + }); + + form.insertAdjacentHTML("beforeend", ``); + + formContainer.appendChild(form); + doc.appendChild(formContainer); + } + + function sendData(mode, data) { + let fd = new URLSearchParams(data).toString(); + axios.request({ + method: (mode == "add" ? "POST" : "PATCH"), + url: "ajax/user.php", + data: fd + }).then((res) => { + pageManager.snackbar("操作成功!"); + router.navigate("/user"); + }).catch((err) => { + switch (err.response.data.status) { + case "userexists": + pageManager.snackbar("使用者已經存在"); + break; + case "nouser": + pageManager.snackbar("使用者不存在"); + break; + case "noname": + pageManager.snackbar("請填寫暱稱"); + break; + case "noemail": + pageManager.snackbar("請填寫信箱"); + break; + case "emailused": + pageManager.snackbar("信箱已被其他使用者使用"); + break; + default: + pageManager.snackbar("發生錯誤"); + break; + } + }); + } + + function deleteUser(username) { + axios.request({ + method: "DELETE", + url: "ajax/user.php?username=" + username + }).then((res) =>{ + pageManager.snackbar("刪除成功。"); + pageManager.load("user", "list"); + }).catch((err) => { + switch (err.response.data.status) { + case "nouser": + pageManager.snackbar("使用者不存在"); + break; + case "deleteowner": + pageManager.snackbar("你不能刪掉站長!"); + break; + default: + pageManager.snackbar("刪除使用者時發生錯誤") + break; + } + }); + } + + function bindListener(mode) { + router.updatePageLinks(); + if (mode == "list") { + $('tbody').on('click', 'a.negative', function(e) { + e.preventDefault(); + + let el = e.currentTarget; + let username = el.dataset.username; + showModal(username); + }); + + function showModal(username) { + swal({ + type: 'question', + title: '確定要刪除嗎?', + showCancelButton: true, + confirmButtonText: '確定', + cancelButtonText: '取消' + }).then((result) => { + if (result.value) { // confirm + deleteUser(username); + } + }); + } + } else { + $('form').on('submit', function (e) { + e.preventDefault(); + sendData(mode, new FormData(this)); + }) + } + } + + function create(tag, className="") { + let el = document.createElement(tag); + el.className = className; + return el; } pageManager.register("user", function () { return { render: function (...args) { - pageManager.setHeader("使用者"); - setTimeout(() => { - pageManager.document.innerHTML = args[0]; - pageManager.setLoaderState(false) - }, 500); + fetchUser(...args); } } });