Creating an admin permissions section in laravel - laravel-4

I've created a couple of pages they are users, groups and permissions.
I would like the admin to be able to create groups and set what those groups can do via the permissions page.
So on the permissions page I would have a list of things a user could do e.g.: add content, delete content.
And if I check the add content box then the group can only add content and not delete content.
The problem I'm having is that I don't know where to go to look for information on how to go about it. I've already got my database set up and I'm thinking maybe sessions and routes is the way to go, but I'm not sure.

Frameworks is the way to go for something this complex. I'm working on a very similar project for my work (a dashboard to do different things based on User Role/Permissions) and I found it incredibly difficult to manage without the use of a framework. I would highly recommend Cartalyst/Sentry for this. It turns complex database operations like checking permissions, update permissions, creating groups etc into simple one. Here is a link to the manual:
Cartalyst/Sentry
It has a database backend already created (and modifiable) for you, so you simply follow the installation instructions and go over the documentation to get a better understanding. In your example, it would be as simple as creating a group and it's permissions:
// Define permissions (1 is allowed, 0 is not allowed)
$permissions = array('content.create' => 1, 'content.delete' => 1, etc etc...));
$group = Sentry::createGroup(array('name' => 'Admin', 'permissions' => $permissions));
Creating a user and adding them to the group:
$user = Sentry::createUser(array('email' => 'test#test.com', 'first_name' => ..., etc));
$group = Sentry::findGroupByName('Admin');
$user->addGroup($group);
And then checking their permissions during routing:
$user = Sentry::check(); // Aka get the current user.
if($user->hasAccess('content.create'){
// Continue
} else {
// Redirect to error page, etc
}
Now that's a brief overview of the system, and I assume you know how to use controllers and routes, but play around with it and I'm sure you'll come to see how powerful this Framework is when working with Laravel.
Hope that helps!
Then checking whether or not a user

Related

Laravel menu based on role?

i have codeigniter background. Now, i'm learning about laravel. So, i'm in this condition (Example), I'm trying to create a webapp, which has multiple users. The UsersType A , they can access menu a, menu b & menu c and UsersType B they only can access Menu a.
Now, i'm using https://github.com/lavary/laravel-menu . Well, if it's only have two types , i can write it manually. But, what if there are five types of user or more.
When i'm using codeigniter. I create 4 table Users , UsersType , Menu & MenuAccess. You must be understand how it's work. I just, play it with query then i show it.
UsersType (Users) -> TypeId (UsersType) -> MenuId (MenuAccess) -> MenuId (Menu)
I already use google and I found this https://github.com/Zizaco/entrust but what i can see from that package. It's only give the permission on the action (input,edit & delete)
So, Can i do my codeigniter way in my laravel ? Save my routes properties than show it in my rouotes/web.php (I don't know if it possible, haven't try it yet). sorry for my english.
What I would do is put a function in the User class which checks it's own permission and then returns a view which contains the menu that user has access to.
public function menu()
{
switch($this->role) {
case 'admin':
return view('menus.admin');
[etc]
}
}
Then in the view just check if the user is logged in and show the menu:
#if Auth::check()
{{ Auth::user->menu() }}
#endif
As mentioned in the comments,it sounds like what you want is the ability to conditionally display content based on whether a user has certain permissions.
There's a number of implementations of this. Essentially what they all do is store permissions that can be granted to users, and optionally store roles that allow permissions to be assigned to a role and then users can be given that role, automatically granting them the permissions associated with that role.
I've found spatie/laravel-permission which appears to be quite good. Then, if you pass your user model into the view, you can do something like this:
#if ($user->can('edit-posts'))
<a>Edit post</a>
#endif
That should be flexible enough that it can be reused for different permissions too. If that doesn't do the trick, then it's not hard to roll your own permission system using Laravel's authorization system and you should be able to use the can() method in the same way.

How to use Authority package for Laravel

After some searching, I succesfully installed the Authority-l4 package to use for my Laravel project. The docs are clear but small (not much info/examples). This is what my config file looks like atm:
return array[
'initialize' => function($authority) {
$user = $authority->getCurrentUser();
$authority->addAlias('manage', ['create', 'read', 'update', 'delete']);
if($user->hasRole('admin')) {
//Admin can manage all resources
$authority->allow('manage', 'all');
}
// User can manage his own post
Authority::allow('manage', 'User', function($self, $user){
return $self->getCurrentUser()->id === $user->id;
});
// User can manage his own post
Authority::allow('manage', 'Post', function($self, $post){
return $self->getCurrentUser()->id === $post->id;
});
}
];
I have some questions about this:
How to add a role to a user? hasRole() exists, why not setRole()?
I noticed nothing gets saved into the database, isn't this better?
How do I use my database with Authority? Could someone give me a head start, I've been strugling four hours now.
In some articles they say that the class Role should be changed to have many permissions instead of a user having many permissions, isn't this better?
Probably I'm thinking way to difficult about this package, searching the internet doesn't help either. Any help is appreciated!
I'm the author of Authority, and I maintain Authority-l4 though it was written primarily by Conar Welsh.
Since roles, as defined in the package, are just an Eloquent relation so you can simply add them like any other relation in Eloquent.
I have no idea what you're asking here, can you rephrase?
Can you elaborate on the question beyond what's in the readme (the part just above General Usage)?
Probably - either works. You don't need to use this structure to use Authority-l4. It's just an optional structure that you are 100% free to setup as you'd like. I personally don't use this at all and just use the Authority facade that it generates. Most of my permissions aren't stored in the DB though so that plays a factor.
The idea behind Authority is that it is implementation agnostic. It genuinely does not care where you store your data, you just need to tell authority what to do with your rules. Reading the section of the readme referenced above and the readme on the Authority core repo should be able to give you a general idea of how it expects information to be loaded - anything beyond that is up to your discretion.

Basset 4 (pre-beta)

I'm using Basset 4 to manage assets.
In the config file i'm declaring a collection 'admin'
return array(
'collections' => array(
'admin' => function($collection)
{
$collection->directory('assets/js', function($collection)
{
$collection->add('vendor/jquery-1.9.1.min.js');
});
},
),
...
)
later in a view, I would like to add an extra file in admin collection.
I've try the following code, but it doesn't work:
Basset::collection('admin', function($collection)
{
$collection->add('function.js');
});
Is there a way to add file into a collection from a view or from a controller?
Thank you
Basset isn't really designed to work like that. You should be defining all your assets within that initial call, even though the ability to add assets throughout the execution of an application is possible, it's not recommended.
When building a collection assets that are added for a particular route won't be available to the builder since Artisan doesn't fire any routes, etc.
Adjusting a collection in numerous places can often lead to confusion further down the line.
I know this isn't ideal as you're probably looking at implementing page specific JavaScript, correct? I've thought about it but can't really think of a clean solution (suggestions?), although I've heard of people assigning a unique ID to the body or perhaps some classes that their JavaScript can then attach themselves to.
It's not brilliant but that's the best I can give you at the moment.

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?

Joomla - Determining whether logged-in user is an Admin

I am having tons of fun working on a big project that was, for reasons hard to justify, based on Joomla! (which I don't mean to criticise, Joomla! is great, just not for the task I am faced with currently) and when I googled for a way of determining whether the currently logged-in user is an Admin, I found a post that quite boldly recommends using the following code:
$user =& JFactory::getUser();
if($user->usertype == "Super Administrator" || $user->usertype == "Administrator"){ ... }
To me, this looks like a rather strange way of checking for Admin users. I would appreciate a $user->isAdmin() method to do this rather than a couple of hard-coded strings.
I fail to find a more elegant solution to checking for admin users within the Joomla! framework. Can anyone help?
Actually, as the Access levels are hard coded into the database in Joomla! 1.5, the only way this string comparison could fail is when someone deliberately hacked new groups into it. Strings can be changed in the .ini-Files (so that non-english installations still use the english words in the database - this is not true for other tables like the names of plugins or components.)
You could get the group id via JFactory::getACL(), and then $acl->getGroupsByUser($userid, false) (see docs), but assuming that a greater id means greater privileges as well, seems a bit hacky, too (though true for a standard installation).
Other than that, you could take over a Joomla! capability: define more explicitly, what a "admin user" is: someone who can install new software? who can change the system's configuration? Just make a reasonable assumption, something related to what you want him to do as a admin user, use it in a authorize()-Call (see docs), and maybe document it in your interface.
The only clean solution (that I know of) would be to define new entries for the ACL-authorize-lookuptable (currently implemented in php only, not SQL). This is the only way to ensure that it will be Joomla! 1.6-proof, where custom user groups will be possible (and so the admin user can choose to give this authorization to a user group or not). For example:
$acl =& JFactory::getACL();
$acl->addACL('{com_nameOfExtension}', '{action}', 'users', 'super administrator');
$acl->addACL('{com_nameOfExtension}', '{action}', 'users', 'administrator');
And there we have them again, hard-coded groupnames. Well.
Peter,
I concur on the joomla sentiments, we use .net/php here as well and have a few projects that were started on joomla for some unknown reason !!
amnyway, another finer grained approach may be to examine the actual rights that the user has, rather than them being suoper admin etc. you can get to this info along the following lines:
$user =& JFactory::getUser();
if ($user->authorize('com_content', 'edit', 'content', 'all')) {
echo "<p>You may edit all content.</p>";
} else {
echo "<p>You may not edit all content.</p>";
}
if ($user->authorize('com_content', 'publish', 'content', 'own')) {
echo "<p>You may publish your own content.</p>";
} else {
echo "<p>You may not publish your own content.</p>";
}
i know it's still hardcoded but at least it's user specific, rather than priviledge specific. this approach does however allow you to target specific 'component' related priviledges, so might be useful for you.
I'll track the replies to see if there's a 'proper' answer as it definately is an omission.
jim
The following could be a hack on Joomla. I tried it and got worked.
Take the case of sessions
$_SESSION[__default][user]->usertype;
This will give the type of user logged in you can use this in any conditional statements
You can check 'assigned user groups' of the logged in user using getUser() function.
$user =& JFactory::getUser();
$assigned_usergroups = $user->groups; // Array of assigned User Group
if (in_array(8, $assigned_usergroups)) {
echo "Super Admin";
}
else if (in_array(7, $assigned_usergroups)) {
echo "Admin";
}
else {
echo "Other"; //Any of Guest/Public/Others
}
You can see the following snapshot of the Joomla's predefined IDs for each User Group in the Database:
Snapshot here
If ur joomla administrator username is admin then u can use below code aspeter described before
$user =& JFactory::getUser();
if($user->usertype == "Super Administrator" && $user->username == "admin")
{
//... do what ever
}

Resources