diff --git a/.htaccess b/.htaccess index 8cf4f04f36dc698e440bd929731d212dea8dddda..4156ac75425ccdeffed62046c21d3220dfe152ef 100644 --- a/.htaccess +++ b/.htaccess @@ -6,4 +6,4 @@ Options +FollowSymLinks -MultiViews RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.php [L] -</IfModule> \ No newline at end of file +</IfModule> diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000000000000000000000000000000000000..f7aac01a7ff31ab8916340fab31c96812683b19e --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,10 @@ +<component name="ProjectCodeStyleConfiguration"> + <code_scheme name="Project" version="173"> + <PHPCodeStyleSettings> + <option name="LOWER_CASE_BOOLEAN_CONST" value="true" /> + <option name="LOWER_CASE_NULL_CONST" value="true" /> + <option name="ELSE_IF_STYLE" value="COMBINE" /> + <option name="VARIABLE_NAMING_STYLE" value="CAMEL_CASE" /> + </PHPCodeStyleSettings> + </code_scheme> +</component> \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000000000000000000000000000000000000..79ee123c2b23e069e35ed634d687e17f731cc702 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ +<component name="ProjectCodeStyleConfiguration"> + <state> + <option name="USE_PER_PROJECT_SETTINGS" value="true" /> + </state> +</component> \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000000000000000000000000000000000000..60838b337a064d4f476788dd6ad1faaa0742ed89 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="DataSourceManagerImpl" format="xml" multifile-model="true"> + <data-source source="LOCAL" name="srvMinecraft" uuid="bf92c0da-066e-4fe8-abc0-c86fa43e4d90"> + <driver-ref>mysql.8</driver-ref> + <synchronize>true</synchronize> + <remarks>BDD Serveur MC</remarks> + <jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver> + <jdbc-url>jdbc:mysql://node.sl-projects.com:3306/srvMinecraft</jdbc-url> + <working-dir>$ProjectFileDir$</working-dir> + </data-source> + </component> +</project> \ No newline at end of file diff --git a/.idea/deployment.xml b/.idea/deployment.xml index d818e2e25047bb1361585120e81251ec8e62bc57..69e82a98284901b5f6adc2f7ad782aa06e649016 100644 --- a/.idea/deployment.xml +++ b/.idea/deployment.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="PublishConfigData" autoUpload="On explicit save action" serverName="SL-Craft" remoteFilesAllowedToDisappearOnAutoupload="false" autoUploadExternalChanges="true" showEqualInSync="true"> + <component name="PublishConfigData" autoUpload="On explicit save action" serverName="SL-Craft" deleteMissingItems="true" remoteFilesAllowedToDisappearOnAutoupload="false" autoUploadExternalChanges="true" showEqualInSync="true" showNewOnTargetInSync="false"> <serverData> <paths name="SL-Craft"> <serverdata> diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000000000000000000000000000000000000..d8e9561668720df93b3f31794ece7217fb8ff4b0 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="DiscordProjectSettings"> + <option name="show" value="PROJECT_FILES" /> + <option name="description" value="" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000000000000000000000000000000000..57baa960af2d0a77cc694b3b46ab628bce696661 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,37 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="FunctionNamingConventionJS" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z]*" /> + <option name="m_minLength" value="4" /> + <option name="m_maxLength" value="32" /> + </inspection_tool> + <inspection_tool class="JSClassNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="LocalVariableNamingConventionJS" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z]*" /> + <option name="m_minLength" value="1" /> + <option name="m_maxLength" value="32" /> + </inspection_tool> + <inspection_tool class="ParameterNamingConventionJS" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z]*" /> + <option name="m_minLength" value="1" /> + <option name="m_maxLength" value="32" /> + </inspection_tool> + <inspection_tool class="PhpClassNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="PhpConstantNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="PhpFunctionNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z\d]*" /> + <option name="m_maxLength" value="24" /> + </inspection_tool> + <inspection_tool class="PhpMethodNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_maxLength" value="24" /> + </inspection_tool> + <inspection_tool class="PhpPropertyNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="PhpUndefinedVariableInspection" enabled="true" level="ERROR" enabled_by_default="true"> + <option name="IGNORE_INCLUDE" value="true" /> + </inspection_tool> + <inspection_tool class="PhpVariableNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z\d]*" /> + </inspection_tool> + </profile> +</component> \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000000000000000000000000000000000000..23e77e1612d38475653e63b930e101375dfb150a --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="SqlDialectMappings"> + <file url="file://$PROJECT_DIR$/core/classes/Item.php" dialect="GenericSQL" /> + <file url="file://$PROJECT_DIR$/core/classes/Shop.php" dialect="GenericSQL" /> + <file url="PROJECT" dialect="MariaDB" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/sshConfigs.xml b/.idea/sshConfigs.xml index cafa4ab8f6f18041c33616fa3424e425ab25c499..8f8c7ac77d742a90393e6a02d63680b23411b514 100644 --- a/.idea/sshConfigs.xml +++ b/.idea/sshConfigs.xml @@ -2,7 +2,7 @@ <project version="4"> <component name="SshConfigs"> <configs> - <sshConfig authType="PASSWORD" host="192.168.1.16" id="97adedb8-8832-47f7-a52a-6c1ae617a01a" port="22" nameFormat="DESCRIPTIVE" username="root" useOpenSSHConfig="true" /> + <sshConfig authType="PASSWORD" host="node.sl-projects.com" id="97adedb8-8832-47f7-a52a-6c1ae617a01a" port="22" nameFormat="DESCRIPTIVE" username="root" useOpenSSHConfig="true" /> </configs> </component> </project> \ No newline at end of file diff --git a/.idea/webServers.xml b/.idea/webServers.xml index c0d2a4f23f0ba0714f9a3a10ea966b2c2f6da4dd..fb0366713d444b3a94f0fcd6ec7dd43624e957dd 100644 --- a/.idea/webServers.xml +++ b/.idea/webServers.xml @@ -3,7 +3,7 @@ <component name="WebServers"> <option name="servers"> <webServer id="24631c59-2e41-4506-ad50-24435095dc45" name="SL-Craft" url="https://dev.sl-craft.fr/"> - <fileTransfer rootFolder="/home/serveur-web/sl-craft-dev/" accessType="SFTP" host="192.168.1.16" port="22" sshConfigId="97adedb8-8832-47f7-a52a-6c1ae617a01a" sshConfig="root@192.168.1.16:22 password"> + <fileTransfer rootFolder="/home/serveur-web/sl-craft-dev/" accessType="SFTP" host="node.sl-projects.com" port="22" sshConfigId="97adedb8-8832-47f7-a52a-6c1ae617a01a" sshConfig="root@node.sl-projects.com:22 password"> <advancedOptions> <advancedOptions dataProtectionLevel="Private" keepAliveTimeout="0" passiveMode="true" shareSSLContext="true" /> </advancedOptions> diff --git a/configuration.php b/configuration.php new file mode 100644 index 0000000000000000000000000000000000000000..e1227d289ed6298794a6120be2fc35df20b7783c --- /dev/null +++ b/configuration.php @@ -0,0 +1,6 @@ +<?php +// Informations de connexion à la base de données +$config['db']['hostName'] = 'node.sl-projects.com'; +$config['db']['databaseName'] = 'srvMinecraftDev'; +$config['db']['userName'] = 'srvMinecraft'; +$config['db']['userPassword'] = 'YIn2hTln5iMQap1W'; diff --git a/core/classes/Admin.php b/core/classes/Admin.php index f09706dedc9b59e0c27fde40a4563226c02481df..826aaa2307be264d81871699120716e88afbac20 100644 --- a/core/classes/Admin.php +++ b/core/classes/Admin.php @@ -1,6 +1,9 @@ <?php class Admin{ // Charger une page admin + /** + * @throws Exception + */ public static function loadPage($alias){ if(Admin::checkAdmin()){ if($alias[0]=="backTasks" && (!empty($_POST)||!empty($_GET))){ @@ -11,7 +14,7 @@ public static function loadPage($alias){ }else{ // On va vérifier que la page existe if(file_exists('pages/admin/'.$alias[0].'.php')){ - if(verifyUserPermission($_SESSION['userId'], "adminPanel.".$alias[0]."Access")){ + if(verifyUserPermission($_SESSION['uuid'], "slcraft.website.admin.".$alias[0]."access")){ require 'pages/admin/'.$alias[0].'.php'; }else{ Admin::show403($alias[0]); @@ -23,7 +26,7 @@ public static function loadPage($alias){ } }else{ // Retrour sur la page de connexion si non conneté, ou s'il n'a pas les perms - header("Location: ".genPageLink("/login")); + header("Location: /login"); } } diff --git a/core/classes/BddConn.php b/core/classes/BddConn.php new file mode 100644 index 0000000000000000000000000000000000000000..1b1a0c78c0e306e959c2be88fc0076ba31e06115 --- /dev/null +++ b/core/classes/BddConn.php @@ -0,0 +1,37 @@ +<?php +class BddConn { + // Attribut de la classe BddConn paramètres d'encodage + static private array $tabUTF8 = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"); + + // Attribut de la classe BddConn qui recevra l'instance PDO + static private PDO $pdoDriver; + + // Getter de pdo + static public function getPdo(): PDO { + return self::$pdoDriver; + } + + // Fonction de connexion + static public function connect() { + // On vérifie si l'instance PDO est déjà créée + if(!isset(self::$pdoDriver)) { + // On crée une instance de PDO + // On récupère le fichier de configuration + require 'configuration.php'; + // On récupère les paramètres de connexion + $hostName = $config['db']['hostName']; + $databaseName = $config['db']['databaseName']; + $userName = $config['db']['userName']; + $userPassword = $config['db']['userPassword']; + + $options = self::$tabUTF8; + try { + self::$pdoDriver = new PDO("mysql:host=$hostName;dbname=$databaseName",$userName,$userPassword,$options); + self::$pdoDriver->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } catch(PDOException $error) { + echo "Erreur de connexion : " . $error->getMessage(); + } + + } + } +} \ No newline at end of file diff --git a/core/classes/Client.php b/core/classes/Client.php index c962d17d324798573d4dbba36aeaf5fedfd2a753..b98632264236d93c217a9ab1a96563ec8013ee02 100644 --- a/core/classes/Client.php +++ b/core/classes/Client.php @@ -2,6 +2,7 @@ class Client{ // Charger une page client public static function loadPage($alias){ + // Charger le fichier de la page if($alias[0]=="backTasks" && (!empty($_POST)||!empty($_GET))){ // Si le premier alias est backTasks, on va donc charger la page backTasks // backTasks est un alias que l'on appel pour toutes requêtes Javascript ex: vérification de l'existence d'un email dans la bdd diff --git a/core/classes/Connexion.php b/core/classes/Connexion.php deleted file mode 100644 index 5fc6467457e38c2d194bc9355f15d2e3c8a5159d..0000000000000000000000000000000000000000 --- a/core/classes/Connexion.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -class Connexion { - -/* -// attributs de la classe Connexion paramètres de connexion à la base -static private $hostname = 'localhost'; -static private $database = 'marmiuton'; -static private $login = 'marmiuton'; -static private $password = 's6rqTiA0hNKmcgy7'; -*/ - -// attribut de la classe Connexion paramètres d'encodage -static private $tabUTF8 = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"); - -// attribut de la classe Connexion qui recevra l'instance PDO -static private $pdo; - -// getter de pdo -static public function pdo() {return self::$pdo;} - -// fonction de connexion -static public function connect() { - require "core/conf/ConfigurationGenerale.php"; // Ce fichier contient les identifiants - $h = $bddHost; - $d = $bddName; - $l = $bddUsername; - $p = $bddUserPassword; - $t = self::$tabUTF8; - try { - self::$pdo = new PDO("mysql:host=$h;dbname=$d",$l,$p,$t); - self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } catch(PDOException $e) { - echo "Erreur de connexion !"; - } - } -} \ No newline at end of file diff --git a/core/classes/Item.php b/core/classes/Item.php index 85054d6e2f8f2d1a21444d33920b2bffab4ec9b8..68dd3907e763f4bb6a76a87ae1079523564ff3f8 100644 --- a/core/classes/Item.php +++ b/core/classes/Item.php @@ -1,86 +1,149 @@ <?php class Item{ - private $label; - private $price; - private $css; - private $type; - private $id; - private $displayName; - private $enchants; - - public function __construct($item){ - if(is_array($item)){ - $this->id = strtolower($item['type']); + private string $label; + private string $cssClassName; + private $representation; + private string $type; + private string $displayName; + private array $enchants; + + /** + * @throws Exception + */ + public function __construct($itemInfos){ + if(is_array($itemInfos)){ + // On va vérifier qu'il s'agit bien d'un tableau contenant les infos d'un item + if(!isset($itemInfos["type"])){ + throw new Exception("Ce tableau n'est pas un item"); + } + $this->type = strtolower($itemInfos['type']); - if(isset($item['meta'])){ - if(isset($item['meta']['display-name'])){ - $displayNameJson = json_decode($item['meta']['display-name'], true); + // L'item peut avoir des caractéristiques particulières, comme des enchantements par exemple + if(isset($itemInfos['meta'])){ + if(isset($itemInfos['meta']['display-name'])){ + $displayNameJson = json_decode($itemInfos['meta']['display-name'], true); $this->displayName = $displayNameJson['text']; + }else{ + $this->displayName = ""; } - if(isset($item['meta']['enchants'])){ - $this->enchants = $item['meta']['enchants']; + if(isset($itemInfos['meta']['enchants'])){ + $this->enchants = $itemInfos['meta']['enchants']; + }else{ + $this->enchants = []; } + }else{ + $this->displayName = ""; + $this->enchants = []; } }else{ - $this->id=$item; + // Ici on a un nom d'item + $this->type=$itemInfos; + $this->displayName = ""; + $this->enchants = []; } - $query = Connexion::pdo()->prepare("SELECT * FROM site_itemsAssoc WHERE name=?"); - $query->execute(array($this->id)); + // On va chercher l'item dans la table d'association des items afin de récupérer les infos + $query = BddConn::getPdo()->prepare("SELECT * FROM site_itemsAssoc WHERE name=?"); + $query->execute(array($this->type)); $result= $query->fetch(PDO::FETCH_ASSOC); $this->label = $result['label']; - $this->css = $result['css']; + $this->cssClassName = $result['css']; + $this->representation = $result['representation']; } - public function getLabel(){ + public function getLabel(): string + { return $this->label; } - public function getPrice(){ - return $this->price; - } - - public function getCss(){ - return $this->css; + public function getCssClassName(): string + { + return $this->cssClassName; } - public function getType(){ + public function getType(): string + { return $this->type; } - - public function getId(){ - return $this->id; - } - public function getRepresentation(){ + + public function getRepresentation(): array + { $return["texture"] = array(); - if(file_exists("data/images/textures/block/".$this->id.".png")){ - $return["type"] = "block"; - $return["texture"][0] = "data/images/textures/block/".$this->id.".png"; - if(file_exists("data/images/textures/block/".$this->id."_top.png")){ - $return["texture"][1] = "data/images/textures/block/".$this->id."_top.png"; - } - }elseif(file_exists("data/images/textures/block/".$this->id."_side.png")){ - $return["type"] = "block"; - $return["texture"][0] = "data/images/textures/block/".$this->id."_side.png"; - if(file_exists("data/images/textures/block/".$this->id."_top.png")){ - $return["texture"][1] = "data/images/textures/block/".$this->id."_top.png"; + + // On va regarder si on a une représentation pour cet item + // Ça sera plus rapide avec la représentation de sauvegardée + if(isset($this->representation) && !empty($this->representation) && isset($this->representation["type"])){ + if($this->representation["type"] == "block"){ + $return["type"] = "block"; + $return["texture"][0] = "data/images/textures/block/".$this->type.".png"; + if($this->representation["hasTop"]){ + $return["texture"][1] = "data/images/textures/block/".$this->type."_top.png"; + }else{ + $return["texture"][1] = $return["texture"][0]; + } + }else if($this->representation["type"] == "block_side"){ + $return["type"] = "block"; + $return["texture"][0] = "data/images/textures/block/".$this->type."_side.png"; + if($this->representation["hasTop"]){ + $return["texture"][1] = "data/images/textures/block/".$this->type."_top.png"; + }else{ + $return["texture"][1] = $return["texture"][0]; + } + }else if($this->representation["type"] == "item") { + $return["type"] = "item"; + $return["texture"][0] = "data/images/textures/item/" . $this->type . ".png"; + }else{ + $return["type"] = "unknown"; + $return["texture"][0] = "data/images/textures/missing.png"; } - }elseif(file_exists("data/images/textures/item/".$this->id.".png")){ - $return["type"] = "item"; - $return["texture"][0] = "data/images/textures/item/".$this->id.".png"; }else{ - $return["type"] = "unknown"; - $return["texture"][0] = "data/images/textures/missing.png"; - } + // Sera plus long à éxecuter vu qu'on va tout vérifier + $representation = array(); + if(file_exists("data/images/textures/block/".$this->type.".png")){ + $return["type"] = "block"; + $representation["type"] = "block"; + $return["texture"][0] = "data/images/textures/block/".$this->type.".png"; + if(file_exists("data/images/textures/block/".$this->type."_top.png")){ + $return["texture"][1] = "data/images/textures/block/".$this->type."_top.png"; + $representation["hasTop"] = true; + }else{ + $representation["hasTop"] = false; + } + }elseif(file_exists("data/images/textures/block/".$this->type."_side.png")){ + $return["type"] = "block_side"; + $representation["type"] = "block"; + $return["texture"][0] = "data/images/textures/block/".$this->type."_side.png"; + if(file_exists("data/images/textures/block/".$this->type."_top.png")){ + $return["texture"][1] = "data/images/textures/block/".$this->type."_top.png"; + $representation["hasTop"] = true; + }else{ + $representation["hasTop"] = false; + } + }elseif(file_exists("data/images/textures/item/".$this->type.".png")){ + $return["type"] = "item"; + $representation["type"] = "item"; + $return["texture"][0] = "data/images/textures/item/".$this->type.".png"; + }else{ + $return["type"] = "unknown"; + $representation["type"] = "unknown"; + $return["texture"][0] = "data/images/textures/missing.png"; + } + + if(!isset($return["texture"][1])){ + $return["texture"][1] = $return["texture"][0]; + } - if(!isset($return["texture"][1])){ - $return["texture"][1] = $return["texture"][0]; + // On va mettre à jour la représentation de l'item + $query = BddConn::getPdo()->prepare("UPDATE site_itemsAssoc SET representation=? WHERE name=?"); + $query->execute(array(json_encode($representation), $this->type)); } return $return; } - public function getDisplayName(){ + public function getDisplayName(): string + { return $this->displayName; } - public function getEnchants(){ + public function getEnchants(): array + { return $this->enchants; } } \ No newline at end of file diff --git a/core/classes/Seller.php b/core/classes/Seller.php index f433c8e998acc22447b1dcfebb89900a18fc8ca1..64f1d2e06d80b42b5b1379b9e96b7134edb11ba2 100644 --- a/core/classes/Seller.php +++ b/core/classes/Seller.php @@ -1,26 +1,29 @@ <?php class Seller{ - private $uuid; - private $username; - private $skin; + private string $uuid; + private string $username; + private string $skin; public function __construct($uuid){ $this->uuid = $uuid; - $json = file_get_contents('https://sessionserver.mojang.com/session/minecraft/profile/'.$uuid); - $profile = json_decode($json, true); - $this->username = $profile['name']; + $jsonProfileInfos = file_get_contents('https://sessionserver.mojang.com/session/minecraft/profile/'.$uuid); + $profileInfos = json_decode($jsonProfileInfos, true); + $this->username = $profileInfos['name']; - $properties = json_decode(base64_decode($profile['properties'][0]['value']), true); + $properties = json_decode(base64_decode($profileInfos['properties'][0]['value']), true); $this->skin = $properties['textures']['SKIN']['url']; } - public function getUuid(){ + public function getUuid(): string + { return $this->uuid; } - public function getUsername(){ + public function getUsername(): string + { return $this->username; } - public function getSkin(){ + public function getSkin(): string + { return $this->skin; } } \ No newline at end of file diff --git a/core/classes/Shop.php b/core/classes/Shop.php index 67fca8737512476bfac1fccdfa1446e59e364676..af08cbccea57fc35faebb8296cf5df46f734ee1e 100644 --- a/core/classes/Shop.php +++ b/core/classes/Shop.php @@ -1,7 +1,9 @@ <?php class Shop{ - public static function getAllProducts(){ - $itemsConfig = Connexion::pdo()->query("SELECT itemConfig FROM qs_shops")->fetchAll(PDO::FETCH_ASSOC); + public static function getAllProducts(): array + { + // On récupère tous les items des magasins + $itemsConfigsYaml = BddConn::getPdo()->query("SELECT itemConfig FROM qs_shops")->fetchAll(PDO::FETCH_ASSOC); /* item: @@ -9,36 +11,50 @@ public static function getAllProducts(){ v: 2865 type: WHEAT */ - - $return = array(); - foreach($itemsConfig as $itemConfig){ - $item = yaml_parse($itemConfig['itemConfig']); - $itemAleadyEntered = false; - foreach($return as $checkItem){ - if(strtolower($item['item']['type']) == $checkItem->getId()){ - $itemAleadyEntered = true; + // On va faire la liste de tous les items + $items = array(); + foreach($itemsConfigsYaml as $itemConfigYaml){ + // On parse le YAML + $itemConfig = yaml_parse($itemConfigYaml['itemConfig']); + + $alreadyInList = false; + foreach($items as $checkItem){ + if(strtolower($itemConfig['item']['type']) == $checkItem->getType()){ + $alreadyInList = true; + break; // On sort de la boucle } } - if(!$itemAleadyEntered){ - $return[] = new Item($item['item']['type']); + if(!$alreadyInList){ + $items[] = new Item($itemConfig['item']['type']); } } - return $return; + return $items; } - public static function getShops($search=null){ - if(is_array($search)){ - }else{ - // On récupère les shops - $shops = Connexion::pdo()->query("SELECT * FROM qs_external_cache NATURAL JOIN qs_shops")->fetchAll(PDO::FETCH_ASSOC); - for($i=0;$i<count($shops);$i++){ - $item = yaml_parse($shops[$i]['itemConfig']); - $shops[$i]['item'] = new Item($item['item']); - $owner = json_decode($shops[$i]['owner'], true); - $shops[$i]['seller'] = new Seller($owner["owner"]); + /** + * @throws Exception + */ + public static function getShops($search=array()): array + { + if(is_array($search)){ + if(empty($search)){ + // On récupère les shops + $shops = BddConn::getPdo()->query("SELECT * FROM qs_external_cache NATURAL JOIN qs_shops")->fetchAll(PDO::FETCH_ASSOC); + for($index=0;$index<count($shops);$index++){ + $itemConfig = yaml_parse($shops[$index]['itemConfig']); + $shops[$index]['item'] = new Item($itemConfig['item']); + $owner = json_decode($shops[$index]['owner'], true); + $shops[$index]['seller'] = new Seller($owner["owner"]); + } + return $shops; + }else{ + // TODO: faire une recherche par critère + return array(); } - return $shops; + }else{ + // On lance une exception car on souhaite avoir un array + throw new Exception("Search doit être un array"); } } } \ No newline at end of file diff --git a/core/conf/ConfigurationGenerale.php b/core/conf/ConfigurationGenerale.php deleted file mode 100644 index 493a315361151acd0e4b33225710751e7ed57b60..0000000000000000000000000000000000000000 --- a/core/conf/ConfigurationGenerale.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php -// attributs de la classe Connexion paramètres de connexion à la base -$bddHost = 'node.sl-projects.com'; -$bddName = 'srvMinecraft'; -$bddUsername = 'srvMinecraft'; -$bddUserPassword = 'YIn2hTln5iMQap1W'; - -// Cette variable défini le mode de reconnaissance des url -// Sur le serveur de l'IUT, on ne peut pas utiliser les alias de l'url pour détecter les pages, vu que nous ne sommes pas sur la racine du domaine -// Il faut donc fonctionner avec les paramètres de l'url. \ No newline at end of file diff --git a/core/controller/adminBackTasks.php b/core/controller/adminBackTasks.php index d17bb56945f247970da225daf9f639c99573436e..c7db02be6a45f4fb2829e33d59b33882c255fea7 100644 --- a/core/controller/adminBackTasks.php +++ b/core/controller/adminBackTasks.php @@ -2,7 +2,7 @@ if(isset($_GET['saveSettings']) && !empty($_POST)){ foreach($_POST as $index => $value){ if(!empty($index)){ - $query = Connexion::pdo()->prepare('UPDATE `m_siteSetting` SET `value` = ? WHERE `name` = ?'); + $query = BddConn::getPdo()->prepare('UPDATE `m_siteSetting` SET `value` = ? WHERE `name` = ?'); $query->execute([$value, $index]); } } diff --git a/core/controller/functions.php b/core/controller/functions.php index d956263d0ba94a720aca8565485d64b434dd87b6..8c10f034558152fd222dca023ee8085db7c9b444 100644 --- a/core/controller/functions.php +++ b/core/controller/functions.php @@ -1,7 +1,14 @@ <?php +// Récupération du lien du site (évite de devoir appeler la base de donnée) +function getWebsiteUrl(): string +{ + global $httpProtocol; + return $httpProtocol."://" . $_SERVER['HTTP_HOST'] . "/"; +} + //Chargement des pages function loadPage(){ - global $localSettings, $urlPath; + global $urlPath; // S'il existe un paramètre on l'affecte à pageName $alias = $urlPath; @@ -13,7 +20,7 @@ function loadPage(){ // Maintenant qu'alias[0] aura toujours une valeur, on peut commencer à la comparer if($alias[0]=="admin"){ - if(!isset($alias[1])||empty($alias[1])){ + if(empty($alias[1])){ $alias[1] = "index"; } @@ -28,257 +35,96 @@ function loadPage(){ } } -// Vérifie si un username ou un email existe dans la bdd -function checkUsernameEmail($data){ - $pos = strpos($data, "@"); - if ($pos !== false) { - $response = Connexion::pdo()->prepare("SELECT * FROM site_userSetting WHERE name='email' AND value=?"); - $response->execute([strtolower($data)]); - if (empty($response->fetch())) { - return false; - } else { - return true; - } - } else { - $response = Connexion::pdo()->prepare("SELECT * FROM site_user WHERE username=?"); - $response->execute([strtolower($data)]); - if (empty($response->fetch())) { - return false; - } else { - return true; - } - } -} -function login($usernameEmail, $password){ - global $ip; - $usernameEmail = strtolower($usernameEmail); - $pos = strpos($usernameEmail, "@"); - if ($pos !== false) { - $response = Connexion::pdo()->prepare("SELECT userId FROM site_userSetting WHERE name='email' AND value=?"); - $response->execute([$usernameEmail]); - $supposedUserId = $response->fetchColumn(); - - $response = Connexion::pdo()->prepare("SELECT * FROM site_user WHERE id=?"); - $response->execute([$supposedUserId]); - } else { - $response = Connexion::pdo()->prepare("SELECT * FROM site_user WHERE username=?"); - $response->execute([$usernameEmail]); - } - $user=$response->fetch(PDO::FETCH_ASSOC); - if (!empty($user)) { - if(password_verify($password, $user["password"])){ - // On vérifie l'ip - $response = Connexion::pdo()->prepare("SELECT * FROM site_userSetting WHERE userId=? AND name='lastIp'"); - $response->execute([$user['id']]); - $result = $response->fetch(PDO::FETCH_ASSOC); - - if (empty($result)) { - // Aucun champ d'ip n'existe - $response = Connexion::pdo()->prepare("INSERT INTO site_userSetting (`userId`, `name`, `value`) VALUES (?,?,?)"); - $response->execute([$user['id'], 'lastIp', $ip]); - }else{ - if($result["value"]!=$ip){ - // Il existe un champ, on va le comparer - $response = Connexion::pdo()->prepare("UPDATE site_userSetting SET `value`=? WHERE `userId`=? AND name='lastIp'"); - $response->execute([$ip, $user['id']]); - } - - } - - $_SESSION['userId'] = $user['id']; - $_SESSION['userName'] = $user['username']; - $_SESSION['userGroupId'] = $user['groupId']; - - $userProfilPic = Connexion::pdo()->prepare("SELECT value FROM site_userSetting WHERE userId=? AND name='profilPic'"); - $userProfilPic->execute([$user['id']]); - $userProfilPic = $userProfilPic->fetchColumn(); - - if (empty($userProfilPic)) { - $userProfilPic = "data/images/misc/user.png"; - } - $userProfilPic = getWebsiteSetting("websiteUrl") . $userProfilPic; - - $_SESSION['userProfilePic'] = $userProfilPic; - $return["success"] = "Connexion réussie, bienvenue " . $_SESSION['userName'] . "! 🥳"; - } else { - $return["error"] = "Mauvais couple identifiant/mot de passe."; - } - } else { - $return["error"] = "Mauvais couple identifiant/mot de passe."; - } - return $return; -} - -function registerUser($username, $password, $email){ - if (preg_match('/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,32}$/', $password)==1) { - $username = strtolower(htmlspecialchars($username)); - $email = strtolower(htmlspecialchars($email)); // ici on converti l'email donné en casse minuscule - $password = password_hash($password, PASSWORD_DEFAULT); - - // Ici on récupère l'id du groupe des utilisateurs - $userGroupId = Connexion::pdo()->query("SELECT id FROM site_userGroup WHERE nom='utilisateur'")->fetchColumn(); - - // Là on va insérer l'utilisateur dans la table des utilisateurs - $query = Connexion::pdo()->prepare("INSERT INTO site_user (id, groupId, username, password) VALUES (?,?, ?, ?)"); - $query->execute([null, $userGroupId, $username, $password]); - - // Maintenant on va récuper son id - $query = Connexion::pdo()->prepare("SELECT id FROM site_user WHERE username=?"); - $query->execute([$username]); - $userId = $query->fetchColumn(); - - // On va insérer son adresse mail - $query = Connexion::pdo()->prepare("INSERT INTO site_userSetting (`userId`, `name`, `value`) VALUES (?,?,?)"); - $query->execute([$userId, 'email', $email]); - - // Sa date d'inscription - $query = Connexion::pdo()->prepare("INSERT INTO site_userSetting (`userId`, `name`, `value`) VALUES (?,?,?)"); - $query->execute([$userId, 'joinedDate', date("Y-m-d H:i:s")]); - - $return["success"] = "Inscription réussie, tu peux désormais te connecter! 🥳"; - } else { - $return["error"] = 'Ton mot de passe doit être long d\'au moins 8 caractères et doit contenir au moins 1 majuscule, 1 minuscule et 1 nombre.'; - } - return $return; -} - // Vérifie les permissions -function verifyUserPermission($userId, $permission){ - // $permission peut être un tableau ou un string - if(is_array($permission)){ - if(count($permission)!=2){ - throw new Exception('Erreur! Le tableau doit être composé de 2 éléments.'); - } - $groupName = $permission[0]; - $permissionName = $permission[1]; +/** + * @throws Exception + */ +function verifyUserPermission($userUUID, $permission): bool +{ + // $permission doit être un string + if (!is_string($permission)) { + throw new Exception("La permission doit être une chaîne de caractères"); + } + // On va vérifier la permission dans les tables de LuckPerms + $permission = strtolower($permission); + + // On va regarder si l'utilisateur a une autorisation particulière + $permissionExists = BddConn::getPdo()->prepare("SELECT * FROM luckperms_user_permissions WHERE uuid = :user_uuid AND permission = :permission AND value = 1"); + $permissionExists->bindParam(":user_uuid", $userUUID); + $permissionExists->bindParam(":permission", $permission); + $permissionExists->execute(); + $permissionExists = $permissionExists->fetch(PDO::FETCH_ASSOC); + + if($permissionExists){ + $hasPermission = true; }else{ - if(strpos($permission, '.') == false){ - throw new Exception('Erreur! La permission doit suivre la règle suivante: groupeName.permissionName'); - }else{ - $temp = explode('.', $permission); - if(count($temp)!=2){ - throw new Exception('Erreur! La permission doit suivre la règle suivante: groupeName.permissionName'); - } - $groupName = $temp[0]; - $permissionName = $temp[1]; - } + // L'utilisateur n'a pas d'autorisation particulière + // Du coup on va regarder à quel groupe appartient l'utilisateur + $groupName = BddConn::getPdo()->prepare("SELECT primary_group FROM luckperms_players WHERE uuid = :uuid"); + $groupName->bindParam(":uuid", $userUUID); + $groupName->execute(); + $groupName = $groupName->fetch(PDO::FETCH_COLUMN); + + // Maintenant on va chercher si le groupe a la permission + $hasPermission = verifyGroupPermission($groupName, $permission); } - // On peut maintenant vérifier dans la bdd - $response = Connexion::pdo()->prepare("SELECT site_permission.id FROM site_permissionGroup INNER JOIN site_permission ON site_permissionGroup.id=site_permission.groupId WHERE site_permissionGroup.name=? AND site_permission.name=?"); - $response->execute([$groupName, $permissionName]); - $targetPermId = $response->fetchColumn(); + // On retourne le résultat + return $hasPermission; +} - if(empty($targetPermId)){ - throw new Exception('Erreur! La permission \''.$groupName.'.'.$permissionName.'\' n\'existe pas.'); +// Vérifie les permissions d'un groupe +/** + * @throws Exception + */ +function verifyGroupPermission($groupName, $permission): bool +{ + // $permission doit être un string + if (!is_string($permission)) { + throw new Exception("La permission doit être une chaîne de caractères"); } - - // On va commencer par vérifier les permissions de l'utilisateur - if(isSuperAdmin($userId)){ - return true; + // On va dire que par défaut, il n'a pas les perms + $hasPermission = false; + + // On va vérifier si le groupe a toutes les permissions + $permissionExists = BddConn::getPdo()->prepare("SELECT * FROM luckperms_group_permissions WHERE name = :name AND permission = '*' AND value = 1"); + $permissionExists->bindParam(":name", $groupName); + $permissionExists->execute(); + $permissionExists = $permissionExists->fetch(PDO::FETCH_ASSOC); + + if($permissionExists){ + // Le groupe a toutes les permissions + $hasPermission = true; }else{ - $response = Connexion::pdo()->prepare("SELECT COUNT(*) FROM site_userPermission WHERE userId=? AND permId=?"); - $response->execute([$userId, $targetPermId]); - $hasPermission = $response->fetchColumn(); - if($hasPermission == 0)$hasPermission = false; - else $hasPermission = true; - } - - - // Si l'utilisateur n'a pas la permission, on va vérifier si le groupe l'a - if(!$hasPermission){ - $response = Connexion::pdo()->prepare("SELECT groupId FROM site_user WHERE id=?"); - $response->execute([$userId]); - $userGroupId = $response->fetchColumn(); - - if(empty($userGroupId)){ - throw new Exception('Erreur! L\'utilisateur n\'existe pas.'); + $permissionExists = BddConn::getPdo()->prepare("SELECT * FROM luckperms_group_permissions WHERE name = :name AND permission LIKE :permission"); + $permissionExists->bindParam(":name", $groupName); + $permissionExists->bindParam(":permission", $permission); + $permissionExists->execute(); + $permissionExists = $permissionExists->fetch(PDO::FETCH_ASSOC); + + if ($permissionExists) { + $hasPermission = true; } - - $response = Connexion::pdo()->prepare("SELECT COUNT(*) FROM site_userGroupPermission WHERE groupId=? AND permId=?"); - $response->execute([$userGroupId, $targetPermId]); - $hasPermission = $response->fetchColumn(); - if($hasPermission == 0)$hasPermission = false; - else $hasPermission = true; } - return $hasPermission; } -// Check si l'utilisateur est surper utilisateur -function isSuperAdmin($userId){ - $superAdminGroupId = Connexion::pdo()->query("SELECT id FROM site_userGroup WHERE nom='superAdmin'")->fetchColumn(); - $response = Connexion::pdo()->prepare("SELECT COUNT(*) FROM site_user WHERE id=? AND groupId=?"); - $response->execute([$userId, $superAdminGroupId]); - $isSuperAdmin = $response->fetchColumn(); - if($isSuperAdmin == 0) return false; - else return true; -} - // Récupère les paramètres du site function getWebsiteSetting($setting){ - $response = Connexion::pdo()->prepare("SELECT value FROM site_siteSetting WHERE name=?"); - $response->execute([$setting]); - $settingValue = $response->fetchColumn(); - return $settingValue; // Retourne null si le paramètre n'existe pas -} - -// Récupère les utilisateurs -function getUtilisateur($search=""){ - if(is_array($search)){ - $userId = $search["userId"] ?? ""; - - // Si l'id utilisateur passé en paramètre est vide, il s'agit du compte Marmiton - if($userId==0){ - $userMarmiton["username"] = "Marmiton"; - return $userMarmiton; - } // S'arrête ici - - $username = $search["username"] ?? ""; - - $queryString = "SELECT * FROM site_user WHERE 1=1"; - if(!empty($userId)){ - $queryString .= " AND id=:userId"; - } - if(!empty($username)){ - $queryString .= " AND id LIKE :username"; - } - - // On la prépare - $query = Connexion::pdo()->prepare($queryString." ORDER BY username"); - - // On rempli les paramètres - if(!empty($userId)){ - $query->bindParam(':userId', $userId); - } - if(!empty($username)){ - $query->bindParam(':username', "%".$username."%"); - } - - // On exécute - $query->execute(); - // Et on retourne le résultat - return $query->fetch(PDO::FETCH_ASSOC); - }else{ - // Si $search n'est pas un array, on va chercher tous les utilisateurs - $query = Connexion::pdo()->prepare("SELECT * FROM site_user ORDER BY username"); - $query->execute(); - return $query->fetchAll(PDO::FETCH_ASSOC); - } -} - -// Regarde si l'utilisateur est connecté, le renvoie vers la page de connexion s'il ne l'est pas -function isConnected(){ - if(empty($_SESSION["userId"])){ - header("Location: ".genPageLink("/login")); - exit(); + // On va vérifier qu'on ne demande pas l'url du site, vu qu'on a créé une fonction pour la récupérer + if($setting == "websiteUrl"){ + return getWebsiteUrl(); } + $response = BddConn::getPdo()->prepare("SELECT value FROM site_siteSetting WHERE name=?"); + $response->execute([$setting]); + return $response->fetchColumn(); // Retourne null si le paramètre n'existe pas } -function getRandomString($length) { +function getRandomString($length): string +{ $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charactersLength = strlen($characters); $randomString = ''; - for ($i = 0; $i < $length; $i++) { + for ($index = 0; $index < $length; $index++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString; diff --git a/core/controller/variables.php b/core/controller/variables.php index c7b80852b9a930733f94822f68acc494a6376118..9cd3c8db872b9d2423dc1a8d255e99eff05716e4 100644 --- a/core/controller/variables.php +++ b/core/controller/variables.php @@ -2,18 +2,19 @@ // Ce fichier ne contient que les variables qui seront constament utilisées // On récupère l'ip +$clientIp = null; if (!empty($_SERVER['HTTP_CLIENT_IP'])) { - $ip = $_SERVER['HTTP_CLIENT_IP']; + $clientIp = $_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; + $clientIp = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { - $ip = $_SERVER['REMOTE_ADDR']; + $clientIp = $_SERVER['REMOTE_ADDR']; } // Vérifie le type de connexion -if(isset($_SERVER['HTTPS'])) $http = "https"; else $http = "http"; +if(isset($_SERVER['HTTPS'])) $httpProtocol = "https"; else $httpProtocol = "http"; // Variables permettant la gestion des pages à afficher -$url = parse_url("$http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"); -$urlPath = explode("/", $url["path"]); +$urlRequest = parse_url("$httpProtocol://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"); +$urlPath = explode("/", $urlRequest["path"]); array_shift($urlPath); // Je suprime le premier élément car il sera toujours vide pour une raison que j'ignore \ No newline at end of file diff --git a/index.php b/index.php index ff1af6823b5006408617fcc059c19c1bc563351f..1fa8e3bdfb7ae0f145f2cf503a4f1caa7f6fb633 100644 --- a/index.php +++ b/index.php @@ -1,9 +1,13 @@ <?php +// On va afficher les erreurs à l'écran +ini_set('display_errors', 1); +ini_set('display_startup_errors', 1); +error_reporting(E_ALL); + session_start(); // Ici on commence par intégrer les différents fichiers qui nous serviront à faire fonctionner le site -require_once "core/conf/ConfigurationGenerale.php"; // Ce fichier contient divers paramètres -require_once "core/classes/Connexion.php"; // Ce fichier se charge de la connexion à la base de donnée +require_once "core/classes/BddConn.php"; // Ce fichier se charge de la connexion à la base de donnée require_once "core/classes/Shop.php"; require_once "core/classes/Item.php"; require_once "core/classes/Seller.php"; @@ -11,6 +15,6 @@ require_once "core/controller/functions.php"; // Et celui-ci des différentes fonctions // On initialise la connexion à la base de données -Connexion::connect(); +BddConn::connect(); // Et on appelle la page demandée loadPage(); \ No newline at end of file diff --git a/pages/admin/settings.php b/pages/admin/settings.php index ea2eff5857ab751859c9caff4fbc30de98c50998..8517537baf96ef6015ab6b00f54bbb7e1778121f 100644 --- a/pages/admin/settings.php +++ b/pages/admin/settings.php @@ -15,7 +15,7 @@ <form id="settingsForm" class="width-50em"> <?php - $settings = Connexion::pdo()->query("SELECT * FROM m_siteSetting")->fetchAll(PDO::FETCH_ASSOC); + $settings = BddConn::getPdo()->query("SELECT * FROM m_siteSetting")->fetchAll(PDO::FETCH_ASSOC); foreach($settings as $setting){ echo ('<div class="form-group"> <label>'.$setting["name"].'</label> diff --git a/pages/client/shops.php b/pages/client/shops.php index 31873e5c665fd5b0e4adc657c1c1da3bffd57fae..4088540dccc20c2c62d6d0df2c0c76ba2a424316 100644 --- a/pages/client/shops.php +++ b/pages/client/shops.php @@ -38,12 +38,12 @@ <?php $items = Shop::getAllProducts(); foreach($items as $item) { - if(isset($_GET["blocs"]) && in_array($item->getId(), $_GET["blocs"])){ + if(isset($_GET["blocs"]) && in_array($item->getType(), $_GET["blocs"])){ $selected = "selected"; }else{ $selected = ""; } - echo '<option value="'.$item->getId().'" '.$selected.'><i class="icon-minecraft '.$item->getCss().'"></i> '.$item->getLabel().'</option>'; + echo '<option value="'.$item->getType().'" '.$selected.'><i class="icon-minecraft '.$item->getCssClassName().'"></i> '.$item->getLabel().'</option>'; } ?> </select> @@ -101,7 +101,7 @@ } $shopId = getRandomString(4); - echo ('<div class="col-sm mb-2" id="'.$shopId.'" x="'.$shop['x'].'" y="'.$shop['y'].'" z="'.$shop['z'].'" world="'.$shop['world'].'" displayName="'.urlencode($shop['item']->getDisplayName()).'" enchants="'.urlencode(json_encode($shop['item']->getEnchants())).'" type="'.$shop['item']->getId().'" price="'.$shop['price'].'"> + echo ('<div class="col-sm mb-2" id="'.$shopId.'" x="'.$shop['x'].'" y="'.$shop['y'].'" z="'.$shop['z'].'" world="'.$shop['world'].'" displayName="'.urlencode($shop['item']->getDisplayName()).'" enchants="'.urlencode(json_encode($shop['item']->getEnchants())).'" type="'.$shop['item']->getType().'" price="'.$shop['price'].'"> <div class="card" style="width: 18rem;"> <div class="card-body"> <span class="badge badge-'.$badge.'">Stock: '.$shop['stock'].'</span>