Modified: trunk/app/controllers/workflows_controller.rb (2425 => 2426)
--- trunk/app/controllers/workflows_controller.rb 2010-06-03 13:01:38 UTC (rev 2425)
+++ trunk/app/controllers/workflows_controller.rb 2010-06-08 12:55:56 UTC (rev 2426)
@@ -599,7 +599,7 @@
def find_workflows_rss
# Only carry out if request is for RSS
if params[:format] and params[:format].downcase == 'rss'
- @rss_workflows = Authorization.authorised_index(:type => Workflow, :limit => 30, :order => 'updated_at DESC', :user => current_user)
+ @rss_workflows = Authorization.authorised_index(Workflow, :all, :limit => 30, :order => 'updated_at DESC', :authorised_user => current_user)
end
end
Modified: trunk/app/models/contribution.rb (2425 => 2426)
--- trunk/app/models/contribution.rb 2010-06-03 13:01:38 UTC (rev 2425)
+++ trunk/app/models/contribution.rb 2010-06-08 12:55:56 UTC (rev 2426)
@@ -36,9 +36,10 @@
# This uses the proprietary MySQL feature "SQL_CALC_FOUND_ROWS" to
# determine the total number of rows if it weren't for the LIMIT clause
- results = Authorization.authorised_index(:type => klass,
+ results = Authorization.authorised_index(klass,
+ :all,
:select => 'SQL_CALC_FOUND_ROWS contributions.*',
- :user => user,
+ :authorised_user => user,
:contribution_records => true,
:limit => "#{offset}, #{num}",
:joins => args["joins"],
@@ -77,14 +78,14 @@
# returns the 'most recent' Contributions
# the maximum number of results is set by #limit#
- def self.most_recent(limit=10, klass=nil)
- Authorization.authorised_index(:type => klass ? Object.const_get(klass) : nil, :contribution_records => true, :limit => limit, :order => 'created_at DESC')
+ def self.most_recent(limit = 10, klass = 'Contribution')
+ Authorization.authorised_index(Object.const_get(klass), :all, :contribution_records => true, :limit => limit, :order => 'created_at DESC')
end
# returns the 'last updated' Contributions
# the maximum number of results is set by #limit#
- def self.last_updated(limit=10, klass=nil)
- Authorization.authorised_index(:type => klass ? Object.const_get(klass) : nil, :contribution_records => true, :limit => limit, :order => 'updated_at DESC')
+ def self.last_updated(limit = 10, klass = 'Contribution')
+ Authorization.authorised_index(Object.const_get(klass), :all, :contribution_records => true, :limit => limit, :order => 'updated_at DESC')
end
# returns the 'most favourited' Contributions
Modified: trunk/lib/authorization.rb (2425 => 2426)
--- trunk/lib/authorization.rb 2010-06-03 13:01:38 UTC (rev 2425)
+++ trunk/lib/authorization.rb 2010-06-08 12:55:56 UTC (rev 2426)
@@ -732,45 +732,45 @@
end
end
- def self.authorised_index(args = {})
+ def self.authorised_index(model, *args)
- def self.get_friend_ids(user)
- user.friendships_accepted.map do |fs| fs.user_id end +
- user.friendships_completed.map do |fs| fs.friend_id end
- end
+ def self.view_conditions(user_id = nil, friends = nil, networks = nil)
- def self.get_network_ids(user)
- (user.networks_owned + user.networks).map do |n| n.id end
- end
+ return "(share_mode = 0 OR share_mode = 1 OR share_mode = 2)" if user_id.nil?
- def self.view_part(user_id = nil, friends = nil)
+ policy_part =
+ "((contributions.contributor_type = 'User' AND contributions.contributor_id = #{user_id}) OR
+ (share_mode = 0 OR share_mode = 1 OR share_mode = 2) OR
+ ((share_mode = 1 OR share_mode = 3 OR share_mode = 4 OR update_mode = 1 OR (update_mode = 0 AND (share_mode = 1 OR share_mode = 3))) AND
+ (contributions.contributor_type = 'User' AND contributions.contributor_id IN #{friends})))"
- return "share_mode = 0 OR share_mode = 1 OR share_mode = 2" if user_id.nil?
-
- "((contributions.contributor_type = 'User' AND contributions.contributor_id = #{user_id}) OR
- (share_mode = 0 OR share_mode = 1 OR share_mode = 2) OR
- ((share_mode = 1 OR share_mode = 3 OR share_mode = 4 OR update_mode = 1 OR (update_mode = 0 AND (share_mode = 1 OR share_mode = 3))) AND
- (contributions.contributor_type = 'User' AND contributions.contributor_id IN #{friends})))"
+ "(#{policy_part} OR #{permission_part(['view', 'download', 'edit'], user_id, networks)})"
end
- def self.download_part(user_id = nil, friends = nil)
+ def self.download_conditions(user_id = nil, friends = nil, networks = nil)
- return "share_mode = 0" if user_id.nil?
+ return "(share_mode = 0)" if user_id.nil?
- "((contributions.contributor_type = 'User' AND contributions.contributor_id = #{user_id}) OR
- (share_mode = 0) OR
- ((share_mode = 1 OR share_mode = 3 OR update_mode = 1 OR (update_mode = 0 AND (share_mode = 1 OR share_mode = 3))) AND
- (contributions.contributor_type = 'User' AND contributions.contributor_id IN #{friends})))"
+ policy_part =
+ "((contributions.contributor_type = 'User' AND contributions.contributor_id = #{user_id}) OR
+ (share_mode = 0) OR
+ ((share_mode = 1 OR share_mode = 3 OR update_mode = 1 OR (update_mode = 0 AND (share_mode = 1 OR share_mode = 3))) AND
+ (contributions.contributor_type = 'User' AND contributions.contributor_id IN #{friends})))"
+
+ "(#{policy_part} OR #{permission_part(['download', 'edit'], user_id, networks)})"
end
- def self.edit_part(user_id = nil, friends = nil)
+ def self.edit_conditions(user_id = nil, friends = nil, networks = nil)
- return "share_mode = 0 AND update_mode = 0" if user_id.nil?
+ return "(share_mode = 0 AND update_mode = 0)" if user_id.nil?
- "((contributions.contributor_type = 'User' AND contributions.contributor_id = #{user_id}) OR
- (share_mode = 0 AND update_mode = 0) OR
- ((update_mode = 1 OR (update_mode = 0 AND (share_mode = 1 OR share_mode = 3))) AND
- (contributions.contributor_type = 'User' AND contributions.contributor_id IN #{friends})))"
+ policy_part =
+ "((contributions.contributor_type = 'User' AND contributions.contributor_id = #{user_id}) OR
+ (share_mode = 0 AND update_mode = 0) OR
+ ((update_mode = 1 OR (update_mode = 0 AND (share_mode = 1 OR share_mode = 3))) AND
+ (contributions.contributor_type = 'User' AND contributions.contributor_id IN #{friends})))"
+
+ "(#{policy_part} OR #{permission_part(['edit'], user_id, networks)})"
end
def self.permission_part(permissions, user_id, networks)
@@ -782,123 +782,90 @@
(permissions.contributor_type = 'Network' AND permissions.contributor_id IN #{networks})))"
end
- user = args[:user]
+ # extract the opts hash
+ opts = args.last.class == Hash ? args.pop.clone : {}
+
+ user = opts.delete(:authorised_user)
+
+ joins = []
+ conditions = []
+
if (user != 0) && (user != nil)
user_id = user.id
- friend_ids = get_friend_ids(user)
- network_ids = get_network_ids(user)
+ friend_ids = user.friendships_accepted.map do |fs| fs.user_id end +
+ user.friendships_completed.map do |fs| fs.friend_id end
+ network_ids = (user.networks_owned + user.networks).map do |n| n.id end
+
friends = friend_ids.empty? ? "(-1)" : "(#{friend_ids.join(",")})"
networks = network_ids.empty? ? "(-1)" : "(#{network_ids.join(",")})"
end
- # pagination
+ # filtering
- if args[:limit]
- if args[:offset]
- limit_part = "LIMIT #{args[:offset]}, #{args[:limit]}"
- else
- limit_part = "LIMIT #{args[:limit]}"
- end
- else
- limit_part = ""
- end
+ conditions.push(view_conditions(user_id, friends, networks))
+ conditions.push("contributions.contributable_type = '#{model.name}'") if model != Contribution
- # ordering
+ # result model
- if args[:order]
- order_part = "ORDER BY #{args[:order]}"
- else
- order_part = ''
+ if opts.delete(:contribution_records)
+ model = Contribution
end
- # filtering
-
- if user_id
- where_bits = ["#{view_part(user_id, friends)} OR #{permission_part(['view', 'download', 'edit'], user_id, networks)}"]
- else
- where_bits = [view_part]
+ if model != Contribution
+ joins.push("INNER JOIN contributions ON contributions.contributable_id = #{model.table_name}.id AND contributions.contributable_type = '#{model.name}'")
end
- if args[:type]
- where_bits.push("contributions.contributable_type = '#{args[:type].name}'")
- end
-
- where_part = where_bits.map do |b| "(#{b})" end.join(" AND ")
-
- # result type
-
- if !args[:type] || args[:contribution_records]
- contributable_type = nil
- result_model = Contribution
- from_part = "FROM contributions"
- else
- contributable_type = args[:type].name.underscore.pluralize
- result_model = args[:type]
- from_part = "FROM #{contributable_type} INNER JOIN contributions ON contributions.contributable_id = #{contributable_type}.id"
- end
-
# selection
- if args[:select]
- select_part = args[:select]
- elsif contributable_type
- select_part = "#{args[:type].name.underscore.pluralize}.*"
- else
- select_part = "contributions.*"
- end
+ opts[:select] = "#{model.table_name}.*" unless opts[:select]
- # do the query
+ # add in the extra joins needed for the authorisation checks
- if user_id
+ joins.push("INNER JOIN policies ON contributions.policy_id = policies.id")
+ joins.push("LEFT OUTER JOIN permissions ON policies.id = permissions.policy_id") if user_id
- # This is the version used for a member
+ # include the effective permissions in the result?
- query = "
+ if opts.delete(:include_permissions)
- SELECT #{select_part},
+ opts[:select] << ", BIT_OR(#{view_conditions(user_id, friends, networks)}) AS view_permission"
+ opts[:select] << ", BIT_OR(#{download_conditions(user_id, friends, networks)}) AS download_permission"
+ opts[:select] << ", BIT_OR(#{edit_conditions(user_id, friends, networks)}) AS edit_permission"
+ end
- BIT_OR(#{view_part(user_id, friends)} OR #{permission_part(['view', 'download', 'edit'], user_id, networks)}) AS view,
- BIT_OR(#{download_part(user_id, friends)} OR #{permission_part(['view', 'download'], user_id, networks)}) AS download,
- BIT_OR(#{edit_part(user_id, friends)} OR #{permission_part(['view'], user_id, networks)}) AS edit
+ # merge the joins
- #{from_part}
- #{args[:joins]}
- INNER JOIN policies ON contributions.policy_id = policies.id
- LEFT OUTER JOIN permissions ON policies.id = permissions.policy_id
- WHERE #{where_part}
- GROUP BY contributable_type, contributable_id
- #{order_part}
- #{limit_part}"
+ if joins.length > 0
+ opts[:joins] = [] unless opts[:joins]
+ opts[:joins] = [opts[:joins]] unless opts[:joins].class == Array
+ opts[:joins] = opts[:joins] + joins
+ opts[:joins] = opts[:joins].join(" ") # Rails 1 does not support arrays here
+ end
- result_model.find_by_sql(query)
+ # merge the conditions
- else
+ if conditions.length > 0
- # This is the version used for non-members
+ conditions = conditions.map do |c| "(#{c})" end
- query = "
+ case opts[:conditions].class.name
+ when "Array"; opts[:conditions][0] = "(#{([opts[:conditions][0]] + conditions).join(') AND (')})"
+ when "String"; opts[:conditions] = "(#{([opts[:conditions]] + conditions).join(') AND (')})"
+ else; opts[:conditions] = "(#{conditions.join(') AND (')})"
+ end
+ end
- SELECT #{select_part},
+ # enforce grouping by contributable type and id
- BIT_OR(#{view_part}) AS view,
- BIT_OR(#{download_part}) AS download,
- BIT_OR(#{edit_part}) AS edit
+ opts[:group] = 'contributable_type, contributable_id'
- #{from_part}
- #{args[:joins]}
- INNER JOIN policies ON contributions.policy_id = policies.id
- WHERE #{where_part}
- GROUP BY contributable_type, contributable_id
- #{order_part}
- #{limit_part}"
+ # do it
- result_model.find_by_sql(query)
-
- end
+ model.find(*args + [opts])
end
end