Best way to make sure username isn't a reserved word? - validation

Let's say I'm building a web application whose user pages can be found at http://example.com/NAME. What's the best way to make sure the username doesn't conflict with a reserved word (e.g. 'about', 'contact', etc.)? I can think of two ways:
Maintain a list somewhere in my code. This is great and all, but means I have another piece of code I have to edit if I decide to, say, change the "about" page to "aboutus".
Request the URI (e.g. http://example.com/someusername) and check if it exists (doesn't return a 404). This feels kind of like a hack, but on the other hand it does exactly what it's supposed to do. On the other hand, I can't reserve anything without making a page for it.
What would be the best way to go about this? Manual validation of usernames is not an option. Thanks!
EDIT: I forgot to mention, the username has to go at the root, like this:
http://example.com/USERNAME
Not like this:
http://example.com/users/USERNAME
Hence why I'm asking this question. This is for technical reasons, don't ask.

I would strongly suggest using a unique path like http://example.com/users/NAME instead. Otherwise, what are you going to do if you want to add a reserved word, but a user has already taken it as their user name? You'll end up with all kinds of potential migration problems down the track.
Alternatively, if you must have something that goes straight off http://example.com/, could you possibly prefix all user names? So that user jerryjvl would translate to link http://example.com/user_jerryjvl?
If there is really no other possible solution, then I'd say either check user names against whatever data source determines what the 'reserved words' are, or make a lookup file / table / structure somewhere that contains all the reserved words.

In the interest of completeness, if you can't change the routing. Another possibility is to have your user routes and your non-user routes have a programmatic distinction. For example, if you appended a '_' to the end of each of your user routes, then you can make sure that users are located at: http://example.com/NAME_ and the other route would never end in '_'

How about changing your routing scheme so that users are at example.com/users/NAME ?

I maintain the reserved words inside the code.
This is the PERL code that I use in the http://postbit.com/ website to check if the usernamename is a reserved word:
# Black list of logins and sub-domains reserved keywords
my #black_list = qw(
about access account accounts add address adm admin administration
adult advertising affiliate affiliates ajax analytics android anon
anonymous api app apps archive atom auth authentication
...
);
my $username_normalized = lc($username);
$username_normalized =~ s/\W//gs; # 'log-in' -> 'login'
for my $this_username (#black_list) {
if ($username_normalized eq $this_username) {
die("This username is already taken. Please choose other username.\n");
}
}
The complete list of reserved names (like 'css', 'images', 'js', 'admin', 'root', 'old', 'test', 'www', 'admin', 'login', 'devel'...) with more than 300 login usernames is posted here:
http://blog.postbit.com/reserved-username-list.html

You only know what are these 'reserved' words. So better maintain a list and validate against it.
Another method will be if you use a CMS, then all these keywods 'about', 'contact' etc. will be there in your database. Validate against it.

Right next to the text box something like: "Please use your personal nickname or you real name. Usernames with common words indicating affiliation with the site administration may be revoked".

How about just create dummy accounts first with all the reserve words? just list all the possible ones and create them.
if you use
www.example.com/user/name
then there will be no problem but it seems like you'd like the URL to be short.

Maintain a list somewhere in my code. This is great and all, but means I have another piece of code I have to edit if I decide to, say, change the "about" page to "aboutus".
Your menus should be stored in an array/list. This way you would have only 1 piece of code to edit, not 2. =]
Then, since all menus are in one array, you can match username with elements in the array.
for example
$menu = array('About', 'Contact', 'Home')
if( in_array($username, $menu) ) {
echo 'invalid username'
}

You could always look and see how stackoverflow.com works.

Related

Codeigniter - Where should I store an array of reserved usernames?

I'm building a site and would like to create a list of reserved usernames to keep people from creating usernames like account, index, profile and others. I already have my list, I'm just not sure where in Codeigniter to store this data/array.
I'm pretty familiar with Codeingiter and I like to keep things where they are suppose to be. Helpers, libraries and configs just don't seem like places to store an array of reserved variables... but maybe i'm wrong.
I would appreciate suggestions! Thanks in advance.
It depends on your need and preference, config is right but helper is also right because if you keep it in helper file then you may also create a helper function right there, for example
function is_reserved_username($username)
{
$reserved_words = array('account', 'index');
return in_array($username, $reserved_words);
}
So, from anywhere, you can use
if(is_reserved_username($this->input->post('username'))) {
// it's a reserved word
}
Also, if you are using your own base controller (MY_Controller) then you may keep it in that base controller, so it'll be available in every classes and you can access it using something like
In MY_Controller if it's available as
$reserved_words = array('account', 'index');
Use it from a controller/model
if(in_array($username, $this->reserved_words)) {
// it's a reserved word
}
I don't think there is any "right" way to do this. Personally I would just create a table in my database. I'd then create a function that would check this table for reserved names when a new user is registering and return TRUE if the username isn't reserved and FALSE if it is reserved

MVC Putting an action in the most appropriate correct controller

I was just wondering what the best practice approach is for deciding where to create an action/view in certain situations.
If User hasMany Video
where is the best place to create the action/view to show user videos?
So within the Users account page 'My Videos' link do you
just create a users/my_videos action and view.
create videos/my_videos action and view.
or as is most likely you would already have a Controller/Action of videos/index which would have search functionality. Simply use this passing in a user id.
Any thoughts/advice greatly appreciated
Thanks
Leo
One potential option is to do the following:
Since the videos likely have much more code around them than a simple which user has which videos lookup the video list action should be in the VideosController.
In past projects I have (in CakePHP 1.3) used prefix routing to address some of this.
In config/core.php make sure you enable routing.prefixes to include a 'user' prefix.
<?php
... in routes.php ...
Routing.prefixes = array( 'user' );
?>
In the videos controller make an action with the following signature:
<?php
...
public function user_index( $userID = null ){
...
}
?>
and in the views where you link to the list of users videos the html::link call should look similar to the following:
<?php
...
echo $this->Html->link( 'User\'s Videos', array(
'controller' => 'videos',
'action' => 'index',
'prefix' => 'user',
$this->Session->read( 'Auth.User.id' )
));
?>
Of course this assumes you are using the Auth component here to track the logged in user. The Session helper code to read the authenticated user id might need tweaking.
This lets you a) Not worry too much about routing aside from enabling prefix routing and b) will quickly let you have pretty links like so -- site.com/user/videos/index/419
Couple this with some Slug love ( this is the best link for this I have seen - no slug field required on the db layer - http://42pixels.com/blog/slugs-ugly-bugs-pretty-urls )
You could even end up with urls like so quite easily: site.com/user/videos/index/eben-roux
and with just a tiny bit of editing to app/config/routes.php you could eliminate the /index/ portion and the results would be SEO friendly and user friendly in the format:
site.com/user/videos/eben-roux
http://book.cakephp.org/view/945/Routes-Configuration
As always with code you have the two extremes of:
1) Putting everything in a single controller
2) Having every action in a separate controller
The ideal approach will nearly always be somewhere between the two so how to decide what is grouped together and what is separated?
In MVC I tend to look at the Views and see what the commonalities are: as you point out Users have a ref to a collection of Videos in the Model, but would you want both sets of Data in any single View? i.e. In this example is it likely that you would be on a page that both managed user details, and displayed the list of vids? If not then I'd suggest separate controllers.
If either controller would then be extremely simple - e.g. one method, then may be worth considering merging the two.
I like to keeps things separate.
What I'd do is an index action in videos controller, passing user's id as argument and then displaying only current users video.
public function index($id = null){
$this->paginate = array( 'conditions'=> array('Video.user_id' => $id));
$this->set('videos', $this->paginate());
}
My take is that it depends on the responsibility you assign to the controllers.
I would say that something like a User or a Video controller should be concerned with only those entities.
You may want to consider something like a UserDashboard (or something similar but appropriately named) as alluded to by Dunhamzzz in the comments. This can aggegate all the functionality from an "entry" point-of-view. The same way a banner / shortcut / action menu would work.
Your UserDashboard would use whatever data layer / repository is required to get the relevant data (such as the IVideoRepository or IVideoQuery implementation).
Usually when something doesn't feel right it isn't. Try splitting it out and see how it works. You can alsways re-arrange / refactor again later.
Just a thought.
I don't think there's a 'one-rule-fits-all' solution to this question, but I would try to take an approach in which you would determine what the main object is that you're dealing with, and adding the action/view to that object's controller.
In your example I'd say that your main object is a video and that the action you're requiring is a list of video's filtered by a specific property (in this case the user's id, but this could very well be a category, a location, etc.).
One thing I would not do is let your desired URL determine in which controller you put your functionality. URLs are trivially changed with routes.

Displaying specific content to specific user in Joomla 1.5

To be short, It's a website for an investigations lab.
I need to display specific content (lab report) to specific user. Users will be given a username and a password when leaving and will be asked to login on the website to access his/her report with the credentials given to him.
So , it's a "specific content" for "specific user" - Moving to 1.6 is not an option.
I have a solution in mind but involve a lot of core hacking and will take some time ... If any one been in a similar situation or have an idea in mind I would appreciate your help.
Ok, this can be done but it's going to take a little trickery to get there. First, you are going to need a way to post the lab reports and associate them with a user. I would use K2 for this since you can add the report as an attachment to an item. You can also add extra fields to K2, which would be the next step. You'll need an extra field where you can enter a user ID number that you will use to determine if a user is allowed to view the content.
There are several steps you will need to take to now filter the content so only the associated user can see it.
You will need to get the user ID once the user is logged in:
$user =& JFactory::getUser();
$usr_id = $user->get('id');
You'll need a menu item that links to a K2 Category where all the lab reports go.
You'll need a subtemplate with a modified category_item.php for that category that only displays the associate reports:
if($this->item->extra_fields[USER_ID_EXTRA_FIELD_NAME]==$usr_id){
all the category item stuff
}
You'll need a subtemplate with a modified item.php for the category that again blocks users other than the associated user, basically the same code as #3 to either display the content or an error message.
The only other way I can think of that you can accomplish this would be to use an ACL component with a group for each user.
The K2 method with subtemplates would not require any core hacks and will work with a little work.
You can achieve what you want with Flexicontent http://www.flexicontent.org/ and Flexiaccess
Flexicontent is a K2 type component and I use them interchangeably. With Flexiaccess you can create items that are only available to certain users.
No hacks required.
Bad News: That cant be done with standard Joomla 1.5 (without hacking)
Good News: You can use one of the free or commercial Extensions for Joomla to accomplish that. I would suggest for example:
Admin-User-Access
http://extensions.joomla.org/extensions/access-a-security/backend-a-full-access-control/9040
Or you can search for yourself:
http://extensions.joomla.org/extensions/access-a-security/backend-a-full-access-control

CakePHP, organize site structure around groups

So, I'm not quite sure how I should structure this in CakePHP to work correctly in the proper MVC form.
Let's, for argument sake, say I have the following data structure which are related in various ways:
Team
Task
Equipment
This is generally how sites are and is quite easy to structure and make in Cake. For example, I would have the a model, controller and view for each item set.
My problem (and I'm sure countless others have had it and already solved it) is that I have a level above the item sets. So, for example:
Department
Team
Task
Equipment
Department
Team
Task
Equipment
Department
Team
Task
Equipment
In my site, I need the ability for someone to view the site at an individual group level as well as move to view it all together (ie, ignore the groups).
So, I have models, views and controls for Depart, Team, Task and Equipment.
How do I structure my site so that from the Department view, someone can select a Department then move around the site to the different views for Team/Task/Equipment showing only those that belong to that particular Department.
In this same format, is there a way to also move around ignoring the department associations?
Hopefully the following example URLs clarifies anything that was unclear:
// View items while disregarding which group-set record they belong to
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
http://www.example.com/Departments
// View items as if only those associated with the selected group-set record exist
http://www.example.com/Department/HR/Team/action/id
http://www.example.com/Department/HR/Task/action/id
http://www.example.com/Department/HR/Equipment/action/id
Can I get the controllers to function in this manner? Is there someone to read so I can figure this out?
Thanks to those that read all this :)
I think I know what you're trying to do. Correct me if I'm wrong:
I built a project manager for myself in which I wanted the URLs to be more logical, so instead of using something like
http://domain.com/project/milestones/add/MyProjectName I could use
http://domain.com/project/MyProjectName/milestones/add
I added a custom route to the end (!important) of my routes so that it catches anything that's not already a route and treats it as a "variable route".
Router::connect('/project/:project/:controller/:action/*', array(), array('project' => '[a-zA-Z0-9\-]+'));
Whatever route you put means that you can't already (or ever) have a controller by that name, for that reason I consider it a good practice to use a singular word instead of a plural. (I have a Projects Controller, so I use "project" to avoid conflicting with it.)
Now, to access the :project parameter anywhere in my app, I use this function in my AppController:
function __currentProject(){
// Finding the current Project's Info
if(isset($this->params['project'])){
App::import('Model', 'Project');
$projectNames = new Project;
$projectNames->contain();
$projectInfo = $projectNames->find('first', array('conditions' => array('Project.slug' => $this->params['project'])));
$project_id = $projectInfo['Project']['id'];
$this->set('project_name_for_layout', $projectInfo['Project']['name']);
return $project_id;
}
}
And I utilize it in my other controllers:
function overview(){
$this->layout = 'project';
// Getting currentProject id from App Controller
$project_id = parent::__currentProject();
// Finding out what time it is and performing queries based on time.
$nowStamp = time();
$nowDate = date('Y-m-d H:i:s' , $nowStamp);
$twoWeeksFromNow = $nowDate + 1209600;
$lateMilestones = $this->Project->Milestone->find('all', array('conditions'=>array('Milestone.project_id' => $project_id, 'Milestone.complete'=> 0, 'Milestone.duedate <'=> $nowDate)));
$this->set(compact('lateMilestones'));
$currentProject = $this->Project->find('all', array('conditions'=>array('Project.slug' => $this->params['project'])));
$this->set(compact('currentProject'));
}
For your project you can try using a route like this at the end of your routes.php file:
Router::connect('/:groupname/:controller/:action/*', array(), array('groupname' => '[a-zA-Z0-9\-]+'));
// Notice I removed "/project" from the beginning. If you put the :groupname first, as I've done in the last example, then you only have one option for these custom url routes.
Then modify the other code to your needs.
If this is a public site, you may want to consider using named variables. This will allow you to define the group on the URL still, but without additional functionality requirements.
http://example.com/team/group:hr
http://example.com/team/action/group:hr/other:var
It may require custom routes too... but it should do the job.
http://book.cakephp.org/view/541/Named-parameters
http://book.cakephp.org/view/542/Defining-Routes
SESSIONS
Since web is stateless, you will need to use sessions (or cookies). The question you will need to ask yourself is how to reflect the selection (or not) of a specific department. It could be as simple as putting a drop down selection in the upper right that reflects ALL, HR, Sales, etc. When the drop down changes, it will set (or clear) the Group session variable.
As for the functionality in the controllers, you just check for the Session. If it is there, you limit the data by the select group. So you would use the same URLs, but the controller or model would manage how the data gets displayed.
// for all functionality use:
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
You don't change the URL to accommodate for the functionality. That would be like using a different URL for every USER wanting to see their ADDRESS, PHONE NUMBER, or BILLING INFO. Where USER would be the group and ADDRESS, PHONE NUMBER< and BILLING INFO would be the item sets.
WITHOUT SESSIONS
The other option would be to put the Group filter on each page. So for example on Team/index view you would have a group drop down to filter the data. It would accomplish the same thing without having to set and clear session variables.
The conclusion is and the key thing to remember is that the functionality does not change nor does the URLs. The only thing that changes is that you will be working with filtered data sets.
Does that make sense?

Modifying view based on ACL in CakePHP

I want to be able to show or hide certain elements in a view based on ACL. For instance, if a user is looking at my Users/index view, I don't want to show a 'Delete User' element if he doesn't have permission to delete users. If he does have permission to edit users, I do want to show a 'Edit User' link.
I can hack this together, but being very new to Cake I'm hoping that there is an elegant solution. The best I've done involves keeping logic in two places, so it's hell to maintain.
Thanks!
I know this is an old question now but for anyone looking for a way like I was...
In AppController::beforeFilter you can assign the ACL component to a view variable and then use it in your view:
$this->set('user', $this->Auth->user());
$this->set('acl', $this->Acl);
And then in you view just juse it like thie:
if($acl->check(array('User' => $user), 'controllers/groupd/admin_delete')) {
This is't necessarily the most correct way to do it but it does work nicely
There is no generic "elegant solution" :) I've always wanted to make such thing as well. Anyway how you could do it:
Overwrite the Html Helper in your app directory - make a copy from /cake/libs/views/helpers/html.php to /app/views/helpers/html.php and made some changes in the Html::link function.
For example you can check if the url contain action edit or delete.
The other part is to pass the proper parameters from the controller. In AppController::beforeFilter you can read the rights of the user (it's better to be cached) and to pass it in a special Auth variable to the View.
So when you have the rights in your View it's easy to modify the link. :)
As I said I haven't did it in real example, but this is the way I would do it.
There is 1 bad point in that - if the original Html helper is changed, your one will remain the same. But I believe that Html helper is mature enough so for me is not a big issue.
I do it like this in app_controller.php, although you could just as well do it in specific controllers. The view variables $usersIndexAllowed and $configureAllowed are then used in conditional statements in the view.
function beforeRender()
{
if($this->layout=='admin')
{
$usersIndexAllowed = $this->Acl->check($user,"users/index");
$configureAllowed = $this->Acl->check($user,"siteAdmins/configure");
}
$this->set(compact('usersIndexAllowed','configureAllowed'));
}
In case you don't want to mess around with overriding core helpers and you want a more automatic way of checking (without hard-coding user group names and users or setting separate link-specific variables) here's my suggestion:
Store all user permissions as session vars when the user logs in (clear on logout) and create a permissions helper to check if logged on user has permissions for a specific action.
code and example here
hope that helps
There's multiple approaches to this scenario. As Nik stated, using a helper to do the checks for you is a quick way to "outsource" the logic and centralize it for ease of use.
Actually, have a look at the AclLinkHelper - it does exactly what you're looking for, however restricted to links only.

Resources