Продолжение разработки 23.10.31

Добавлен .gitignore, скрыты несколько нинужных файлов, в целом продолжен запил основных частей функционала, начат микрорефакторинг (теперь концентрация индусского кода будет чуть меньше).
This commit is contained in:
Shr3dd3r 2023-10-31 21:57:17 +03:00
parent e487ed79c4
commit 12143c148d
15 changed files with 608 additions and 166 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
_temp/
front/styles/bg_pattern_peace_old.png
test.png
TODO.md

View File

@ -1,6 +1,7 @@
<?php
require_once("_db.php"); //("api/_db.php");
// Includes
require_once("_db.php");

View File

@ -22,4 +22,16 @@ if (!$Config) {
die("invalid configuration file");
}
// Checking paths on existence
function CreateDirIfNotExist ($path) {
if (!is_dir($path))
mkdir($path, 0755, true);
}
CreateDirIfNotExist("../" . $Config["media"]["pics_path"]);
CreateDirIfNotExist("../" . $Config["media"]["prevs_path"]);
?>

View File

@ -1,19 +0,0 @@
<?php
// Internal errors
$Err_Int_JSONEncode = "int.jsonencode"; // Failed to encode JSON data
$Err_Int_Unexpected = "int.unexpected"; // Unexpected result
// Request data parsing errors
$Err_RDP_InvalidID = "rdp.invalidid"; // Requested ID of resource is invalid
$Err_RDP_InvalidArgs = "rdp.invalidargs"; // Invalid arguments supplied to method
// Data processing errors
$Err_DP_IDNotFound = "dp.idnotfound"; // Resource not found by requested ID
$Err_DP_AlreadyLoggedIn = "dp.alreadyloggedin"; // User already logged into account
$Err_DP_RegClosed = "dp.regclosed"; // Registration is closed
$Err_DP_NotEnoughRole = "dp.notenoughrole"; // Power level is not enough for performing action
$Err_DP_FileTooLarge = "dp.filetoolarge"; // Size of file in request is too large
$Err_DP_FileWrongType = "dp.filewrongtype"; // Type of file is invalid
$Err_DP_ImageWrongRes = "dp.imagewrongres"; // Resolution of image is invalid
?>

104
api/_errorslist.php Normal file
View File

@ -0,0 +1,104 @@
<?php // All existing errors
// All existing error codes as integers
const E_NOERROR = 0; // No error
// Unknown (unspecific) errors
const E_UNS_UNEXPECTED = 101; // Unexpected result
const E_UNS_NOTFOUND = 102; // Object not found
const E_UNS_INTERNAL = 103; // Internal error occured
const E_UNS_JSONBADINP = 104; // Cant encode object to JSON string
const E_UNS_NOTIMPL = 105; // Not yet implemented
// User input errors
const E_UIN_WRONGID = 201; // Wrong object id (not found)
const E_UIN_WRONGPATH = 202; // Wrong object path (not found)
const E_UIN_FILE2LARGE = 203; // File size is too large
const E_UIN_FILETYPE = 204; // Wrong file type
const E_UIN_IMGBADRES = 205; // Invalid image resolution
const E_UIN_INSUFARGS = 206; // Not enough arguments was supplied to method
const E_UIN_BADARGS = 207; // Bad arguments
// Authentication errors
const E_AUT_ALRLOGIN = 301; // User is already logged in
const E_AUT_REGCLOSED = 302; // Registrations are closed
const E_AUT_PWD2WEAK = 303; // Password is too weak
const E_AUT_NOTAUTHED = 304; // Not authenticated
// Access errors
const E_ACS_PERMDENIED = 401; // Permission to object denied
const E_ACS_INSUFROLE = 402; // Insufficient role
// Database-related errors
const E_DBE_INSERTFAIL = 501; // INSERT query failed
const E_DBE_SELECTFAIL = 502; // SELECT query failed
const E_DBE_DELETEFAIL = 503; // DELETE query failed
// All existing errors as two-dimensional array
$Errors_Enum = array(
array("noerror", E_NOERROR, "no error"),
// Unspecific errors
array("uns.unexpected", E_UNS_UNEXPECTED, "unexpected result"),
array("uns.notfound", E_UNS_NOTFOUND, "object not found"),
array("uns.internal", E_UNS_INTERNAL, "internal error occured"),
array("uns.jsonbadinp", E_UNS_JSONBADINP, "cant encode object to json string"),
array("uns.notimpl", E_UNS_NOTIMPL, "not yet implemented"),
// User input errors
array("uin.wrongid", E_UIN_WRONGID, "wrong object id (not found)"),
array("uin.wrongpath", E_UIN_WRONGPATH, "wrong object path (not found)"),
array("uin.file2large", E_UIN_FILE2LARGE, "file size is too large"),
array("uin.filetype", E_UIN_FILETYPE, "wrong file type"),
array("uin.imgbadres", E_UIN_IMGBADRES, "invalid image resolution"),
array("uin.insufargs", E_UIN_INSUFARGS, "not enough arguments was supplied to method"),
array("uin.badargs", E_UIN_BADARGS, "bad arguments"),
// Authentication errors
array("aut.alrlogin", E_AUT_ALRLOGIN, "already logged in"),
array("aut.regclosed", E_AUT_REGCLOSED, "registrations are closed"),
array("aut.pwd2weak", E_AUT_PWD2WEAK, "password is too weak"),
array("aut.notauthed", E_AUT_NOTAUTHED, "not authenticated"),
// Access errors
array("acs.permdenied", E_ACS_PERMDENIED, "permission denied"),
array("acs.insufrole", E_ACS_INSUFROLE, "insufficient role"),
// Database-related errors
array("dbe.insertfail", E_DBE_INSERTFAIL, "insert query failed"),
array("dbe.selectfail", E_DBE_SELECTFAIL, "select query failed"),
array("dbe.deletefail", E_DBE_DELETEFAIL, "delete query failed")
);
// Get error code by its name
function Errors_ResolveCodeByName (string $name): int {
global $Errors_Enum;
$m = count($Errors_Enum);
for ($i = 0; $i < $m; ++$i) {
if ($Errors_Enum[$i][0] === $name)
return $Errors_Enum[$i][1];
}
return -1;
}
// Get error name by its code
function Errors_ResolveNameByCode (int $id): string {
global $Errors_Enum;
$m = count($Errors_Enum);
for ($i = 0; $i < $m; ++$i) {
if ($Errors_Enum[$i][1] === $id)
return $Errors_Enum[$i][0];
}
return "";
}
// Get error short description by its code
function Errors_ResolveDescByCode (int $id): string {
global $Errors_Enum;
$m = count($Errors_Enum);
for ($i = 0; $i < $m; ++$i) {
if ($Errors_Enum[$i][1] === $id)
return $Errors_Enum[$i][2];
}
return "";
}
?>

View File

@ -1,24 +1,42 @@
<?php
<?php // JSON-related functions
require_once("_errors.php");
// Includes
require_once("_errorslist.php");
function ReturnJSONData ($arr) {
// Write valid JSON data to stdout and exit
function JSON_ReturnData ($arr) {
$data = json_encode($arr);
if (!$data) {
$data = json_encode(array("error" => $Err_Int_JSONEncode));
$data = json_encode(
array(
"error" => Errors_ResolveNameByCode(E_UNS_JSONBADINP)
)
);
}
header("Content-Type: application/json; charset=utf-8");
echo $data;
exit;
}
function ReturnJSONError ($err, $desc) {
ReturnJSONData(array(
"error" => $err,
"description" => $desc
// Return error as JSON data to stdout and exit
function JSON_ReturnError (int $code = -1, string $name = "", string $desc = "") {
if ($code === -1 && empty($name))
JSON_ReturnError(code: E_UNS_INTERNAL, desc: "cant return error without specified code or name");
else if ($code === -1)
$code = Errors_ResolveCodeByName($name);
else if (empty($name))
$name = Errors_ResolveNameByCode($code);
JSON_ReturnData(array(
"error" => $name, // Name
"error_code" => $code, // Code
"error_hum" => Errors_ResolveDescByCode($code), // Common description
"description" => $desc // Detailed decription
));
}
?>

91
api/_types.php Normal file
View File

@ -0,0 +1,91 @@
<?php // Necessary functions, types and other stuff
// Includes
require_once("_errorslist.php");
require_once("_json.php");
final class ErrorT {
private int $Code;
private string $Name;
private string $Description;
// Ctor
public function __construct(int $code = -1, string $name = "", string $desc = "") {
if ($code === -1 && empty($name))
JSON_ReturnError(code: E_UNS_INTERNAL, desc: "cant construct ErrorT without at least error code or name");
else if ($code === -1)
$code = Errors_ResolveCodeByName($name);
else if (empty($name))
$name = Errors_ResolveNameByCode($code);
$this->Code = $code;
$this->Name = $name;
$this->Description = $desc;
}
// Getter for error code
public function GetCode (): int {
return $this->Code;
}
// Getter for error name
public function GetName (): string {
return $this->Name;
}
// Getter for error description
public function GetDescription (): string {
return $this->Description;
}
// Stringify error
public function Stringify (): string {
if (isset($this->Description))
return "error " . $this->Name . " (" . strval($this->Code) . "): " . $this->Description;
else
return "error " . $this->Name . " (" . strval($this->Code) . ")";
}
}
// Return type of API method
final class ReturnT {
private ErrorT $ErrorObj;
private $Data;
// Ctor
public function __construct($data = null, int $err_code = 0, string $err_name = "", string $err_desc = "") {
$this->ErrorObj = new ErrorT($err_code, $err_name, $err_desc);
$this->Data = $data;
}
// Setter/getter for data
public function SetData ($d) {
$this->Data = $d;
}
public function GetData () {
return $this->Data;
}
// Get string representation of error
public function GetError (): string {
return $this->ErrorObj->Stringify();
}
// Is there any error
public function IsError (): bool {
return $this->ErrorObj->GetCode() !== E_NOERROR;
}
// Throw JSON error
function ThrowJSONError () {
JSON_ReturnError(
$this->ErrorObj->GetCode(),
$this->ErrorObj->GetName(),
$this->ErrorObj->Stringify()
);
}
}
?>

View File

@ -1,12 +1,14 @@
<?php // Utility functions
// Check if request was to specified file
function ThisFileIsRequested ($fullpath): bool {
function Utils_ThisFileIsRequested ($fullpath): bool {
return substr($fullpath, -strlen($_SERVER["SCRIPT_NAME"])) === $_SERVER["SCRIPT_NAME"];
}
// Generate secure random string
function GenerateRandomString (int $length, string $keyspace = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"): string {
function Utils_GenerateRandomString (int $length, string $keyspace = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"): string {
if ($length < 1) {
die("cant generate random string of size less than 1");
}
@ -18,11 +20,22 @@ function GenerateRandomString (int $length, string $keyspace = "abcdefghijklmnop
return implode('', $pieces);
}
// Get aspect ratio from width and height
function GetAspectRatio ($x, $y) {
// Get ratio from two values
function Utils_GetRatio ($x, $y) {
if ($x === $y)
return 1;
return max($x, $y) / min($x, $y);
}
// Join two or more paths pieces to single
function Utils_JoinPaths () {
$paths = array();
foreach (func_get_args() as $arg) {
if ($arg !== '') { $paths[] = $arg; }
}
return preg_replace('#/+#','/',join('/', $paths));
}
?>

47
api/comments/index.php Normal file
View File

@ -0,0 +1,47 @@
<?php // Get all comments from comment section by ID and base methods for managing comment sections
require_once("../_auth.php");
require_once("../_utils.php");
// Get comments from range of selected comment section
function ComSec_Get ($sec_id, $ts_from, $ts_to) {
global $db;
$result = array();
$s = $db->prepare("SELECT * FROM posts WHERE id = ?");
$s->bind_param("s", $id);
$s->execute();
$d = $s->get_result()->fetch_assoc();
if (!(bool)$d) {
return null;
}
if (ThisFileIsRequested(__FILE__)) {
require_once("../_json.php");
$SectionID = null;
if (isset($_REQUEST["id"])) {
if (!ctype_digit($_REQUEST["id"]))
ReturnJSONError($Err_RDP_InvalidID, "id must be numeric");
$SectionID = intval($_REQUEST["id"]);
} else {
ReturnJSONError($Err_RDP_InvalidID, "id must be specified");
}
/*
$ResponseData = ComSec_GetComms($SectionID);
if ($ResponseData)
ReturnJSONData($ResponseData);
else
ReturnJSONError($Err_DP_IDNotFound, "wrong id");
*/
}
?>

View File

@ -1,25 +1,96 @@
<?php // Create new post
// Includes
require_once("../_auth.php");
require_once("../_utils.php");
require_once("../_types.php");
require_once("../user/index.php");
// Create single publication
function Post_Create ($author, $tags, $pic_path, $title = null, $prev_path = null, $comms_enabled = false, $edit_lock = false) {
/*
* FUNCTION
* Check if image size properties are valid
*/
function ImageSizeIsValid ($x, $y) {
global $Config;
return ($x <= $Config["media"]["max_pic_res"]["x"])
&& ($y <= $Config["media"]["max_pic_res"]["y"])
&& (GetRatio($x, $y) <= $Config["media"]["max_pic_res"]["ratio"]);
}
/*
* FUNCTION
* Create preview version of image
*/
function Post_CreatePreviewFromImage ($src, $dst) {
$img = null;
// Reading image from source path
switch (mime_content_type($src)) {
case "image/jpeg":
$img = imagecreatefromjpeg($src);
break;
case "image/png":
$img = imagecreatefrompng($src);
break;
default:
throw new Exception("invalid mime type");
}
// Saving it as LQ JPEG
imagejpeg($img, $dst, 30);
}
/*
* FUNCTION
* Store image
*/
function Post_StoreImage ($path, $preview = true) {
global $Config;
// Paths
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
$fileName = strval(time()) . "_" . GenerateRandomString(4);
$targetDir = "../../" . $Config["media"]["pics_path"];
$targetPath = JoinPaths($targetDir, $fileName . "." . $ext);
// Creating preview file
if ($Config["media"]["previews_enabled"] && $preview) {
$previewDir = "../../" . $Config["media"]["prevs_path"];
$previewPath = JoinPaths($previewDir, $fileName . ".jpg");
Post_CreatePreviewFromImage($path, $previewPath);
}
move_uploaded_file($path, $targetPath);
}
/*
* METHOD
* Create single publication
*/
function Post_Create ($author, $tags, $pic_path, $title = null, $prev_path = null, $comms_enabled = false, $edit_lock = false): ReturnT {
global $db;
// $s = $db->prepare("INSERT ...");
// $s->bind_param("s", $author);
// $s->execute();
// $d = $s->get_result()->fetch_assoc();
//
// if (!(bool)$d) {
// return null;
// }
$result = null;
return $result;
// Check post params
// Author ID should exist
if (!User_IDExist($author))
// TODO
// Performing SQL query
$s = $db->prepare("INSERT INTO posts (author_id,comment_section_id,tags,title,pic_path,preview_path,comments_enabled,edit_lock) VALUES (?,?,?,?,?,?,?,?)");
$s->bind_param("ssssssss", $author, null, $tags, $title, $pic_path, $prev_path, $comms_enabled, $edit_lock);
if ($s->execute() !== true) {
return new ReturnT(null, 601, "failed to create post record in DB");
}
return new ReturnT($result);
}
@ -54,8 +125,16 @@ if (ThisFileIsRequested(__FILE__)) {
// Check if resolution is bigger than allowed or have unacceptable aspect ratio
list($SzX, $SzY, $Type, $Attr) = getimagesize($TmpFilePath);
if ($SzX > $Config["media"]["max_pic_res"]["x"] || $SzY > $Config["media"]["max_pic_res"]["y"] || (GetAspectRatio($SzX, $SzY) > $Config["media"]["max_pic_res"]["ratio"]))
if (!Post_ImageIsValid($SzX, $SzY))
ReturnJSONError($Err_DP_ImageWrongRes, "image with that resolution or aspect ratio cant be accepted");
// TODO: delete image if unacceptable
// Copy picture to storage folder
Post_StoreImage($TmpFilePath, $Config)
// Create post
//$success = Post_Create(
}
?>

View File

@ -1,23 +1,26 @@
<?php // Start session as any user
// ATTENTION: FOR DEBUG PURPOSES ONLY!
// Includes
require_once("../_auth.php");
require_once("../_utils.php");
require_once("../_errorslist.php");
if (ThisFileIsRequested(__FILE__)) {
if (Utils_ThisFileIsRequested(__FILE__)) {
require_once("../_json.php");
if (!$Config["debug"])
ReturnJSONError(null, "you need to enable debug mode in configuration file first");
JSON_ReturnError(code: E_UNS_INTERNAL, desc: "you need to enable debug mode in configuration file first");
if (!isset($_REQUEST["id"]))
ReturnJSONError($Err_RDP_InvalidID, "valid id must be specified");
JSON_ReturnError(code: E_UIN_WRONGID, desc: "valid id must be specified");
if (!isset($_SESSION["userid"]))
session_start();
$_SESSION["userid"] = intval($_REQUEST["id"]);
ReturnJSONData($_SESSION);
JSON_ReturnData($_SESSION);
}
?>

View File

@ -1,16 +1,85 @@
<?php // Creating account
// Includes
require_once("../_auth.php");
require_once("../_utils.php");
require_once("./index.php");
require_once("../_errorslist.php");
require_once("../_types.php");
require_once("index.php");
// Create new user account
function User_Create ($login, $password, $email = null, $invite_id = null, $avatar_path = null): bool {
global $db;
// Methods
$salt = GenerateRandomString(8);
/*
* METHOD
* Create new user account
*/
function User_Create_Method (array $req): ReturnT {
global $db, $Config, $LOGGED_IN;
$login = null;
$password = null;
$email = null;
$invite_id = null;
$avatar_path = null;
// Input sanity checks
// If registration turned off
if (!$Config["registration"]["active"])
return new ReturnT(err_code: E_AUT_REGCLOSED);
// If user is logged in, then we should not allow creation of account
if ($LOGGED_IN)
return new ReturnT(err_code: E_AUT_ALRLOGIN);
// If we have some base data
if (isset($req["login"]) && isset($req["password"])) {
$login = $req["login"];
$password = $req["password"];
// If password is too weak
if (strlen($password) < 8)
return new ReturnT(err_code: E_AUT_PWD2WEAK);
// If we need email but it isnt supplied
if ($Config["registration"]["need_email"] && !isset($req["email"])) {
return new ReturnT(err_code: E_UIN_INSUFARGS, err_desc: "email is necessary");
} elseif (isset($req["email"])) {
// Validation of email
if (!filter_var($req["email"], FILTER_VALIDATE_EMAIL))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "email is invalid");
$email = $req["email"];
}
// If we need invite but it isnt supplied
if ($Config["registration"]["need_invite"] && !isset($req["invite_id"])) {
return new ReturnT(err_code: E_UIN_INSUFARGS, err_desc: "registrations are invite-only, you need to specify invite ID");
} elseif (isset($req["invite_id"])) {
// TODO: check invite and reject if it invalid
//$invite_id = $req["invite_id"];
return new ReturnT(err_code: E_UNS_NOTIMPL, err_desc: "invitations are not implemented");
}
// Check login and password for pattern match
$preg_str = "/[^" . $Config["registration"]["allowed_syms"] . "]/";
if (preg_match($preg_str, $login) || preg_match($preg_str, $password))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "only allowed symbols are: " . $Config["registration"]["allowed_syms"]);
// Check if login already exists
if (User_LoginExist($login))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "login already exists");
// TODO: check $avatar_path
} else { // Not enough arguments
return new ReturnT(err_code: E_UIN_INSUFARGS, err_desc: "not enough or no arguments were supplied");
}
// Actions
$result = null;
$salt = Utils_GenerateRandomString(8);
$pwd_hash = hash("sha256", $password . $salt, true);
// TODO: process invite
@ -18,71 +87,31 @@ function User_Create ($login, $password, $email = null, $invite_id = null, $avat
$s = $db->prepare("INSERT INTO users (login,email,password_hash,salt,avatar_path,role,invite_id) VALUES (?,?,?,?,?,?,?)");
$role = "newbie";
$s->bind_param("sssssss", $login, $email, $pwd_hash, $salt, $avatar_path, $role, $invite_id);
return $s->execute() !== false;
$result = ($s->execute() !== false);
if (!$result)
return new ReturnT(err_code: E_DBE_INSERTFAIL, err_desc: "cant insert record to users DB");
return new ReturnT(data: $result);
}
if (ThisFileIsRequested(__FILE__)) {
if (Utils_ThisFileIsRequested(__FILE__)) {
require_once("../_json.php");
// Dirty hack for debugging purposes. Will be removed later
// HACK: for debugging purposes. Will be removed later
if ($Config["debug"])
$_POST = $_REQUEST;
// If registration turned off
if (!$Config["registration"]["active"]) {
ReturnJSONError($Err_DP_RegClosed, "registrations are closed");
}
// Create account
$result = User_Create_Method($_POST);
// If user is logged in, then we should not allow creation of account
if ($LOGGED_IN)
ReturnJSONError($Err_DP_AlreadyLoggedIn, "you are already logged in");
// If we have some POST data
if (isset($_POST["login"]) && isset($_POST["password"])) {
$login = $_POST["login"];
$password = $_POST["password"];
$email = null;
$invite = null;
// If password is too weak
if (strlen($password) < 8)
ReturnJSONError($Err_RDP_InvalidArgs, "password too weak");
// If we need email but it isnt supplied
if ($Config["registration"]["need_email"] && !isset($_POST["email"])) {
ReturnJSONError($Err_RDP_InvalidArgs, "email is necessary");
} elseif (isset($_POST["email"])) {
// Validation of email
if (!filter_var($_POST["email"], FILTER_VALIDATE_EMAIL))
ReturnJSONError($Err_RDP_InvalidArgs, "email is invalid");
$email = $_POST["email"];
}
// If we need invite but it isnt supplied
if ($Config["registration"]["need_invite"] && !isset($_POST["invite_id"])) {
ReturnJSONError($Err_RDP_InvalidArgs, "registrations are invite-only");
} elseif (isset($_POST["invite_id"])) {
// TODO: check invite and reject if it invalid
//$invite = $_POST["invite_id"];
}
// Check login and password for pattern match
$preg_str = "/[^" . $Config["registration"]["allowed_syms"] . "]/";
if (preg_match($preg_str, $login) || preg_match($preg_str, $password)) {
ReturnJSONError($Err_RDP_InvalidArgs, "only allowed symbols are: " . $Config["registration"]["allowed_syms"]);
}
// Check if login already exists
if (User_LoginExist($login))
ReturnJSONError($Err_RDP_InvalidArgs, "login already exists");
// Create account
$result = User_Create($login, $password, $email, $invite);
ReturnJSONData(["success" => $result]);
} else { // Not enough arguments
ReturnJSONError($Err_RDP_InvalidArgs, "not enough or no arguments were supplied");
}
// Checking result
if ($result->IsError())
$result->ThrowJSONError();
else
JSON_ReturnData(["success" => $result->GetData()]);
}
?>

View File

@ -1,48 +1,66 @@
<?php // Deleting existing account
// Includes
require_once("../_auth.php");
require_once("../_utils.php");
require_once("../_errorslist.php");
require_once("./index.php");
// Delete existing account
function User_Delete ($id) {
global $db;
$s = $db->prepare("delete from users where id = ?");
$s->bind_param("s", $id);
return $s->execute() !== false;
}
// Methods
/*
* METHOD
* Delete existing account
*/
function User_Delete_Method (array $req): ReturnT {
global $db, $LOGGED_IN, $THIS_USER;
$id = null;
if (ThisFileIsRequested(__FILE__)) {
require_once("../_json.php");
// Input sanity checks
// Dirty hack for debugging purposes. Will be removed later
if ($Config["debug"])
$_POST = $_REQUEST;
if (isset($_POST["id"]) && $LOGGED_IN) {
if (!ctype_digit($_POST["id"]))
ReturnJSONError($Err_RDP_InvalidID, "id must be numeric");
$UserID = intval($_POST["id"]);
} elseif (!isset($_POST["id"]) && $LOGGED_IN) {
$UserID = $_SESSION["userid"];
if (isset($req["id"]) && $LOGGED_IN) {
if (!ctype_digit($req["id"]))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "id must be numeric");
$id = intval($req["id"]);
} elseif (!isset($req["id"]) && $LOGGED_IN) {
$id = $THIS_USER;
} else {
ReturnJSONError($Err_RDP_InvalidID, "valid session must be provided");
return new ReturnT(err_code: E_AUT_NOTAUTHED, err_desc: "valid session must be provided");
}
// If its attempt to delete other account
if (!User_HasRole($_SESSION["userid"], "admin") && $_SESSION["userid"] !== $UserID)
ReturnJSONError($Err_DP_NotEnoughRole, "you need to be admin to delete other accounts");
if (!User_HasRole($THIS_USER, "admin") && $THIS_USER !== $id)
return new ReturnT(err_code: E_ACS_INSUFROLE, err_desc: "you must be admin to delete other accounts");
$result = User_Delete($UserID);
// Actions
// If it was self-deletion
if ($UserID === $_SESSION["userid"])
EndSession();
$s = $db->prepare("delete from users where id = ?");
$s->bind_param("s", $id);
ReturnJSONData(["success" => $result]);
return new ReturnT(data: ($s->execute() !== false));
}
if (Utils_ThisFileIsRequested(__FILE__)) {
require_once("../_json.php");
// HACK: for debugging purposes. Will be removed later
if ($Config["debug"])
$_POST = $_REQUEST;
$result = User_Delete_Method($_POST);
if ($result->IsError()) {
$result->ThrowJSONError();
} else {
// If it was self-deletion
if ($id === $THIS_USER)
EndSession();
JSON_ReturnData(["success" => $result->GetData()]);
}
}
?>

View File

@ -1,11 +1,19 @@
<?php // Viewing account data
// Includes
require_once("../_auth.php");
require_once("../_utils.php");
require_once("../_errorslist.php");
require_once("../_types.php");
// Check if user with supplied login exists
// Functions
/*
* FUNCTION
* Check if user with supplied login exists
*/
function User_LoginExist ($login): bool {
global $db;
@ -16,7 +24,24 @@ function User_LoginExist ($login): bool {
return (bool)$s->get_result()->fetch_assoc();
}
// Check if user has specified role
/*
* FUNCTION
* Check if user with supplied ID exists
*/
function User_IDExist ($id): bool {
global $db;
$s = $db->prepare("SELECT * FROM users WHERE id = ?");
$s->bind_param("s", $id);
$s->execute();
return (bool)$s->get_result()->fetch_assoc();
}
/*
* FUNCTION
* Check if user has specified role
*/
function User_HasRole ($id, $role) {
global $db;
@ -25,18 +50,19 @@ function User_HasRole ($id, $role) {
$s->execute();
$d = $s->get_result()->fetch_assoc();
if (!(bool)$d) {
if (!(bool)$d)
return null;
}
if ($d["role"] == $role) {
if ($d["role"] == $role)
return true;
}
return false;
}
// Check if user is moderator
/*
* FUNCTION
* Check if user is moderator (or higher)
*/
function User_IsMod ($id) {
global $db;
@ -52,9 +78,32 @@ function User_IsMod ($id) {
return in_array($d["role"], array("mod", "admin"));
}
// Get user information from DB
function User_GetInfoByID ($id) {
global $db, $THIS_USER;
// Methods
/*
* METHOD
* Get user information from DB
*/
function User_GetInfoByID_Method (array $req): ReturnT {
global $db, $THIS_USER, $LOGGED_IN;
// Input sanity checks
$id = null;
if (isset($req["id"])) {
if (!ctype_digit($req["id"]))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "id must be numeric");
$id = intval($req["id"]);
} else {
if ($LOGGED_IN)
$id = $THIS_USER;
else
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "id must be specified or valid session must be provided");
}
// Actions
$result = array();
@ -63,9 +112,9 @@ function User_GetInfoByID ($id) {
$s->execute();
$d = $s->get_result()->fetch_assoc();
if (!(bool)$d) {
return null;
}
if (!(bool)$d)
return new ReturnT(err_code: E_UIN_WRONGID, err_desc: "user not found in database");
//return new ReturnT(err_code: E_DBE_SELECTFAIL, err_desc: "failed to get user record");
$result["id"] = $d["id"];
$result["created_at"] = $d["created_at"];
@ -78,32 +127,22 @@ function User_GetInfoByID ($id) {
$result["invite_id"] = $d["invite_id"];
}
return $result;
return new ReturnT(data: $result);
}
if (ThisFileIsRequested(__FILE__)) {
if (Utils_ThisFileIsRequested(__FILE__)) {
require_once("../_json.php");
$UserID = null;
$result = User_GetInfoByID_Method($_REQUEST);
if (isset($_REQUEST["id"])) {
if (!ctype_digit($_REQUEST["id"]))
ReturnJSONError($Err_RDP_InvalidID, "id must be numeric");
$UserID = intval($_REQUEST["id"]);
} else {
if ($LOGGED_IN)
$UserID = $THIS_USER;
else
ReturnJSONError($Err_RDP_InvalidID, "id must be specified or valid session must be provided");
}
$ResponseData = User_GetInfoByID($UserID);
if ($ResponseData)
ReturnJSONData($ResponseData);
if ($result->IsError())
$result->ThrowJSONError();
else
ReturnJSONError($Err_DP_IDNotFound, "wrong id");
JSON_ReturnData($result->GetData());
}
?>

View File

@ -16,6 +16,9 @@
"external_avatars": false
},
"media": {
"pics_path": "media/pics/",
"prevs_path": "media/prevs/",
"previews_enabled": true,
"max_pic_size": 56623104,
"max_pic_res": {
"x": 8192,