Метод API для одобренных тегов

Запрос одобренных тегов и проверка конкретного на одобренность, частичные правки мусорных варнов в логах, полунерабочая функция проверки строки на соответствие ASCII, проверки ввода в методе создания поста, мелкие оптимизации запросов к БД в методе запроса данных юзера.
This commit is contained in:
Shr3dd3r 2024-01-20 20:05:45 +03:00
parent e180c04e44
commit 93a2286d46
10 changed files with 151 additions and 14 deletions

View File

@ -4,7 +4,7 @@
// Includes // Includes
if ($IS_FRONTEND) if (isset($IS_FRONTEND) && $IS_FRONTEND)
require_once("api/_db.php"); require_once("api/_db.php");
else else
require_once("_db.php"); require_once("_db.php");

View File

@ -35,7 +35,7 @@ function CreateDirIfNotExist ($path) {
} }
// Creating dirs at correct path // Creating dirs at correct path
if ($IS_FRONTEND) { if (isset($IS_FRONTEND) && $IS_FRONTEND) {
CreateDirIfNotExist($Config["media"]["pics_path"]); CreateDirIfNotExist($Config["media"]["pics_path"]);
CreateDirIfNotExist($Config["media"]["prevs_path"]); CreateDirIfNotExist($Config["media"]["prevs_path"]);
} else { } else {

View File

@ -4,7 +4,7 @@
// Includes // Includes
if ($IS_FRONTEND) if (isset($IS_FRONTEND) && $IS_FRONTEND)
require_once("api/_config.php"); require_once("api/_config.php");
else else
require_once("_config.php"); require_once("_config.php");

View File

@ -4,7 +4,7 @@
// Includes // Includes
if ($IS_FRONTEND) if (isset($IS_FRONTEND) && $IS_FRONTEND)
require_once("api/_errorslist.php"); require_once("api/_errorslist.php");
else else
require_once("_errorslist.php"); require_once("_errorslist.php");

View File

@ -4,7 +4,7 @@
// Includes // Includes
if ($IS_FRONTEND) { if (isset($IS_FRONTEND) && $IS_FRONTEND) {
require_once("api/_errorslist.php"); require_once("api/_errorslist.php");
require_once("api/_json.php"); require_once("api/_json.php");
} else { } else {

View File

@ -18,7 +18,7 @@ function Utils_GenerateRandomString (int $length, string $keyspace = "abcdefghij
for ($i = 0; $i < $length; ++$i) { for ($i = 0; $i < $length; ++$i) {
$pieces []= $keyspace[random_int(0, $max)]; $pieces []= $keyspace[random_int(0, $max)];
} }
return implode('', $pieces); return implode("", $pieces);
} }
// Get ratio from two values // Get ratio from two values
@ -37,6 +37,11 @@ function Utils_JoinPaths () {
return preg_replace('#/+#','/',join('/', $paths)); return preg_replace('#/+#','/',join('/', $paths));
} }
// Check if string is valid ASCII
function Utils_IsAscii (string $str): bool {
return (bool)!preg_match("/[\\x80-\\xff]+/", $string);
}
?> ?>

View File

@ -4,18 +4,20 @@
// Includes // Includes
if ($IS_FRONTEND) { if (isset($IS_FRONTEND) && $IS_FRONTEND) {
require_once("api/_auth.php"); require_once("api/_auth.php");
require_once("api/_utils.php"); require_once("api/_utils.php");
require_once("api/_errorslist.php"); require_once("api/_errorslist.php");
require_once("api/_types.php"); require_once("api/_types.php");
require_once("api/user/index.php"); require_once("api/user/index.php");
require_once("api/tags/index.php");
} else { } else {
require_once("../_auth.php"); require_once("../_auth.php");
require_once("../_utils.php"); require_once("../_utils.php");
require_once("../_errorslist.php"); require_once("../_errorslist.php");
require_once("../_types.php"); require_once("../_types.php");
require_once("../user/index.php"); require_once("../user/index.php");
require_once("../tags/index.php");
} }
@ -203,12 +205,20 @@ function Post_Create_Method (array $req, array $files): ReturnT {
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags string length exceeds limit: " . strval($Config["posting"]["tags"]["max_raw_input_str_length"])); return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags string length exceeds limit: " . strval($Config["posting"]["tags"]["max_raw_input_str_length"]));
elseif ($tagsLen < 1) elseif ($tagsLen < 1)
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags cant be empty"); return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags cant be empty");
// TODO: check if it is ASCII string // Check if supplied string is ASCII
if (!Utils_IsAscii($req["tags"]))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tags must be ASCII-only");
// Parsing tags // Parsing tags
$parsedTags = Post_ParseRawTagString($req["tags"]); $parsedTags = Post_ParseRawTagString($req["tags"]);
if ($parsedTags->IsError()) if ($parsedTags->IsError())
return $parsedTags; return $parsedTags;
// TODO: check if tags are approved $parsedTags = $parsedTags->GetData();
// Check if tags are approved
foreach ($parsedTags as $singleTag) {
if (!Tags_IsTagApproved($singleTag))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag $singleTag is not approved");
}
// Concatenating parsed tags to single comma-separated string
$tags = implode(",", $parsedTags); $tags = implode(",", $parsedTags);
// Check user role TODO: add rate-limiting, instead of this // Check user role TODO: add rate-limiting, instead of this

View File

@ -87,7 +87,7 @@ function Post_GetByID (int $id): ReturnT {
$result["edit_lock"] = $d["edit_lock"]; $result["edit_lock"] = $d["edit_lock"];
$r = Post_AddView($id); // TODO: add rate-limit or completely rework $r = Post_AddView($id); // TODO: add rate-limit or completely rework
if ($r.IsError()) if ($r->IsError())
return $r; return $r;
return new ReturnT(data: $result); return new ReturnT(data: $result);

122
api/tags/index.php Normal file
View File

@ -0,0 +1,122 @@
<?php
// Get info about tags
// Includes
if (isset($IS_FRONTEND) && $IS_FRONTEND) {
require_once("api/_auth.php");
require_once("api/_utils.php");
require_once("api/_errorslist.php");
require_once("api/_types.php");
} else {
require_once("../_auth.php");
require_once("../_utils.php");
require_once("../_errorslist.php");
require_once("../_types.php");
}
// Functions
/*
* FUNCTION
* Get list of all approved tags
*/
function Tags_GetListOfApproved (): array {
global $db;
$result = array();
$s = $db->prepare("SELECT * FROM approved_tags ORDER BY value");
$s->execute();
$d = $s->get_result();
if (!(bool)$d)
return $result;
while ($row = $d->fetch_array()) {
$result[] = $row["value"];
}
return $result;
}
/*
* FUNCTION
* Check if tag is in list of approved tags
*/
function Tags_IsTagApproved (string $str): bool {
global $db;
$s = $db->prepare("SELECT value FROM approved_tags WHERE value = ?");
$s->bind_param("s", $str);
$s->execute();
return (bool)$s->get_result()->fetch_assoc();
}
// Methods
/*
* METHOD
* Check if tag is approved
*/
function Tags_IsTagApproved_Method (array $req): ReturnT {
global $Config;
$requestedTag = $req["value"];
// Input sanity checks
// Check length
$maxTagLen = $Config["posting"]["tags"]["max_single_length"];
$realLen = strlen($requestedTag);
if ($realLen > $maxTagLen)
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag length must be equal to or less than " . strval($maxTagLen));
elseif ($realLen < 1)
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "tag can not be empty");
// Check symbols
$allowedSymbols = $Config["posting"]["tags"]["allowed_syms"];
$preg_str = "/[^" . $allowedSymbols . "]/";
if (preg_match($preg_str, $requestedTag))
return new ReturnT(err_code: E_UIN_BADARGS, err_desc: "only allowed symbols in tags are: " . $allowedSymbols);
// Actions
return new ReturnT(data: array(
"tag" => $requestedTag,
"is_approved" => Tags_IsTagApproved($requestedTag)
));
}
/*
* METHOD
* Get list of all approved tags
*/
function Tags_GetListOfApproved_Method (): ReturnT {
// Actions
return new ReturnT(data: Tags_GetListOfApproved());
}
if (Utils_ThisFileIsRequested(__FILE__)) {
require_once("../_json.php");
if (isset($_REQUEST["value"]))
$result = Tags_IsTagApproved_Method($_REQUEST);
else
$result = Tags_GetListOfApproved_Method();
if ($result->IsError())
$result->ThrowJSONError();
else
JSON_ReturnData($result->GetData());
}
?>

View File

@ -27,7 +27,7 @@ if ($IS_FRONTEND) {
function User_LoginExist (string $login): bool { function User_LoginExist (string $login): bool {
global $db; global $db;
$s = $db->prepare("SELECT * FROM users WHERE login = ?"); $s = $db->prepare("SELECT id FROM users WHERE login = ?");
$s->bind_param("s", $login); $s->bind_param("s", $login);
$s->execute(); $s->execute();
@ -41,7 +41,7 @@ function User_LoginExist (string $login): bool {
function User_IDExist (int $id): bool { function User_IDExist (int $id): bool {
global $db; global $db;
$s = $db->prepare("SELECT * FROM users WHERE id = ?"); $s = $db->prepare("SELECT id FROM users WHERE id = ?");
$s->bind_param("s", $id); $s->bind_param("s", $id);
$s->execute(); $s->execute();
@ -55,7 +55,7 @@ function User_IDExist (int $id): bool {
function User_HasRole (int $id, string $role): ReturnT { function User_HasRole (int $id, string $role): ReturnT {
global $db; global $db;
$s = $db->prepare("SELECT * FROM users WHERE id = ?"); $s = $db->prepare("SELECT role FROM users WHERE id = ?");
$s->bind_param("s", $id); $s->bind_param("s", $id);
$s->execute(); $s->execute();
$d = $s->get_result()->fetch_assoc(); $d = $s->get_result()->fetch_assoc();
@ -73,7 +73,7 @@ function User_HasRole (int $id, string $role): ReturnT {
function User_IsMod (int $id): ReturnT { function User_IsMod (int $id): ReturnT {
global $db; global $db;
$s = $db->prepare("SELECT * FROM users WHERE id = ?"); $s = $db->prepare("SELECT role FROM users WHERE id = ?");
$s->bind_param("s", $id); $s->bind_param("s", $id);
$s->execute(); $s->execute();
$d = $s->get_result()->fetch_assoc(); $d = $s->get_result()->fetch_assoc();