Check if another function is declared, otherwise change location - php

I've got a "make-do" page authenticator which defines what usergroups are allowed to access that page, however, some of my scripts allow the user to pass if that page is, say, his user edit page but not touch any other users edit page. For that, I disabled access to the usergroups except if you're an admin or the user edit page you are currently on is your own.
I tried to create a function to do this, but the allowOnly usergroups function deals out the punishment without checking to see if the other function is defined elsewhere on the page.
Here's the "make-do" functions and an example of how I'd like them to work:
public function allowOnly($officer, $administrator, $superuser)
{
$authority = 0;
if ($officer == true && $this->session->isOfficer()) {
$authority++;
}
elseif ($administrator == true & $this->session->isAdmin()) {
$authority++;
}
elseif ($superuser == true & $this->session->isSuperuser()) {
$authority++;
}
if ($authority != 0) {
return true;
}
else {
header("Location: ../incorrectRights.php");
exit;
}
}
function allowCurrentUser()
{
global $authority;
$authority++;
}
This changes the users location if they're not any of the allowed usergroups, but since that code is executed before "allowCurrentUser", it changes the location before the function gets the chance to allow the user through.
I'd like it to work like this:
<?php
include("functions.php");
$functions->allowOnly(false, false, true);
if($session->username == $allowedUserName) {
$functions->allowCurrentUser();
}
I'm sorry if I'm not descriptive enough, or my code lacks efficiency, heck, even if I've missed a built-in php function which does this for me!

you should check out PHP's function_exists(), this will tell you wether or not the function already exist.
you have some error in your code too.
$administrator == true & $this->session->isAdmin()
should be
$administrator == true && $this->session->isAdmin()
as you have used only single & whereas it should be &&
and also change
$superuser == true & $this->session->isSuperuser()
to
$superuser == true && $this->session->isSuperuser()
after reading your code, i realized you are using $authority variable to hold the value and to check wether to authorize user or not. and plus you are using global. i would never have done that way, instead i would declare $authority as class property below is the example of how you could do it.
class functions
{
//declare class propert and set default value to 0
protected $_authority = 0;
public function allowOnly($officer, $administrator, $superuser)
{
if ($officer == true && $this->session->isOfficer()) {
$this->_authority++;
}
elseif ($administrator == true && $this->session->isAdmin()) {
$this->_authority++;
}
elseif ($superuser == true && $this->session->isSuperuser()) {
$this->_authority++;
}
if ($this->_authority != 0) {
return true;
}
else {
header("Location: ../incorrectRights.php");
exit;
}
}
public function allowCurrentUser()
{
$this->_authority++;
return $this->_authority;
}
}
UPDATE:
instead of redirecting the page why not return false and redirect during function call, you can do it this way.
class functions
{
//declare class propert and set default value to 0
protected $_authority = 0;
public function allowOnly($officer, $administrator, $superuser)
{
if ($officer == true && $this->session->isOfficer()) {
$this->_authority++;
}
elseif ($administrator == true && $this->session->isAdmin()) {
$this->_authority++;
}
elseif ($superuser == true && $this->session->isSuperuser()) {
$this->_authority++;
}
return ($this->_authority != 0) ? true : false;
}
public function allowCurrentUser()
{
$this->_authority++;
return $this->_authority;
}
}
and while in function call.
include("functions.php");
if($functions->allowOnly(false, false, true)) {
//person is allowed access
}
//else allow current user
elseif($session->username == $allowedUserName) {
$functions->allowCurrentUser();
}
else {
//redirect here
header("Location: ../incorrectRights.php");
exit;
}

I'm not completely certain if this is the answer you are looking for based on the title but this is what I get the impression you are asking for.
Assuming what happens is that your check against allowOnly() takes the user to the "../incorrectRights.php"-page before you've checked if the user logged in is the same as the page looked at, what you need to do is put the check inside the allowOnly function or at least before you do the check for $authority != 0.
Here's a quick example of how you could solve this:
public function allowOnly($officer, $administrator, $superuser)
{
$authority = 0;
if ($officer == true && $this->session->isOfficer()) {
$authority++;
}
elseif ($administrator == true && $this->session->isAdmin()) {
$authority++;
}
elseif ($superuser == true && $this->session->isSuperuser()) {
$authority++;
}
if(function_exists('allowCurrentUser')){
if (allowCurrentUser()) {
return true;
}
}
if ($authority != 0) {
return true;
}
else {
header("Location: ../incorrectRights.php");
exit;
}
}
function allowCurrentUser()
{
if($session->username == $allowedUserName){
return true;
}
else {
return false;
}
}
Then your useage would result in something more like
<?php
include("functions.php");
$functions->allowOnly(false, false, true);
?>
As you can see I also threw in the function_exists('functionnamehere') call that seems to be requested in the question title, since we actually declare the function and therefore know it exists you could also just do this:
if ($authority != 0 || allowCurrentUser()) {
return true;
}

Related

session variable changing when it shouldn't

When i receive a request from site:
public function getSiteToken() {
session_start();
if (strpos($_SERVER['REQUEST_URI'], '/api/v3/') !== 0) {
$_SESSION['siteToken'] = md5(CURRENT_URL.time());
}
return $_SESSION['siteToken'];
}
And when i receive from site to the API:
if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_SERVER['HTTP_X_SITE_TOKEN']) && isset($_SESSION['siteToken'])) {
if($_SERVER['HTTP_X_SITE_TOKEN'] == $_SESSION['siteToken']) return true;
}
This works perfectly when i test in POSTMAN. But in the chrome, the second code returns FALSE. Why???

Why does the validation email returns an error?

I am developing a Register/Login system with validation. Registering system is working well. For example, when I register the same email twice, the following message appears:
Email already registered!
However, when I log-in with the same e-mail and password, an error occurs. The following message appears as a validation error:
Email not registered!
Even if the email is registered in DB.
Code for e-mail validation:
<?php
public function validateEmail($par)
{
if (filter_var($par, FILTER_VALIDATE_EMAIL)) {
return true;
} else {
$this->setErro("Invalid Email!");
return false;
}
}
public function validateIssetEmail($email, $action = null)
{
$b = $this->cadastro->getIssetEmail($email);
if ($action == null) {
if ($b > 0) {
$this->setErro("Email already registered!");
return false;
} else {
return true;
}
} else {
if ($b > 0) {
return true;
} else {
$this->setErro("Email not registered!");
return false;
}
}
}
Code for login controller:
<?php
$validate = new Classes\ClassValidate();
$validate->validateFields($_POST);
$validate->validateEmail($email);
$validate->validateIssetEmail($email,"login");
$validate->validateStrongSenha($senha);
$validate->validateSenha($email,$senha);
var_dump($validate->getErro());
Code for class login:
<?php
namespace Models;
class ClassLogin extends ClassCrud
{
# Returns user data
public function getDataUser($email)
{
$b = $this->selectDB(
"*",
"users",
"where email=?",
array(
$email
)
);
$f = $b->fetch(\PDO::FETCH_ASSOC);
$r = $b->rowCount();
return $arrData = [
"data" => $f,
"rows" => $r
];
}
}
My getIssetEmail method exists on Register code only.
# Check directly at the bank if the email is registered
public function getIssetEmail($email)
{
$b = $this->selectDB(
"*",
"users",
"where email=?",
[
$email
]
);
return $r = $b->rowCount(); // returns the amount of rows in the search
}
And ClassPassword
<?php
namespace Classes;
use Models\ClassLogin;
class ClassPassword
{
private $db;
public function __construct()
{
$this->db = new ClassLogin();
}
# Create password's hash to save in DB
public function passwordHash($senha)
{
return password_hash($senha, PASSWORD_DEFAULT);
}
# Verify if password's hash is correct
public function verifyHash($email, $senha)
{
$hashDb = $this->db->getDataUser($email);
return password_verify($senha, $hashDb["data"]["senha"]);
}
}
This is not an answer but hopefully it will help in debugging.
First, I'm going to change your code. This is 100% a style choice but I personally think it is easier to follow. If you have an if statement that always returns, you don't technically need an else. Once again, this is a style choice and you don't have to follow it.
Second, if you can, try adding logging into your workflow, it will save you so much time debugging. It isn't always an option, especially for legacy code bases, but it is awesome when you can inspect complex code. In this example, I"m just making a couple of helper methods that dump stuff but normally I'd use something like Monolog to write to a stream that I can tail, and I can easily turn it off in production. When logging, sometimes it helps to avoid identical messages so that you can easily find the exact line number you are on, too.
So with those changes, try running this code inside of your class:
private function logMessage($message)
{
echo $message . PHP_EOL;
}
private function logVariable($variable)
{
var_dump($variable);
}
public function validateIssetEmail($email, $action = null)
{
$this->logVariable($email);
$this->logVariable($action);
$b = $this->cadastro->getIssetEmail($email);
$this->logVariable($b);
if ($action === null) {
$this->logMessage('Action was null');
if ($b > 0) {
$this->logMessage('B is greater than zero');
$this->setErro("Email already registered!");
return false;
}
$this->logMessage('B was not greater than zero');
return true;
}
$this->logMessage('Action was not null');
if ($b > 0) {
$this->logMessage('B is greater than zero');
return true;
}
$this->logMessage('B was not greater than zero');
$this->setErro("Email not registered!");
return false;
}
This should log in human-readable form every step. You should be able to walk through this and identify where your bug is. For instance, in the comments above you said that a variable was 0 in a block that was guarded by a check that guarantees that that shouldn't happen.
This is the wrong part i guess you assigned login as action so you can call cadastro class inside of the function
$cadastro = new Cadastro();
$b = $cadastro->getIssetEmail($email);
if ($action == null) {
if ($b > 0) {
$this->setErro("Email already registered!");
return false;
} else {
return true;
}
} else {
if ($b > 0) {
return true;
} else {
$this->setErro("Email not registered!");
return false;
}
}

PHP isset $_session equal to string

So guys I'm new to PHP OOP
I make Login with Roles, and make function(checkrole) for knowing what role it is.
This is how my function looks like
public static function hasadmin()
{
if(session_id() == '') {
session_start();
}
if(isset($_SESSION['role']) == 'A') {
return true;
}
}
and call it into navbar partial :
<?php if (helper::login() == true && helper::hasadmin() == true) { ?>
<li style="float:\right">Logout</li>
<li>Petugas</li>
<li>Laporan</li>
Function helper::login works perfectly.
Every time I login with another role the partial (petugas, laporan)
still comes out.
isset returns a boolean. Run the isset and check the actual value.
if(isset($_SESSION['role']) && $_SESSION['role'] == 'A') {

$_SESSION never getting set

I'm working on an assignment on a PHP course, and I'm stucked at the last part of it.
The assignment is to create a simple login form and use a session as well as hardcoded usernames and passwords (i.e. no db).
What I have problems with is the class that handles the login, and sessions especially. There's a lot of code and I didn't know what I could remove and therefore I've put it on Pastebin instead, hope that's alright.
Thing is that the unit tests that's built into the class passes except for nr. 4, the one that's checking that the user is logged in. The problem seems to be that $_SESSION[$this->loginSession] doesn't get set, and this is what I need help with.
The variable $loginSession is declared in the beginning of the class, and should be set to "isLoggedIn" when a user types a correct username and password, but that doesn't happen (no error message).
My class is:
<?php
class LoginHandler {
private $loginSession;
public function IsLoggedIn() {
if($_SESSION[$this->loginSession] == "isLoggedIn") {
return true;
}
else {
return false;
}
}
public function DoLogin($username, $password){
if ($username != null && $password != null){
switch ($username){
case "hello";
if ($password == "1234"){
$_SESSION[$this->loginSession] == "isLoggedIn";
return true;
}
else return false;
case "hello2";
if ($password == "12345"){
$_SESSION[$this->loginSession] == "isLoggedIn";
return true;
}
else return false;
}
}
else {
return false;
}
}
public function DoLogout(){
unset($_SESSION[$this->loginSession]);
}
public function Test() {
$this->DoLogout();
// Test 1: Check so you're not logged in.
if($this->IsLoggedIn() == true){
echo "Test 1 failed";
return false;
}
// Test 2: Check so that it's not possible to login with wrong password.
if ($this->DoLogin("hello", "4321") == true){
echo "Test 2 failed";
return false;
}
// Test 3: Check that it's possible to log in.
if ($this->DoLogin("hello", "1234") == false){
echo "Test 3 failed";
return false;
}
// Test 4: Check that you're logged in
if ($this->IsLoggedIn() == false){
echo "Test 4 failed";
return false;
}
return true;
}
}
?>
I hope it's enough to include the class and not all the other files, otherwise I'll put them up.
Now I see it :-)
$_SESSION[$this->loginSession] == "isLoggedIn";
== should be =
== compares while = sets
You need to start the session. session_start(); Place it at the very top of the documents (only one time on a page load) you are using.
$this->loginSession is never set so it's NULL
$_SESSION[null] is not possible as far as i know
change your code to
private $loginSession = 'testing';
and it should work
Why do you put semicolon in your case instruction case "hello";There should be a colon. case "hello": { ...instructions}

Simple PHP Function Boolean Problem

Someone please explain to me why this doesn't work, and what I am doing wrong. For some reason, when I run the function validateUsername, the $error variable remains completely unchanged, instead of evaluating to true. How is this possible?
Yet, if I remove the code within the function and run it straight without a function call, it works. The example below is so simple it is practically pseudo code, and yet it doesn't work. Is this behavior unique to PHP? I don't want to run into this again in some other language.
<?php
$username = 'danielcarvalho';
$error = false;
function validateUsername()
{
if (strlen($username) > 10)
{
$error = true;
}
}
validateUsername();
if ($error == false)
{
echo 'Success.';
}
else
{
echo 'Failure.';
}
?>
This isn't working because $username isn't available within the scope of your validateUsername function. (Neither is the $error variable.) See the variable scope section of the PHP manual for more information.
You could fix this by adding global $username, $error; within your function, although this isn't a particularly elegant approach, as global variables are shunned for reasons too detailed to go into here. As such, it would be better to accept $username as an argument to your function as follows:
<?php
function validateUsername($username) {
if (strlen($username) > 10) {
return false;
}
return true;
}
if (validateUsername('danielcarvalho')) {
echo 'Success.';
}
else {
echo 'Failure.';
}
?>
$error has local scope in function validateUsername. To access global variables, use global keyword.
Read about scopes here. Change your function to:
function validateUsername($username)
{
global $error;
if (strlen($username) > 10)
{
$error = true;
}
}
validateUsername($username);
Better implementation using function parameter:
function validateUsername($username, &$error)
{
if (strlen($username) > 10)
{
$error = true;
}
}
validateUsername($username, $error);
Another implementation:
function validateUsername($username)
{
if (strlen($username) > 10)
{
return true;
}
return false;
}
$error = validateUsername($username);

Categories