User Registration and Profile System

Got something cool to share with AppGini users? Feel free to post it here!
Post Reply
sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

User Registration and Profile System

Post by sathukorala » 2021-04-01 00:55

A small query from experts,
Can we build a system where users can register themselves in the system by creating a profile and manage his profile through AppGini?
Anyone who has done it?

pfrumkin
Veteran Member
Posts: 119
Joined: 2020-02-18 17:58
Location: Albuquerque, New Mexico USA

Re: User Registration and Profile System

Post by pfrumkin » 2021-04-01 13:48

Hi,

It is not clear what your requirements are. I looked at https://bigprof.com/appgini/help/advanc ... obal-hooks and viewtopic.php?t=2639 to help build for our site. You can specify if the registrant can automatically sign up or if it needs a site administrator approval. The sign up form is limited to four data fields so it is more work to build a more complete profile (I did not take that on). AG covers adding the record to the membership table. I added code in the _global.php to INSERT records into our site user database.

Good luck.

~Paul

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-02 03:21

The need is to build a custom form of registration where the user can register with admin approval and then the user should be able to login to the profile to update his profile.
Imagine a registration process in Wordpress or Joomla.
Can we do it in AppGini?

User avatar
jsetzer
AppGini Super Hero
AppGini Super Hero
Posts: 1050
Joined: 2018-07-06 06:03
Location: Kiel, Germany
Contact:

Re: User Registration and Profile System

Post by jsetzer » 2021-04-02 04:09

In a project I did it other way round: I did not modify any of the default membership_* tables, but created a new userprofiles table containing the fields the customer needed.
  1. Create an additional table userprofiles
    • id (PK)
    • memberID VARCHAR[100], unique, readonly
    • ... more fields depending on your needs
      profile-image, lookups for city, ...
  2. Grant permissions for users-group:
    • insert = false
    • view = owner
    • edit = owner
    • delete = no
  3. Enable registration for new users (default AppGini feature)
  4. New users register themselves using the default registration form
  5. Admin confirms registration (or auto-accept registrations according to your needs) (default AppGini features)
  6. Now some magic: :o ;)
    on login, automically create a record in userprofiles table for that member, if not exists.
    You can use sql() function in login_ok()-hook in hooks/__global.php.

    Important:
    After insert, (1) get the primary key (id) of the new record and (2) change the owner to the currently logged in user.
    You can use set_record_owner() function for that.
  7. As a result, every user logged in user will have an own (exactly one) record in userprofiles table and will be able to edit his/her own record.

In that project there are a few additional features:
  • After login, if the userprofile has not been filled out completely, auto-redirect to that record, otherwise redirect to a product catalog
  • Additional "toolbar" at the top, linked to the user profiles
    chrome_bndN9gSWdv.png
    chrome_bndN9gSWdv.png (1.75 KiB) Viewed 699 times
  • Show a hint in that toolbar if the profile has not been filled completely
  • I have replaced the default navbar link at the top right (next to logout-button) by a link which directs to the custom profile page instead using Javascript

Custom profile-page

This is how the userprofile page looks like in View-mode. It is as custom page, showing not only the userprofile information but also related records and favourites for example. As this is a custom page, you can display whatever you want.

chrome_3Tyd2DamxM.png
chrome_3Tyd2DamxM.png (53.29 KiB) Viewed 699 times

There is a button for editing the own profile. Due to the permissions set, every user can only edit his/her own record.


This is the editable userprofile page:
chrome_1ZWRMNFlkF.png
chrome_1ZWRMNFlkF.png (38.31 KiB) Viewed 699 times

Customized homepage

Custom Homepage with header-image, search-bar, product-catalog (grid of product-categories) and sidebar for advertising

chrome_wQYeXJuxR3.png
chrome_wQYeXJuxR3.png (147.81 KiB) Viewed 699 times
-
Hopefully this gives you a good starting point for a sligthly different approach. I hope you like it.
Kind regards,
<js />

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-02 05:10

This is excellent Jan,
But If you can elaborate more on how to do this, most of us will get the benefit

1. on login, automically create a record in userprofiles table for that member, if not exists.
You can use sql() function in login_ok()-hook in hooks/__global.php.
Important:
After insert, (1) get the primary key (id) of the new record and (2) change the owner to the currently logged in user.
You can use set_record_owner() function for that.
As a result, every user logged in user will have an own (exactly one) record in userprofiles table and will be able to edit his/her own record.

2. After login, if the userprofile has not been filled out completely, auto-redirect to that record, otherwise redirect to a product catalog

3. Additional "toolbar" at the top, linked to the user profiles

User avatar
jsetzer
AppGini Super Hero
AppGini Super Hero
Posts: 1050
Joined: 2018-07-06 06:03
Location: Kiel, Germany
Contact:

Re: User Registration and Profile System

Post by jsetzer » 2021-04-02 05:31

1. on login, automically create a record in userprofiles table for that member, if not exists.
You can use sql() function in login_ok()-hook in hooks/__global.php.
Important:
After insert, (1) get the primary key (id) of the new record and (2) change the owner to the currently logged in user.
You can use set_record_owner() function for that.
As a result, every user logged in user will have an own (exactly one) record in userprofiles table and will be able to edit his/her own record.
What about something like this (not tested!):

Code: Select all

function login_ok($memberInfo, &$args)
{
	$tn  = "userprofiles"; // this is the table name of your custom userprofiles table
	$memberID = getLoggedMemberID(); // or take info from $memberInfo, if you prefer
	$userprofile_id = sqlValue("SELECT `id` FROM `{$tn}` WHERE `memberID`='{$memberID}'"); // I assume "id" as primary key column name
	if (!$userprofile_id) {
		$eo = null;
		sql("INSERT INTO {$tn}(memberID) VALUES('{$memberID}'", $eo);
		if ($eo) die($eo); // add error handling here
		$userprofile_id = db_insert_id(db_link());
		set_record_owner($tn, $userprofile_id, $memberID);
	}
	return ''; // if you like, do some redirection here
}
2. After login, if the userprofile has not been filled out completely, auto-redirect to that record, otherwise redirect to a product catalog
Not required. Configure your fields right inside your AppGini project according to your needs.
https://bigprof.com/appgini/help/workin ... ble-fields
3. Additional "toolbar" at the top, linked to the user profiles
Not required. You can use HTML or PHP or Javascript to prepend or append a button-group of any buttons, for example in header-extras.php.
Here are the docs for Bootstrap 3 button groups: https://www.w3schools.com/bootstrap/boo ... groups.asp
Kind regards,
<js />

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-02 05:49

jsetzer wrote:
2021-04-02 05:31
1. on login, automically create a record in userprofiles table for that member, if not exists.
You can use sql() function in login_ok()-hook in hooks/__global.php.
Important:
After insert, (1) get the primary key (id) of the new record and (2) change the owner to the currently logged in user.
You can use set_record_owner() function for that.
As a result, every user logged in user will have an own (exactly one) record in userprofiles table and will be able to edit his/her own record.
What about something like this (not tested!):

Code: Select all

function login_ok($memberInfo, &$args)
{
	$tn  = "userprofiles"; // this is the table name of your custom userprofiles table
	$memberID = getLoggedMemberID(); // or take info from $memberInfo, if you prefer
	$userprofile_id = sqlValue("SELECT `id` FROM `{$tn}` WHERE `memberID`='{$memberID}'"); // I assume "id" as primary key column name
	if (!$userprofile_id) {
		$eo = null;
		sql("INSERT INTO {$tn}(memberID) VALUES('{$memberID}'", $eo);
		if ($eo) die($eo); // add error handling here
		$userprofile_id = db_insert_id(db_link());
		set_record_owner($tn, $userprofile_id, $memberID);
	}
	return ''; // if you like, do some redirection here
}
2. After login, if the userprofile has not been filled out completely, auto-redirect to that record, otherwise redirect to a product catalog
Not required. Configure your fields right inside your AppGini project according to your needs.
https://bigprof.com/appgini/help/workin ... ble-fields
3. Additional "toolbar" at the top, linked to the user profiles
Not required. You can use HTML or PHP or Javascript to prepend or append a button-group of any buttons, for example in header-extras.php.
Here are the docs for Bootstrap 3 button groups: https://www.w3schools.com/bootstrap/boo ... groups.asp


Great !!!
You are always a life-saver Jan.
I will test it and comment

User avatar
jsetzer
AppGini Super Hero
AppGini Super Hero
Posts: 1050
Joined: 2018-07-06 06:03
Location: Kiel, Germany
Contact:

Re: User Registration and Profile System

Post by jsetzer » 2021-04-02 05:52

You are always a life-saver Jan.
Thanks, but: Just a few lines of PHP code...it was not so hard, was it?
Kind regards,
<js />

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-02 06:19

jsetzer wrote:
2021-04-02 05:52
You are always a life-saver Jan.
Thanks, but: Just a few lines of PHP code...it was not so hard, was it?
It may be small but the dedication and the way you explain is useful for most of the AppGini users.
Keep up the good work Jan
Thanks

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-09 10:48

jsetzer wrote:
2021-04-02 05:31
1. on login, automically create a record in userprofiles table for that member, if not exists.
You can use sql() function in login_ok()-hook in hooks/__global.php.
Important:
After insert, (1) get the primary key (id) of the new record and (2) change the owner to the currently logged in user.
You can use set_record_owner() function for that.
As a result, every user logged in user will have an own (exactly one) record in userprofiles table and will be able to edit his/her own record.

What about something like this (not tested!):

Code: Select all

function login_ok($memberInfo, &$args)
{
	$tn  = "userprofiles"; // this is the table name of your custom userprofiles table
	$memberID = getLoggedMemberID(); // or take info from $memberInfo, if you prefer
	$userprofile_id = sqlValue("SELECT `id` FROM `{$tn}` WHERE `memberID`='{$memberID}'"); // I assume "id" as primary key column name
	if (!$userprofile_id) {
		$eo = null;
		sql("INSERT INTO {$tn}(memberID) VALUES('{$memberID}'", $eo);
		if ($eo) die($eo); // add error handling here
		$userprofile_id = db_insert_id(db_link());
		set_record_owner($tn, $userprofile_id, $memberID);
	}
	return ''; // if you like, do some redirection here
}
Above works correctly escept for a bracket missing in the below line

Code: Select all

sql("INSERT INTO {$tn}(memberID) VALUES('{$memberID}')", $eo);
Please help with the following,

1. How to make it mandatory to fill blank fileds?
2. After login, if the userprofile has not been filled out completely, auto-redirect to that record, otherwise redirect to a product catalog
Not required. Configure your fields right inside your AppGini project according to your needs.
https://bigprof.com/appgini/help/workin ... ble-fields
2. When registering username is made unique but the email is not checked for duplicated user profiles. Can we filter and avoid 2 profiles with the same email?

3. When logged in how to redirect straight to the detail view page instead of table view for normal users?

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-09 11:12

I tried this block in hooks\_global.php in function login_ok but the SelctedID=#ID# seems to be not working

Code: Select all

if($memberInfo['group']=="Registered")
	return 'userprofiles_view.php?SelectedID=#ID#';
       else
        return "";

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-09 11:49

a.gneady wrote:
2015-02-17 04:50
For now, you could open the generated membership_signup.php file in a text editor, find this code block:

Code: Select all

		if(!$email){
			echo error_message($Translation['email invalid']);
			exit;
		}
Add the following check below it:

Code: Select all

		if(sqlValue("select count(1) from membership_users where lcase(email)='$email'")){
			echo error_message('This email is already registered.');
			exit;
		}
This was suggested earlier but it is obsolete now.

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-09 12:27

I have implemented two of the above
1. Redirecting to the detail view
2. adding email to the record

Code: Select all

function login_ok($memberInfo, &$args)
	{
	$tn  = "userprofiles"; // this is the table name of your custom userprofiles table
	$memberID = getLoggedMemberID(); // or take info from $memberInfo, if you prefer
	$userprofile_id = sqlValue("SELECT `id` FROM `{$tn}` WHERE `memberID`='{$memberID}'"); // I assume "id" as primary key column name
	if (!$userprofile_id) {
		$eo = null;
		sql("INSERT INTO {$tn}(memberID, email) VALUES('{$memberInfo['username']}','{$memberInfo['email']}')", $eo);
		if ($eo) die($eo); // add error handling here
		$userprofile_id = db_insert_id(db_link());
		set_record_owner($tn, $userprofile_id, $memberID);
	}
	if($memberInfo['group']=="Registered")
		{
		$getrecordcount = sqlValue("select COUNT(*) FROM ".$tn." WHERE memberID = '".$memberInfo['username']."'");			
		if ($getrecordcount > 0) {
			$recid = sqlValue("select id FROM ".$tn." WHERE memberID = '".$memberInfo['username']."'");
			return "userprofiles_view.php?SelectedID=$recid";
		}
		else
        return "";
		}
	}
But please help to solve the email validation (avoid duplicate email registration) problem

User avatar
jsetzer
AppGini Super Hero
AppGini Super Hero
Posts: 1050
Joined: 2018-07-06 06:03
Location: Kiel, Germany
Contact:

Re: User Registration and Profile System

Post by jsetzer » 2021-04-09 12:45

Please share with us what you already have solved, so all can benefit.
Thanks!
Kind regards,
<js />

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-09 14:22

jsetzer wrote:
2021-04-09 12:45
Please share with us what you already have solved, so all can benefit.
Thanks!
I have done the following

1. Create an additional table userprofiles
  • id (PK)
    memberID VARCHAR[100], unique, readonly
    email
    name
    address
2. Create user group "Registered" and Grant permissions for user-group:
  • insert = false
    view = owner
    edit = owner
    delete = no
3. Enable registration for new users (default AppGini feature)
4. New users register themselves using the default registration form
5. Admin confirms registration (or auto-accept registrations according to your needs) (default AppGini features)

6. When user login, automically create a record in userprofiles table for that member, if not exists.
use sql() function in login_ok()-hook in hooks/__global.php.
  • This adds username to memberID and registered email address to email field
    and Redirecting to the detail view

Code: Select all

function login_ok($memberInfo, &$args)
	{
	$tn  = "userprofiles"; // this is the table name of your custom userprofiles table
	$memberID = getLoggedMemberID(); // or take info from $memberInfo, if you prefer
	$userprofile_id = sqlValue("SELECT `id` FROM `{$tn}` WHERE `memberID`='{$memberID}'"); // I assume "id" as primary key column name
	if (!$userprofile_id) {
		$eo = null;
		sql("INSERT INTO {$tn}(memberID, email) VALUES('{$memberInfo['username']}','{$memberInfo['email']}')", $eo);
		if ($eo) die($eo); // add error handling here
		$userprofile_id = db_insert_id(db_link());
		set_record_owner($tn, $userprofile_id, $memberID);
	}
	if($memberInfo['group']=="Registered")
		{
		$getrecordcount = sqlValue("select COUNT(*) FROM ".$tn." WHERE memberID = '".$memberInfo['username']."'");			
		if ($getrecordcount > 0) {
			$recid = sqlValue("select id FROM ".$tn." WHERE memberID = '".$memberInfo['username']."'");
			return "userprofiles_view.php?SelectedID=$recid";
		}
		else
        return "";
		}
	}
What is additionally needed is to solve the email validation (avoid duplicate email registration) problem

User avatar
jsetzer
AppGini Super Hero
AppGini Super Hero
Posts: 1050
Joined: 2018-07-06 06:03
Location: Kiel, Germany
Contact:

Re: User Registration and Profile System

Post by jsetzer » 2021-04-09 14:50

Thanks for sharing with the community!

Issues with duplicate email-addresses

There was a huge discussion somewhere here between several community members naming pro's and con's.

As far as I know and as far as I can see, when having self-registration enabled (users are allowed to register themselves), there is no hooks-only solution for avoiding duplicate email-addresses right now, but I may be wrong.

Without self-registration:
By default, the Administrator user registers new members. So, by default, you can ensure unique email-addresses by organization (Admin cares for this) and/or by defining a unique contraint on the memberID column in membership_users table.
Kind regards,
<js />

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-09 15:39

jsetzer wrote:
2021-04-09 14:50
Thanks for sharing with the community!

Issues with duplicate email-addresses

There was a huge discussion somewhere here between several community members naming pro's and con's.

As far as I know and as far as I can see, when having self-registration enabled (users are allowed to register themselves), there is no hooks-only solution for avoiding duplicate email-addresses right now, but I may be wrong.

Without self-registration:
By default, the Administrator user registers new members. So, by default, you can ensure unique email-addresses by organization (Admin cares for this) and/or by defining a unique contraint on the memberID column in membership_users table.
Thanks Jan for the immense support,
Is there a way to look for duplicates in email like the username is filtered?
Even we put a unique constraint in user profile table, users can register with duplicate emails.

sathukorala
AppGini Super Hero
AppGini Super Hero
Posts: 121
Joined: 2020-02-16 16:29

Re: User Registration and Profile System

Post by sathukorala » 2021-04-10 03:59

A solution to validate email was found. It is a complicated process but works perfectly !!!

1. Add following lines to membership_signup.php (in root folder)
just below:

Code: Select all

<div class="form-group">
	<label for="email" class="control-label"><?php echo $Translation['email']; ?></label>
	<input class="form-control" type="text" required="" placeholder="<?php echo $Translation['email']; ?>" id="email" name="email">
Put below code block:

Code: Select all

<span id="emailAvailable" class="help-block hidden pull-left"><i class="glyphicon glyphicon-ok"></i> <?php echo str_ireplace(array("'", '"', '<memberid>'), '', "Email available for registration"); ?></span>
<span id="emailNotAvailable" class="help-block hidden pull-left"><i class="glyphicon glyphicon-remove"></i> <?php echo str_ireplace(array("'", '"', '<memberid>'), '', "Email is invalid or already registered !!!. Try resetting the password or contact admin"); ?></span>
<div class="clearfix"></div>
just below:

Code: Select all

$j('#confirmPassword').on('keyup blur', function() {
	if($j('#confirmPassword').val() != $j('#password').val() || !$j('#confirmPassword').val().length) {
		$j('#confirmPassword').parents('.form-group').removeClass('has-success').addClass('has-error');
	} else {
		$j('#confirmPassword').parents('.form-group').removeClass('has-error').addClass('has-success');
		}
	});
Put below code block:

Code: Select all

/* email availability check */
$j('#emailAvailable, #emailNotAvailable').click(function() { $j('#email').focus(); });
$j('#email').on('keyup blur', checkEmail);
just below:

Code: Select all

function reset_username_status(status) {
			$j('#usernameNotAvailable, #usernameAvailable')
				.addClass('hidden')
				.parents('.form-group')
				.removeClass('has-error has-success');

			if(status == undefined) return;
			if(status == 'success') {
				$j('#usernameAvailable')
					.removeClass('hidden')
					.parents('.form-group')
					.addClass('has-success');
			}
			if(status == 'error') {
				$j('#usernameNotAvailable')
					.removeClass('hidden')
					.parents('.form-group')
					.addClass('has-error');
			}
		}
Put below code block:

Code: Select all

var uaro2; // email availability request object
		function checkEmail() {
			// abort previous request, if any
			if(uaro2 != undefined) uaro2.abort();

			reset_email_status();

			uaro2 = $j.ajax({
					url: 'checkEmail.php',
					type: 'GET',
					data: { 'email': $j('#email').val() },
					success: function(resp) {
						var ua=resp;
						if(ua.match(/\<!-- AVAILABLE --\>/)) {
							reset_email_status('success');
						} else {
							reset_email_status('error');
						}
					}
			});
		}

		function reset_email_status(status) {
			$j('#emailNotAvailable, #emailAvailable')
				.addClass('hidden')
				.parents('.form-group')
				.removeClass('has-error has-success');

			if(status == undefined) return;
			if(status == 'success') {
				$j('#emailAvailable')
					.removeClass('hidden')
					.parents('.form-group')
					.addClass('has-success');
			}
			if(status == 'error') {
				$j('#emailNotAvailable')
					.removeClass('hidden')
					.parents('.form-group')
					.addClass('has-error');
			}
		}
Just below:

Code: Select all

if(!validateEmail(email)) {
				modal_window({ message: '<div class="alert alert-danger"><?php echo html_attr($Translation['email invalid']); ?></div>', title: "<?php echo html_attr($Translation['error:']); ?>", close: function() { $j('#email').focus(); } });
				return false;
			}
Put following code block:

Code: Select all

/* email exists? */
			if(!$j('#email').parents('.form-group').hasClass('has-success')) {
				modal_window({ message: '<div class="alert alert-danger"><?php echo html_attr("This email address is already registered !!! Please try resetting the password or contact admin" ); ?></div>', title: "<?php echo html_attr($Translation['error:']); ?>", close: function() { $j('#email').focus(); } });
				return false;
			}


2. Create a file named checkEmail.php in the root folder and put the following code in it

Code: Select all

<?php
	$currDir = dirname(__FILE__);
	include_once("{$currDir}/lib.php");
	include_once("{$currDir}/header.php");

	$current_user = isset($_REQUEST['currentUser']) ? $_REQUEST['currentUser'] : false;
	$email = is_allowed_email($_REQUEST['email'], $current_user);
?>

<style>
	nav, .hidden-print{ display: none; }
</style>

<div style="height: 1em;"></div>
<?php if($email) { ?>
	<div class="alert alert-success">
		<i class="glyphicon glyphicon-ok"></i>
		<?php echo str_replace('<email>', "<b>{$username}</b>", "Email already registered !!!"); ?>
		<!-- AVAILABLE -->
	</div>
<?php } else { ?>
	<div class="alert alert-danger">
		<i class="glyphicon glyphicon-warning-sign"></i>
		<?php echo str_replace('<email>', '<b>' . html_attr($_REQUEST['email']) . '</b>', "Email is invalid !!!"); ?>
		<!-- NOT AVAILABLE -->
	</div>
<?php } ?>

<div class="text-center">
	<input type="button" value="Close" onClick="window.close();" autofocus class="btn btn-default btn-lg">
</div>

<?php include_once("{$currDir}/footer.php"); ?>


3. Goto admin/incFunctions.php and look for

Code: Select all

########################################################################
	function is_allowed_username($username, $exception = false) {
		$username = trim(strtolower($username));
		if(!preg_match('/^[a-z0-9][a-z0-9 [email protected]]{3,100}$/', $username) || preg_match('/(@@|  |\.\.|___)/', $username)) return false;

		if($username == $exception) return $username;

		if(sqlValue("select count(1) from membership_users where lcase(memberID)='{$username}'")) return false;
		return $username;
	}
	########################################################################
Add the following code block just below the above code

Code: Select all

function is_allowed_email($email, $exception = false) {
		$email = trim(strtolower($email));

		if(sqlValue("select count(1) from membership_users where lcase(email)='{$email}'")) return false;
		return $email;
	}
If all these changes are successfully made your registration form will look for the existing email addresses and alert the user if he is using one of the already registered email addresses like the system check for the same username.

Hope our experts suggest a simple method or Ahamed add this in the next release......
Open for discussion....

Post Reply