Nature and Aims of the CakePHP Application

http://pict.uws.ac.uk/~sss04/cakephp/

The aim of the following blog is to show my development through the module “Server Side Systems”. This blog is focused on my CakePHP development work.

My CakePHP application is based on existing project. During next few weeks I will be fixing and extending the given CakePHP USCMS.

The purpose of the Football Stars Cake PHP application is to gather information about football players. Every logged-in application user can add new football players. One single post describes one football player.

The initial core functions that will be included are:
• Authentication and permissions for posts, comments and users,
• User registration and log-in,
• User roles with an admin role, so the admin can edit other users,
• Item editing for admins only,
• Utilizing ENUM for drop downs,
• Styling and layout,
• Data Sanatization,
• Pagination,
• Data Validation.

Database Structure & Possible Roles

a -admin

u –authenticated users

v -non-authenticated visitors

C R U D
Posts a u a u v a u a u
Comments a u a u v a u a u
Users a u a u a u a
    Posts table:

  • id (auto increment primary key to uniquely identify the post)
  • title (a title for the content)
  • content (the actual content)
  • file_name, file_type, file_size (optional resources)
  • user_id (foreign key, a post belongsTo an identified admin user responsible for the post, an admin user potentially hasMany posts)
    Comments table:

  • id (auto increment primary key to uniquely identify the comment)
  • post_id (foreign key, a comment belongsTo a post and a post potentially hasMany comments)
  • user_id (foreign key, a comment belongsTo an identified user responsible for the comment and a user potentially hasMany comments)
  • comment (the text or the comment or query added by the user)
  • created (timestamp)
  • modified (timestamp)
    Users table:

  • id (auto increment primary key to uniquely identify the user)
  • name (eg”real” name)
  • username (for login)
  • Password (encrypted)
  • role (user type information)

A user potentially hasMany posts and potentially hasMany comments.

Cakephp’s Auth Component – add new users, drop down menu for ENUM

In the Football Stars application, every unauthenticated visitor can register and create account. The non-logged users have access to add users view:
add view

During registration, the non-logged user must fill in the ‘Name’, ‘Username’, ‘Password’ and ‘Password Confirmation’ inputs but cannot choose role. The default role for each new user created by unauthenticated visitors is ‘user’.
Non-logged user’s add view:
add view2

The admin can also create new users, but admin can set up new user’s role (‘user’ or ‘admin’ role):
add view3

The public function that checks if logged user’s role is ‘admin’:
add view4

Admin add (register new users) view:
add view5

Cakephp’s Auth Component – validation

The registration form for new users follows validation rules. All the inputs are required. The username should be unique and the username length should be between 3 and 15 characters.
validation_codes1

If user or admin choose username that has already been taken, the user account will not be created and the following error will be displayed:
validation_unique

If user or admin type username that is shorter than 3 or longer than 15 characters, the user account will not be created and the following error will be displayed:
validation_length

The password field and confirmed password field should matched. The rule ‘matchPassword’ is not cakePHP rule, since cakePHP does not have rule to compare fields.
The public function ‘matchPassword’ takes one argument – data. The function compares if password field value matches the confirmed password field value. If fields are equal than function returns true. If fields are not equal than the password confirmation field is invalidate, the error message is displayed and the function returns false.

validation_codes2

If user or admin type password and confirmed password that do not match, the user account will not be created and the following errors will be displayed:
validation_psswd_match

Check the previous screens – password and password confirmation fields are hashed. The public function beforeSave() hashed passwords before stored in database:
hash

Cakephp’s Auth Component – user’s navigation panel

To create user’s navigation panel at the top of each page, default.ctp layout file has been changed. Inside ‘user-nav’ div, conditional statement has been added.
If user is logged in the ‘Welcome’ message, the user’s username and ‘Logout’ link are displayed. If user is logout, the two links are displayed: ‘Register’ and ‘Login’.
default_codes

The function _loggedIn() checks if user is logged in. If user is logged in, the function returns true, otherwise returns false.
loggedin_codes

If user is logged in not only the ‘Welcome’ message is displayed, but also the user’s username is displayed. The function _usersUsername() checks if user is logged in. If user is logged in, the function returns the user’s username.
usersusername_codes

The logged in user’s navigation panel at the top of the page with the ‘Welcome’ message, the user’s username and ‘Logout’ link:
loggedin

The non-logged in user’s navigation panel at the top of the page with the ‘Register’ and ‘Login’ links:
nonloggedin

Cakephp’s Auth Component – edit/delete user’s profile

Users can edit or delete only his/her own profile. Admin can edit/delete others users profiles. Public function isAuthorized compares logged-in user’s id with user’s id from the URL. If the ids match, edit and delete buttons work, otherwise do not work. It also checks if user’s role is ‘admin’.
user_edit_code1

Moreover the edit/delete buttons associated with others users in users view are hidden:
user_edit_code2

The users view with hidden edit/delete buttons:
user_edit1

If the user wants to bypass the isAuthorized function and hidden edit/delete buttons by typing edit user URL with someone’s else id e.g.:
http://pict.uws.ac.uk/~sss04/cakephp/users/edit/13 (user fred id=14 is typing wilma’s id=13)
the error message ‘You can’t access that page’ appears:
user_edit2

Routes

When users logging in, after correctly typing username and password, he/she is redirecting to default URL:
http://pict.uws.ac.uk/~sss04/cakephp/
route1

To change redirected URL, routes.php file should be updated:
route3

Now, the logged-in user is redirecting to the users view:
route2

Check Users view URL from previous post.
The non-redirected Users view URL is:
http://pict.uws.ac.uk/~sss04/cakephp/users/
The redirected Users view URL is:
http://pict.uws.ac.uk/~sss04/cakephp/

Cakephp’s Auth Component – edit/delete user’s comments

Users can edit or delete only his/her own comments. Admin can edit/delete others users comments. If the user wants to edit/delete someone’s else comment by clicking edit/delete button or by typing edit/delete comment URL with someone’s else comment’s id e.g.:
http://pict.uws.ac.uk/~sss04/cakephp/comments/edit/12 (fred is typing admin’s comment id=12)
the error message ‘You are not authorized’ appears:
comments1

There is no point to display edit/delete buttons associated with others users comments in comments view. To hide those buttons, comments index.ctp file should be updated. It compares logged-in user’s id with comment’s user id. If the ids match, edit and delete buttons are displayed, otherwise do not. It also checks if user’s role is ‘admin’. If so, the others users edit/delete comment buttons are displayed.
comments2

User ‘fred’ can only use edit/delete buttons associated with his own comments:
comments3

Cakephp’s Auth Component – edit/delete user’s posts

Logged-in users can edit/delete only his/her own posts. Admin can edit/delete others users posts. If the user wants to edit/delete someone’s else post by clicking edit/delete button or by typing edit/delete post URL with someone’s else post’s id e.g.:
http://pict.uws.ac.uk/~sss04/cakephp/posts/edit/43 (fred is typing admin’s post id=43)
the error message ‘You are not authorized’ appears:
post3

Hiding an option from a view does not add authentication restriction to controller functionality. The authentication restriction is added to PostsController.
The edit posts function in PostsController.php compares user’s id who made the post with the user’s id who wants to edit that post. If those ids match or the user role is ‘admin’ then the post is updated. If those ids do not matched, the error message ‘You are not authorized’ appears.
post4

The delete posts function in PostsController.php works similar to the edit posts function. It compares user’s id who made the post with the user’s id who wants to delete that post. If those ids match or the user role is ‘admin’ then the post is deleted. If those ids do not matched, the error message ‘You are not authorized’ appears.
post5

The edit/delete buttons associated with others users posts in posts view are hidden. To hide those buttons, posts index.ctp file should be updated. It compares logged-in user’s id with post’s user id. If the ids match, edit and delete buttons are displayed, otherwise do not. It also checks if user’s role is ‘admin’. If so, the others users edit/delete comment buttons are displayed.
post6

User ‘fred’ can only use edit/delete buttons associated with his own posts:
post7

Customising Layout and Style

To make the web site more personalised, the layout and style have been changed. This was done by updating the default.ctp and cake.generic.css files.
To change the site title, $cakeDescription in default.ctp file has been updated:
$cakeDescription = __d('cake_dev', 'Football Stars: CakePHP');

I customised the body and content backgrounds, header, header icon, and by editing cake.generic.css:
body {
background: #fff url('../img/grass.jpg') top center no-repeat;
color: #fff;
font-family:'lucida grande',verdana,helvetica,arial,sans-serif;
font-size:90%;
margin: 0;
}

#content{
background:rgba(255,255,255, 0.9);
clear: both;
color: #333;
padding: 10px 20px 40px 20px;
margin: 0 10px;
overflow: auto;
}

h1 {
color: #003d4c;
font-size: 120%;
font-weight: bold;
}

The body background is an image. The content background is transparent. To set transparency rgba(255,255,255, 0.9) function was used. RGBa extends the RGB colors model to include the alpha channel, allowing specification of the opacity of a color(the 4th value – 0.9- means 90% opaque white). ‘0’ means transparent; ‘1’ means opaque.

layout

Remove Visible Hashed Password

The application was set up so that all users could see other users hashed passwords. This isn’t safe solution since hashed passwords allow offer clues to password cracking. If somebody has the same password hash as other user then he/she knows their password is the same. There is no point to show hashed passwords. Right now user index shows user’s passwords:
hash1

To remove password column from the users view, two lines of code from index.ctp were commented out:
hash2

The user index with no user’s passwords:
hash3

User’s view also display user’s hashed password:
hash4

To hide user’s password from users view two lilnes of code from view.ctp were commented out:
hash5

The user view with no user’s passwords:
hash6

Edit user’s view also display user’s hashed password:
hash7

To remove hashed password from password field from edit user’s view array('value' => '') has been added to password field:
hash8

Right now password field display correct password length:
hash9

Commenting out these lines or removing them completely will remove the password hashing from the users page and will allow the application to be much safer from any kind of password guessing or hacking.

Retention of Old Password if Both Password Fields are Empty – Problem Unsolved

When users edit their details both field – password and password confirmation are mandatory.
validation

It is a good idea to change it that if the user doesn’t type the password and password confirmation, the user details can be saved without having to re-enter the passwords.

To fix this issue I created the following emptyPassword() function in the User.php file:

function emptyPassword(){
if($this->data[‘User’][‘password_confirmation’] == “”){
unset($this->data[‘User’][‘password_confirmation’]);
}
}

And the rule:
’emptyPassword’ => array(
‘rule’ => array(’emptyPassword’, ‘password’),
‘on’ => ‘update’,  //Only in the edit user form

But emptyPassword() function did not run since errors returning from matchPassword() function occurred first. I added ‘on’ => ‘create’ and ‘required’=>false conditions to the  password array, that it runs only when creating new user, but in also did not work.

password

Instead matchPasswords() function I tried to use emptyPassword() function:
password1

Again, errors that both password fields should be filled-in appears.
I decided to move forward and back to that problem in the future.

Data Sanitization

Data Sanitization is used to ensure that no malicious code is put into the application.
CakePHP has a sanitize class set up. This core library can be placed anywhere in the application.
App::uses(‘Sanitize’); could have been added to every single controller but by using App::uses(‘Sanitize’, ‘Utility’); in the AppController.php file all controllers will be sanitized.
The code calls the sanitize.php file that is located in app/lib/cake/Utility. Sanitize cleans data that is in a string or an array:
san1

A clean options array should be placed in the AppController.php file:
san2

The clean option:
• replaces odd spaces with regular ones,
• encodes changes any hmtl into entities e.g. < becomes &lt ;.
• the dollar sign is escaped by prepending a \.
• adds \r (carriage return character) which causes a new line in the console but has no effect on web pages,
• replaces unicode with non-unicode,
• escapes using Sanitize::escape (when true).

Controllers for the user input now should be updated. This is done by changing the index function in the CommentsController.php and the PostsController.php:
$this->set('comments', Sanitize::clean($this->paginate(),$this->cleanOptions) ); //ED.
$this->set('posts', Sanitize::clean($this->paginate(),$this->cleanOptions) ); //ED.

san3

To test this solution a comment with 5 spaces between the word in the comment (My _______ spaced comment.) has been created:
san4

And after saving, comment appears it looks like this:
san5

Found Bug – Cakephp’s Auth Component – edit/delete user’s comments

When browsing application pages, I found bug. Logged-in users can see edit/delete buttons associated with other users comments in posts view. Clicking on those buttons returns error message, so there is no point to display those buttons:
bug1

To hide edit/delete buttons associated with others users comments, posts index.ctp file should be updated. It compares logged-in user’s id with comment’s user id. If the ids match, edit and delete buttons are displayed, otherwise do not. It also checks if user’s role is ‘admin’. If so, the others users edit/delete comment buttons are displayed:
bug2

Right now user fred can see only his own edit/delete buttons:
bug3

Images Content

Right now images are displayed only by clicking ‘View file’ link inside the post.
To display the ‘thumbnail’ inside the following line of codes had been added to view.ctp file:
img

After that image is displayed inside the post:
img1

To display the ‘thumbnail’ inside the posts list three line of codes had been added to index.ctp file:
img2

And images are displayed inside the posts list:
img3

Back From Post View to Posts Index – Non-Logged in Users

In the current version of application, on posts view page non-logged in users have no actions to choose. It is very inconvinient since non-logged in users can preview posts list and all posts. On the post index page, there is no need to add any action buttons, but on the post view page it would be easier to move between posts pages if ‘Lists Posts’ button appears.
The following line displays ‘Lists Posts’ button that takes from Post view to posts list (index.ctp). It would be displayed for not only non-logged in users, but also for logged in users and for admin.
button

Non-logged in user can move to the list posts index from post view:
button1

Drop Down List for ENUM – Revision

To create FormEnum the first file that has to be modified is the UsesController.php :
enum1

After that user add.ctp file was altered:
enum2

Unfortunately refreshing the user add page returns error:
enym3

In order to fix this error FormEnumHelper.php helper has to be added to app/View/Helper.
Once this file has been added to the appropriate folder on the server admin can see drop-down menu for user roles:
enum4

To display drop-down disabled list for non-admin users, the following else statement was added to the already existing if statement (in add.ctp and edit.ctp files):
enum5

Right now new users can see disabled role during registration process:

enum6

And an existing non-admin users can also see disabled role on edit user profile page:
enum7