Created
January 6, 2011 23:27
-
-
Save elricstorm/768843 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Create permissions to populate the permissions table with. | |
permissions = Forumpermission.create([ | |
{:name => 'view', :description => 'view index', :bitfield => 1}, | |
{:name => 'search', :description => 'search forum', :bitfield => 2}, | |
{:name => 'viewtopics', :description => 'view topics', :bitfield => 4}, | |
{:name => 'createtopics', :description => 'create topics', :bitfield => 8}, | |
{:name => 'edittopic', :description => 'edit own topic', :bitfield => 16}, | |
{:name => 'deletetopic', :description => 'delete own topic', :bitfield => 32}, | |
{:name => 'editothertopics', :description => 'edit other topics', :bitfield => 64}, | |
{:name => 'deleteothertopics', :description => 'delete other topics', :bitfield => 128}, | |
{:name => 'locktopics', :description => 'lock topics', :bitfield => 256}, | |
{:name => 'stickytopics', :description => 'sticky topics', :bitfield => 512}, | |
{:name => 'createpost', :description => 'create a post', :bitfield => 1024}, | |
{:name => 'editpost', :description => 'edit own post', :bitfield => 2048}, | |
{:name => 'deletepost', :description => 'delete own post', :bitfield => 4096}, | |
{:name => 'editotherposts', :description => 'edit other posts', :bitfield => 8192}, | |
{:name => 'deleteotherposts', :description => 'delete other posts', :bitfield => 16384}, | |
{:name => 'createpoll', :description => 'create a poll', :bitfield => 32768}, | |
{:name => 'editownpoll', :description => 'edit own poll', :bitfield => 65536}, | |
{:name => 'deleteownpoll', :description => 'delete own poll', :bitfield => 131072}, | |
{:name => 'editotherpolls', :description => 'edit other polls', :bitfield => 262144}, | |
{:name => 'deleteotherpolls', :description => 'delete other polls', :bitfield => 524288}, | |
{:name => 'addattachments', :description => 'add own attachments', :bitfield => 1048576}, | |
{:name => 'editattachments', :description => 'edit own attachments', :bitfield => 2097152}, | |
{:name => 'deleteattachments', :description => 'delete own attachments', :bitfield => 4194304}, | |
{:name => 'editotherattachments', :description => 'edit other attachments', :bitfield => 8388608}, | |
{:name => 'deleteotherattachments', :description => 'delete other attachments', :bitfield => 16777216}, | |
{:name => 'createforum', :description => 'create forums', :bitfield => 33554432}, | |
{:name => 'editforum', :description => 'edit forums', :bitfield => 67108864}, | |
{:name => 'deleteforum', :description => 'delete forum', :bitfield => 134217728} | |
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example bitfields from Kirin Forum Software | |
# Author is Joel Dezenzio => Elricstorm => Alpha Blue | |
module ForumPermissions | |
# The BitPermissions class is used to read and compare | |
# bitfields between an object (user) and the currently | |
# allowed permissions stored in a model (Forum Permissions). | |
# It determines what actions the user object is allowed to | |
# performed based upon the comparative result. | |
class BitPermissions | |
def initialize(bitfield) | |
@bitfield = bitfield | |
end | |
def find_permissions | |
# Find a bit listing of all permissions | |
permissions_table = Forumpermission.find(:all) | |
# create an action array | |
action_permissions = [] | |
permissions_table.each do |permission| | |
# compare each bitfield against the permissions bitfield | |
# and determine if it's greater than zero. If so, then | |
# the permission is added to action_permissions for the | |
# current user object. | |
if @bitfield & permission.bitfield > 0 | |
action_permissions << permission.name | |
end | |
end | |
return action_permissions | |
end | |
end | |
# Authorize method checks the membergroupids of the currently logged in user | |
# and separates the comma-delimited IDs, subsequently searching for the | |
# bitfield forum permissions of each membergroup ID. It then passes the | |
# bitfield to the BitPermissions class in the custom lib which returns an | |
# array of all matching permission strings ['canview', 'canedittopics', 'etc.] | |
# Because there are multiple membergroups, the array is built from all groups | |
# returned, flattened and then only unique entries remain. This allows a | |
# user to be a member of say 8 different groups which might have different | |
# permissions, and these permissions would be combined to show the full set. | |
def authorize | |
if user_signed_in? | |
mybits = [] | |
memberids = @current_user.forumuser.membergroupids | |
memberids.split(',').each do |perms| | |
mybits << forum_permissions(Usergroup.find(perms).forumpermissions) | |
end | |
@current_user[:bfpermissions] = mybits.flatten!.uniq | |
end | |
end | |
# Uses a custom lib class BitPermissions to compare permissions within a group | |
def forum_permissions(bitfield) | |
BitPermissions.new(bitfield).find_permissions | |
end | |
# This method is used for checking singleton actions that are not dependent on | |
# specific models or require user_id matching. It is mainly defined in views | |
# for accessing hidden functions. | |
def user_can?(action) | |
user_signed_in? && @current_user[:bfpermissions].include?(action) ? true : false | |
end | |
# This method is used for checking actions that are dependent on specific | |
# models and requires that the currently logged in user matches the model | |
# user_id. If the user has access to actions that affect others, no | |
# user_id matching is required. Examples of the latter are (i.e. editothertopics, | |
# editotherposts, etc.) Actions that affect others supercede singleton permissions. | |
def authorize_bits(action, model, other=false) | |
if user_signed_in? && other == true | |
@current_user[:bfpermissions].include?(action) ? true : false | |
elsif user_signed_in? && other == false | |
@current_user.id == model.user_id && @current_user[:bfpermissions].include?(action) == true ? true : false | |
else | |
return false | |
end | |
end | |
# This method determines if a user can perform a controller action based on bitfield permissions. | |
# If the bitfield permissions match the required accessible action, then the user | |
# permissions are authorized. Otherwise, the user is redirected to a url based on | |
# the access_to_action_denied method. It has some dependency on user_id matching. | |
# This method is used exclusively for controller actions and is not a valid helper method. | |
def can_user(action, otheraction, model) | |
unless authorize_bits(action, model) == true || authorize_bits(otheraction, model, true) == true | |
access_to_action_denied | |
end | |
end | |
# Used in the forum, topic, and post controllers if bitfield permissions | |
# and other criteria return false | |
def access_to_action_denied | |
redirect_to root_url, :notice => "You are not authorized to perform this action." and return false | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This makes it so that you can do a lot of things with bitpermissions. You could feasibly create bitfield permission tables for different categories. By the time you finished, you could have 5,000 actionable permissions and it wouldn't be difficult to administrate because all you are doing is deciding exactly what each object is authorized to do. Authorization at extreme levels. :)