# User routing versus admin routing strategies?

**URL:** <https://www.ruby-forum.com/t/user-routing-versus-admin-routing-strategies/189555>\
**Category:** Rails\
**Created:** [June 3, 2010, 1:16am UTC](https://www.ruby-forum.com/t/user-routing-versus-admin-routing-strategies/189555 "2010-06-03T01:16:20Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [June 3, 2010, 1:16am UTC](https://www.ruby-forum.com/t/user-routing-versus-admin-routing-strategies/189555/1 "2010-06-03T01:16:20Z")

</div>

In an app where ordinary users are limited to viewing and editing their  
own “stuff”, but someone with admin privs can view and edit anybody’s  
stuff, what’s the right strategy for routing?

At first blush, I’d think that an ordinary user (e.g. with id 565)  
should see something like:

[http://example.com/mystuff.html](http://example.com/mystuff.html)

… where the controller assumes @current\_user has been established by  
authlogic or whatnot. But if you’re logged in as an admin, you could  
get at that same user’s stuff via:

[http://example.com/users/565/mystuff.html](http://example.com/users/565/mystuff.html)

and you could list and administer all the users via:

[http://example.com/users](http://example.com/users)

Does this sound like the right approach? If so, what are the patterns  
for the routes and controllers? If not, what’s the accepted DRY,  
RESTful approach?

t.i.a.

- ff

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [June 3, 2010, 3:14am UTC](https://www.ruby-forum.com/t/user-routing-versus-admin-routing-strategies/189555/2 "2010-06-03T03:14:44Z")

</div>

Check out acl9 for access control [GitHub - be9/acl9: Yet another role-based authorization system for Rails](http://github.com/be9/acl9)

With acl9 you control what users have access to which specific methods  
and assign users roles on specific objects. You could set it up in the  
create method of stuffs\_controller so the current\_user is the “owner” of  
that stuff and only allow owners to edit that specific object, then  
admin has access to all.

In that approach it’s all handled in the models and controllers so  
routes are set up however you want.

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [June 3, 2010, 3:40am UTC](https://www.ruby-forum.com/t/user-routing-versus-admin-routing-strategies/189555/3 "2010-06-03T03:40:18Z")

</div>

I’m using Cancan, which works really well and is pretty cleanly  
implemented. Check out Ryan B. Railscast here  
[#192 Authorization with CanCan - RailsCasts](http://railscasts.com/episodes/192-authorization-with-cancan).

The urls you have up there end in .html, which doesn’t really happen  
all that often in rails. With routes, what you’re more likely going to  
have is:  
[http://example.com/users/###](http://example.com/users/###)

…where ### is the user\_id (or whatever). This goes to the show  
action for user ###. If the user\_id matches the current\_user or if  
current\_user is an admin, they get to access to that model. If not,  
they’ll get redirected. Furthermore, if current\_user is an admin, they  
would also get access to:  
[http://example.com/users](http://example.com/users)

…which goes to the index action to list all of the users. Other (non-  
admin) users will get a nasty flash message and redirected elsewhere.

Hope I’m answering the right question. 🙂

Dee

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [June 3, 2010, 3:51am UTC](https://www.ruby-forum.com/t/user-routing-versus-admin-routing-strategies/189555/4 "2010-06-03T03:51:19Z")

</div>

@Dee:

Yes, you’re answering the right question. My addition of the .html  
suffixes (suffixen?) was a brain bubble and should be ignored.

I wonder if exposing the user id in the url is useful or prudent. I  
agree with most RESTful philosophy, but even if authorization code is in  
place to prevent the user 123 from accessing the account of user 142,  
exposing the db-level user ID in the URL doesn’t feel right.

That’s why I was asking about having two styles of routing: one where  
the user ID is implicit (derived from session and authentication  
credentials) for ordinary users, and one where the user ID is manifest  
in the URL (for the administrator).

But: CanCan looks like a sensible adjunct to Authlogic (even though I’ve  
already written a Role model). I’ll just go with the flow and use that  
as it was intended.

Thanks for the pointer.

- ff

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [June 4, 2010, 4:06am UTC](https://www.ruby-forum.com/t/user-routing-versus-admin-routing-strategies/189555/5 "2010-06-04T04:06:06Z")

</div>

I see your point, but the user\_id is just an arbitrary number used for  
the lookup of the correct user record. You could use anything, like  
user name (User.find\_first\_by\_username(params[:username]) if you have  
the correct route set up. Or you could do the same thing with a  
randomly generated unique id that identifies the user. This all  
assumes you are concerned with user\_id being a sequential integer. At  
any rate, it’s tried and true.

You should be able to use your implementation of role models with  
CanCan. It doesn’t provide roles, just authorization based on your  
implementation of “roles”. You could, for instance, use CanCan to  
control access based on something as arbitrary as which UserAgent  
their browser is reports. Just remember to restrict access in both the  
View and the Controller (especially).

Good luck on your project.

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [June 4, 2010, 4:28am UTC](https://www.ruby-forum.com/t/user-routing-versus-admin-routing-strategies/189555/6 "2010-06-04T04:28:55Z")

</div>

Oh, and one other thought. If you are still concerned about the id in  
the url, in UserController#Index you could also check if the user is  
an admin, and if not then set params[:user\_id] = current\_user and then  
render :action =\> show instead of the index action. I haven’t tried it  
in a while, but as I remember this would give non-admins a url that  
looks like index (e.g. [http://example.com/users](http://example.com/users)) but would be doing  
the the show action (e.g. same as [http://example.com/users/####](http://example.com/users/####)). You  
wouldn’t have to play with the routing at all.

This is only a partial solution, because while it would work with the  
show action, the all of the other actions would still require the id  
in the url (i.e. [http://example.com/users/####/edit](http://example.com/users/####/edit)). There might be  
something you could do in a routing block to hide it, or maybe  
something like inserting the id through rack, but I think all of those  
are going to be a lot of work and not much bang for the buck.
