I have this line of code that I want to apply to a login page. I want to restrict the login for only user with certain domain name like "#mycompany.com" no other user can register without having this domain.
But the problem is that I can't get it to work, it passes all domains I have tried and does not return to false
The codes are copied and paste from two different forumpages, one that has no rules for domains and the second code with rules for restricted domains ( from line "//validate tld")that I pasted in and edited. Where does it go wrong, at the moment I can't see where?
public static function validateUserEmail($user_email, $user_email_repeat)
{
if (empty($user_email)) {
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_FIELD_EMPTY'));
return false;
}
if ($user_email !== $user_email_repeat)
{
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_REPEAT_WRONG'));
return false;
}
// validate the email with PHP's internal filter
// side-fact: Max length seems to be 254 chars
// #see http://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address
if (!filter_var($user_email, FILTER_VALIDATE_EMAIL)) {
//validate tld
$validTlds = str_replace(".", "\.", VALID_EMAIL_TLDS);
$validTlds = "\.".str_replace(",", "|\.", $validTlds);
//$validTlds = str_replace(",", "|\.", $validTlds);
$emailArr = explode("#", $user_email);
$emailTld = $emailArr[1];
if ($emailTld !== 'mycompany.com')
{
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_DOES_NOT_FIT_DOMAIN'));
return false;
}
if (!preg_match('/^[-a-z0-9]+('.$validTlds.')\z/', strtolower($emailTld))) {
//check main domain here
$exValidTlds = explode(",", VALID_EMAIL_TLDS);
$exValidTlds = array_map('trim', $exValidTlds);
foreach($exValidTlds as $tld) {//if exist then
if(!strstr($emailTld, ".".$tld)) {
if($tld !== strrchr($emailTld, $tld)) {
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_DOES_NOT_FIT_PATTERN'));
return false;
}
}
}
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_DOES_NOT_FIT_PATTERN'));
return false;
}
}
return true;
}
This is the original code I started with and the validation of domain I added in later. All this validation domain code seems to be ignored...
public static function validateUserEmail($user_email, $user_email_repeat)
{
if (empty($user_email)) {
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_FIELD_EMPTY'));
return false;
}
if ($user_email !== $user_email_repeat) {
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_REPEAT_WRONG'));
return false;
}
// validate the email with PHP's internal filter
// side-fact: Max length seems to be 254 chars
// #see http://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address
if (!filter_var($user_email, FILTER_VALIDATE_EMAIL)) {
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_DOES_NOT_FIT_PATTERN'));
return false;
}
return true;
}
EDIT...
I finally made it to work and this is how, so far it is working for me... The goal is that I don't want other people outside the organisation to be able to log in to the website.
if (filter_var($user_email, FILTER_VALIDATE_EMAIL)) {
$server = strstr($user_email, '#');
if ($server !== '#mycompany.com') {
Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_DOES_NOT_FIT_PATTERN'));
return false;
}
}
Your not operator is on the wrong side of the variable. It should be like this...
if ($emailTld !== 'mycompany.com')
Related
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;
}
}
I am using Moodle 3.1+. I am trying to add a custom validation into profile edit. The field is a custom user profile field. I have created a function
function validYop($element_name,$element_value) {
$len = strlen($element_value);
// If the string is empty, then return false
if ($len == 0) { return false; }
$first_letter = $element_value{0};
$last_letter = $element_value{$len-1};
if ($first_letter == $last_letter) {
return true;
} else {
return false;
}
}
Then I have registered the rule using below code.
$mform->registerRule('same_firstandlast','function','validYop');
$mform->addRule('profile_field_YearOfPassing','The first and last letters must be the same', 'same_firstandlast');
But the code is not working. Please help
I am writing a method that uses POST variables posted by AJAX to add a user to a certain course in the database, but I can't get the callback to work correctly:
public function enroll()
{
$package = array();
$this->load->library('form_validation');
$this->form_validation->set_rules('course', 'Vak', 'required|callback_not_enrolled');
$fields = array("course");
if ($this->form_validation->run($this) === FALSE) {
$errors = array();
$success = array();
foreach ($fields as $field) {
$error = form_error($field);
if ($error !== "") {
$errors[$field] = $error;
} else {
$success[$field] = True;
}
}
$package["field_errors"] = $errors;
$package["field_success"] = $success;
$package["success"] = False;
} else {
$package["database"] = $this->course_model->enroll_user($this->data["user"], $this->input->post("course"));
$package["success"] = True;
}
echo json_encode($package);
}
I wrote the callback not_enrolled to check if the user is not already enrolled to the database. Note that I can't use is_unique because I have to test the combined uniqueness of two fields (so just one or two separate ones don't do the trick) and the id of the user is not included in the form (because it's part of the Code Igniter session).
The callback function:
public function _not_enrolled($course)
{
$exists = ($this->user->is_enrolled($course, $this->data["user_id"]) != False);
if ($exists != False) {
$this->form_validation->set_message("not_enrolled", "Already enrolled");
return False;
} else {
return True;
}
}
And finally the method is_enrolled from the model:
public function is_enrolled($course, $user=False) {
if($user==False){
$user = $this->data["user_id"];
}
$this->db->select()->from("course_participant")->where("user_id", $user)->where("course_id", $course);
$query = $this->db->get();
return($query->num_rows()>0);
}
Through a call to var_dump($this->_not_enrolled($existing_course_id)); I know that both the callback function and the method from the model work, as it correctly returned true.
When I var_dump the $package array or validation_errors() I don't get any validation errors except that it says Unable to access an error message corresponding to your field name Vak(not_enrolled).
I tried removing the initial _ from the function name but that gives me a Server Status 500 error.
I have another setup exactly like this, albeit other database calls, with a callback using the same syntax. This method works perfectly.
It's been few days that I have been trying to learn Codeigniter and while making small applications I came to this point where I have to update DB.
I have inserted data using validations but when it comes to updating, it looks like it is always "FALSE" as those records are already in DB that I am editing. Result, it doesn't take it.
Seeking some help here to overcome this problem.
Validation (Controller):
$this->form_validation->set_rules('v_member_email', 'Email Address', 'trim|required|valid_email|callback_check_if_email_exists');
public function check_if_email_exists($requested_email) {
$email_available = $this->update_model->check_if_email_exists($requested_email);
if ($email_available) {
return TRUE;
} else {
return FALSE;
}}
It always returns "Validation Error" as this email is already in use.
Model:
function check_if_email_exists($email) {
$this->db->where('v_member_email', $email);
$result = $this->db->get('vbc_registered_members');
if ($result->num_rows() > 0){
return FALSE; //Email Taken
} else {
return TRUE; // Available
}}
Yes, because, email is already present.
All you have to do is, pass the is to callback while updating like this,
callback_check_if_email_exists['.$id.']
Id is the database id.
In controller
public function check_if_email_exists($requested_email, $id) {
$email_available = $this->update_model->check_if_email_exists($requested_email, $id);
if ($email_available) {
return TRUE;
} else {
return FALSE;
}
}
In model
if ($id) {
$this->db->where('id !=', $id);
}
$this->db->where('email', $str);
$res = $this->db->get('users');
if ($res->num_rows()) {
return false;
} else {
return true;
}
}
What we are doing here is, if you are passing the id to callback, then
check if the email is present except this id,
If id is not passed, check only for email without considering the id
in your controller you return true if the email exists. and false if not, but in your model you return false if exists and true if not.
$this->form_validation->set_rules('v_member_email', 'Email Address', 'trim|required|valid_email|callback_check_if_email_exists');
public function check_if_email_exists($requested_email) {
$email_available = $this->update_model->check_if_email_exists($requested_email);
// here you check if the return from the model is true or false if true the email exists otherwise the email not exists
if ($email_available) {
return TRUE; // here true mean the email is exists and not Available
} else {
return FALSE; // here it mean the email not exists and Available
}}
and that's the problem you should return true in your model if the email exists to make it work.
function check_if_email_exists($email) {
$this->db->where('v_member_email', $email);
$result = $this->db->get('vbc_registered_members');
if ($result->num_rows() > 0){
return true; // here true mean the email is exists and not Available
} else {
return false; // here it mean the email not exists and Available
}
}
I'm developing an app that will look up an email inbox and save specific emails as part of it's functionality. What happens is an imap connection is made and then all emails that are set as UNSEEN are retrieved. Each email is checked against pre-defined conditions and then saved to a DB if they are met. These conditions can be set by the user and can be the following:
Subject
Contains string
Does not contain string
Body
Contains string
Does not contain string
From
Specific address
Conditions can be "chained" for instance:
FILTER WHERE
Subject CONTAINS "Order Confirmation"
AND
Email FROM "billyjones26#gmail.com" OR "billyjones26#googlemail.com"
I'm having trouble thinking of how to format and store these conditions. I need to have a GUI where the user can create these conditions.
My questions is how should I store these conditions? I.e some sort of DB table structure, or maybe converted into a string format and stored in a single table. There needs to be a unlimited number of conditions for an unlimited number of users, and I need to know what operators there are, etc.
Hope that's enough information!
* EDIT FOR MICHAEL *
So I can create the conditions and save them. Now I'm retrieving them and trying to match emails. I created a filter with one condition: Subject contains 'TEST'. Only one email should match this but somehow all emails are being added to the matched array.
My controller that is getting the emails/conditions:
public function check_email(){
$filters = $this->filters_model->get_filters($owner_id=1);
foreach($filters->result() as $filter){
$emails = $this->gmail->get_emails($mailbox_id = $filter->mailbox_id, $limit = 10);
$matched = array();
$conditions = unserialize($filter->conditions);
foreach($emails as $email){
if($conditions->isMet($email) == TRUE){
$matched[] = $email;
}
}
echo count($matched);
echo '<pre>'.$filter->title.'<br /.';
print_r($conditions);
echo '</pre><br />-----';
exit;
}
}
Keyvalueprerequisite.php
This seems to work fine as a var_dump of stripos($subject, $this->value) !== FALSE; shows only TRUE for 1 email.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Keyvalueprerequisite {
private $key;
private $comparator;
private $value;
public function __construct($key, $comparator, $value){
$this->key = $key;
$this->comparator = $comparator;
$this->value = $value;
}
public function isMet(&$context)
{
switch ($this->key) {
case "subject":
$subject = $context["subject"];
if ($this->comparator === "in"){
return stripos($subject, $this->value) !== FALSE;
} else if ($this->comparator === "!in") {
return stripos($subject, $this->value) === FALSE;
}
return FALSE;
break;
case "body":
$body = $context["body"];
if ($this->comparator === "in") {
return stripos($body, $this->value) !== FALSE;
} else if ($this->comparator === "!in") {
return stripos($body, $this->value) === FALSE;
}
return FALSE;
break;
case "from_address":
$from = $context["from"];
if ($this->comparator === "=") {
return $this->value === $from;
} else if ($this->comparator === "!=") {
return $this->value !== $from;
} else{
return false;
}
break;
default:
}
return FALSE;
}
}
Prerequisistegroup.php
Something might not be quite write here. a var_dump of $result = $result && $is_met returns true for each of the 10 emails.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Prerequisitegroup {
private $type;
private $prerequisites;
public function __construct($type = 'AND'){
$this->type = $type;
}
public function add(){
foreach(func_get_args() as $prerequisite){
$this->prerequisites[] = $prerequisite;
}
}
public function isMet(&$context)
{
if (empty($this->prerequisites) === FALSE) {
$result = TRUE;
foreach ($this->prerequisites as $prerequisite) {
$is_met = $prerequisite->isMet($context);
if ($this->type === 'AND') {
$result = $result && $is_met;
if ($result === FALSE) {
return FALSE;
}
} else {
$result = $result || $is_met;
if ($result === TRUE) {
return TRUE;
}
}
}
return $result;
}
return TRUE;
}
}
These are my conditions that are being checked:
string(3) "AND"
["prerequisites":"Prerequisitegroup":private]=>
array(1) {
[0]=>
object(Prerequisitegroup)#23 (2) {
["type":"Prerequisitegroup":private]=>
string(2) "OR"
["prerequisites":"Prerequisitegroup":private]=>
array(1) {
[0]=>
object(Keyvalueprerequisite)#24 (3) {
["key":"Keyvalueprerequisite":private]=>
string(7) "subject"
["comparator":"Keyvalueprerequisite":private]=>
string(2) "in"
["value":"Keyvalueprerequisite":private]=>
string(4) "TEST"
}
}
}
}
}
For a CMS I solved a similar problem, by abstracting the conditions (Prerequisites) into two classes: Prerequisite and PrerequisiteGroup (a subclass of the former, and then serialized them, or more precisely the object, since there would only be one into a BLOB in MySQL.
The advantage of this was that I could simply deserialize the object and invoke an isMet() function without bothering about the depth or complexity of the perquisites. The disadvantage was of course that I couldn't make DB queries on this objects. But that wasn't a problem in this particular case, and from your own suggestions I think it isn't in yours as well.
The Prerequisite class (or interface) implements one method isMet($context) that tells you where your condition is true or not. The context in your case would be the $email to be examined. E.g. if from email matches "billyjones26#gmail.com".
The PrerequisiteGroup represents AND and OR, in a simplified way. The default way to group conditions is by
Here is an example of creating and storing the conditions:
$c1 = new KeyValuePrerequisite("EmailFrom", "=", "billyjones26#gmail.com");
$c2 = new KeyValuePrerequisite("EmailFrom", "=", "billyjones26#googlemail.com");
$c3 = new KeyValuePrerequisite("Subject", "in", "Order Confirmation");
$from_condition = new PrerequisiteGroup('or');
$from_condition->add($c1, $c2);
$final_condition = new PrerequisiteGroup($c3, $from_condition); // defaults to and
$db->query("INSERT INTO conditions SET user_id = %i, conditions = %l", $user_id, serialize($final_condition));
Here is an example usage:
// Fetch conditions
$email_conditions = $user->getEmailConditions()
// Connect to your inbox and fetch relevant emails
$matching_emails = array();
foreach ($emails as $email) {
if ($email_conditions->isMet($email) {
$matching_emails[] = $email;
}
}
Prerequisite interface:
interface Prerequisite
{
/**
* Must return TRUE or FALSE.
*/
public function isMet(&$context);
}
KeyValuePrerequisite implementation (in my implementation this actually an abstract class but for your purpose you can implement everything here, you could call it EmailPrerequisite or EmailCondition):
class KeyValuePrerequisite extends PrerequisiteGroup
{
protected $key;
protected $comparator;
protected $value;
public function __construct($key, $comparator, $value = NULL)
{
$this->key = $key;
$this->comparator = $comparator;
$this->value = $value;
}
public function isMet(&$context)
{
switch ($this->key) {
case "Subject":
$subject = $context["subject"];
if ($this->comparator === "in") }
return stripos($subject, $this->value) !== FALSE;
} else if ($this->comparator === "not int") {
return stripos($subject, $this->value) === FALSE;
}
return FALSE;
break;
case "EmailFrom":
$from = $context["from"];
return $this->value === $from;
break;
default:
}
return FALSE;
}
}
PrerequisiteGroup implementation:
class PrerequisiteGroup implements Prerequisite
{
private $type;
private $prerequisites;
public function __construct($type = 'AND')
{
$this->type = $type;
}
public function add(Prerequisite $prerequisite)
{
if ($prerequisite instanceof Prerequisite) {
$this->prerequisites[] = $prerequisite;
} else {
throw new Exception('Unknown Prerequisite type ' . get_class($prerequisite));
}
}
public function isMet(&$context)
{
if (empty($this->prerequisites) === FALSE) {
$result = $this->type === 'AND';
foreach ($this->prerequisites as $prerequisite) {
$is_met = $prerequisite->isMet($context);
if ($this->type === 'AND') {
$result = $result && $is_met;
if ($result === FALSE) {
return FALSE;
}
} else {
$result = $result || $is_met;
if ($result === TRUE) {
return TRUE;
}
}
}
return $result;
}
return TRUE;
}
}
GUI
When it comes to GUI there are several approaches/patterns. The most common, I think, for email related apps is to have a number of rows of expressions that are ANDed and a [+] to add more conditions:
Row 1: [select: subject] [select:contains] [input:"Order Confirmation"]
When it comes to the from we need to express OR. This is hard to do with just rows. This is where the concept of a Prerequisite or Condition group becomes handy. You simply add a new row which is a group and let the user to choose to use AND or OR.
The outer group is an AND group.
So the GUI elements are fairly easy to transform into code and vice versa - especially with the KeyValuePrerequisite impl. of Prerequisite.
Hope this helps or at least sparked some ideas to solve your problem.