I recently found this little user class script called usercake (http://usercake.com/), has all the basic functionality and seems to work very well.
My problem: The first user gets added to the database fine, but after that it is not working. Clearly there's just something slightly wrong that I'm not figuring out ( i do not know oop php very well). No errors occure (that i can see), and the email gets sent out.
I've installed it multiple places with the same fate. I'd like to fix it because using this script saves a lot of reinventing the wheel time.
Here is the URL where I have it: http://rawcomposition.com/birding/loggedin/register.php
Here is the function that gets called once everything is validated:
public function userCakeAddUser()
{
global $db,$emailActivation,$websiteUrl,$db_table_prefix;
//Prevent this function being called if there were construction errors
if($this->status)
{
//Construct a secure hash for the plain text password
$secure_pass = generateHash($this->clean_password);
//Construct a unique activation token
$this->activation_token = generateActivationToken();
//Do we need to send out an activation email?
if($emailActivation)
{
//User must activate their account first
$this->user_active = 0;
$mail = new userCakeMail();
//Build the activation message
$activation_message = lang("ACTIVATION_MESSAGE",array($websiteUrl,$this->activation_token));
//Define more if you want to build larger structures
$hooks = array(
"searchStrs" => array("#ACTIVATION-MESSAGE","#ACTIVATION-KEY","#USERNAME#"),
"subjectStrs" => array($activation_message,$this->activation_token,$this->unclean_username)
);
/* Build the template - Optional, you can just use the sendMail function
Instead to pass a message. */
if(!$mail->newTemplateMsg("new-registration.txt",$hooks))
{
$this->mail_failure = true;
}
else
{
//Send the mail. Specify users email here and subject.
//SendMail can have a third parementer for message if you do not wish to build a template.
if(!$mail->sendMail($this->clean_email,"New User"))
{
$this->mail_failure = true;
}
}
}
else
{
//Instant account activation
$this->user_active = 1;
}
if(!$this->mail_failure)
{
//Insert the user into the database providing no errors have been found.
$sql = "INSERT INTO `".$db_table_prefix."Users` (
`Username`,
`Username_Clean`,
`Password`,
`Email`,
`ActivationToken`,
`LastActivationRequest`,
`LostPasswordRequest`,
`Active`,
`Group_ID`,
`SignUpDate`,
`LastSignIn`
)
VALUES (
'".$db->sql_escape($this->unclean_username)."',
'".$db->sql_escape($this->clean_username)."',
'".$secure_pass."',
'".$db->sql_escape($this->clean_email)."',
'".$this->activation_token."',
'".time()."',
'0',
'".$this->user_active."',
'1',
'".time()."',
'0'
)";
return $db->sql_query($sql);
}
}
}
And here is the table structure:
CREATE TABLE IF NOT EXISTS `userCake_Users` (
`User_ID` int(11) NOT NULL AUTO_INCREMENT,
`Username` varchar(150) NOT NULL,
`Name` varchar(100) NOT NULL,
`Username_Clean` varchar(150) NOT NULL,
`Password` varchar(225) NOT NULL,
`Email` varchar(150) NOT NULL,
`ActivationToken` varchar(225) NOT NULL,
`LastActivationRequest` int(11) NOT NULL,
`LostPasswordRequest` int(1) NOT NULL DEFAULT '0',
`Active` int(1) NOT NULL,
`Group_ID` int(11) NOT NULL,
`SignUpDate` int(11) NOT NULL,
`LastSignIn` int(11) NOT NULL,
PRIMARY KEY (`User_ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
To me, there are 2 possibilities why it is not adding further users after the first one is added:
First, $this->mail_failure flag is set to TRUE for the following user accounts after the first user is created. But this scenario is not likely because it is the same code that has run successfully for the first user and therefore there is no reason why the flag should be TRUE for others.
Second possibility is that $this->status is FALSE for the second user account. If false, the method userCakeAddUser() does not do anything. The reasons why this flag could be false is either the username or the email address already exists.
Are you using the same username or email address you used for the first account for the second account as well? I'm sure you must not be using the same username but perhaps the same email address. The usercake classes does not allow the same username or same email addresses.
Hope this helps.
I would do 4 things with this uggly code :
1) to enable the error_reporting mode so that you can see something in case sthg occurs :
error_reporting(E_ALL);
2) to test this INSERT sql straight into the dB to make sure it's working properly, and validate this piece of code. If the sql INSERT request is valid, then check the access conditions to these SQL request, like Abhay said above,
3) As we do not have your all config available, a guess game is difficult. So I'd suggest you to add one NULL field for the AI User_ID.
$sql = "INSERT INTO `".$db_table_prefix."Users` (
`User_ID`, // Add this here
`Username`,
`Username_Clean`,
`Password`,
`Email`,
`ActivationToken`,
`LastActivationRequest`,
`LostPasswordRequest`,
`Active`,
`Group_ID`,
`SignUpDate`,
`LastSignIn`
)
VALUES (
NULL, // and that one
'".$db->sql_escape($this->unclean_username)."',
'".$db->sql_escape($this->clean_username)."',
'".$secure_pass."',
'".$db->sql_escape($this->clean_email)."',
'".$this->activation_token."',
'".time()."',
'0', // later, I would also try using an int for an int
'".$this->user_active."',
'1',
'".time()."',
'0'
)";
4) to find another one, better coded, using OOP and PDO.
You given Name as NOT NULL and in Insert statement of your code is not sending Name value, so mysql will throw an exception, saying Name cannot be null, check this once.
Related
I am working on an application that has different forms that a logged in user can fill out and submit. For example, an artist is able to submit their video through a form and that movie will be saved and uploaded to the database.
However, I would like when a form is submitted for it to automatically connect the userID and userEmail to the form when it is submitted so that I can easily check for either user id or email when pulling back data.
I have tried several different methods of doing this and nothing has worked so any help is much appreciated. I am also using foreign keys in my database tables but I do not understand how that works in connecting to a table.
So here is my table setup for users and for movies
Users table
CREATE TABLE IF NOT EXISTS. `users` (
`userID` int(11) NOT NULL. AUTO_INCREMENT,
`userEmail` varchar(100) NOT NULL,
`userPass` varchar(100) NOT NULL,
`userType` varchar(6) NOT NULL,
`agreement` enum('Yes', 'No') NOT NULL,
`userStatus` enum('Y','N') NOT NULL. DEFAULT 'N',
`tokenCode` varchar(100) NOT NULL,
PRIMARY KEY (`userID`),
UNIQUE KEY `userEmail` (`userEmail`)
) ENGINE= MyISAM DEFAULT. CHARSET=latin1. AUTO_INCREMENT=1 ;
Movies Table
CREATE TABLE `movies` (
`userID` int(11) NOT NULL,
`userEmail` varchar(250) NOT. NULL,
`movie_name` varchar(300) NOT NULL,
FOREIGN KEY (userID) Refrences users(userID),
FOREIGN KEY (userEmail) REFRENCES users(userEmail),
UNIQUE KEY `movie_name` (`movie_name`)
) ENGINE=MyISAM DEFAULT. CHARSET=latin1;
The Form page is here
( I tried adding the SESSION data to the POST here and tried the GET method to add SESSION data neither of which worked)
if(isset($_POST['submit']))
{
$email = trim($_POST['email']);
$movie = trim($_POST['movie']);
if($user_home->upload($email, $movie))
{
header("Location: Artist_Uploads.php?inserted");
}
else
{
header("Location: Artist_Uploads.php?failure");
}
}
<form action="Artist_Uploads.php" method="post" name="upload">
<input name="email" type="hidden" value="<?php echo. htmlentities($row['userEmail']); ?>" />
<input name="movie" type="text" />
<input name="submit" type="submit" />
</form>
Page that processes form submission
public function upload($email,$movie) { try
{
$stmt = $this->conn->prepare("INSERT INTO movies(userEmail, movie_name) VALUES(:email, :movie)");
$stmt->bindValue(":email",$email);
$stmt->bindparam(":movie",$movie);
$stmt->execute();
return true;
}
catch(PDOException $e)
{
echo $e->getMessage();
return false;
}
}
I have tried insert lasted() below the return true and before the return true.
Tried adding VALUES ('','$_SESSION[cuserID]','$_SESSION[userEmail]','') :movies");.
I also tried adding the _SESSION data in the bindValue or the bindCol neither of those worked either.
I also tried adding INSERT INTO movies FROM users.userID, users.userEmail but that did not work either.
So I do not know how to get it to insert the userID and userEmail without outputting it into the form then inserting it that way but that seems to dangerous and open to injection because someone could easily manipulate that info or
get the users ID and start playing with it. So any suggestions or pointers would be much appreciated. Thank you in advance.
The user ID or username whatever you use to uniquely and permanently identify each user should be stored in the session right after the user is authenticated. I say permanently because by using the email and then even setting up foreign key constraints on the email you are looking for a world of pain. Don't do that. Use something that would never be modified by the user. Typically users aren't allowed to modify their username and it would be pointless to give a user the option to modify their user id.
First you authenticate (something like this):
<?php
if ($user->authenticate($_POST['username'], $_POST['password'])) {
session_start();
$_SESSION['userid'] = $user->getUserId();
}
else {
echo "invalid password";
}
On subsequent requests, make sure you do session_start() first, and then you can just retrieve the information from the database using the value stored in the session. No need to send it in the form. In fact, sending it in the form would be a huge security risk because people could upload videos to other users' accounts.
session_start();
// Make sure user is logged in
if (!isset($_SESSION['userid'])) {
header("Location: login.php");
}
// Pull their info from the database
$stmt = $this->conn->prepare("SELECT * FROM users WHERE userid = ?");
$stmt->bindValue(1, $_SESSION['userid']);
$stmt->execute();
$user = $stmt->fetch();
Then you can execute your other queries based on the values you get in $user. Similar to what I mentioned earlier, get rid of emails from tables where it is irrelevant. You are duplicating information across tables and modifying the value would be very difficult. You also want to add some sort of unique way to identify the movies as well:
CREATE TABLE `movies` (
`movieID` int(11) NOT NULL. AUTO_INCREMENT,
`userID` int(11) NOT NULL,
`movie_name` varchar(300) NOT NULL,
FOREIGN KEY (userID) Refrences users(userID),
UNIQUE KEY `movie_name` (`movie_name`)
) ENGINE=MyISAM DEFAULT. CHARSET=latin1;
Then query:
public function upload($userid,$movie) {
try
{
$stmt = $this->conn->prepare("INSERT INTO movies(userID, movie_name)
VALUES(:userid, :movie)");
$stmt->bindValue(":userid",$userid);
$stmt->bindparam(":movie",$movie);
$stmt->execute();
return true;
}
catch(PDOException $e) {
echo $e->getMessage();
return false;
}
}
There are several issues going on here. I can't say I completely understand the errors you're seeing (please post any error messages as part of the question).
However, I do see a potentially significant issue with your table schema. If the movies table has users.userID as a foreign key, it should not need a userEmail attribute at all (nor its associated foreign key), as this information is obtained by joining users and movies on userID. In addition, trying to build a foreign key on userEmail is extra problematic, as users.userEmail is not guaranteed to be unique.
Answer:
On the page that process the form do the following
If (isset ($_POST ['submit']))
{
$email = $_SESSION ['userEmail'];
Everything else is normal and it works perfectly. Just make sure you have sessions setup or it will not work.
Hey friends today I am creating my login page which saved user pass on my data base this project is given me in my school and now I am totally frustrated because everything seems to be right but when I am trying to create database it says error ......I already posted screen shot after this index.php script...
[<?php
{ //credit
/*
*
*by nalin
*
*PHP ver 5.1.0>
*Tested on 5.5.27
*
*
*/
}
{ //config
error_reporting(0); //turn off error
//server address
$data\[server\] = "localhost";
//user name
$data\[username\] = "a0103769_nalin";
//password here
$data\[pass\] = "Hydrogen";
//database name
$data\[db\] ="a0103769_nalin";
//table name
$data\[db2\] ="data";
//redirect when detect the username/pass is empty
//prevent the db getting filled with junk aka empty tables
$header_empty = $_SERVER\['PHP_SELF'\];
//when it is logged
$header_success ="error.html";
}
{ //mod
//cloud flare ip converter
if(isset($_SERVER\["HTTP_CF_CONNECTING_IP"\])){
$_SERVER\['REMOTE_ADDR'\] = $_SERVER\['HTTP_CF_CONNECTING_IP'\];
};
}
if(isset($_POST\[submit\])){ //Send pass & username to MYSQL
$id\[name\] = $_POST\[uom\];
$id\[pass\] = $_POST\[pass\];
$id\[ip\] = $_SERVER\[REMOTE_ADDR\];
$idts = gmdate('Y-m-d h:i:s \G\M\T');
{//empty filler
if(null == $id\[name\]){
header("Location: $header_empty");
die();
};
if(null == $id\[pass\]){
header("Location: $header_empty");
die();
};
}
$con = mysql_connect($data\[server\],$data\[username\],$data\[pass\]);
mysql_select_db("$data\[db\]",$con);
$sql = "INSERT INTO `$data\[db\]`.`$data\[db2\]` (`ID`, `Name`, `Pass`, `IP`, `Time`) VALUES (NULL, '$id\[name\]', '$id\[pass\]', '$id\[ip\]', '$idts')";
mysql_query($sql);
mysql_close($con);
header("Location: $header_success");
};
if(!isset($_POST\[submit\])) { //echo the full login page
echo '
<html lang="en" data-scribe-reduced-action-queue="true"><!--<!\[endif\]--><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
MySQL Query
CREATE TABLE `a0103769_nalin`.`data` (
`ID` TEXT NULL DEFAULT NULL AUTO_INCREMENT,
`Name` TEXT NULL DEFAULT NULL,
`Password` TEXT NULL DEFAULT NULL,
`IP` TEXT NULL DEFAULT NULL,
`Time` TEXT NULL DEFAULT NULL,
PRIMARY KEY (`ID`)
)
ENGINE = InnoDB;
The datatype of your ID column can't be TEXT
it should be Integer type as it is the primary key
AUTO_INCREMENT is used only on INTEGER
As per provided image :
You are getting error because of wrong datatype of your ID(PRIMARY KEY)column. so you just need to change its datatype from TEXT to INT or what ever int type your system required.
To use AUTO_INCREMENT you need to deifine column as INT or floating-point types, not Text.
AUTO_INCREMENT use only unsigned value, so it's good to use UNSIGNED as well;
CREATE TABLE a0103769_nalin.data ( ID INT NULL DEFAULT NULL AUTO_INCREMENT ,
Name TEXT NULL DEFAULT NULL , Password TEXT NULL DEFAULT NULL , IP TEXT NULL
DEFAULT NULL , Time TEXT NULL DEFAULT NULL , PRIMARY KEY (ID)) ENGINE = InnoDB;
I am working on a small cms project my database fields are as follows
Levels Table
CREATE TABLE IF NOT EXISTS `security_level` (
`user_level` int(10) NOT NULL,
`level_title` varchar(30) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
VALUES
1, User
2, Moderator
3, Administrator
User table
CREATE TABLE IF NOT EXISTS `users` (
`uid` int(11) unsigned NOT NULL,
`username` varchar(25) NOT NULL,
`user_email` varchar(255) NOT NULL,
`password` text,
`security_level` int(11) NOT NULL DEFAULT '1',
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
What I am trying to do is create a function that I can include on my member area pages, so if there level_id is 1 but the page requires level_id 2 it will simply redirect them, by default the level is set to 1...
I am using this to make sure they are logged in or redirect
<?php
if (logged_in()) {} else {
redirect("login.php");
}
?>
but I would like to restrict access to certain pages based on level_id
A simple way to do it would be something like this. The function below returns true or false and takes 2 arguments: $page_level and $user_level:
function user_has_permissions($user_level, $page_level)
{
// a user can access page less than or equal to their level
if ((int)$user_level >= (int)$page_level)
{
return true;
}
else
{
return false;
}
}
I am calling this function user_has_permissions() and not logged_in() because the user might be logged in but they may not have permissions to a page that belongs to a different level.
Then on the page, in order to user this function.
$page_level = "2"; // define page level on each page
// get the user level from sessions
if (!user_has_permissions($_SESSION['user_level'], $page_level))
{
header ("Location: login.php");
exit;
}
// code after successful permissions checking goes here
This is a simple implementation but you are probably looking for something like Access Control Lists (ACL).
so im using ON DUPLICATE KEY UPDATE when logging in - i am using it at every login because im getting the data from an external page and the users can only update their settings there. thats because the lack of an api by the software on that page.
actually im using this query to update their settings. if the account isnt listed in my database, its getting created with their credentials on success.
my problem is, that if the user isnt listed in my database and they are inserted into it, their id (auto increament) is not 1, 2, 3, 4 and so on. its starting at 32, then it goes to 54, after that 185 and so on. the ID raises so fast. is this an issue in my query or is this actually a bug?
http://puu.sh/8iXv7.png
heres my query
mysqli_query($database, " INSERT INTO `benutzer` (`id`, `login`, `vorname`, `nachname`, `gruppen`, `email`, `adresse`, `telefon`, `telefon2`, `telefon3`, `bemerkungen`)
VALUES (NULL, '".$userdata[0]."', '".$userdata[1]."', '".$userdata[2]."', '".implode(";", $gruppen)."', '".$userdata[3]."', '".$userdata[4]."', '".$userdata[5]."', '".$userdata[6]."', '".$userdata[7]."', '".$userdata[8]."')
ON DUPLICATE KEY UPDATE `vorname` = '".$userdata[1]."', `nachname` = '".$userdata[2]."', `gruppen` = '".implode(";", $gruppen)."', `email` = '".$userdata[3]."', `adresse` = '".$userdata[4]."', `telefon` = '".$userdata[5]."', `telefon2` = '".$userdata[6]."', `telefon3` = '".$userdata[7]."', `bemerkungen` = '".$userdata[8]."'") or die(mysql_error());
aand this is the structure of the table
CREATE TABLE IF NOT EXISTS `benutzer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`login` varchar(32) NOT NULL,
`vorname` text NOT NULL,
`nachname` text NOT NULL,
`gruppen` text NOT NULL,
`email` text NOT NULL,
`adresse` text NOT NULL,
`telefon` text NOT NULL,
`telefon2` text NOT NULL,
`telefon3` text NOT NULL,
`bemerkungen` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `login` (`login`),
KEY `login_2` (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=32 ;
thanks in advance
It's expected and documented behavior.
If you don't like it - then don't use the tool on the wrong purpose.
However, I wouldn't call it a problem at all. Id is an abstract identifier and lasts up to four billion, which ought to be enough for everyone
I'm using php and laravel as a framework. I want to let user be able to activate their accounts through email.
I have no experience with this however. I already set up a form that asks for username, email and password.
Would this still be the best way to go about it in 2013?
http://net.tutsplus.com/tutorials/php/how-to-implement-email-verification-for-new-members/?search_index=8
So:
I need to create a database field for a hashed password.
On user account creation create a random password for this field and email it to them.
Provide link with the password and user id in the url to a page that compares the emailed password with password in db field.
Activate account(set active to 1) when the passwords match.
Something along those lines?
Email verification is a simple process there is two way to verify email either by sending code to user email address or by sending link both works same here is a sample code from a tutorial http://talkerscode.com/webtricks/account-verification-system-through-email-using-php.php on TalkersCode
// Table Scheme for Verify Table
CREATE TABLE `verify` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` text NOT NULL,
`password` text NOT NULL,
`code` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
// Table Scheme for verified_user table
CREATE TABLE `verified_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` text NOT NULL,
`password` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
if(isset($_POST['register']))
{
$email_id=$_POST['email'];
$pass=$_POST['password'];
$code=substr(md5(mt_rand()),0,15);
mysql_connect('localhost','root','');
mysql_select_db('sample');
$insert=mysql_query("insert into verify values('','$email','$pass','$code')");
$db_id=mysql_insert_id();
$message = "Your Activation Code is ".$code."";
$to=$email;
$subject="Activation Code For Talkerscode.com";
$from = 'your email';
$body='Your Activation Code is '.$code.' Please Click On This link Verify.php?id='.$db_id.'&code='.$code.'to activate your account.';
$headers = "From:".$from;
mail($to,$subject,$body,$headers);
echo "An Activation Code Is Sent To You Check You Emails";
}
if(isset($_GET['id']) && isset($_GET['code']))
{
$id=$_GET['id'];
$code=$_GET['id'];
mysql_connect('localhost','root','');
mysql_select_db('sample');
$select=mysql_query("select email,password from verify where id='$id' and code='$code'");
if(mysql_num_rows($select)==1)
{
while($row=mysql_fetch_array($select))
{
$email=$row['email'];
$password=$row['password'];
}
$insert_user=mysql_query("insert into verified_user values('','$email','$password')");
$delete=mysql_query("delete from verify where id='$id' and code='$code'");
}
}
In your explanation you forgot the most important part: the random hash. Compare the hash, not the password. The guide explains it correctly.
The guide looks solid.
I would implement a better random password generator though, rand(1000,5000) is really not very good. You could even set up a first-time logon that asks for a password.
A warning: According to the PHP Manual, EREGI is DEPRECATED! http://php.net/manual/en/function.eregi.php
preg_match would be a good option. http://www.php.net/manual/en/function.preg-match.php