Commit c22f58b9286d8d9e92cedcdb014dfec6e31c06a8
Exists in
staging
and in
1 other branch
Merge branch 'staging' of softwarepublico.gov.br:noosferogov/noosfero into staging
Showing
497 changed files
with
4932 additions
and
7914 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 497 files displayed.
@@ -0,0 +1,89 @@ | @@ -0,0 +1,89 @@ | ||
1 | +require_dependency 'api/helpers' | ||
2 | + | ||
3 | +module Api | ||
4 | + class App < Grape::API | ||
5 | + use Rack::JSONP | ||
6 | + | ||
7 | + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log")) | ||
8 | + logger.formatter = GrapeLogging::Formatters::Default.new | ||
9 | + #use GrapeLogging::Middleware::RequestLogger, { logger: logger } | ||
10 | + | ||
11 | + rescue_from :all do |e| | ||
12 | + logger.error e | ||
13 | + error! e.message, 500 | ||
14 | + end unless Rails.env.test? | ||
15 | + | ||
16 | + @@NOOSFERO_CONF = nil | ||
17 | + def self.NOOSFERO_CONF | ||
18 | + if @@NOOSFERO_CONF | ||
19 | + @@NOOSFERO_CONF | ||
20 | + else | ||
21 | + file = Rails.root.join('config', 'noosfero.yml') | ||
22 | + @@NOOSFERO_CONF = File.exists?(file) ? YAML.load_file(file)[Rails.env] || {} : {} | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + before { set_locale } | ||
27 | + before { setup_multitenancy } | ||
28 | + before { detect_stuff_by_domain } | ||
29 | + before { filter_disabled_plugins_endpoints } | ||
30 | + before { init_noosfero_plugins } | ||
31 | + after { set_session_cookie } | ||
32 | + | ||
33 | + version 'v1' | ||
34 | + prefix [ENV['RAILS_RELATIVE_URL_ROOT'], "api"].compact.join('/') | ||
35 | + format :json | ||
36 | + content_type :txt, "text/plain" | ||
37 | + | ||
38 | + helpers Helpers | ||
39 | + | ||
40 | + mount V1::Session | ||
41 | + mount V1::Articles | ||
42 | + mount V1::Comments | ||
43 | + mount V1::Users | ||
44 | + mount V1::Communities | ||
45 | + mount V1::People | ||
46 | + mount V1::Enterprises | ||
47 | + mount V1::Categories | ||
48 | + mount V1::Tasks | ||
49 | + mount V1::Tags | ||
50 | + mount V1::Environments | ||
51 | + mount V1::Search | ||
52 | + mount V1::Contacts | ||
53 | + mount V1::Boxes | ||
54 | + mount V1::Blocks | ||
55 | + mount V1::Profiles | ||
56 | + mount V1::Activities | ||
57 | + | ||
58 | + # hook point which allow plugins to add Grape::API extensions to Api::App | ||
59 | + #finds for plugins which has api mount points classes defined (the class should extends Grape::API) | ||
60 | + @plugins = Noosfero::Plugin.all.map { |p| p.constantize } | ||
61 | + @plugins.each do |klass| | ||
62 | + if klass.public_methods.include? :api_mount_points | ||
63 | + klass.api_mount_points.each do |mount_class| | ||
64 | + mount mount_class if mount_class && ( mount_class < Grape::API ) | ||
65 | + end | ||
66 | + end | ||
67 | + end | ||
68 | + | ||
69 | + def self.endpoint_unavailable?(endpoint, environment) | ||
70 | + api_class = endpoint.options[:app] || endpoint.options[:for] | ||
71 | + if api_class.present? | ||
72 | + klass = api_class.name.deconstantize.constantize | ||
73 | + return klass < Noosfero::Plugin && !environment.plugin_enabled?(klass) | ||
74 | + end | ||
75 | + end | ||
76 | + | ||
77 | + class << self | ||
78 | + def endpoints_with_plugins(environment = nil) | ||
79 | + if environment.present? | ||
80 | + cloned_endpoints = endpoints_without_plugins.dup | ||
81 | + cloned_endpoints.delete_if { |endpoint| endpoint_unavailable?(endpoint, environment) } | ||
82 | + else | ||
83 | + endpoints_without_plugins | ||
84 | + end | ||
85 | + end | ||
86 | + alias_method_chain :endpoints, :plugins | ||
87 | + end | ||
88 | + end | ||
89 | +end |
@@ -0,0 +1,269 @@ | @@ -0,0 +1,269 @@ | ||
1 | +module Api | ||
2 | + module Entities | ||
3 | + | ||
4 | + Entity.format_with :timestamp do |date| | ||
5 | + date.strftime('%Y/%m/%d %H:%M:%S') if date | ||
6 | + end | ||
7 | + | ||
8 | + PERMISSIONS = { | ||
9 | + :admin => 0, | ||
10 | + :self => 10, | ||
11 | + :private_content => 20, | ||
12 | + :logged_user => 30, | ||
13 | + :anonymous => 40 | ||
14 | + } | ||
15 | + | ||
16 | + def self.can_display_profile_field? profile, options, permission_options={} | ||
17 | + permissions={:field => "", :permission => :private_content} | ||
18 | + permissions.merge!(permission_options) | ||
19 | + field = permissions[:field] | ||
20 | + permission = permissions[:permission] | ||
21 | + return true if profile.public? && profile.public_fields.map{|f| f.to_sym}.include?(field.to_sym) | ||
22 | + | ||
23 | + current_person = options[:current_person] | ||
24 | + | ||
25 | + current_permission = if current_person.present? | ||
26 | + if current_person.is_admin? | ||
27 | + :admin | ||
28 | + elsif current_person == profile | ||
29 | + :self | ||
30 | + elsif profile.display_private_info_to?(current_person) | ||
31 | + :private_content | ||
32 | + else | ||
33 | + :logged_user | ||
34 | + end | ||
35 | + else | ||
36 | + :anonymous | ||
37 | + end | ||
38 | + PERMISSIONS[current_permission] <= PERMISSIONS[permission] | ||
39 | + end | ||
40 | + | ||
41 | + class Image < Entity | ||
42 | + root 'images', 'image' | ||
43 | + | ||
44 | + expose :url do |image, options| | ||
45 | + image.public_filename | ||
46 | + end | ||
47 | + | ||
48 | + expose :icon_url do |image, options| | ||
49 | + image.public_filename(:icon) | ||
50 | + end | ||
51 | + | ||
52 | + expose :minor_url do |image, options| | ||
53 | + image.public_filename(:minor) | ||
54 | + end | ||
55 | + | ||
56 | + expose :portrait_url do |image, options| | ||
57 | + image.public_filename(:portrait) | ||
58 | + end | ||
59 | + | ||
60 | + expose :thumb_url do |image, options| | ||
61 | + image.public_filename(:thumb) | ||
62 | + end | ||
63 | + end | ||
64 | + | ||
65 | + class CategoryBase < Entity | ||
66 | + root 'categories', 'category' | ||
67 | + expose :name, :id, :slug | ||
68 | + end | ||
69 | + | ||
70 | + class Category < CategoryBase | ||
71 | + root 'categories', 'category' | ||
72 | + expose :full_name do |category, options| | ||
73 | + category.full_name | ||
74 | + end | ||
75 | + expose :parent, :using => CategoryBase, if: { parent: true } | ||
76 | + expose :children, :using => CategoryBase, if: { children: true } | ||
77 | + expose :image, :using => Image | ||
78 | + expose :display_color | ||
79 | + end | ||
80 | + | ||
81 | + class Region < Category | ||
82 | + root 'regions', 'region' | ||
83 | + expose :parent_id | ||
84 | + end | ||
85 | + | ||
86 | + class Block < Entity | ||
87 | + root 'blocks', 'block' | ||
88 | + expose :id, :type, :settings, :position, :enabled | ||
89 | + expose :mirror, :mirror_block_id, :title | ||
90 | + expose :api_content, if: lambda { |object, options| options[:display_api_content] || object.display_api_content_by_default? } | ||
91 | + end | ||
92 | + | ||
93 | + class Box < Entity | ||
94 | + root 'boxes', 'box' | ||
95 | + expose :id, :position | ||
96 | + expose :blocks, :using => Block do |box, options| | ||
97 | + box.blocks.select {|block| block.visible_to_user?(options[:current_person]) } | ||
98 | + end | ||
99 | + end | ||
100 | + | ||
101 | + class Profile < Entity | ||
102 | + expose :identifier, :name, :id | ||
103 | + expose :created_at, :format_with => :timestamp | ||
104 | + expose :updated_at, :format_with => :timestamp | ||
105 | + expose :additional_data do |profile, options| | ||
106 | + hash ={} | ||
107 | + profile.public_values.each do |value| | ||
108 | + hash[value.custom_field.name]=value.value | ||
109 | + end | ||
110 | + | ||
111 | + private_values = profile.custom_field_values - profile.public_values | ||
112 | + private_values.each do |value| | ||
113 | + if Entities.can_display_profile_field?(profile,options) | ||
114 | + hash[value.custom_field.name]=value.value | ||
115 | + end | ||
116 | + end | ||
117 | + hash | ||
118 | + end | ||
119 | + expose :image, :using => Image | ||
120 | + expose :region, :using => Region | ||
121 | + expose :type | ||
122 | + expose :custom_header | ||
123 | + expose :custom_footer | ||
124 | + end | ||
125 | + | ||
126 | + class UserBasic < Entity | ||
127 | + expose :id | ||
128 | + expose :login | ||
129 | + end | ||
130 | + | ||
131 | + class Person < Profile | ||
132 | + root 'people', 'person' | ||
133 | + expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' } | ||
134 | + expose :vote_count | ||
135 | + expose :comments_count do |person, options| | ||
136 | + person.comments.count | ||
137 | + end | ||
138 | + expose :following_articles_count do |person, options| | ||
139 | + person.following_articles.count | ||
140 | + end | ||
141 | + expose :articles_count do |person, options| | ||
142 | + person.articles.count | ||
143 | + end | ||
144 | + end | ||
145 | + | ||
146 | + class Enterprise < Profile | ||
147 | + root 'enterprises', 'enterprise' | ||
148 | + end | ||
149 | + | ||
150 | + class Community < Profile | ||
151 | + root 'communities', 'community' | ||
152 | + expose :description | ||
153 | + expose :admins, :if => lambda { |community, options| community.display_info_to? options[:current_person]} do |community, options| | ||
154 | + community.admins.map{|admin| {"name"=>admin.name, "id"=>admin.id, "username" => admin.identifier}} | ||
155 | + end | ||
156 | + expose :categories, :using => Category | ||
157 | + expose :members, :using => Person , :if => lambda{ |community, options| community.display_info_to? options[:current_person] } | ||
158 | + end | ||
159 | + | ||
160 | + class CommentBase < Entity | ||
161 | + expose :body, :title, :id | ||
162 | + expose :created_at, :format_with => :timestamp | ||
163 | + expose :author, :using => Profile | ||
164 | + expose :reply_of, :using => CommentBase | ||
165 | + end | ||
166 | + | ||
167 | + class Comment < CommentBase | ||
168 | + root 'comments', 'comment' | ||
169 | + expose :children, as: :replies, :using => Comment | ||
170 | + end | ||
171 | + | ||
172 | + class ArticleBase < Entity | ||
173 | + root 'articles', 'article' | ||
174 | + expose :id | ||
175 | + expose :body | ||
176 | + expose :abstract, documentation: {type: 'String', desc: 'Teaser of the body'} | ||
177 | + expose :created_at, :format_with => :timestamp | ||
178 | + expose :updated_at, :format_with => :timestamp | ||
179 | + expose :title, :documentation => {:type => "String", :desc => "Title of the article"} | ||
180 | + expose :created_by, :as => :author, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile author that create the article'} | ||
181 | + expose :profile, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile associated with the article'} | ||
182 | + expose :categories, :using => Category | ||
183 | + expose :image, :using => Image | ||
184 | + expose :votes_for | ||
185 | + expose :votes_against | ||
186 | + expose :setting | ||
187 | + expose :position | ||
188 | + expose :hits | ||
189 | + expose :start_date | ||
190 | + expose :end_date, :documentation => {type: 'DateTime', desc: 'The date of finish of the article'} | ||
191 | + expose :tag_list | ||
192 | + expose :children_count | ||
193 | + expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"} | ||
194 | + expose :path | ||
195 | + expose :followers_count | ||
196 | + expose :votes_count | ||
197 | + expose :comments_count | ||
198 | + expose :archived, :documentation => {:type => "Boolean", :desc => "Defines if a article is readonly"} | ||
199 | + expose :type | ||
200 | + expose :comments, using: CommentBase, :if => lambda{|obj,opt| opt[:params] && ['1','true',true].include?(opt[:params][:show_comments])} | ||
201 | + expose :published | ||
202 | + expose :accept_comments?, as: :accept_comments | ||
203 | + end | ||
204 | + | ||
205 | + class Article < ArticleBase | ||
206 | + root 'articles', 'article' | ||
207 | + expose :parent, :using => ArticleBase | ||
208 | + expose :children, :using => ArticleBase do |article, options| | ||
209 | + article.children.published.limit(V1::Articles::MAX_PER_PAGE) | ||
210 | + end | ||
211 | + end | ||
212 | + | ||
213 | + class User < Entity | ||
214 | + root 'users', 'user' | ||
215 | + | ||
216 | + attrs = [:id,:login,:email,:activated?] | ||
217 | + aliases = {:activated? => :activated} | ||
218 | + | ||
219 | + attrs.each do |attribute| | ||
220 | + name = aliases.has_key?(attribute) ? aliases[attribute] : attribute | ||
221 | + expose attribute, :as => name, :if => lambda{|user,options| Entities.can_display_profile_field?(user.person, options, {:field => attribute})} | ||
222 | + end | ||
223 | + | ||
224 | + expose :person, :using => Person, :if => lambda{|user,options| user.person.display_info_to? options[:current_person]} | ||
225 | + expose :permissions, :if => lambda{|user,options| Entities.can_display_profile_field?(user.person, options, {:field => :permissions, :permission => :self})} do |user, options| | ||
226 | + output = {} | ||
227 | + user.person.role_assignments.map do |role_assigment| | ||
228 | + if role_assigment.resource.respond_to?(:identifier) && !role_assigment.role.nil? | ||
229 | + output[role_assigment.resource.identifier] = role_assigment.role.permissions | ||
230 | + end | ||
231 | + end | ||
232 | + output | ||
233 | + end | ||
234 | + end | ||
235 | + | ||
236 | + class UserLogin < User | ||
237 | + root 'users', 'user' | ||
238 | + expose :private_token, documentation: {type: 'String', desc: 'A valid authentication code for post/delete api actions'}, if: lambda {|object, options| object.activated? } | ||
239 | + end | ||
240 | + | ||
241 | + class Task < Entity | ||
242 | + root 'tasks', 'task' | ||
243 | + expose :id | ||
244 | + expose :type | ||
245 | + end | ||
246 | + | ||
247 | + class Environment < Entity | ||
248 | + expose :name | ||
249 | + expose :id | ||
250 | + expose :description | ||
251 | + expose :settings, if: lambda { |instance, options| options[:is_admin] } | ||
252 | + end | ||
253 | + | ||
254 | + class Tag < Entity | ||
255 | + root 'tags', 'tag' | ||
256 | + expose :name | ||
257 | + end | ||
258 | + | ||
259 | + class Activity < Entity | ||
260 | + root 'activities', 'activity' | ||
261 | + expose :id, :params, :verb, :created_at, :updated_at, :comments_count, :visible | ||
262 | + expose :user, :using => Profile | ||
263 | + expose :target do |activity, opts| | ||
264 | + type_map = {Profile => ::Profile, ArticleBase => ::Article}.find {|h| activity.target.kind_of?(h.last)} | ||
265 | + type_map.first.represent(activity.target) unless type_map.nil? | ||
266 | + end | ||
267 | + end | ||
268 | + end | ||
269 | +end |
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +module Api | ||
2 | + class Entity < Grape::Entity | ||
3 | + | ||
4 | + def initialize(object, options = {}) | ||
5 | + object = nil if object.is_a? Exception | ||
6 | + super object, options | ||
7 | + end | ||
8 | + | ||
9 | + def self.represent(objects, options = {}) | ||
10 | + if options[:has_exception] | ||
11 | + data = super objects, options.merge(is_inner_data: true) | ||
12 | + if objects.is_a? Exception | ||
13 | + data.merge ok: false, error: { | ||
14 | + type: objects.class.name, | ||
15 | + message: objects.message | ||
16 | + } | ||
17 | + else | ||
18 | + data = data.serializable_hash if data.is_a? Entity | ||
19 | + data.merge ok: true, error: { type: 'Success', message: '' } | ||
20 | + end | ||
21 | + else | ||
22 | + super objects, options | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + end | ||
27 | +end |
@@ -0,0 +1,484 @@ | @@ -0,0 +1,484 @@ | ||
1 | +require 'base64' | ||
2 | +require 'tempfile' | ||
3 | + | ||
4 | +module Api | ||
5 | + module Helpers | ||
6 | + PRIVATE_TOKEN_PARAM = :private_token | ||
7 | + DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier, :archived] | ||
8 | + | ||
9 | + include SanitizeParams | ||
10 | + include Noosfero::Plugin::HotSpot | ||
11 | + include ForgotPasswordHelper | ||
12 | + include SearchTermHelper | ||
13 | + | ||
14 | + def set_locale | ||
15 | + I18n.locale = (params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en') | ||
16 | + end | ||
17 | + | ||
18 | + def init_noosfero_plugins | ||
19 | + plugins | ||
20 | + end | ||
21 | + | ||
22 | + def current_tmp_user | ||
23 | + private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s | ||
24 | + ## Get the "captcha" session store | ||
25 | + @current_tmp_user = Noosfero::API::SessionStore.get("captcha##{private_token}") | ||
26 | + @current_tmp_user | ||
27 | + end | ||
28 | + | ||
29 | + def logout_tmp_user | ||
30 | + @current_tmp_user = nil | ||
31 | + end | ||
32 | + | ||
33 | + def current_user | ||
34 | + private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s | ||
35 | + @current_user ||= User.find_by private_token: private_token | ||
36 | + @current_user ||= plugins.dispatch("api_custom_login", request).first | ||
37 | + @current_user | ||
38 | + end | ||
39 | + | ||
40 | + def current_person | ||
41 | + current_user.person unless current_user.nil? | ||
42 | + end | ||
43 | + | ||
44 | + def is_admin?(environment) | ||
45 | + return false unless current_user | ||
46 | + return current_person.is_admin?(environment) | ||
47 | + end | ||
48 | + | ||
49 | + def logout | ||
50 | + @current_user = nil | ||
51 | + end | ||
52 | + | ||
53 | + def environment | ||
54 | + @environment | ||
55 | + end | ||
56 | + | ||
57 | + def present_partial(model, options) | ||
58 | + if(params[:fields].present?) | ||
59 | + begin | ||
60 | + fields = JSON.parse(params[:fields]) | ||
61 | + if fields.present? | ||
62 | + options.merge!(fields.symbolize_keys.slice(:only, :except)) | ||
63 | + end | ||
64 | + rescue | ||
65 | + fields = params[:fields] | ||
66 | + fields = fields.split(',') if fields.kind_of?(String) | ||
67 | + options[:only] = Array.wrap(fields) | ||
68 | + end | ||
69 | + end | ||
70 | + present model, options | ||
71 | + end | ||
72 | + | ||
73 | + include FindByContents | ||
74 | + | ||
75 | + #################################################################### | ||
76 | + #### SEARCH | ||
77 | + #################################################################### | ||
78 | + def multiple_search?(searches=nil) | ||
79 | + ['index', 'category_index'].include?(params[:action]) || (searches && searches.size > 1) | ||
80 | + end | ||
81 | + #################################################################### | ||
82 | + | ||
83 | + def logger | ||
84 | + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log")) | ||
85 | + logger.formatter = GrapeLogging::Formatters::Default.new | ||
86 | + logger | ||
87 | + end | ||
88 | + | ||
89 | + def limit | ||
90 | + limit = params[:limit].to_i | ||
91 | + limit = default_limit if limit <= 0 | ||
92 | + limit | ||
93 | + end | ||
94 | + | ||
95 | + def period(from_date, until_date) | ||
96 | + return nil if from_date.nil? && until_date.nil? | ||
97 | + | ||
98 | + begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date | ||
99 | + end_period = until_date.nil? ? DateTime.now : until_date | ||
100 | + | ||
101 | + begin_period..end_period | ||
102 | + end | ||
103 | + | ||
104 | + def parse_content_type(content_type) | ||
105 | + return nil if content_type.blank? | ||
106 | + content_type.split(',').map do |content_type| | ||
107 | + content_type.camelcase | ||
108 | + end | ||
109 | + end | ||
110 | + | ||
111 | + def find_article(articles, id) | ||
112 | + article = articles.find(id) | ||
113 | + article.display_to?(current_person) ? article : forbidden! | ||
114 | + end | ||
115 | + | ||
116 | + def post_article(asset, params) | ||
117 | + return forbidden! unless current_person.can_post_content?(asset) | ||
118 | + | ||
119 | + klass_type = params[:content_type] || params[:article].delete(:type) || TinyMceArticle.name | ||
120 | + return forbidden! unless klass_type.constantize <= Article | ||
121 | + | ||
122 | + article = klass_type.constantize.new(params[:article]) | ||
123 | + article.last_changed_by = current_person | ||
124 | + article.created_by= current_person | ||
125 | + article.profile = asset | ||
126 | + | ||
127 | + if !article.save | ||
128 | + render_api_errors!(article.errors.full_messages) | ||
129 | + end | ||
130 | + present_partial article, :with => Entities::Article | ||
131 | + end | ||
132 | + | ||
133 | + def present_article(asset) | ||
134 | + article = find_article(asset.articles, params[:id]) | ||
135 | + present_partial article, :with => Entities::Article, :params => params | ||
136 | + end | ||
137 | + | ||
138 | + def present_articles_for_asset(asset, method = 'articles') | ||
139 | + articles = find_articles(asset, method) | ||
140 | + present_articles(articles) | ||
141 | + end | ||
142 | + | ||
143 | + def present_articles(articles) | ||
144 | + present_partial paginate(articles), :with => Entities::Article, :params => params | ||
145 | + end | ||
146 | + | ||
147 | + def find_articles(asset, method = 'articles') | ||
148 | + articles = select_filtered_collection_of(asset, method, params) | ||
149 | + if current_person.present? | ||
150 | + articles = articles.display_filter(current_person, nil) | ||
151 | + else | ||
152 | + articles = articles.published | ||
153 | + end | ||
154 | + articles | ||
155 | + end | ||
156 | + | ||
157 | + def find_task(asset, id) | ||
158 | + task = asset.tasks.find(id) | ||
159 | + current_person.has_permission?(task.permission, asset) ? task : forbidden! | ||
160 | + end | ||
161 | + | ||
162 | + def post_task(asset, params) | ||
163 | + klass_type= params[:content_type].nil? ? 'Task' : params[:content_type] | ||
164 | + return forbidden! unless klass_type.constantize <= Task | ||
165 | + | ||
166 | + task = klass_type.constantize.new(params[:task]) | ||
167 | + task.requestor_id = current_person.id | ||
168 | + task.target_id = asset.id | ||
169 | + task.target_type = 'Profile' | ||
170 | + | ||
171 | + if !task.save | ||
172 | + render_api_errors!(task.errors.full_messages) | ||
173 | + end | ||
174 | + present_partial task, :with => Entities::Task | ||
175 | + end | ||
176 | + | ||
177 | + def present_task(asset) | ||
178 | + task = find_task(asset, params[:id]) | ||
179 | + present_partial task, :with => Entities::Task | ||
180 | + end | ||
181 | + | ||
182 | + def present_tasks(asset) | ||
183 | + tasks = select_filtered_collection_of(asset, 'tasks', params) | ||
184 | + tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)} | ||
185 | + return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset) | ||
186 | + present_partial tasks, :with => Entities::Task | ||
187 | + end | ||
188 | + | ||
189 | + def make_conditions_with_parameter(params = {}) | ||
190 | + parsed_params = parser_params(params) | ||
191 | + conditions = {} | ||
192 | + from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from] | ||
193 | + until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until] | ||
194 | + | ||
195 | + conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil? | ||
196 | + | ||
197 | + conditions[:created_at] = period(from_date, until_date) if from_date || until_date | ||
198 | + conditions.merge!(parsed_params) | ||
199 | + | ||
200 | + conditions | ||
201 | + end | ||
202 | + | ||
203 | + # changing make_order_with_parameters to avoid sql injection | ||
204 | + def make_order_with_parameters(object, method, params) | ||
205 | + order = "created_at DESC" | ||
206 | + unless params[:order].blank? | ||
207 | + if params[:order].include? '\'' or params[:order].include? '"' | ||
208 | + order = "created_at DESC" | ||
209 | + elsif ['RANDOM()', 'RANDOM'].include? params[:order].upcase | ||
210 | + order = 'RANDOM()' | ||
211 | + else | ||
212 | + field_name, direction = params[:order].split(' ') | ||
213 | + assoc = object.class.reflect_on_association(method.to_sym) | ||
214 | + if !field_name.blank? and assoc | ||
215 | + if assoc.klass.attribute_names.include? field_name | ||
216 | + if direction.present? and ['ASC','DESC'].include? direction.upcase | ||
217 | + order = "#{field_name} #{direction.upcase}" | ||
218 | + end | ||
219 | + end | ||
220 | + end | ||
221 | + end | ||
222 | + end | ||
223 | + return order | ||
224 | + end | ||
225 | + | ||
226 | + def make_timestamp_with_parameters_and_method(params, method) | ||
227 | + timestamp = nil | ||
228 | + if params[:timestamp] | ||
229 | + datetime = DateTime.parse(params[:timestamp]) | ||
230 | + table_name = method.to_s.singularize.camelize.constantize.table_name | ||
231 | + timestamp = "#{table_name}.updated_at >= '#{datetime}'" | ||
232 | + end | ||
233 | + | ||
234 | + timestamp | ||
235 | + end | ||
236 | + | ||
237 | + def by_reference(scope, params) | ||
238 | + reference_id = params[:reference_id].to_i == 0 ? nil : params[:reference_id].to_i | ||
239 | + if reference_id.nil? | ||
240 | + scope | ||
241 | + else | ||
242 | + created_at = scope.find(reference_id).created_at | ||
243 | + scope.send("#{params.key?(:oldest) ? 'older_than' : 'younger_than'}", created_at) | ||
244 | + end | ||
245 | + end | ||
246 | + | ||
247 | + def by_categories(scope, params) | ||
248 | + category_ids = params[:category_ids] | ||
249 | + if category_ids.nil? | ||
250 | + scope | ||
251 | + else | ||
252 | + scope.joins(:categories).where(:categories => {:id => category_ids}) | ||
253 | + end | ||
254 | + end | ||
255 | + | ||
256 | + def by_period(scope, params, attribute) | ||
257 | + from_param = "from_#{attribute}".to_sym | ||
258 | + until_param = "until_#{attribute}".to_sym | ||
259 | + from_date = DateTime.parse(params.delete(from_param)) if params[from_param] | ||
260 | + until_date = DateTime.parse(params.delete(until_param)) if params[until_param] | ||
261 | + scope = scope.where("#{attribute} >= ?", from_date) unless from_date.nil? | ||
262 | + scope = scope.where("#{attribute} <= ?", until_date) unless until_date.nil? | ||
263 | + scope | ||
264 | + end | ||
265 | + | ||
266 | + def select_filtered_collection_of(object, method, params) | ||
267 | + conditions = make_conditions_with_parameter(params) | ||
268 | + order = make_order_with_parameters(object,method,params) | ||
269 | + timestamp = make_timestamp_with_parameters_and_method(params, method) | ||
270 | + | ||
271 | + objects = object.send(method) | ||
272 | + objects = by_reference(objects, params) | ||
273 | + objects = by_categories(objects, params) | ||
274 | + [:start_date, :end_date].each { |attribute| objects = by_period(objects, params, attribute) } | ||
275 | + | ||
276 | + objects = objects.where(conditions).where(timestamp).reorder(order) | ||
277 | + | ||
278 | + params[:page] ||= 1 | ||
279 | + params[:per_page] ||= limit | ||
280 | + paginate(objects) | ||
281 | + end | ||
282 | + | ||
283 | + def authenticate! | ||
284 | + unauthorized! unless current_user | ||
285 | + end | ||
286 | + | ||
287 | + # Allows the anonymous captcha user authentication | ||
288 | + # to pass the check. Used by the articles/vote to allow | ||
289 | + # the vote without login | ||
290 | + def authenticate_allow_captcha! | ||
291 | + unauthorized! unless current_tmp_user || current_user | ||
292 | + end | ||
293 | + | ||
294 | + def profiles_for_person(profiles, person) | ||
295 | + if person | ||
296 | + profiles.listed_for_person(person) | ||
297 | + else | ||
298 | + profiles.visible | ||
299 | + end | ||
300 | + end | ||
301 | + | ||
302 | + # Checks the occurrences of uniqueness of attributes, each attribute must be present in the params hash | ||
303 | + # or a Bad Request error is invoked. | ||
304 | + # | ||
305 | + # Parameters: | ||
306 | + # keys (unique) - A hash consisting of keys that must be unique | ||
307 | + def unique_attributes!(obj, keys) | ||
308 | + keys.each do |key| | ||
309 | + cant_be_saved_request!(key) if obj.find_by(key.to_s => params[key]) | ||
310 | + end | ||
311 | + end | ||
312 | + | ||
313 | + def attributes_for_keys(keys) | ||
314 | + attrs = {} | ||
315 | + keys.each do |key| | ||
316 | + attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false) | ||
317 | + end | ||
318 | + attrs | ||
319 | + end | ||
320 | + | ||
321 | + ########################################## | ||
322 | + # error helpers # | ||
323 | + ########################################## | ||
324 | + | ||
325 | + def not_found! | ||
326 | + render_api_error!('404 Not found', 404) | ||
327 | + end | ||
328 | + | ||
329 | + def forbidden! | ||
330 | + render_api_error!('403 Forbidden', 403) | ||
331 | + end | ||
332 | + | ||
333 | + def cant_be_saved_request!(attribute) | ||
334 | + message = _("(Invalid request) %s can't be saved") % attribute | ||
335 | + render_api_error!(message, 400) | ||
336 | + end | ||
337 | + | ||
338 | + def bad_request!(attribute) | ||
339 | + message = _("(Invalid request) %s not given") % attribute | ||
340 | + render_api_error!(message, 400) | ||
341 | + end | ||
342 | + | ||
343 | + def something_wrong! | ||
344 | + message = _("Something wrong happened") | ||
345 | + render_api_error!(message, 400) | ||
346 | + end | ||
347 | + | ||
348 | + def unauthorized! | ||
349 | + render_api_error!(_('Unauthorized'), 401) | ||
350 | + end | ||
351 | + | ||
352 | + def not_allowed! | ||
353 | + render_api_error!(_('Method Not Allowed'), 405) | ||
354 | + end | ||
355 | + | ||
356 | + # javascript_console_message is supposed to be executed as console.log() | ||
357 | + def render_api_error!(user_message, status, log_message = nil, javascript_console_message = nil) | ||
358 | + message_hash = {'message' => user_message, :code => status} | ||
359 | + message_hash[:javascript_console_message] = javascript_console_message if javascript_console_message.present? | ||
360 | + log_msg = "#{status}, User message: #{user_message}" | ||
361 | + log_msg = "#{log_message}, #{log_msg}" if log_message.present? | ||
362 | + log_msg = "#{log_msg}, Javascript Console Message: #{javascript_console_message}" if javascript_console_message.present? | ||
363 | + logger.error log_msg unless Rails.env.test? | ||
364 | + error!(message_hash, status) | ||
365 | + end | ||
366 | + | ||
367 | + def render_api_errors!(messages) | ||
368 | + messages = messages.to_a if messages.class == ActiveModel::Errors | ||
369 | + render_api_error!(messages.join(','), 400) | ||
370 | + end | ||
371 | + | ||
372 | + #################################################################### | ||
373 | + #### VOTE | ||
374 | + #################################################################### | ||
375 | + def do_vote(article, current_person, value) | ||
376 | + begin | ||
377 | + vote = Vote.new(:voteable => article, :voter => current_person, :vote => value) | ||
378 | + return vote.save! | ||
379 | + rescue ActiveRecord::RecordInvalid => e | ||
380 | + render_api_error!(e.message, 400) | ||
381 | + return false | ||
382 | + end | ||
383 | + end | ||
384 | + | ||
385 | + protected | ||
386 | + | ||
387 | + def set_session_cookie | ||
388 | + cookies['_noosfero_api_session'] = { value: @current_user.private_token, httponly: true } if @current_user.present? | ||
389 | + # Set also the private_token for the current_tmp_user | ||
390 | + cookies['_noosfero_api_session'] = { value: @current_tmp_user.private_token, httponly: true } if @current_tmp_user.present? | ||
391 | + end | ||
392 | + | ||
393 | + def setup_multitenancy | ||
394 | + Noosfero::MultiTenancy.setup!(request.host) | ||
395 | + end | ||
396 | + | ||
397 | + def detect_stuff_by_domain | ||
398 | + @domain = Domain.by_name(request.host) | ||
399 | + if @domain.nil? | ||
400 | + @environment = Environment.default | ||
401 | + if @environment.nil? && Rails.env.development? | ||
402 | + # This should only happen in development ... | ||
403 | + @environment = Environment.create!(:name => "Noosfero", :is_default => true) | ||
404 | + end | ||
405 | + else | ||
406 | + @environment = @domain.environment | ||
407 | + end | ||
408 | + end | ||
409 | + | ||
410 | + def filter_disabled_plugins_endpoints | ||
411 | + not_found! if Api::App.endpoint_unavailable?(self, @environment) | ||
412 | + end | ||
413 | + | ||
414 | + def asset_with_image params | ||
415 | + if params.has_key? :image_builder | ||
416 | + asset_api_params = params | ||
417 | + asset_api_params[:image_builder] = base64_to_uploadedfile(asset_api_params[:image_builder]) | ||
418 | + return asset_api_params | ||
419 | + end | ||
420 | + params | ||
421 | + end | ||
422 | + | ||
423 | + def base64_to_uploadedfile(base64_image) | ||
424 | + tempfile = base64_to_tempfile base64_image | ||
425 | + converted_image = base64_image | ||
426 | + converted_image[:tempfile] = tempfile | ||
427 | + return {uploaded_data: ActionDispatch::Http::UploadedFile.new(converted_image)} | ||
428 | + end | ||
429 | + | ||
430 | + def base64_to_tempfile base64_image | ||
431 | + base64_img_str = base64_image[:tempfile] | ||
432 | + decoded_base64_str = Base64.decode64(base64_img_str) | ||
433 | + tempfile = Tempfile.new(base64_image[:filename]) | ||
434 | + tempfile.write(decoded_base64_str.encode("ascii-8bit").force_encoding("utf-8")) | ||
435 | + tempfile.rewind | ||
436 | + tempfile | ||
437 | + end | ||
438 | + private | ||
439 | + | ||
440 | + def parser_params(params) | ||
441 | + parsed_params = {} | ||
442 | + params.map do |k,v| | ||
443 | + parsed_params[k.to_sym] = v if DEFAULT_ALLOWED_PARAMETERS.include?(k.to_sym) | ||
444 | + end | ||
445 | + parsed_params | ||
446 | + end | ||
447 | + | ||
448 | + def default_limit | ||
449 | + 20 | ||
450 | + end | ||
451 | + | ||
452 | + def parse_content_type(content_type) | ||
453 | + return nil if content_type.blank? | ||
454 | + content_types = content_type.split(',').map do |content_type| | ||
455 | + content_type = content_type.camelcase | ||
456 | + content_type == 'TextArticle' ? Article.text_article_types : content_type | ||
457 | + end | ||
458 | + content_types.flatten.uniq | ||
459 | + end | ||
460 | + | ||
461 | + def period(from_date, until_date) | ||
462 | + begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date | ||
463 | + end_period = until_date.nil? ? DateTime.now : until_date | ||
464 | + begin_period..end_period | ||
465 | + end | ||
466 | + | ||
467 | + | ||
468 | + ########################################## | ||
469 | + # captcha_helpers # | ||
470 | + ########################################## | ||
471 | + | ||
472 | + def verify_captcha(remote_ip, params, environment) | ||
473 | + captcha_plugin_enabled = plugins.dispatch(:verify_captcha, remote_ip, params, environment).map {|p| p if ! ( p===nil ) } | ||
474 | + return true if captcha_plugin_enabled.size == 0 | ||
475 | + if captcha_plugin_enabled.size > 1 | ||
476 | + return render_api_error!(_("Error processing Captcha"), 500, nil, "More than one captcha plugin enabled") | ||
477 | + end | ||
478 | + test_result = captcha_plugin_enabled[0] | ||
479 | + return true if test_result === true | ||
480 | + render_api_error!(test_result[:user_message], test_result[:status], test_result[:log_message], test_result[:javascript_console_message]) | ||
481 | + end | ||
482 | + | ||
483 | + end | ||
484 | +end |
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Activities < Grape::API | ||
4 | + before { authenticate! } | ||
5 | + | ||
6 | + resource :profiles do | ||
7 | + | ||
8 | + get ':id/activities' do | ||
9 | + profile = Profile.find_by id: params[:id] | ||
10 | + | ||
11 | + not_found! if profile.blank? || profile.secret || !profile.visible | ||
12 | + forbidden! if !profile.secret && profile.visible && !profile.display_private_info_to?(current_person) | ||
13 | + | ||
14 | + activities = profile.activities.map(&:activity) | ||
15 | + present activities, :with => Entities::Activity, :current_person => current_person | ||
16 | + end | ||
17 | + end | ||
18 | + end | ||
19 | + end | ||
20 | +end |
@@ -0,0 +1,329 @@ | @@ -0,0 +1,329 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Articles < Grape::API | ||
4 | + | ||
5 | + ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} | ||
6 | + | ||
7 | + MAX_PER_PAGE = 50 | ||
8 | + | ||
9 | + resource :articles do | ||
10 | + | ||
11 | + paginate max_per_page: MAX_PER_PAGE | ||
12 | + # Collect articles | ||
13 | + # | ||
14 | + # Parameters: | ||
15 | + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created | ||
16 | + # oldest - Collect the oldest articles. If nothing is passed the newest articles are collected | ||
17 | + # limit - amount of articles returned. The default value is 20 | ||
18 | + # | ||
19 | + # Example Request: | ||
20 | + # GET host/api/v1/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 | ||
21 | + | ||
22 | + desc 'Return all articles of all kinds' do | ||
23 | + detail 'Get all articles filtered by fields in query params' | ||
24 | + params Entities::Article.documentation | ||
25 | + success Entities::Article | ||
26 | + failure [[403, 'Forbidden']] | ||
27 | + named 'ArticlesList' | ||
28 | + headers [ | ||
29 | + 'Per-Page' => { | ||
30 | + description: 'Total number of records', | ||
31 | + required: false | ||
32 | + } | ||
33 | + ] | ||
34 | + end | ||
35 | + get do | ||
36 | + present_articles_for_asset(environment) | ||
37 | + end | ||
38 | + | ||
39 | + desc "Return the articles followed by me" | ||
40 | + get 'followed_by_me' do | ||
41 | + present_articles_for_asset(current_person, 'following_articles') | ||
42 | + end | ||
43 | + | ||
44 | + desc "Return one article by id" do | ||
45 | + detail 'Get only one article by id. If not found the "forbidden" http error is showed' | ||
46 | + params Entities::Article.documentation | ||
47 | + success Entities::Article | ||
48 | + failure [[403, 'Forbidden']] | ||
49 | + named 'ArticleById' | ||
50 | + end | ||
51 | + get ':id', requirements: {id: /[0-9]+/} do | ||
52 | + present_article(environment) | ||
53 | + end | ||
54 | + | ||
55 | + post ':id' do | ||
56 | + article = environment.articles.find(params[:id]) | ||
57 | + return forbidden! unless article.allow_edit?(current_person) | ||
58 | + article.update_attributes!(asset_with_image(params[:article])) | ||
59 | + present_partial article, :with => Entities::Article | ||
60 | + end | ||
61 | + | ||
62 | + delete ':id' do | ||
63 | + article = environment.articles.find(params[:id]) | ||
64 | + return forbidden! unless article.allow_delete?(current_person) | ||
65 | + begin | ||
66 | + article.destroy | ||
67 | + { :success => true } | ||
68 | + rescue Exception => exception | ||
69 | + render_api_error!(_('The article couldn\'t be removed due to some problem. Please contact the administrator.'), 400) | ||
70 | + end | ||
71 | + end | ||
72 | + | ||
73 | + desc 'Report a abuse and/or violent content in a article by id' do | ||
74 | + detail 'Submit a abuse (in general, a content violation) report about a specific article' | ||
75 | + params Entities::Article.documentation | ||
76 | + failure [[400, 'Bad Request']] | ||
77 | + named 'ArticleReportAbuse' | ||
78 | + end | ||
79 | + post ':id/report_abuse' do | ||
80 | + article = find_article(environment.articles, params[:id]) | ||
81 | + profile = article.profile | ||
82 | + begin | ||
83 | + abuse_report = AbuseReport.new(:reason => params[:report_abuse]) | ||
84 | + if !params[:content_type].blank? | ||
85 | + article = params[:content_type].constantize.find(params[:content_id]) | ||
86 | + abuse_report.content = article_reported_version(article) | ||
87 | + end | ||
88 | + | ||
89 | + current_person.register_report(abuse_report, profile) | ||
90 | + | ||
91 | + if !params[:content_type].blank? | ||
92 | + abuse_report = AbuseReport.find_by reporter_id: current_person.id, abuse_complaint_id: profile.opened_abuse_complaint.id | ||
93 | + Delayed::Job.enqueue DownloadReportedImagesJob.new(abuse_report, article) | ||
94 | + end | ||
95 | + | ||
96 | + { | ||
97 | + :success => true, | ||
98 | + :message => _('Your abuse report was registered. The administrators are reviewing your report.'), | ||
99 | + } | ||
100 | + rescue Exception => exception | ||
101 | + #logger.error(exception.to_s) | ||
102 | + render_api_error!(_('Your report couldn\'t be saved due to some problem. Please contact the administrator.'), 400) | ||
103 | + end | ||
104 | + | ||
105 | + end | ||
106 | + | ||
107 | + desc "Returns the articles I voted" do | ||
108 | + detail 'Get the Articles I make a vote' | ||
109 | + failure [[403, 'Forbidden']] | ||
110 | + named 'ArticleFollowers' | ||
111 | + end | ||
112 | + #FIXME refactor this method | ||
113 | + get 'voted_by_me' do | ||
114 | + present_articles(current_person.votes.where(:voteable_type => 'Article').collect(&:voteable)) | ||
115 | + end | ||
116 | + | ||
117 | + desc 'Perform a vote on a article by id' do | ||
118 | + detail 'Vote on a specific article with values: 1 (if you like) or -1 (if not)' | ||
119 | + params Entities::UserLogin.documentation | ||
120 | + failure [[401,'Unauthorized']] | ||
121 | + named 'ArticleVote' | ||
122 | + end | ||
123 | + post ':id/vote' do | ||
124 | + ## The vote api should allow regular login or with captcha | ||
125 | + authenticate_allow_captcha! | ||
126 | + value = (params[:value] || 1).to_i | ||
127 | + # FIXME verify allowed values | ||
128 | + render_api_error!('Vote value not allowed', 400) unless [-1, 1].include?(value) | ||
129 | + article = find_article(environment.articles, params[:id]) | ||
130 | + ## If login with captcha | ||
131 | + if @current_tmp_user | ||
132 | + # Vote allowed only if data does not include this article | ||
133 | + vote = (@current_tmp_user.data.include? article.id) ? false : true | ||
134 | + if vote | ||
135 | + @current_tmp_user.data << article.id | ||
136 | + @current_tmp_user.store | ||
137 | + {:vote => do_vote(article, current_person, value)} | ||
138 | + else | ||
139 | + {:vote => false} | ||
140 | + end | ||
141 | + else | ||
142 | + {:vote => do_vote(article, current_person, value)} | ||
143 | + end | ||
144 | + end | ||
145 | + | ||
146 | + | ||
147 | + desc "Returns the total followers for the article" do | ||
148 | + detail 'Get the followers of a specific article by id' | ||
149 | + failure [[403, 'Forbidden']] | ||
150 | + named 'ArticleFollowers' | ||
151 | + end | ||
152 | + get ':id/followers' do | ||
153 | + article = find_article(environment.articles, params[:id]) | ||
154 | + total = article.person_followers.count | ||
155 | + {:total_followers => total} | ||
156 | + end | ||
157 | + | ||
158 | + desc "Return the articles followed by me" | ||
159 | + get 'followed_by_me' do | ||
160 | + present_articles_for_asset(current_person, 'following_articles') | ||
161 | + end | ||
162 | + | ||
163 | + desc "Add a follower for the article" do | ||
164 | + detail 'Add the current user identified by private token, like a follower of a article' | ||
165 | + params Entities::UserLogin.documentation | ||
166 | + failure [[401, 'Unauthorized']] | ||
167 | + named 'ArticleFollow' | ||
168 | + end | ||
169 | + post ':id/follow' do | ||
170 | + authenticate! | ||
171 | + article = find_article(environment.articles, params[:id]) | ||
172 | + if article.article_followers.exists?(:person_id => current_person.id) | ||
173 | + {:success => false, :already_follow => true} | ||
174 | + else | ||
175 | + article_follower = ArticleFollower.new | ||
176 | + article_follower.article = article | ||
177 | + article_follower.person = current_person | ||
178 | + article_follower.save! | ||
179 | + {:success => true} | ||
180 | + end | ||
181 | + end | ||
182 | + | ||
183 | + desc 'Return the children of a article identified by id' do | ||
184 | + detail 'Get all children articles of a specific article' | ||
185 | + params Entities::Article.documentation | ||
186 | + failure [[403, 'Forbidden']] | ||
187 | + named 'ArticleChildren' | ||
188 | + end | ||
189 | + | ||
190 | + paginate per_page: MAX_PER_PAGE, max_per_page: MAX_PER_PAGE | ||
191 | + get ':id/children' do | ||
192 | + article = find_article(environment.articles, params[:id]) | ||
193 | + | ||
194 | + #TODO make tests for this situation | ||
195 | + votes_order = params.delete(:order) if params[:order]=='votes_score' | ||
196 | + articles = select_filtered_collection_of(article, 'children', params) | ||
197 | + articles = articles.display_filter(current_person, article.profile) | ||
198 | + | ||
199 | + #TODO make tests for this situation | ||
200 | + if votes_order | ||
201 | + articles = articles.joins('left join votes on articles.id=votes.voteable_id').group('articles.id').reorder('sum(coalesce(votes.vote, 0)) DESC') | ||
202 | + end | ||
203 | + Article.hit(articles) | ||
204 | + present_articles(articles) | ||
205 | + end | ||
206 | + | ||
207 | + desc 'Return one child of a article identified by id' do | ||
208 | + detail 'Get a child of a specific article' | ||
209 | + params Entities::Article.documentation | ||
210 | + success Entities::Article | ||
211 | + failure [[403, 'Forbidden']] | ||
212 | + named 'ArticleChild' | ||
213 | + end | ||
214 | + get ':id/children/:child_id' do | ||
215 | + article = find_article(environment.articles, params[:id]) | ||
216 | + child = find_article(article.children, params[:child_id]) | ||
217 | + child.hit | ||
218 | + present_partial child, :with => Entities::Article | ||
219 | + end | ||
220 | + | ||
221 | + desc 'Suggest a article to another profile' do | ||
222 | + detail 'Suggest a article to another profile (person, community...)' | ||
223 | + params Entities::Article.documentation | ||
224 | + success Entities::Task | ||
225 | + failure [[401,'Unauthorized']] | ||
226 | + named 'ArticleSuggest' | ||
227 | + end | ||
228 | + post ':id/children/suggest' do | ||
229 | + authenticate! | ||
230 | + parent_article = environment.articles.find(params[:id]) | ||
231 | + | ||
232 | + suggest_article = SuggestArticle.new | ||
233 | + suggest_article.article = params[:article] | ||
234 | + suggest_article.article[:parent_id] = parent_article.id | ||
235 | + suggest_article.target = parent_article.profile | ||
236 | + suggest_article.requestor = current_person | ||
237 | + | ||
238 | + unless suggest_article.save | ||
239 | + render_api_errors!(suggest_article.article_object.errors.full_messages) | ||
240 | + end | ||
241 | + present_partial suggest_article, :with => Entities::Task | ||
242 | + end | ||
243 | + | ||
244 | + # Example Request: | ||
245 | + # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body | ||
246 | + desc 'Add a child article to a parent identified by id' do | ||
247 | + detail 'Create a new article and associate to a parent' | ||
248 | + params Entities::Article.documentation | ||
249 | + success Entities::Article | ||
250 | + failure [[401,'Unauthorized']] | ||
251 | + named 'ArticleAddChild' | ||
252 | + end | ||
253 | + post ':id/children' do | ||
254 | + parent_article = environment.articles.find(params[:id]) | ||
255 | + params[:article][:parent_id] = parent_article.id | ||
256 | + post_article(parent_article.profile, params) | ||
257 | + end | ||
258 | + end | ||
259 | + | ||
260 | + resource :profiles do | ||
261 | + get ':id/home_page' do | ||
262 | + profiles = environment.profiles | ||
263 | + profiles = profiles.visible_for_person(current_person) | ||
264 | + profile = profiles.find_by id: params[:id] | ||
265 | + present_partial profile.home_page, :with => Entities::Article | ||
266 | + end | ||
267 | + end | ||
268 | + | ||
269 | + kinds = %w[profile community person enterprise] | ||
270 | + kinds.each do |kind| | ||
271 | + resource kind.pluralize.to_sym do | ||
272 | + segment "/:#{kind}_id" do | ||
273 | + resource :articles do | ||
274 | + | ||
275 | + desc "Return all articles associate with a profile of type #{kind}" do | ||
276 | + detail 'Get a list of articles of a profile' | ||
277 | + params Entities::Article.documentation | ||
278 | + success Entities::Article | ||
279 | + failure [[403, 'Forbidden']] | ||
280 | + named 'ArticlesOfProfile' | ||
281 | + end | ||
282 | + get do | ||
283 | + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) | ||
284 | + | ||
285 | + if params[:path].present? | ||
286 | + article = profile.articles.find_by path: params[:path] | ||
287 | + if !article || !article.display_to?(current_person) | ||
288 | + article = forbidden! | ||
289 | + end | ||
290 | + | ||
291 | + present_partial article, :with => Entities::Article | ||
292 | + else | ||
293 | + | ||
294 | + present_articles_for_asset(profile) | ||
295 | + end | ||
296 | + end | ||
297 | + | ||
298 | + desc "Return a article associate with a profile of type #{kind}" do | ||
299 | + detail 'Get only one article of a profile' | ||
300 | + params Entities::Article.documentation | ||
301 | + success Entities::Article | ||
302 | + failure [[403, 'Forbidden']] | ||
303 | + named 'ArticleOfProfile' | ||
304 | + end | ||
305 | + get ':id' do | ||
306 | + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) | ||
307 | + present_article(profile) | ||
308 | + end | ||
309 | + | ||
310 | + # Example Request: | ||
311 | + # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body | ||
312 | + desc "Add a new article associated with a profile of type #{kind}" do | ||
313 | + detail 'Create a new article and associate with a profile' | ||
314 | + params Entities::Article.documentation | ||
315 | + success Entities::Article | ||
316 | + failure [[403, 'Forbidden']] | ||
317 | + named 'ArticleCreateToProfile' | ||
318 | + end | ||
319 | + post do | ||
320 | + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) | ||
321 | + post_article(profile, params) | ||
322 | + end | ||
323 | + end | ||
324 | + end | ||
325 | + end | ||
326 | + end | ||
327 | + end | ||
328 | + end | ||
329 | +end |
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + | ||
4 | + class Blocks < Grape::API | ||
5 | + resource :blocks do | ||
6 | + get ':id' do | ||
7 | + block = Block.find(params["id"]) | ||
8 | + return forbidden! unless block.visible_to_user?(current_person) | ||
9 | + present block, :with => Entities::Block, display_api_content: true | ||
10 | + end | ||
11 | + end | ||
12 | + end | ||
13 | + | ||
14 | + end | ||
15 | +end |
@@ -0,0 +1,45 @@ | @@ -0,0 +1,45 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + | ||
4 | + class Boxes < Grape::API | ||
5 | + | ||
6 | + kinds = %w[profile community person enterprise] | ||
7 | + kinds.each do |kind| | ||
8 | + | ||
9 | + resource kind.pluralize.to_sym do | ||
10 | + | ||
11 | + segment "/:#{kind}_id" do | ||
12 | + resource :boxes do | ||
13 | + get do | ||
14 | + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) | ||
15 | + return forbidden! unless profile.display_info_to?(current_person) | ||
16 | + present profile.boxes, with: Entities::Box, current_person: current_person | ||
17 | + end | ||
18 | + end | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
22 | + end | ||
23 | + | ||
24 | + resource :environments do | ||
25 | + [ '/default', '/context', ':environment_id' ].each do |route| | ||
26 | + segment route do | ||
27 | + resource :boxes do | ||
28 | + get do | ||
29 | + if (route.match(/default/)) | ||
30 | + env = Environment.default | ||
31 | + elsif (route.match(/context/)) | ||
32 | + env = environment | ||
33 | + else | ||
34 | + env = Environment.find(params[:environment_id]) | ||
35 | + end | ||
36 | + present env.boxes, with: Entities::Box, current_person: current_person | ||
37 | + end | ||
38 | + end | ||
39 | + end | ||
40 | + end | ||
41 | + end | ||
42 | + end | ||
43 | + | ||
44 | + end | ||
45 | +end |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Categories < Grape::API | ||
4 | + | ||
5 | + resource :categories do | ||
6 | + | ||
7 | + get do | ||
8 | + type = params[:category_type] | ||
9 | + include_parent = params[:include_parent] == 'true' | ||
10 | + include_children = params[:include_children] == 'true' | ||
11 | + | ||
12 | + categories = type.nil? ? environment.categories : environment.categories.where(:type => type) | ||
13 | + present categories, :with => Entities::Category, parent: include_parent, children: include_children | ||
14 | + end | ||
15 | + | ||
16 | + desc "Return the category by id" | ||
17 | + get ':id' do | ||
18 | + present environment.categories.find(params[:id]), :with => Entities::Category, parent: true, children: true | ||
19 | + end | ||
20 | + | ||
21 | + end | ||
22 | + | ||
23 | + end | ||
24 | + end | ||
25 | +end |
@@ -0,0 +1,63 @@ | @@ -0,0 +1,63 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Comments < Grape::API | ||
4 | + MAX_PER_PAGE = 20 | ||
5 | + | ||
6 | + | ||
7 | + resource :articles do | ||
8 | + paginate max_per_page: MAX_PER_PAGE | ||
9 | + # Collect comments from articles | ||
10 | + # | ||
11 | + # Parameters: | ||
12 | + # reference_id - comment id used as reference to collect comment | ||
13 | + # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected | ||
14 | + # limit - amount of comments returned. The default value is 20 | ||
15 | + # | ||
16 | + # Example Request: | ||
17 | + # GET /articles/12/comments?oldest&limit=10&reference_id=23 | ||
18 | + get ":id/comments" do | ||
19 | + article = find_article(environment.articles, params[:id]) | ||
20 | + comments = select_filtered_collection_of(article, :comments, params) | ||
21 | + comments = comments.without_spam | ||
22 | + comments = comments.without_reply if(params[:without_reply].present?) | ||
23 | + comments = plugins.filter(:unavailable_comments, comments) | ||
24 | + present paginate(comments), :with => Entities::Comment, :current_person => current_person | ||
25 | + end | ||
26 | + | ||
27 | + get ":id/comments/:comment_id" do | ||
28 | + article = find_article(environment.articles, params[:id]) | ||
29 | + present article.comments.find(params[:comment_id]), :with => Entities::Comment, :current_person => current_person | ||
30 | + end | ||
31 | + | ||
32 | + # Example Request: | ||
33 | + # POST api/v1/articles/12/comments?private_token=2298743290432&body=new comment&title=New | ||
34 | + post ":id/comments" do | ||
35 | + authenticate! | ||
36 | + article = find_article(environment.articles, params[:id]) | ||
37 | + return forbidden! unless article.accept_comments? | ||
38 | + options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article) | ||
39 | + begin | ||
40 | + comment = Comment.create!(options) | ||
41 | + rescue ActiveRecord::RecordInvalid => e | ||
42 | + render_api_error!(e.message, 400) | ||
43 | + end | ||
44 | + present comment, :with => Entities::Comment, :current_person => current_person | ||
45 | + end | ||
46 | + | ||
47 | + delete ":id/comments/:comment_id" do | ||
48 | + article = find_article(environment.articles, params[:id]) | ||
49 | + comment = article.comments.find_by_id(params[:comment_id]) | ||
50 | + return not_found! if comment.nil? | ||
51 | + return forbidden! unless comment.can_be_destroyed_by?(current_person) | ||
52 | + begin | ||
53 | + comment.destroy | ||
54 | + present comment, with: Entities::Comment, :current_person => current_person | ||
55 | + rescue => e | ||
56 | + render_api_error!(e.message, 500) | ||
57 | + end | ||
58 | + end | ||
59 | + end | ||
60 | + | ||
61 | + end | ||
62 | + end | ||
63 | +end |
@@ -0,0 +1,82 @@ | @@ -0,0 +1,82 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Communities < Grape::API | ||
4 | + | ||
5 | + resource :communities do | ||
6 | + | ||
7 | + # Collect comments from articles | ||
8 | + # | ||
9 | + # Parameters: | ||
10 | + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created | ||
11 | + # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected | ||
12 | + # limit - amount of comments returned. The default value is 20 | ||
13 | + # | ||
14 | + # Example Request: | ||
15 | + # GET /communities?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10 | ||
16 | + # GET /communities?reference_id=10&limit=10&oldest | ||
17 | + get do | ||
18 | + communities = select_filtered_collection_of(environment, 'communities', params) | ||
19 | + communities = profiles_for_person(communities, current_person) | ||
20 | + communities = communities.by_location(params) # Must be the last. May return Exception obj | ||
21 | + present communities, :with => Entities::Community, :current_person => current_person | ||
22 | + end | ||
23 | + | ||
24 | + | ||
25 | + # Example Request: | ||
26 | + # POST api/v1/communties?private_token=234298743290432&community[name]=some_name | ||
27 | + # for each custom field for community, add &community[field_name]=field_value to the request | ||
28 | + post do | ||
29 | + authenticate! | ||
30 | + params[:community] ||= {} | ||
31 | + | ||
32 | + params[:community][:custom_values]={} | ||
33 | + params[:community].keys.each do |key| | ||
34 | + params[:community][:custom_values][key]=params[:community].delete(key) if Community.custom_fields(environment).any?{|cf| cf.name==key} | ||
35 | + end | ||
36 | + | ||
37 | + begin | ||
38 | + community = Community.create_after_moderation(current_person, params[:community].merge({:environment => environment})) | ||
39 | + rescue | ||
40 | + community = Community.new(params[:community]) | ||
41 | + end | ||
42 | + | ||
43 | + if !community.save | ||
44 | + render_api_errors!(community.errors.full_messages) | ||
45 | + end | ||
46 | + | ||
47 | + present community, :with => Entities::Community, :current_person => current_person | ||
48 | + end | ||
49 | + | ||
50 | + get ':id' do | ||
51 | + community = profiles_for_person(environment.communities, current_person).find_by_id(params[:id]) | ||
52 | + present community, :with => Entities::Community, :current_person => current_person | ||
53 | + end | ||
54 | + | ||
55 | + end | ||
56 | + | ||
57 | + resource :people do | ||
58 | + | ||
59 | + segment '/:person_id' do | ||
60 | + | ||
61 | + resource :communities do | ||
62 | + | ||
63 | + get do | ||
64 | + person = environment.people.find(params[:person_id]) | ||
65 | + | ||
66 | + not_found! if person.blank? | ||
67 | + forbidden! if !person.display_info_to?(current_person) | ||
68 | + | ||
69 | + communities = select_filtered_collection_of(person, 'communities', params) | ||
70 | + communities = communities.visible | ||
71 | + present communities, :with => Entities::Community, :current_person => current_person | ||
72 | + end | ||
73 | + | ||
74 | + end | ||
75 | + | ||
76 | + end | ||
77 | + | ||
78 | + end | ||
79 | + | ||
80 | + end | ||
81 | + end | ||
82 | +end |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Contacts < Grape::API | ||
4 | + | ||
5 | + resource :communities do | ||
6 | + | ||
7 | + resource ':id/contact' do | ||
8 | + #contact => {:name => 'some name', :email => 'test@mail.com', :subject => 'some title', :message => 'some message'} | ||
9 | + desc "Send a contact message" | ||
10 | + post do | ||
11 | + profile = environment.communities.find(params[:id]) | ||
12 | + forbidden! unless profile.present? | ||
13 | + contact = Contact.new params[:contact].merge(dest: profile) | ||
14 | + if contact.deliver | ||
15 | + {:success => true} | ||
16 | + else | ||
17 | + {:success => false} | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + end | ||
22 | + end | ||
23 | + | ||
24 | + end | ||
25 | + end | ||
26 | +end |
@@ -0,0 +1,55 @@ | @@ -0,0 +1,55 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Enterprises < Grape::API | ||
4 | + | ||
5 | + resource :enterprises do | ||
6 | + | ||
7 | + # Collect enterprises from environment | ||
8 | + # | ||
9 | + # Parameters: | ||
10 | + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created | ||
11 | + # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected | ||
12 | + # limit - amount of comments returned. The default value is 20 | ||
13 | + # georef params - read `Profile.by_location` for more information. | ||
14 | + # | ||
15 | + # Example Request: | ||
16 | + # GET /enterprises?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10 | ||
17 | + # GET /enterprises?reference_id=10&limit=10&oldest | ||
18 | + get do | ||
19 | + enterprises = select_filtered_collection_of(environment, 'enterprises', params) | ||
20 | + enterprises = enterprises.visible | ||
21 | + enterprises = enterprises.by_location(params) # Must be the last. May return Exception obj. | ||
22 | + present enterprises, :with => Entities::Enterprise, :current_person => current_person | ||
23 | + end | ||
24 | + | ||
25 | + desc "Return one enterprise by id" | ||
26 | + get ':id' do | ||
27 | + enterprise = environment.enterprises.visible.find_by(id: params[:id]) | ||
28 | + present enterprise, :with => Entities::Enterprise, :current_person => current_person | ||
29 | + end | ||
30 | + | ||
31 | + end | ||
32 | + | ||
33 | + resource :people do | ||
34 | + | ||
35 | + segment '/:person_id' do | ||
36 | + | ||
37 | + resource :enterprises do | ||
38 | + | ||
39 | + get do | ||
40 | + person = environment.people.find(params[:person_id]) | ||
41 | + enterprises = select_filtered_collection_of(person, 'enterprises', params) | ||
42 | + enterprises = enterprises.visible.by_location(params) | ||
43 | + present enterprises, :with => Entities::Enterprise, :current_person => current_person | ||
44 | + end | ||
45 | + | ||
46 | + end | ||
47 | + | ||
48 | + end | ||
49 | + | ||
50 | + end | ||
51 | + | ||
52 | + | ||
53 | + end | ||
54 | + end | ||
55 | +end |
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Environments < Grape::API | ||
4 | + | ||
5 | + resource :environment do | ||
6 | + | ||
7 | + desc "Return the person information" | ||
8 | + get '/signup_person_fields' do | ||
9 | + present environment.signup_person_fields | ||
10 | + end | ||
11 | + | ||
12 | + get ':id' do | ||
13 | + local_environment = nil | ||
14 | + if (params[:id] == "default") | ||
15 | + local_environment = Environment.default | ||
16 | + elsif (params[:id] == "context") | ||
17 | + local_environment = environment | ||
18 | + else | ||
19 | + local_environment = Environment.find(params[:id]) | ||
20 | + end | ||
21 | + present_partial local_environment, :with => Entities::Environment, :is_admin => is_admin?(local_environment) | ||
22 | + end | ||
23 | + | ||
24 | + end | ||
25 | + | ||
26 | + end | ||
27 | + end | ||
28 | +end |
@@ -0,0 +1,127 @@ | @@ -0,0 +1,127 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class People < Grape::API | ||
4 | + | ||
5 | + MAX_PER_PAGE = 50 | ||
6 | + | ||
7 | + desc 'API Root' | ||
8 | + | ||
9 | + resource :people do | ||
10 | + paginate max_per_page: MAX_PER_PAGE | ||
11 | + | ||
12 | + # -- A note about privacy -- | ||
13 | + # We wold find people by location, but we must test if the related | ||
14 | + # fields are public. We can't do it now, with SQL, while the location | ||
15 | + # data and the fields_privacy are a serialized settings. | ||
16 | + # We must build a new table for profile data, where we can set meta-data | ||
17 | + # like: | ||
18 | + # | id | profile_id | key | value | privacy_level | source | | ||
19 | + # | 1 | 99 | city | Salvador | friends | user | | ||
20 | + # | 2 | 99 | lng | -38.521 | me only | automatic | | ||
21 | + | ||
22 | + # Collect people from environment | ||
23 | + # | ||
24 | + # Parameters: | ||
25 | + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created | ||
26 | + # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected | ||
27 | + # limit - amount of comments returned. The default value is 20 | ||
28 | + # | ||
29 | + # Example Request: | ||
30 | + # GET /people?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10 | ||
31 | + # GET /people?reference_id=10&limit=10&oldest | ||
32 | + | ||
33 | + desc "Find environment's people" | ||
34 | + get do | ||
35 | + people = select_filtered_collection_of(environment, 'people', params) | ||
36 | + people = people.visible | ||
37 | + present_partial people, :with => Entities::Person, :current_person => current_person | ||
38 | + end | ||
39 | + | ||
40 | + desc "Return the logged user information" | ||
41 | + get "/me" do | ||
42 | + authenticate! | ||
43 | + present_partial current_person, :with => Entities::Person, :current_person => current_person | ||
44 | + end | ||
45 | + | ||
46 | + desc "Return the person information" | ||
47 | + get ':id' do | ||
48 | + person = environment.people.visible.find_by(id: params[:id]) | ||
49 | + return not_found! if person.blank? | ||
50 | + present person, :with => Entities::Person, :current_person => current_person | ||
51 | + end | ||
52 | + | ||
53 | + desc "Update person information" | ||
54 | + post ':id' do | ||
55 | + authenticate! | ||
56 | + return forbidden! if current_person.id.to_s != params[:id] | ||
57 | + current_person.update_attributes!(asset_with_image(params[:person])) | ||
58 | + present current_person, :with => Entities::Person, :current_person => current_person | ||
59 | + end | ||
60 | + | ||
61 | + # POST api/v1/people?person[login]=some_login&person[password]=some_password&person[name]=Jack | ||
62 | + # for each custom field for person, add &person[field_name]=field_value to the request | ||
63 | + desc "Create person" | ||
64 | + post do | ||
65 | + authenticate! | ||
66 | + user_data = {} | ||
67 | + user_data[:login] = params[:person].delete(:login) || params[:person][:identifier] | ||
68 | + user_data[:email] = params[:person].delete(:email) | ||
69 | + user_data[:password] = params[:person].delete(:password) | ||
70 | + user_data[:password_confirmation] = params[:person].delete(:password_confirmation) | ||
71 | + | ||
72 | + params[:person][:custom_values]={} | ||
73 | + params[:person].keys.each do |key| | ||
74 | + params[:person][:custom_values][key]=params[:person].delete(key) if Person.custom_fields(environment).any?{|cf| cf.name==key} | ||
75 | + end | ||
76 | + | ||
77 | + user = User.build(user_data, asset_with_image(params[:person]), environment) | ||
78 | + | ||
79 | + begin | ||
80 | + user.signup! | ||
81 | + rescue ActiveRecord::RecordInvalid | ||
82 | + render_api_errors!(user.errors.full_messages) | ||
83 | + end | ||
84 | + | ||
85 | + present user.person, :with => Entities::Person, :current_person => user.person | ||
86 | + end | ||
87 | + | ||
88 | + desc "Return the person friends" | ||
89 | + get ':id/friends' do | ||
90 | + person = environment.people.visible.find_by(id: params[:id]) | ||
91 | + return not_found! if person.blank? | ||
92 | + friends = person.friends.visible | ||
93 | + present friends, :with => Entities::Person, :current_person => current_person | ||
94 | + end | ||
95 | + | ||
96 | + desc "Return the person permissions on other profiles" | ||
97 | + get ":id/permissions" do | ||
98 | + authenticate! | ||
99 | + person = environment.people.find(params[:id]) | ||
100 | + return not_found! if person.blank? | ||
101 | + return forbidden! unless current_person == person || environment.admins.include?(current_person) | ||
102 | + | ||
103 | + output = {} | ||
104 | + person.role_assignments.map do |role_assigment| | ||
105 | + if role_assigment.resource.respond_to?(:identifier) | ||
106 | + output[role_assigment.resource.identifier] = role_assigment.role.permissions | ||
107 | + end | ||
108 | + end | ||
109 | + present output | ||
110 | + end | ||
111 | + end | ||
112 | + | ||
113 | + resource :profiles do | ||
114 | + segment '/:profile_id' do | ||
115 | + resource :members do | ||
116 | + paginate max_per_page: MAX_PER_PAGE | ||
117 | + get do | ||
118 | + profile = environment.profiles.find_by id: params[:profile_id] | ||
119 | + members = select_filtered_collection_of(profile, 'members', params) | ||
120 | + present members, :with => Entities::Person, :current_person => current_person | ||
121 | + end | ||
122 | + end | ||
123 | + end | ||
124 | + end | ||
125 | + end | ||
126 | + end | ||
127 | +end |
@@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Profiles < Grape::API | ||
4 | + | ||
5 | + resource :profiles do | ||
6 | + | ||
7 | + get do | ||
8 | + profiles = select_filtered_collection_of(environment, 'profiles', params) | ||
9 | + profiles = profiles.visible | ||
10 | + profiles = profiles.by_location(params) # Must be the last. May return Exception obj. | ||
11 | + present profiles, :with => Entities::Profile, :current_person => current_person | ||
12 | + end | ||
13 | + | ||
14 | + get ':id' do | ||
15 | + profiles = environment.profiles | ||
16 | + profiles = profiles.visible | ||
17 | + profile = profiles.find_by id: params[:id] | ||
18 | + | ||
19 | + if profile | ||
20 | + present profile, :with => Entities::Profile, :current_person => current_person | ||
21 | + else | ||
22 | + not_found! | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + desc "Update profile information" | ||
27 | + post ':id' do | ||
28 | + authenticate! | ||
29 | + profile = environment.profiles.find_by(id: params[:id]) | ||
30 | + return forbidden! unless current_person.has_permission?(:edit_profile, profile) | ||
31 | + profile.update_attributes!(params[:profile]) | ||
32 | + present profile, :with => Entities::Profile, :current_person => current_person | ||
33 | + end | ||
34 | + | ||
35 | + delete ':id' do | ||
36 | + authenticate! | ||
37 | + profiles = environment.profiles | ||
38 | + profile = profiles.find_by id: params[:id] | ||
39 | + | ||
40 | + not_found! if profile.blank? | ||
41 | + | ||
42 | + if current_person.has_permission?(:destroy_profile, profile) | ||
43 | + profile.destroy | ||
44 | + else | ||
45 | + forbidden! | ||
46 | + end | ||
47 | + end | ||
48 | + end | ||
49 | + end | ||
50 | + end | ||
51 | +end |
@@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Search < Grape::API | ||
4 | + | ||
5 | + resource :search do | ||
6 | + resource :article do | ||
7 | + paginate max_per_page: 200 | ||
8 | + get do | ||
9 | + # Security checks | ||
10 | + sanitize_params_hash(params) | ||
11 | + # Api::Helpers | ||
12 | + asset = :articles | ||
13 | + context = environment | ||
14 | + | ||
15 | + profile = environment.profiles.find(params[:profile_id]) if params[:profile_id] | ||
16 | + scope = profile.nil? ? environment.articles.is_public : profile.articles.is_public | ||
17 | + scope = scope.where(:type => params[:type]) if params[:type] && !(params[:type] == 'Article') | ||
18 | + scope = scope.where(make_conditions_with_parameter(params)) | ||
19 | + scope = scope.joins(:categories).where(:categories => {:id => params[:category_ids]}) if params[:category_ids].present? | ||
20 | + scope = scope.where('articles.children_count > 0') if params[:has_children].present? | ||
21 | + query = params[:query] || "" | ||
22 | + order = "more_recent" | ||
23 | + | ||
24 | + options = {:filter => order, :template_id => params[:template_id]} | ||
25 | + | ||
26 | + search_result = find_by_contents(asset, context, scope, query, {:page => 1}, options) | ||
27 | + | ||
28 | + articles = search_result[:results] | ||
29 | + | ||
30 | + present_articles(articles) | ||
31 | + end | ||
32 | + end | ||
33 | + end | ||
34 | + | ||
35 | + end | ||
36 | + end | ||
37 | +end |
@@ -0,0 +1,190 @@ | @@ -0,0 +1,190 @@ | ||
1 | +require "uri" | ||
2 | + | ||
3 | +module Api | ||
4 | + module V1 | ||
5 | + class Session < Grape::API | ||
6 | + | ||
7 | + ################################ | ||
8 | + # => Login with captcha only | ||
9 | + # This method will attempt to login the user using only the captcha. | ||
10 | + # To do this, we generate a temporary in-memory user and generate a private | ||
11 | + # token to it. | ||
12 | + ################################ | ||
13 | + post "/login-captcha" do | ||
14 | + remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR']) | ||
15 | + # verify_captcha will render_api_error! and exit in case of any problem | ||
16 | + # this return is just to improve the clarity of the execution path | ||
17 | + return unless verify_captcha(remote_ip, params, environment) | ||
18 | + ## Creates and caches a captcha session store | ||
19 | + store = Noosfero::API::SessionStore.create("captcha") | ||
20 | + ## Initialize the data for the session store | ||
21 | + store.data = [] | ||
22 | + ## Put it back in cache | ||
23 | + store.store | ||
24 | + { "private_token" => "#{store.private_token}" } | ||
25 | + end | ||
26 | + | ||
27 | + # Login to get token | ||
28 | + # | ||
29 | + # Parameters: | ||
30 | + # login (*required) - user login or email | ||
31 | + # password (required) - user password | ||
32 | + # | ||
33 | + # Example Request: | ||
34 | + # POST http://localhost:3000/api/v1/login?login=adminuser&password=admin | ||
35 | + post "/login" do | ||
36 | + begin | ||
37 | + user ||= User.authenticate(params[:login], params[:password], environment) | ||
38 | + rescue User::UserNotActivated => e | ||
39 | + render_api_error!(e.message, 401) | ||
40 | + end | ||
41 | + | ||
42 | + return unauthorized! unless user | ||
43 | + @current_user = user | ||
44 | + present user, :with => Entities::UserLogin, :current_person => current_person | ||
45 | + end | ||
46 | + | ||
47 | + post "/login_from_cookie" do | ||
48 | + return unauthorized! if cookies[:auth_token].blank? | ||
49 | + user = User.where(remember_token: cookies[:auth_token]).first | ||
50 | + return unauthorized! unless user && user.activated? | ||
51 | + @current_user = user | ||
52 | + present user, :with => Entities::UserLogin, :current_person => current_person | ||
53 | + end | ||
54 | + | ||
55 | + # Create user. | ||
56 | + # | ||
57 | + # Parameters: | ||
58 | + # email (required) - Email | ||
59 | + # password (required) - Password | ||
60 | + # login - login | ||
61 | + # Example Request: | ||
62 | + # POST /register?email=some@mail.com&password=pas&password_confirmation=pas&login=some | ||
63 | + params do | ||
64 | + requires :email, type: String, desc: _("Email") | ||
65 | + requires :login, type: String, desc: _("Login") | ||
66 | + #requires :password, type: String, desc: _("Password") | ||
67 | + #requires :password_confirmation, type: String, desc: _("Password confirmation") | ||
68 | + end | ||
69 | + | ||
70 | + post "/register" do | ||
71 | + attrs = attributes_for_keys [:email, :login, :password, :password_confirmation] + environment.signup_person_fields | ||
72 | + remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR']) | ||
73 | + # verify_captcha will render_api_error! and exit in case of any problem | ||
74 | + # this return is just to improve the clarity of the execution path | ||
75 | + return unless verify_captcha(remote_ip, params, environment) | ||
76 | + | ||
77 | + name = params[:name].present? ? params[:name] : attrs[:email] | ||
78 | + attrs[:password_confirmation] = attrs[:password] if !attrs.has_key?(:password_confirmation) | ||
79 | + user = User.new(attrs.merge(:name => name)) | ||
80 | + | ||
81 | + begin | ||
82 | + user.signup! | ||
83 | + user.generate_private_token! if user.activated? | ||
84 | + present user, :with => Entities::UserLogin, :current_person => user.person | ||
85 | + rescue ActiveRecord::RecordInvalid | ||
86 | + message = user.errors.as_json.merge((user.person.present? ? user.person.errors : {}).as_json).to_json | ||
87 | + render_api_error!(message, 400) | ||
88 | + end | ||
89 | + end | ||
90 | + | ||
91 | + params do | ||
92 | + requires :activation_code, type: String, desc: _("Activation token") | ||
93 | + end | ||
94 | + | ||
95 | + # Activate a user. | ||
96 | + # | ||
97 | + # Parameter: | ||
98 | + # activation_code (required) - Activation token | ||
99 | + # Example Request: | ||
100 | + # PATCH /activate?activation_code=28259abd12cc6a64ef9399cf3286cb998b96aeaf | ||
101 | + patch "/activate" do | ||
102 | + user = User.find_by activation_code: params[:activation_code] | ||
103 | + if user | ||
104 | + unless user.environment.enabled?('admin_must_approve_new_users') | ||
105 | + if user.activate | ||
106 | + user.generate_private_token! | ||
107 | + present user, :with => Entities::UserLogin, :current_person => current_person | ||
108 | + end | ||
109 | + else | ||
110 | + if user.create_moderate_task | ||
111 | + user.activation_code = nil | ||
112 | + user.save! | ||
113 | + | ||
114 | + # Waiting for admin moderate user registration | ||
115 | + status 202 | ||
116 | + body({ | ||
117 | + :message => 'Waiting for admin moderate user registration' | ||
118 | + }) | ||
119 | + end | ||
120 | + end | ||
121 | + else | ||
122 | + # Token not found in database | ||
123 | + render_api_error!(_('Token is invalid'), 412) | ||
124 | + end | ||
125 | + end | ||
126 | + | ||
127 | + # Request a new password. | ||
128 | + # | ||
129 | + # Parameters: | ||
130 | + # value (required) - Email or login | ||
131 | + # Example Request: | ||
132 | + # POST /forgot_password?value=some@mail.com | ||
133 | + post "/forgot_password" do | ||
134 | + requestors = fetch_requestors(params[:value]) | ||
135 | + not_found! if requestors.blank? | ||
136 | + remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR']) | ||
137 | + # verify_captcha will render_api_error! and exit in case of any problem | ||
138 | + # this return is just to improve the clarity of the execution path | ||
139 | + return unless verify_captcha(remote_ip, params, environment) | ||
140 | + requestors.each do |requestor| | ||
141 | + ChangePassword.create!(:requestor => requestor) | ||
142 | + end | ||
143 | + end | ||
144 | + | ||
145 | + # Resend activation code. | ||
146 | + # | ||
147 | + # Parameters: | ||
148 | + # value (required) - Email or login | ||
149 | + # Example Request: | ||
150 | + # POST /resend_activation_code?value=some@mail.com | ||
151 | + post "/resend_activation_code" do | ||
152 | + requestors = fetch_requestors(params[:value]) | ||
153 | + not_found! if requestors.blank? | ||
154 | + remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR']) | ||
155 | + # verify_captcha will render_api_error! and exit in case of any problem | ||
156 | + # this return is just to improve the clarity of the execution path | ||
157 | + return unless verify_captcha(remote_ip, params, environment) | ||
158 | + | ||
159 | + requestors.each do |requestor| | ||
160 | + requestor.user.resend_activation_code | ||
161 | + end | ||
162 | + present requestors.map(&:user), :with => Entities::UserLogin | ||
163 | + end | ||
164 | + | ||
165 | + params do | ||
166 | + requires :code, type: String, desc: _("Forgot password code") | ||
167 | + end | ||
168 | + # Change password | ||
169 | + # | ||
170 | + # Parameters: | ||
171 | + # code (required) - Change password code | ||
172 | + # password (required) | ||
173 | + # password_confirmation (required) | ||
174 | + # Example Request: | ||
175 | + # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret | ||
176 | + patch "/new_password" do | ||
177 | + change_password = ChangePassword.find_by code: params[:code] | ||
178 | + not_found! if change_password.nil? | ||
179 | + | ||
180 | + if change_password.update_attributes(:password => params[:password], :password_confirmation => params[:password_confirmation]) | ||
181 | + change_password.finish | ||
182 | + present change_password.requestor.user, :with => Entities::UserLogin, :current_person => current_person | ||
183 | + else | ||
184 | + something_wrong! | ||
185 | + end | ||
186 | + end | ||
187 | + | ||
188 | + end | ||
189 | + end | ||
190 | +end |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Tags < Grape::API | ||
4 | + resource :articles do | ||
5 | + resource ':id/tags' do | ||
6 | + get do | ||
7 | + article = find_article(environment.articles, params[:id]) | ||
8 | + present article.tag_list | ||
9 | + end | ||
10 | + | ||
11 | + desc "Add a tag to an article" | ||
12 | + post do | ||
13 | + authenticate! | ||
14 | + article = find_article(environment.articles, params[:id]) | ||
15 | + article.tag_list=params[:tags] | ||
16 | + article.save | ||
17 | + present article.tag_list | ||
18 | + end | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
22 | + resource :environment do | ||
23 | + desc 'Return the tag counts for this environment' | ||
24 | + get '/tags' do | ||
25 | + present environment.tag_counts | ||
26 | + end | ||
27 | + end | ||
28 | + end | ||
29 | + end | ||
30 | +end |
@@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Tasks < Grape::API | ||
4 | +# before { authenticate! } | ||
5 | + | ||
6 | +# ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} | ||
7 | + | ||
8 | + resource :tasks do | ||
9 | + | ||
10 | + # Collect tasks | ||
11 | + # | ||
12 | + # Parameters: | ||
13 | + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created | ||
14 | + # oldest - Collect the oldest articles. If nothing is passed the newest articles are collected | ||
15 | + # limit - amount of articles returned. The default value is 20 | ||
16 | + # | ||
17 | + # Example Request: | ||
18 | + # GET host/api/v1/tasks?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 | ||
19 | + get do | ||
20 | + tasks = select_filtered_collection_of(environment, 'tasks', params) | ||
21 | + tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)} | ||
22 | + present_partial tasks, :with => Entities::Task | ||
23 | + end | ||
24 | + | ||
25 | + desc "Return the task id" | ||
26 | + get ':id' do | ||
27 | + task = find_task(environment, params[:id]) | ||
28 | + present_partial task, :with => Entities::Task | ||
29 | + end | ||
30 | + end | ||
31 | + | ||
32 | + kinds = %w[community person enterprise] | ||
33 | + kinds.each do |kind| | ||
34 | + resource kind.pluralize.to_sym do | ||
35 | + segment "/:#{kind}_id" do | ||
36 | + resource :tasks do | ||
37 | + get do | ||
38 | + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) | ||
39 | + present_tasks(profile) | ||
40 | + end | ||
41 | + | ||
42 | + get ':id' do | ||
43 | + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) | ||
44 | + present_task(profile) | ||
45 | + end | ||
46 | + | ||
47 | + post do | ||
48 | + profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) | ||
49 | + post_task(profile, params) | ||
50 | + end | ||
51 | + end | ||
52 | + end | ||
53 | + end | ||
54 | + end | ||
55 | + end | ||
56 | + end | ||
57 | +end |
@@ -0,0 +1,43 @@ | @@ -0,0 +1,43 @@ | ||
1 | +module Api | ||
2 | + module V1 | ||
3 | + class Users < Grape::API | ||
4 | + | ||
5 | + resource :users do | ||
6 | + | ||
7 | + get do | ||
8 | + users = select_filtered_collection_of(environment, 'users', params) | ||
9 | + users = users.select{|u| u.person.display_info_to? current_person} | ||
10 | + present users, :with => Entities::User, :current_person => current_person | ||
11 | + end | ||
12 | + | ||
13 | + get "/me" do | ||
14 | + authenticate! | ||
15 | + present current_user, :with => Entities::User, :current_person => current_person | ||
16 | + end | ||
17 | + | ||
18 | + get ":id" do | ||
19 | + user = environment.users.find_by id: params[:id] | ||
20 | + if user | ||
21 | + present user, :with => Entities::User, :current_person => current_person | ||
22 | + else | ||
23 | + not_found! | ||
24 | + end | ||
25 | + end | ||
26 | + | ||
27 | + get ":id/permissions" do | ||
28 | + authenticate! | ||
29 | + user = environment.users.find(params[:id]) | ||
30 | + output = {} | ||
31 | + user.person.role_assignments.map do |role_assigment| | ||
32 | + if role_assigment.resource.respond_to?(:identifier) && role_assigment.resource.identifier == params[:profile] | ||
33 | + output[:permissions] = role_assigment.role.permissions | ||
34 | + end | ||
35 | + end | ||
36 | + present output | ||
37 | + end | ||
38 | + | ||
39 | + end | ||
40 | + | ||
41 | + end | ||
42 | + end | ||
43 | +end |
@@ -0,0 +1,160 @@ | @@ -0,0 +1,160 @@ | ||
1 | +module AuthenticatedSystem | ||
2 | + | ||
3 | + protected | ||
4 | + | ||
5 | + def self.included base | ||
6 | + if base < ActionController::Base | ||
7 | + base.around_filter :user_set_current | ||
8 | + base.before_filter :login_from_cookie | ||
9 | + end | ||
10 | + | ||
11 | + # Inclusion hook to make #current_user and #logged_in? | ||
12 | + # available as ActionView helper methods. | ||
13 | + base.helper_method :current_user, :logged_in? | ||
14 | + end | ||
15 | + | ||
16 | + # Returns true or false if the user is logged in. | ||
17 | + # Preloads @current_user with the user model if they're logged in. | ||
18 | + def logged_in? | ||
19 | + current_user != nil | ||
20 | + end | ||
21 | + | ||
22 | + # Accesses the current user from the session. | ||
23 | + def current_user | ||
24 | + @current_user ||= begin | ||
25 | + id = session[:user] | ||
26 | + user = User.where(id: id).first if id | ||
27 | + user.session = session if user | ||
28 | + User.current = user | ||
29 | + user | ||
30 | + end | ||
31 | + end | ||
32 | + | ||
33 | + # Store the given user in the session. | ||
34 | + def current_user=(new_user) | ||
35 | + if new_user.nil? | ||
36 | + session.delete(:user) | ||
37 | + else | ||
38 | + session[:user] = new_user.id | ||
39 | + new_user.session = session | ||
40 | + new_user.register_login | ||
41 | + end | ||
42 | + @current_user = User.current = new_user | ||
43 | + end | ||
44 | + | ||
45 | + # See impl. from http://stackoverflow.com/a/2513456/670229 | ||
46 | + def user_set_current | ||
47 | + User.current = current_user | ||
48 | + yield | ||
49 | + ensure | ||
50 | + # to address the thread variable leak issues in Puma/Thin webserver | ||
51 | + User.current = nil | ||
52 | + end | ||
53 | + | ||
54 | + # Check if the user is authorized. | ||
55 | + # | ||
56 | + # Override this method in your controllers if you want to restrict access | ||
57 | + # to only a few actions or if you want to check if the user | ||
58 | + # has the correct rights. | ||
59 | + # | ||
60 | + # Example: | ||
61 | + # | ||
62 | + # # only allow nonbobs | ||
63 | + # def authorize? | ||
64 | + # current_user.login != "bob" | ||
65 | + # end | ||
66 | + def authorized? | ||
67 | + true | ||
68 | + end | ||
69 | + | ||
70 | + # Filter method to enforce a login requirement. | ||
71 | + # | ||
72 | + # To require logins for all actions, use this in your controllers: | ||
73 | + # | ||
74 | + # before_filter :login_required | ||
75 | + # | ||
76 | + # To require logins for specific actions, use this in your controllers: | ||
77 | + # | ||
78 | + # before_filter :login_required, :only => [ :edit, :update ] | ||
79 | + # | ||
80 | + # To skip this in a subclassed controller: | ||
81 | + # | ||
82 | + # skip_before_filter :login_required | ||
83 | + # | ||
84 | + def login_required | ||
85 | + username, passwd = get_auth_data | ||
86 | + if username && passwd | ||
87 | + self.current_user ||= User.authenticate(username, passwd) || nil | ||
88 | + end | ||
89 | + if logged_in? && authorized? | ||
90 | + true | ||
91 | + else | ||
92 | + if params[:require_login_popup] | ||
93 | + render :json => { :require_login_popup => true } | ||
94 | + else | ||
95 | + access_denied | ||
96 | + end | ||
97 | + end | ||
98 | + end | ||
99 | + | ||
100 | + # Redirect as appropriate when an access request fails. | ||
101 | + # | ||
102 | + # The default action is to redirect to the login screen. | ||
103 | + # | ||
104 | + # Override this method in your controllers if you want to have special | ||
105 | + # behavior in case the user is not authorized | ||
106 | + # to access the requested action. For example, a popup window might | ||
107 | + # simply close itself. | ||
108 | + def access_denied | ||
109 | + respond_to do |accepts| | ||
110 | + accepts.html do | ||
111 | + if request.xhr? | ||
112 | + render :text => _('Access denied'), :status => 401 | ||
113 | + else | ||
114 | + store_location | ||
115 | + redirect_to :controller => '/account', :action => 'login' | ||
116 | + end | ||
117 | + end | ||
118 | + accepts.xml do | ||
119 | + headers["Status"] = "Unauthorized" | ||
120 | + headers["WWW-Authenticate"] = %(Basic realm="Web Password") | ||
121 | + render :text => "Could't authenticate you", :status => '401 Unauthorized' | ||
122 | + end | ||
123 | + end | ||
124 | + false | ||
125 | + end | ||
126 | + | ||
127 | + # Store the URI of the current request in the session. | ||
128 | + # | ||
129 | + # We can return to this location by calling #redirect_back_or_default. | ||
130 | + def store_location(location = request.url) | ||
131 | + session[:return_to] = location | ||
132 | + end | ||
133 | + | ||
134 | + # Redirect to the URI stored by the most recent store_location call or | ||
135 | + # to the passed default. | ||
136 | + def redirect_back_or_default(default) | ||
137 | + if session[:return_to] | ||
138 | + redirect_to(session.delete(:return_to)) | ||
139 | + else | ||
140 | + redirect_to(default) | ||
141 | + end | ||
142 | + end | ||
143 | + | ||
144 | + # When called with before_filter :login_from_cookie will check for an :auth_token | ||
145 | + # cookie and log the user back in if apropriate | ||
146 | + def login_from_cookie | ||
147 | + return if cookies[:auth_token].blank? or logged_in? | ||
148 | + user = User.where(remember_token: cookies[:auth_token]).first | ||
149 | + self.current_user = user if user and user.remember_token? | ||
150 | + end | ||
151 | + | ||
152 | + private | ||
153 | + @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization) | ||
154 | + # gets BASIC auth info | ||
155 | + def get_auth_data | ||
156 | + auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) } | ||
157 | + auth_data = request.env[auth_key].to_s.split unless auth_key.blank? | ||
158 | + return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil] | ||
159 | + end | ||
160 | +end |
app/controllers/application_controller.rb
@@ -18,6 +18,13 @@ class ApplicationController < ActionController::Base | @@ -18,6 +18,13 @@ class ApplicationController < ActionController::Base | ||
18 | end | 18 | end |
19 | before_filter :redirect_to_current_user | 19 | before_filter :redirect_to_current_user |
20 | 20 | ||
21 | + before_filter :set_session_theme | ||
22 | + def set_session_theme | ||
23 | + if params[:theme] | ||
24 | + session[:theme] = environment.theme_ids.include?(params[:theme]) ? params[:theme] : nil | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
21 | def require_login_for_environment | 28 | def require_login_for_environment |
22 | login_required | 29 | login_required |
23 | end | 30 | end |
app/controllers/my_profile/profile_themes_controller.rb
@@ -63,12 +63,12 @@ class ProfileThemesController < ThemesController | @@ -63,12 +63,12 @@ class ProfileThemesController < ThemesController | ||
63 | end | 63 | end |
64 | 64 | ||
65 | def start_test | 65 | def start_test |
66 | - session[:theme] = params[:id] | 66 | + session[:user_theme] = params[:id] |
67 | redirect_to :controller => 'content_viewer', :profile => profile.identifier, :action => 'view_page' | 67 | redirect_to :controller => 'content_viewer', :profile => profile.identifier, :action => 'view_page' |
68 | end | 68 | end |
69 | 69 | ||
70 | def stop_test | 70 | def stop_test |
71 | - session[:theme] = nil | 71 | + session[:user_theme] = nil |
72 | redirect_to :action => 'index' | 72 | redirect_to :action => 'index' |
73 | end | 73 | end |
74 | 74 |
app/controllers/public/api_controller.rb
app/controllers/public/content_viewer_controller.rb
@@ -213,7 +213,7 @@ class ContentViewerController < ApplicationController | @@ -213,7 +213,7 @@ class ContentViewerController < ApplicationController | ||
213 | end | 213 | end |
214 | 214 | ||
215 | if @page.published && @page.uploaded_file? | 215 | if @page.published && @page.uploaded_file? |
216 | - redirect_to @page.public_filename | 216 | + redirect_to "#{Noosfero.root}#{@page.public_filename}" |
217 | else | 217 | else |
218 | send_data data, @page.download_headers | 218 | send_data data, @page.download_headers |
219 | end | 219 | end |
app/helpers/application_helper.rb
@@ -235,13 +235,6 @@ module ApplicationHelper | @@ -235,13 +235,6 @@ module ApplicationHelper | ||
235 | link_to(content_tag('span', text), url, html_options.merge(:class => the_class, :title => text)) | 235 | link_to(content_tag('span', text), url, html_options.merge(:class => the_class, :title => text)) |
236 | end | 236 | end |
237 | 237 | ||
238 | - def button_bar(options = {}, &block) | ||
239 | - options[:class].nil? ? | ||
240 | - options[:class]='button-bar' : | ||
241 | - options[:class]+=' button-bar' | ||
242 | - concat(content_tag('div', capture(&block).to_s + tag('br', :style => 'clear: left;'), options)) | ||
243 | - end | ||
244 | - | ||
245 | def render_profile_actions klass | 238 | def render_profile_actions klass |
246 | name = klass.to_s.underscore | 239 | name = klass.to_s.underscore |
247 | begin | 240 | begin |
@@ -353,7 +346,7 @@ module ApplicationHelper | @@ -353,7 +346,7 @@ module ApplicationHelper | ||
353 | end | 346 | end |
354 | 347 | ||
355 | def is_testing_theme | 348 | def is_testing_theme |
356 | - !controller.session[:theme].nil? | 349 | + !controller.session[:user_theme].nil? |
357 | end | 350 | end |
358 | 351 | ||
359 | def theme_owner | 352 | def theme_owner |
@@ -602,8 +595,8 @@ module ApplicationHelper | @@ -602,8 +595,8 @@ module ApplicationHelper | ||
602 | end | 595 | end |
603 | 596 | ||
604 | if block | 597 | if block |
605 | - field_html ||= '' | ||
606 | - field_html += capture(&block) | 598 | + field_html ||= ''.html_safe |
599 | + field_html = [field_html, capture(&block)].safe_join | ||
607 | end | 600 | end |
608 | 601 | ||
609 | if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') || (controller.controller_name == 'home' && controller.action_name == 'index' && user.nil?) | 602 | if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') || (controller.controller_name == 'home' && controller.action_name == 'index' && user.nil?) |
@@ -612,7 +605,9 @@ module ApplicationHelper | @@ -612,7 +605,9 @@ module ApplicationHelper | ||
612 | end | 605 | end |
613 | else | 606 | else |
614 | if profile.active_fields.include?(name) | 607 | if profile.active_fields.include?(name) |
615 | - result = content_tag('div', field_html + profile_field_privacy_selector(profile, name), :class => 'field-with-privacy-selector') | 608 | + result = content_tag :div, class: 'field-with-privacy-selector' do |
609 | + [field_html, profile_field_privacy_selector(profile, name)].safe_join | ||
610 | + end | ||
616 | end | 611 | end |
617 | end | 612 | end |
618 | 613 | ||
@@ -620,10 +615,6 @@ module ApplicationHelper | @@ -620,10 +615,6 @@ module ApplicationHelper | ||
620 | result = required(result) | 615 | result = required(result) |
621 | end | 616 | end |
622 | 617 | ||
623 | - if block | ||
624 | - concat(result) | ||
625 | - end | ||
626 | - | ||
627 | result | 618 | result |
628 | end | 619 | end |
629 | 620 | ||
@@ -868,7 +859,7 @@ module ApplicationHelper | @@ -868,7 +859,7 @@ module ApplicationHelper | ||
868 | alias :browse_communities_menu :search_communities_menu | 859 | alias :browse_communities_menu :search_communities_menu |
869 | 860 | ||
870 | def pagination_links(collection, options={}) | 861 | def pagination_links(collection, options={}) |
871 | - options = {:previous_label => content_tag(:span, '« ', :class => 'previous-arrow') + _('Previous'), :next_label => _('Next') + content_tag(:span, ' »', :class => 'next-arrow'), :inner_window => 1, :outer_window => 0 }.merge(options) | 862 | + options = {:previous_label => content_tag(:span, '« '.html_safe, :class => 'previous-arrow') + _('Previous'), :next_label => _('Next') + content_tag(:span, ' »'.html_safe, :class => 'next-arrow'), :inner_window => 1, :outer_window => 0 }.merge(options) |
872 | will_paginate(collection, options) | 863 | will_paginate(collection, options) |
873 | end | 864 | end |
874 | 865 | ||
@@ -990,6 +981,7 @@ module ApplicationHelper | @@ -990,6 +981,7 @@ module ApplicationHelper | ||
990 | values = {} | 981 | values = {} |
991 | values.merge!(task.information[:variables]) if task.information[:variables] | 982 | values.merge!(task.information[:variables]) if task.information[:variables] |
992 | values.merge!({:requestor => link_to(task.requestor.name, task.requestor.url)}) if task.requestor | 983 | values.merge!({:requestor => link_to(task.requestor.name, task.requestor.url)}) if task.requestor |
984 | + values.merge!({:target => link_to(task.target.name, task.target.url)}) if (task.target && task.target.respond_to?(:url)) | ||
993 | values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject | 985 | values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject |
994 | values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject | 986 | values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject |
995 | (task.information[:message] % values).html_safe | 987 | (task.information[:message] % values).html_safe |
app/helpers/article_helper.rb
@@ -188,9 +188,9 @@ module ArticleHelper | @@ -188,9 +188,9 @@ module ArticleHelper | ||
188 | def following_button(page, user) | 188 | def following_button(page, user) |
189 | if !user.blank? and user != page.author | 189 | if !user.blank? and user != page.author |
190 | if page.is_followed_by? user | 190 | if page.is_followed_by? user |
191 | - button :cancel, unfollow_button_text(page), {:controller => 'profile', :action => 'unfollow_article', :article_id => page.id, :profile => page.profile.identifier} | 191 | + button :cancel, unfollow_button_text(page), {controller: :profile, profile: page.profile.identifier, action: :unfollow_article, article_id: page.id} |
192 | else | 192 | else |
193 | - button :add, follow_button_text(page), {:controller => 'profile', :action => 'follow_article', :article_id => page.id, :profile => page.profile.identifier} | 193 | + button :add, follow_button_text(page), {controller: :profile, profile: page.profile.identifier, action: :follow_article, article_id: page.id} |
194 | end | 194 | end |
195 | end | 195 | end |
196 | end | 196 | end |
app/helpers/boxes_helper.rb
@@ -99,15 +99,10 @@ module BoxesHelper | @@ -99,15 +99,10 @@ module BoxesHelper | ||
99 | end | 99 | end |
100 | 100 | ||
101 | def render_block_content block | 101 | def render_block_content block |
102 | - # FIXME: this conditional should be removed after all | ||
103 | - # block footer from plugins methods get refactored into helpers and views. | ||
104 | - # They are a failsafe until all of them are done. | ||
105 | - return block.content if block.method(:content).owner != Block | ||
106 | render_block block | 102 | render_block block |
107 | end | 103 | end |
108 | 104 | ||
109 | def render_block_footer block | 105 | def render_block_footer block |
110 | - return block.footer if block.method(:footer).owner != Block | ||
111 | render_block block, 'footers/' | 106 | render_block block, 'footers/' |
112 | end | 107 | end |
113 | 108 |
app/helpers/buttons_helper.rb
1 | module ButtonsHelper | 1 | module ButtonsHelper |
2 | + | ||
3 | + def button_bar(options = {}, &block) | ||
4 | + options[:class] ||= '' | ||
5 | + options[:class] << ' button-bar' | ||
6 | + | ||
7 | + content_tag :div, options do | ||
8 | + [ | ||
9 | + capture(&block).to_s, | ||
10 | + tag(:br, style: 'clear: left;'), | ||
11 | + ].safe_join | ||
12 | + end | ||
13 | + end | ||
14 | + | ||
2 | def button(type, label, url, html_options = {}) | 15 | def button(type, label, url, html_options = {}) |
3 | html_options ||= {} | 16 | html_options ||= {} |
4 | the_class = 'with-text' | 17 | the_class = 'with-text' |
app/helpers/theme_loader_helper.rb
@@ -2,8 +2,8 @@ module ThemeLoaderHelper | @@ -2,8 +2,8 @@ module ThemeLoaderHelper | ||
2 | def current_theme | 2 | def current_theme |
3 | @current_theme ||= | 3 | @current_theme ||= |
4 | begin | 4 | begin |
5 | - if session[:theme] | ||
6 | - session[:theme] | 5 | + if session[:user_theme] |
6 | + session[:user_theme] | ||
7 | else | 7 | else |
8 | # utility for developers: set the theme to 'random' in development mode and | 8 | # utility for developers: set the theme to 'random' in development mode and |
9 | # you will get a different theme every request. This is interesting for | 9 | # you will get a different theme every request. This is interesting for |
@@ -11,8 +11,8 @@ module ThemeLoaderHelper | @@ -11,8 +11,8 @@ module ThemeLoaderHelper | ||
11 | if Rails.env.development? && environment.theme == 'random' | 11 | if Rails.env.development? && environment.theme == 'random' |
12 | @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand | 12 | @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand |
13 | @random_theme | 13 | @random_theme |
14 | - elsif Rails.env.development? && respond_to?(:params) && params[:theme] && File.exists?(Rails.root.join('public/designs/themes', params[:theme])) | ||
15 | - params[:theme] | 14 | + elsif Rails.env.development? && respond_to?(:params) && params[:user_theme] && File.exists?(Rails.root.join('public/designs/themes', params[:user_theme])) |
15 | + params[:user_theme] | ||
16 | else | 16 | else |
17 | if profile && !profile.theme.nil? | 17 | if profile && !profile.theme.nil? |
18 | profile.theme | 18 | profile.theme |
@@ -34,8 +34,10 @@ module ThemeLoaderHelper | @@ -34,8 +34,10 @@ module ThemeLoaderHelper | ||
34 | end | 34 | end |
35 | 35 | ||
36 | def theme_path | 36 | def theme_path |
37 | - if session[:theme] | 37 | + if session[:user_theme] |
38 | '/user_themes/' + current_theme | 38 | '/user_themes/' + current_theme |
39 | + elsif session[:theme] | ||
40 | + '/designs/themes/' + session[:theme] | ||
39 | else | 41 | else |
40 | '/designs/themes/' + current_theme | 42 | '/designs/themes/' + current_theme |
41 | end | 43 | end |
app/helpers/users_helper.rb
1 | module UsersHelper | 1 | module UsersHelper |
2 | 2 | ||
3 | - FILTER_TRANSLATION = { | 3 | + def filter_translation |
4 | + { | ||
4 | 'all_users' => _('All users'), | 5 | 'all_users' => _('All users'), |
5 | 'admin_users' => _('Admin users'), | 6 | 'admin_users' => _('Admin users'), |
6 | 'activated_users' => _('Activated users'), | 7 | 'activated_users' => _('Activated users'), |
7 | 'deactivated_users' => _('Deativated users'), | 8 | 'deactivated_users' => _('Deativated users'), |
8 | - } | 9 | + } |
10 | + end | ||
9 | 11 | ||
10 | def filter_selector(filter, float = 'right') | 12 | def filter_selector(filter, float = 'right') |
11 | - options = options_for_select(FILTER_TRANSLATION.map {|key, name| [name, key]}, :selected => filter) | 13 | + options = options_for_select(filter_translation.map {|key, name| [name, key]}, :selected => filter) |
12 | url_params = url_for(params.merge(:filter => 'FILTER')) | 14 | url_params = url_for(params.merge(:filter => 'FILTER')) |
13 | onchange = "document.location.href = '#{url_params}'.replace('FILTER', this.value)" | 15 | onchange = "document.location.href = '#{url_params}'.replace('FILTER', this.value)" |
14 | select_field = select_tag(:filter, options, :onchange => onchange) | 16 | select_field = select_tag(:filter, options, :onchange => onchange) |
@@ -19,7 +21,7 @@ module UsersHelper | @@ -19,7 +21,7 @@ module UsersHelper | ||
19 | end | 21 | end |
20 | 22 | ||
21 | def users_filter_title(filter) | 23 | def users_filter_title(filter) |
22 | - FILTER_TRANSLATION[filter] | 24 | + filter_translation[filter] |
23 | end | 25 | end |
24 | 26 | ||
25 | end | 27 | end |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +class ActivitiesCounterCacheJob | ||
2 | + | ||
3 | + def perform | ||
4 | + person_activities_counts = ApplicationRecord.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id WHERE (action_tracker.created_at >= #{ApplicationRecord.connection.quote(ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db))}) AND ( (profiles.type = 'Person' ) ) GROUP BY profiles.id;") | ||
5 | + organization_activities_counts = ApplicationRecord.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id WHERE (action_tracker.created_at >= #{ApplicationRecord.connection.quote(ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db))}) AND ( (profiles.type = 'Community' OR profiles.type = 'Enterprise' OR profiles.type = 'Organization' ) ) GROUP BY profiles.id;") | ||
6 | + activities_counts = person_activities_counts.entries + organization_activities_counts.entries | ||
7 | + activities_counts.each do |count| | ||
8 | + update_sql = ApplicationRecord.__send__(:sanitize_sql, ["UPDATE profiles SET activities_count=? WHERE profiles.id=?;", count['count'].to_i, count['id'] ], '') | ||
9 | + ApplicationRecord.connection.execute(update_sql) | ||
10 | + end | ||
11 | + Delayed::Job.enqueue(ActivitiesCounterCacheJob.new, {:priority => -3, :run_at => 1.day.from_now}) | ||
12 | + end | ||
13 | + | ||
14 | +end |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +class CreateThumbnailsJob < Struct.new(:class_name, :file_id) | ||
2 | + def perform | ||
3 | + return unless class_name.constantize.exists?(file_id) | ||
4 | + file = class_name.constantize.find(file_id) | ||
5 | + file.create_thumbnails | ||
6 | + article = Article.where(:image_id => file_id).first | ||
7 | + if article | ||
8 | + article.touch | ||
9 | + end | ||
10 | + end | ||
11 | +end |
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +class DownloadReportedImagesJob < Struct.new(:abuse_report, :article) | ||
2 | + def perform | ||
3 | + images_paths = article.image? ? [File.join(article.profile.environment.top_url, article.public_filename(:display))] : article.body_images_paths | ||
4 | + images_paths.each do |image_path| | ||
5 | + image = get_image(image_path) | ||
6 | + reported_image = ReportedImage.create!( :abuse_report => abuse_report, | ||
7 | + :uploaded_data => image, | ||
8 | + :filename => File.basename(image_path), | ||
9 | + :size => image.size ) | ||
10 | + abuse_report.content = parse_content(abuse_report, image_path, reported_image) | ||
11 | + end | ||
12 | + abuse_report.save! | ||
13 | + end | ||
14 | + | ||
15 | + def get_image(image_path) | ||
16 | + image = ActionController::UploadedTempfile.new('reported_image') | ||
17 | + image.write(Net::HTTP.get(URI.parse(image_path))) | ||
18 | + image.original_path = 'tmp/' + File.basename(image_path) | ||
19 | + image.content_type = 'image/' + File.extname(image_path).gsub('.','') | ||
20 | + image | ||
21 | + end | ||
22 | + | ||
23 | + def parse_content(report, old_path, image) | ||
24 | + old_path = old_path.gsub(report.reporter.environment.top_url, '') | ||
25 | + report.content.gsub(/#{old_path}/, image.public_filename) | ||
26 | + end | ||
27 | +end |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +class GetEmailContactsJob < Struct.new(:import_from, :login, :password, :contact_list_id) | ||
2 | + def perform | ||
3 | + begin | ||
4 | + Invitation.get_contacts(import_from, login, password, contact_list_id) | ||
5 | + rescue Contacts::AuthenticationError => ex | ||
6 | + ContactList.exists?(contact_list_id) && ContactList.find(contact_list_id).register_auth_error | ||
7 | + rescue Exception => ex | ||
8 | + ContactList.exists?(contact_list_id) && ContactList.find(contact_list_id).register_error | ||
9 | + end | ||
10 | + end | ||
11 | +end |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +class InvitationJob < Struct.new(:person_id, :contacts_to_invite, :message, :profile_id, :contact_list_id, :locale) | ||
2 | + def perform | ||
3 | + Noosfero.with_locale(locale) do | ||
4 | + person = Person.find(person_id) | ||
5 | + profile = Profile.find(profile_id) | ||
6 | + Invitation.invite(person, contacts_to_invite, message, profile) | ||
7 | + ContactList.exists?(contact_list_id) && ContactList.find(contact_list_id).destroy | ||
8 | + end | ||
9 | + end | ||
10 | +end |
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +class LogMemoryConsumptionJob < Struct.new(:last_stat) | ||
2 | + # Number of entries do display | ||
3 | + N = 20 | ||
4 | + | ||
5 | + def perform | ||
6 | + logpath = File.join(Rails.root, 'log', "#{ENV['RAILS_ENV']}_memory_consumption.log") | ||
7 | + logger = Logger.new(logpath) | ||
8 | + stats = Hash.new(0) | ||
9 | + ObjectSpace.each_object {|o| stats[o.class.to_s] += 1} | ||
10 | + i = 1 | ||
11 | + | ||
12 | + logger << "[#{Time.now.strftime('%F %T %z')}]\n" | ||
13 | + stats.sort {|(k1,v1),(k2,v2)| v2 <=> v1}.each do |k,v| | ||
14 | + logger << (sprintf "%-60s %10d", k, v) | ||
15 | + logger << (sprintf " | delta %10d", (v - last_stat[k])) if last_stat && last_stat[k] | ||
16 | + logger << "\n" | ||
17 | + break if i > N | ||
18 | + i += 1 | ||
19 | + end | ||
20 | + logger << "\n" | ||
21 | + end | ||
22 | +end |
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
1 | +class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id) | ||
2 | + NOTIFY_ONLY_COMMUNITY = [ | ||
3 | + 'add_member_in_community' | ||
4 | + ] | ||
5 | + | ||
6 | + NOT_NOTIFY_COMMUNITY = [ | ||
7 | + 'join_community' | ||
8 | + ] | ||
9 | + def perform | ||
10 | + return unless ActionTracker::Record.exists?(tracked_action_id) | ||
11 | + tracked_action = ActionTracker::Record.find(tracked_action_id) | ||
12 | + return unless tracked_action.user.present? | ||
13 | + target = tracked_action.target | ||
14 | + if target.is_a?(Community) && ( NOTIFY_ONLY_COMMUNITY.include?(tracked_action.verb) || ! target.public_profile ) | ||
15 | + ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id) | ||
16 | + return | ||
17 | + end | ||
18 | + | ||
19 | + # Notify the user | ||
20 | + ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id) | ||
21 | + | ||
22 | + # Notify all friends | ||
23 | + ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select f.friend_id, #{tracked_action.id} from friendships as f where person_id=#{tracked_action.user.id} and f.friend_id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id})") | ||
24 | + | ||
25 | + if tracked_action.user.is_a? Organization | ||
26 | + ActionTrackerNotification.connection.execute "insert into action_tracker_notifications(profile_id, action_tracker_id) " + | ||
27 | + "select distinct accessor_id, #{tracked_action.id} from role_assignments where resource_id = #{tracked_action.user.id} and resource_type='Profile' " + | ||
28 | + if tracked_action.user.is_a? Enterprise then "union select distinct person_id, #{tracked_action.id} from favorite_enterprise_people where enterprise_id = #{tracked_action.user.id}" else "" end | ||
29 | + end | ||
30 | + | ||
31 | + if target.is_a?(Community) | ||
32 | + ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb) | ||
33 | + | ||
34 | + ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select distinct profiles.id, #{tracked_action.id} from role_assignments, profiles where profiles.type = 'Person' and profiles.id = role_assignments.accessor_id and profiles.id != #{tracked_action.user.id} and profiles.id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id}) and role_assignments.resource_type = 'Profile' and role_assignments.resource_id = #{target.id}") | ||
35 | + end | ||
36 | + | ||
37 | + if target.is_a?(Article) && target.profile.is_a?(Community) | ||
38 | + ActionTrackerNotification.create(:profile_id => target.profile.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb) | ||
39 | + | ||
40 | + ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select distinct profiles.id, #{tracked_action.id} from role_assignments, profiles where profiles.type = 'Person' and profiles.id = role_assignments.accessor_id and profiles.id != #{tracked_action.user.id} and profiles.id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id}) and role_assignments.resource_type = 'Profile' and role_assignments.resource_id = #{target.profile.id}") | ||
41 | + end | ||
42 | + | ||
43 | + end | ||
44 | +end |
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +class ProfileSuggestionsJob < Struct.new(:person_id) | ||
2 | + | ||
3 | + def self.exists?(person_id) | ||
4 | + !find(person_id).empty? | ||
5 | + end | ||
6 | + | ||
7 | + def self.find(person_id) | ||
8 | + Delayed::Job.by_handler("--- !ruby/struct:ProfileSuggestionsJob\nperson_id: #{person_id}\n") | ||
9 | + end | ||
10 | + | ||
11 | + def perform | ||
12 | + logger = Delayed::Worker.logger | ||
13 | + begin | ||
14 | + person = Person.find(person_id) | ||
15 | + ProfileSuggestion.calculate_suggestions(person) | ||
16 | + UserMailer.profiles_suggestions_email(person).deliver if person.email_suggestions | ||
17 | + rescue Exception => exception | ||
18 | + logger.error("Error with suggestions for person ID %d: %s" % [person_id, exception.to_s]) | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
22 | +end |
app/models/add_member.rb
@@ -37,6 +37,10 @@ class AddMember < Task | @@ -37,6 +37,10 @@ class AddMember < Task | ||
37 | true | 37 | true |
38 | end | 38 | end |
39 | 39 | ||
40 | + def reject_details | ||
41 | + true | ||
42 | + end | ||
43 | + | ||
40 | def footer | 44 | def footer |
41 | true | 45 | true |
42 | end | 46 | end |
@@ -72,8 +76,9 @@ class AddMember < Task | @@ -72,8 +76,9 @@ class AddMember < Task | ||
72 | end | 76 | end |
73 | 77 | ||
74 | def task_cancelled_message | 78 | def task_cancelled_message |
75 | - _("Your request to enter community \"%{target} with the profile \"%{requestor}\" was not accepted. Please contact any profile admin from %{url} for more information.") % | ||
76 | - {:target => self.target.name, :url => self.target.url, | ||
77 | - :requestor => self.requestor.name} | 79 | + _("Your request to enter community \"%{target}\" with the profile \"%{requestor}\" was not accepted. Please contact any profile admin from %{target} for more information. The following explanation was given: \n\n\"%{explanation}\"") % |
80 | + {:target => self.target.name, | ||
81 | + :requestor => self.requestor.name, | ||
82 | + :explanation => self.reject_explanation} | ||
78 | end | 83 | end |
79 | end | 84 | end |
app/models/application_record.rb
1 | class ApplicationRecord < ActiveRecord::Base | 1 | class ApplicationRecord < ActiveRecord::Base |
2 | 2 | ||
3 | - self.abstract_class = true | ||
4 | - | ||
5 | - def self.postgresql? | ||
6 | - self.connection.adapter_name == 'PostgreSQL' | ||
7 | - end | 3 | + self.abstract_class = true |
4 | + self.store_full_sti_class = true | ||
8 | 5 | ||
9 | # an ActionView instance for rendering views on models | 6 | # an ActionView instance for rendering views on models |
10 | def self.action_view | 7 | def self.action_view |
@@ -25,7 +22,7 @@ class ApplicationRecord < ActiveRecord::Base | @@ -25,7 +22,7 @@ class ApplicationRecord < ActiveRecord::Base | ||
25 | alias :meta_cache_key :cache_key | 22 | alias :meta_cache_key :cache_key |
26 | def cache_key | 23 | def cache_key |
27 | key = [Noosfero::VERSION, meta_cache_key] | 24 | key = [Noosfero::VERSION, meta_cache_key] |
28 | - key.unshift(ApplicationRecord.connection.schema_search_path) if ApplicationRecord.postgresql? | 25 | + key.unshift ApplicationRecord.connection.schema_search_path |
29 | key.join('/') | 26 | key.join('/') |
30 | end | 27 | end |
31 | 28 |
app/models/article.rb
@@ -29,6 +29,8 @@ class Article < ApplicationRecord | @@ -29,6 +29,8 @@ class Article < ApplicationRecord | ||
29 | :display => %w[full] | 29 | :display => %w[full] |
30 | } | 30 | } |
31 | 31 | ||
32 | + N_('article') | ||
33 | + | ||
32 | def initialize(*params) | 34 | def initialize(*params) |
33 | super | 35 | super |
34 | if params.present? && params.first.present? | 36 | if params.present? && params.first.present? |
app/models/block.rb
@@ -181,30 +181,6 @@ class Block < ApplicationRecord | @@ -181,30 +181,6 @@ class Block < ApplicationRecord | ||
181 | "/images/block_preview.png" | 181 | "/images/block_preview.png" |
182 | end | 182 | end |
183 | 183 | ||
184 | - # Returns the content to be used for this block. | ||
185 | - # | ||
186 | - # This method can return several types of objects: | ||
187 | - # | ||
188 | - # * <tt>String</tt>: if the string starts with <tt>http://</tt> or <tt>https://</tt>, then it is assumed to be address of an IFRAME. Otherwise it's is used as regular HTML. | ||
189 | - # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME. | ||
190 | - # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The | ||
191 | - # block can then use <tt>render</tt>, <tt>link_to</tt>, etc. | ||
192 | - # | ||
193 | - # The method can also return <tt>nil</tt>, which means "no content". | ||
194 | - # | ||
195 | - # See BoxesHelper#extract_block_content for implementation details. | ||
196 | - def content(args={}) | ||
197 | - "This is block number %d" % self.id | ||
198 | - end | ||
199 | - | ||
200 | - # A footer to be appended to the end of the block. Returns <tt>nil</tt>. | ||
201 | - # | ||
202 | - # Override in your subclasses. You can return the same types supported by | ||
203 | - # #content. | ||
204 | - def footer | ||
205 | - nil | ||
206 | - end | ||
207 | - | ||
208 | # Is this block editable? (Default to <tt>true</tt>) | 184 | # Is this block editable? (Default to <tt>true</tt>) |
209 | def editable?(user=nil) | 185 | def editable?(user=nil) |
210 | self.edit_modes == "all" | 186 | self.edit_modes == "all" |
app/models/community.rb
app/models/enterprise.rb
@@ -12,7 +12,7 @@ class Enterprise < Organization | @@ -12,7 +12,7 @@ class Enterprise < Organization | ||
12 | _('Enterprise') | 12 | _('Enterprise') |
13 | end | 13 | end |
14 | 14 | ||
15 | - N_('Enterprise') | 15 | + N_('enterprise') |
16 | 16 | ||
17 | acts_as_trackable after_add: proc{ |p, t| notify_activity t } | 17 | acts_as_trackable after_add: proc{ |p, t| notify_activity t } |
18 | 18 |
app/models/environment.rb
@@ -750,6 +750,10 @@ class Environment < ApplicationRecord | @@ -750,6 +750,10 @@ class Environment < ApplicationRecord | ||
750 | end | 750 | end |
751 | end | 751 | end |
752 | 752 | ||
753 | + def theme_ids | ||
754 | + settings[:themes] || [] | ||
755 | + end | ||
756 | + | ||
753 | def themes=(values) | 757 | def themes=(values) |
754 | settings[:themes] = values | 758 | settings[:themes] = values |
755 | end | 759 | end |
app/models/link_list_block.rb
@@ -81,10 +81,8 @@ class LinkListBlock < Block | @@ -81,10 +81,8 @@ class LinkListBlock < Block | ||
81 | end | 81 | end |
82 | end | 82 | end |
83 | 83 | ||
84 | - def icons_options | ||
85 | - ICONS.map do |i| | ||
86 | - "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe | ||
87 | - end | 84 | + def icons |
85 | + ICONS | ||
88 | end | 86 | end |
89 | 87 | ||
90 | end | 88 | end |
app/models/person.rb
@@ -13,6 +13,8 @@ class Person < Profile | @@ -13,6 +13,8 @@ class Person < Profile | ||
13 | _('Person') | 13 | _('Person') |
14 | end | 14 | end |
15 | 15 | ||
16 | + N_('person') | ||
17 | + | ||
16 | acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)} | 18 | acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)} |
17 | acts_as_accessor | 19 | acts_as_accessor |
18 | 20 |
app/models/person_notifier.rb
@@ -82,7 +82,7 @@ class PersonNotifier | @@ -82,7 +82,7 @@ class PersonNotifier | ||
82 | helper ActionTrackerHelper | 82 | helper ActionTrackerHelper |
83 | 83 | ||
84 | def session | 84 | def session |
85 | - {:theme => nil} | 85 | + {:user_theme => nil} |
86 | end | 86 | end |
87 | 87 | ||
88 | def content_summary(person, notifications, tasks) | 88 | def content_summary(person, notifications, tasks) |
app/models/profile.rb
@@ -1145,6 +1145,11 @@ private :generate_url, :url_options | @@ -1145,6 +1145,11 @@ private :generate_url, :url_options | ||
1145 | self.data[:fields_privacy] | 1145 | self.data[:fields_privacy] |
1146 | end | 1146 | end |
1147 | 1147 | ||
1148 | + # abstract | ||
1149 | + def active_fields | ||
1150 | + [] | ||
1151 | + end | ||
1152 | + | ||
1148 | def public_fields | 1153 | def public_fields |
1149 | self.active_fields | 1154 | self.active_fields |
1150 | end | 1155 | end |
app/models/recent_documents_block.rb
@@ -31,7 +31,7 @@ class RecentDocumentsBlock < Block | @@ -31,7 +31,7 @@ class RecentDocumentsBlock < Block | ||
31 | end | 31 | end |
32 | 32 | ||
33 | def api_content | 33 | def api_content |
34 | - Noosfero::API::Entities::ArticleBase.represent(docs).as_json | 34 | + Api::Entities::ArticleBase.represent(docs).as_json |
35 | end | 35 | end |
36 | 36 | ||
37 | def display_api_content_by_default? | 37 | def display_api_content_by_default? |
app/views/account/_login_form.html.erb
@@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
11 | <%= hidden_field_tag :terms_accepted, params[:terms_accepted] %> | 11 | <%= hidden_field_tag :terms_accepted, params[:terms_accepted] %> |
12 | <% end %> | 12 | <% end %> |
13 | 13 | ||
14 | -<% button_bar do %> | 14 | +<%= button_bar do %> |
15 | <%= submit_button( 'login', _('Log in') )%> | 15 | <%= submit_button( 'login', _('Log in') )%> |
16 | <%= modal_close_button _('Cancel') if request.xhr? %> | 16 | <%= modal_close_button _('Cancel') if request.xhr? %> |
17 | <% end %> | 17 | <% end %> |
app/views/account/accept_terms.html.erb
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <%= hidden_field_tag :answer, params[:answer] %> | 20 | <%= hidden_field_tag :answer, params[:answer] %> |
21 | 21 | ||
22 | <%= labelled_check_box(environment.terms_of_use_acceptance_text.blank? ? _('I read the terms of use and accepted them') : environment.terms_of_use_acceptance_text, :terms_accepted, '1', false, :id => 'accept-terms') %> | 22 | <%= labelled_check_box(environment.terms_of_use_acceptance_text.blank? ? _('I read the terms of use and accepted them') : environment.terms_of_use_acceptance_text, :terms_accepted, '1', false, :id => 'accept-terms') %> |
23 | - <% button_bar do %> | 23 | + <%= button_bar do %> |
24 | <%= button 'cancel', _('Cancel'), :controller => 'home', :action => 'index' %> | 24 | <%= button 'cancel', _('Cancel'), :controller => 'home', :action => 'index' %> |
25 | <%= submit_button 'forward', _('Continue'), {:disabled => true, :class => 'disabled', :id => 'submit-accept-terms'} %> | 25 | <%= submit_button 'forward', _('Continue'), {:disabled => true, :class => 'disabled', :id => 'submit-accept-terms'} %> |
26 | <% end %> | 26 | <% end %> |
app/views/account/activation_question.html.erb
@@ -24,7 +24,7 @@ | @@ -24,7 +24,7 @@ | ||
24 | 24 | ||
25 | <div class='activation-box'> | 25 | <div class='activation-box'> |
26 | <h2><%= _('Enterprise activation') + ' - ' + (logged_in? ? _('part 1 of 2') : _('part 1 of 3')) %></h2> | 26 | <h2><%= _('Enterprise activation') + ' - ' + (logged_in? ? _('part 1 of 2') : _('part 1 of 3')) %></h2> |
27 | - <%= form_tag( {:action => 'accept_terms'}, {:method => 'get', :onsubmit => (@question == :foundation_year ? 'return check_valid_year(this)' : 'return check_valid_cnpj(this)')}) do %> | 27 | + <%= form_tag( {:action => 'accept_terms'}, {:method => 'get', :onsubmit => (@question == :foundation_year ? 'return check_valid_year(this)' : 'return check_valid_cnpj(this)')}) do %> |
28 | 28 | ||
29 | <p> <strong><%= _('Pay atention! You have only one chance!') %></strong> </p> | 29 | <p> <strong><%= _('Pay atention! You have only one chance!') %></strong> </p> |
30 | 30 | ||
@@ -34,7 +34,7 @@ | @@ -34,7 +34,7 @@ | ||
34 | 34 | ||
35 | <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %> | 35 | <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %> |
36 | 36 | ||
37 | - <% button_bar do %> | 37 | + <%= button_bar do %> |
38 | <%= button 'cancel', _('Cancel'), :action => 'index' %> | 38 | <%= button 'cancel', _('Cancel'), :action => 'index' %> |
39 | <%= submit_button 'forward', _('Continue') %> | 39 | <%= submit_button 'forward', _('Continue') %> |
40 | <% end %> | 40 | <% end %> |
app/views/account/forgot_password.html.erb
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> | 9 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> |
10 | 10 | ||
11 | <div> | 11 | <div> |
12 | - <% button_bar do %> | 12 | + <%= button_bar do %> |
13 | <%= submit_button('send', _('Send instructions')) %> | 13 | <%= submit_button('send', _('Send instructions')) %> |
14 | <% end %> | 14 | <% end %> |
15 | </div> | 15 | </div> |
app/views/account/login.html.erb
@@ -22,7 +22,7 @@ | @@ -22,7 +22,7 @@ | ||
22 | 22 | ||
23 | <%= safe_join(@plugins.dispatch(:login_extra_contents).collect { |content| instance_exec(&content) }, "") %> | 23 | <%= safe_join(@plugins.dispatch(:login_extra_contents).collect { |content| instance_exec(&content) }, "") %> |
24 | 24 | ||
25 | - <% button_bar do %> | 25 | + <%= button_bar do %> |
26 | <%= submit_button( 'login', _('Log in') )%> | 26 | <%= submit_button( 'login', _('Log in') )%> |
27 | <% if is_popin %> | 27 | <% if is_popin %> |
28 | <%= modal_close_button(_('Cancel')) %> | 28 | <%= modal_close_button(_('Cancel')) %> |
@@ -31,7 +31,7 @@ | @@ -31,7 +31,7 @@ | ||
31 | 31 | ||
32 | <% end %> | 32 | <% end %> |
33 | 33 | ||
34 | -<% button_bar do %> | 34 | +<%= button_bar do %> |
35 | <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> | 35 | <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> |
36 | <%= button :add, _("New user"), :controller => 'account', :action => 'signup' %> | 36 | <%= button :add, _("New user"), :controller => 'account', :action => 'signup' %> |
37 | <% end %> | 37 | <% end %> |
app/views/account/login_block.html.erb
@@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
17 | 17 | ||
18 | <%= safe_join(@plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }, "") %> | 18 | <%= safe_join(@plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }, "") %> |
19 | 19 | ||
20 | - <% button_bar do %> | 20 | + <%= button_bar do %> |
21 | <%= submit_button( 'login', _('Log in') )%> | 21 | <%= submit_button( 'login', _('Log in') )%> |
22 | <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> | 22 | <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> |
23 | <%= button(:add, _('New user'), { :controller => 'account', :action => 'signup' }) %> | 23 | <%= button(:add, _('New user'), { :controller => 'account', :action => 'signup' }) %> |
app/views/account/logout_popup.html.erb
1 | <h2><%= _('Are you sure you want to get out?') %></h2> | 1 | <h2><%= _('Are you sure you want to get out?') %></h2> |
2 | <p> | 2 | <p> |
3 | -<% button_bar do %> | 3 | +<%= button_bar do %> |
4 | <%= button :ok, _('Yes'), { :controller => 'account', :action => 'logout' } %> | 4 | <%= button :ok, _('Yes'), { :controller => 'account', :action => 'logout' } %> |
5 | <%= modal_close_button _('No, I want to stay.') %> | 5 | <%= modal_close_button _('No, I want to stay.') %> |
6 | <% end %> | 6 | <% end %> |
app/views/account/new_password.html.erb
@@ -10,7 +10,7 @@ | @@ -10,7 +10,7 @@ | ||
10 | 10 | ||
11 | <%= labelled_form_field(_('Enter new password'), (f.password_field :password)) %> | 11 | <%= labelled_form_field(_('Enter new password'), (f.password_field :password)) %> |
12 | <%= labelled_form_field(_('Confirm the new password'), (f.password_field :password_confirmation)) %> | 12 | <%= labelled_form_field(_('Confirm the new password'), (f.password_field :password_confirmation)) %> |
13 | - <% button_bar do %> | 13 | + <%= button_bar do %> |
14 | <%= submit_button(:ok, _('Change password')) %> | 14 | <%= submit_button(:ok, _('Change password')) %> |
15 | <% end %> | 15 | <% end %> |
16 | 16 |
app/views/account/welcome.html.erb
@@ -3,8 +3,8 @@ | @@ -3,8 +3,8 @@ | ||
3 | 3 | ||
4 | <%= _('%s was successfuly activated. Now you may go to your control panel or to the control panel of your enterprise') % @enterprise.name %> | 4 | <%= _('%s was successfuly activated. Now you may go to your control panel or to the control panel of your enterprise') % @enterprise.name %> |
5 | 5 | ||
6 | - <% button_bar do %> | ||
7 | - <%= button 'forward', _('Go to my control panel'), :action => 'index', :controller => 'profile_editor', :profile => current_user.person.identifier %> | 6 | + <%= button_bar do %> |
7 | + <%= button 'forward', _('Go to my control panel'), :action => 'index', :controller => 'profile_editor', :profile => current_user.person.identifier %> | ||
8 | <%= button 'forward', _('Go to my enterprise control panel') % @enterprise.name, :action => 'index', :controller => 'profile_editor', :profile => @enterprise.identifier %> | 8 | <%= button 'forward', _('Go to my enterprise control panel') % @enterprise.name, :action => 'index', :controller => 'profile_editor', :profile => @enterprise.identifier %> |
9 | <% end %> | 9 | <% end %> |
10 | <% end %> | 10 | <% end %> |
app/views/admin_panel/message_for_disabled_enterprise.html.erb
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | 6 | ||
7 | <%= f.text_area :message_for_disabled_enterprise, :cols => 40, :style => 'width: 90%' %> | 7 | <%= f.text_area :message_for_disabled_enterprise, :cols => 40, :style => 'width: 90%' %> |
8 | 8 | ||
9 | - <% button_bar do %> | 9 | + <%= button_bar do %> |
10 | <%= submit_button(:save, _('Save')) %> | 10 | <%= submit_button(:save, _('Save')) %> |
11 | <%= button(:cancel, _('Cancel'), :action => 'index') %> | 11 | <%= button(:cancel, _('Cancel'), :action => 'index') %> |
12 | <% end %> | 12 | <% end %> |
app/views/admin_panel/set_portal_community.html.erb
@@ -4,14 +4,14 @@ | @@ -4,14 +4,14 @@ | ||
4 | <%= form_tag do %> | 4 | <%= form_tag do %> |
5 | <%= labelled_form_field(_('Portal identifier'), text_field_tag('portal_community_identifier', @portal_community.identifier, :size => 40) ) %> | 5 | <%= labelled_form_field(_('Portal identifier'), text_field_tag('portal_community_identifier', @portal_community.identifier, :size => 40) ) %> |
6 | 6 | ||
7 | - <% button_bar do %> | 7 | + <%= button_bar do %> |
8 | <%= submit_button 'save', _('Save'), :cancel => { :action => 'index' } %> | 8 | <%= submit_button 'save', _('Save'), :cancel => { :action => 'index' } %> |
9 | <% end %> | 9 | <% end %> |
10 | <% end %> | 10 | <% end %> |
11 | <% else %> | 11 | <% else %> |
12 | - <%= _('Portal identifier: %s') % link_to(@portal_community.identifier, @portal_community.url) %> | 12 | + <%= _('Portal identifier: %s').html_safe % link_to(@portal_community.identifier, @portal_community.url) %> |
13 | 13 | ||
14 | - <% button_bar do %> | 14 | + <%= button_bar do %> |
15 | <%if @portal_community.environment.enabled?('use_portal_community') %> | 15 | <%if @portal_community.environment.enabled?('use_portal_community') %> |
16 | <%= button 'cancel', _('Disable'), {:action => 'manage_portal_community', :activate => 0} %> | 16 | <%= button 'cancel', _('Disable'), {:action => 'manage_portal_community', :activate => 0} %> |
17 | <% else %> | 17 | <% else %> |
app/views/admin_panel/set_portal_folders.html.erb
@@ -37,7 +37,7 @@ | @@ -37,7 +37,7 @@ | ||
37 | <%= _('The same order in which you arrange the folders here will be used for arranging the boxes in the environment initial page.') %> | 37 | <%= _('The same order in which you arrange the folders here will be used for arranging the boxes in the environment initial page.') %> |
38 | </p> | 38 | </p> |
39 | 39 | ||
40 | - <% button_bar do %> | 40 | + <%= button_bar do %> |
41 | <%= submit_button 'save', _('Save'), :cancel => {:action => 'index'} %> | 41 | <%= submit_button 'save', _('Save'), :cancel => {:action => 'index'} %> |
42 | <% end %> | 42 | <% end %> |
43 | <% end %> | 43 | <% end %> |
app/views/admin_panel/set_portal_news_amount.html.erb
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | <%= labelled_form_field _('Number of portal news'), select(:environment, :portal_news_amount, (0..10).to_a) %> | 6 | <%= labelled_form_field _('Number of portal news'), select(:environment, :portal_news_amount, (0..10).to_a) %> |
7 | <%= labelled_form_field _('Number of news by folder'), select(:environment, :news_amount_by_folder, (1..10).to_a) %> | 7 | <%= labelled_form_field _('Number of news by folder'), select(:environment, :news_amount_by_folder, (1..10).to_a) %> |
8 | 8 | ||
9 | - <% button_bar do %> | 9 | + <%= button_bar do %> |
10 | <%= submit_button(:save, _('Save')) %> | 10 | <%= submit_button(:save, _('Save')) %> |
11 | <%= button(:cancel, _('Cancel'), :action => 'index') %> | 11 | <%= button(:cancel, _('Cancel'), :action => 'index') %> |
12 | <% end %> | 12 | <% end %> |
app/views/admin_panel/site_info.html.erb
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <% tabs << {:title => _('Signup introduction text'), :id => 'signup-intro', | 20 | <% tabs << {:title => _('Signup introduction text'), :id => 'signup-intro', |
21 | :content => (render :partial => 'signup_intro', :locals => {:f => f})} %> | 21 | :content => (render :partial => 'signup_intro', :locals => {:f => f})} %> |
22 | <%= render_tabs(tabs) %> | 22 | <%= render_tabs(tabs) %> |
23 | - <% button_bar do %> | 23 | + <%= button_bar do %> |
24 | <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> | 24 | <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> |
25 | <% end %> | 25 | <% end %> |
26 | <% end %> | 26 | <% end %> |
app/views/api/playground.html.erb
1 | <h1>API Playground</h1> | 1 | <h1>API Playground</h1> |
2 | 2 | ||
3 | <script> | 3 | <script> |
4 | -<% prefix = Noosfero::API::API.prefix %> | 4 | +<% prefix = Api::App.prefix %> |
5 | var prefix = <%= prefix.to_json %>; | 5 | var prefix = <%= prefix.to_json %>; |
6 | var endpoints = <%= | 6 | var endpoints = <%= |
7 | endpoints.map do |endpoint| | 7 | endpoints.map do |endpoint| |
app/views/box_organizer/_icon_selector.html.erb
@@ -2,6 +2,8 @@ | @@ -2,6 +2,8 @@ | ||
2 | <%= hidden_field_tag 'block[links][][icon]', icon %> | 2 | <%= hidden_field_tag 'block[links][][icon]', icon %> |
3 | <span class='icon-<%= icon %>' style='display:block; width:16px; height:16px;'></span> | 3 | <span class='icon-<%= icon %>' style='display:block; width:16px; height:16px;'></span> |
4 | <div class="icon-selector" style='display:none;'> | 4 | <div class="icon-selector" style='display:none;'> |
5 | - <%= @block.icons_options.join %> | 5 | + <% @block.icons.map do |i| %> |
6 | + <%= content_tag('span', '', :title => i[1], :class => "icon-#{i[0]}", :onclick => "changeIcon(this, '#{i[0]}')") %> | ||
7 | + <% end %> | ||
6 | </div> | 8 | </div> |
7 | </div> | 9 | </div> |
app/views/box_organizer/edit.html.erb
@@ -35,7 +35,7 @@ | @@ -35,7 +35,7 @@ | ||
35 | </div> | 35 | </div> |
36 | <% end %> | 36 | <% end %> |
37 | 37 | ||
38 | - <% button_bar do %> | 38 | + <%= button_bar do %> |
39 | <%= submit_button(:save, _('Save')) %> | 39 | <%= submit_button(:save, _('Save')) %> |
40 | <%= modal_close_button(_('Cancel')) %> | 40 | <%= modal_close_button(_('Cancel')) %> |
41 | <% end %> | 41 | <% end %> |
app/views/box_organizer/index.html.erb
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | 3 | ||
4 | <h1><%= _('Editing sideboxes')%></h1> | 4 | <h1><%= _('Editing sideboxes')%></h1> |
5 | 5 | ||
6 | -<% button_bar :class=>'design-menu' do %> | 6 | +<%= button_bar :class=>'design-menu' do %> |
7 | <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> | 7 | <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> |
8 | <% end %> | 8 | <% end %> |
9 | 9 |
app/views/categories/_form.html.erb
@@ -28,7 +28,7 @@ | @@ -28,7 +28,7 @@ | ||
28 | <%= file_field_or_thumbnail(_('Image:'), @category.image, i) %> | 28 | <%= file_field_or_thumbnail(_('Image:'), @category.image, i) %> |
29 | <% end %> | 29 | <% end %> |
30 | 30 | ||
31 | - <% button_bar do %> | 31 | + <%= button_bar do %> |
32 | <%= submit_button('save', _('Save'), :cancel => {:action => 'index'}) %> | 32 | <%= submit_button('save', _('Save'), :cancel => {:action => 'index'}) %> |
33 | <% end%> | 33 | <% end%> |
34 | <% end %> | 34 | <% end %> |
app/views/cms/_media_new_folder.html.erb
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | <%= labelled_radio_button _('Folder'), :folder_type, 'Folder', false %> | 9 | <%= labelled_radio_button _('Folder'), :folder_type, 'Folder', false %> |
10 | 10 | ||
11 | <%= labelled_form_field _('Name:'), text_field_tag(:new_folder, nil, 'data-url' => url_for({:action => 'new', :profile => profile.identifier})) %> | 11 | <%= labelled_form_field _('Name:'), text_field_tag(:new_folder, nil, 'data-url' => url_for({:action => 'new', :profile => profile.identifier})) %> |
12 | - <% button_bar do %> | 12 | + <%= button_bar do %> |
13 | <%= submit_button(:newfolder, _('Create')) %> | 13 | <%= submit_button(:newfolder, _('Create')) %> |
14 | <% end %> | 14 | <% end %> |
15 | <% end %> | 15 | <% end %> |
app/views/cms/_text_fields.html.erb
1 | -<%= labelled_form_field(_('Publish date'), date_field('article[published_at]', @article.published_at || DateTime.current, {:max_date => '+0d', :date_format => 'yy-mm-dd'}, {:id => "article_published_at"})) %> | 1 | +<%= labelled_form_field(_('Publish date'), date_field('article[published_at]', @article.published_at || DateTime.current, {:max_date => '+0d', :time => true}, {:id => "article_published_at"})) %> |
app/views/cms/_upload_file_form.html.erb
@@ -12,7 +12,7 @@ | @@ -12,7 +12,7 @@ | ||
12 | 12 | ||
13 | <%= hidden_field_tag('back_to', @back_to) %> | 13 | <%= hidden_field_tag('back_to', @back_to) %> |
14 | 14 | ||
15 | -<% button_bar do %> | 15 | +<%= button_bar do %> |
16 | <%= button_to_function :add, _('More files'), "add_new_file_fields()" %> | 16 | <%= button_to_function :add, _('More files'), "add_new_file_fields()" %> |
17 | <% if @back_to %> | 17 | <% if @back_to %> |
18 | <%= submit_button :save, _('Upload'), :cancel => @back_to %> | 18 | <%= submit_button :save, _('Upload'), :cancel => @back_to %> |
app/views/cms/destroy.html.erb
@@ -12,7 +12,7 @@ | @@ -12,7 +12,7 @@ | ||
12 | <% end %> | 12 | <% end %> |
13 | </strong> | 13 | </strong> |
14 | 14 | ||
15 | - <% button_bar do %> | 15 | + <%= button_bar do %> |
16 | <%= submit_button :save, _('Yes, I want.') %> | 16 | <%= submit_button :save, _('Yes, I want.') %> |
17 | <%= button :cancel, _("No, I don't want."), @article.url %> | 17 | <%= button :cancel, _("No, I don't want."), @article.url %> |
18 | <% end %> | 18 | <% end %> |
app/views/cms/edit.html.erb
@@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
21 | </div> | 21 | </div> |
22 | <% end %> | 22 | <% end %> |
23 | 23 | ||
24 | - <% button_bar do %> | 24 | + <%= button_bar do %> |
25 | <%= submit_button :save, _('Save') %> | 25 | <%= submit_button :save, _('Save') %> |
26 | <%= submit_button :save, _('Save and continue'), :name => "continue" %> | 26 | <%= submit_button :save, _('Save and continue'), :name => "continue" %> |
27 | <% end %> | 27 | <% end %> |
@@ -48,7 +48,7 @@ | @@ -48,7 +48,7 @@ | ||
48 | <%= options_for_article(@article, @tokenized_children) %> | 48 | <%= options_for_article(@article, @tokenized_children) %> |
49 | </div> | 49 | </div> |
50 | 50 | ||
51 | - <% button_bar do %> | 51 | + <%= button_bar do %> |
52 | <%= submit_button :save, _('Save') %> | 52 | <%= submit_button :save, _('Save') %> |
53 | 53 | ||
54 | <% if @back_to %> | 54 | <% if @back_to %> |
app/views/cms/publish.html.erb
@@ -25,7 +25,7 @@ | @@ -25,7 +25,7 @@ | ||
25 | <%= hidden_field_tag :back_to, @back_to %> | 25 | <%= hidden_field_tag :back_to, @back_to %> |
26 | <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> | 26 | <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> |
27 | 27 | ||
28 | - <% button_bar do %> | 28 | + <%= button_bar do %> |
29 | <%= submit_button 'spread', _('Spread this') %> | 29 | <%= submit_button 'spread', _('Spread this') %> |
30 | <% end %> | 30 | <% end %> |
31 | <% end %> | 31 | <% end %> |
@@ -41,7 +41,7 @@ | @@ -41,7 +41,7 @@ | ||
41 | <% search_action = url_for(:action => 'search_communities_to_publish') %> | 41 | <% search_action = url_for(:action => 'search_communities_to_publish') %> |
42 | <%= token_input_field_tag(:q, 'search-communities-to-publish', search_action, { :hint_text => _('Type in a search for your community'), :zindex => 10000, :focus => false }) %> | 42 | <%= token_input_field_tag(:q, 'search-communities-to-publish', search_action, { :hint_text => _('Type in a search for your community'), :zindex => 10000, :focus => false }) %> |
43 | <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> | 43 | <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> |
44 | - <% button_bar do %> | 44 | + <%= button_bar do %> |
45 | <%= submit_button 'spread', _('Spread this') %> | 45 | <%= submit_button 'spread', _('Spread this') %> |
46 | <% end %> | 46 | <% end %> |
47 | <% end %> | 47 | <% end %> |
@@ -58,7 +58,7 @@ | @@ -58,7 +58,7 @@ | ||
58 | <%= hidden_field_tag :back_to, @back_to %> | 58 | <%= hidden_field_tag :back_to, @back_to %> |
59 | <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> | 59 | <%= labelled_form_field _('Title'), text_field_tag('name', @article.name) %> |
60 | 60 | ||
61 | - <% button_bar do %> | 61 | + <%= button_bar do %> |
62 | <%= submit_button 'spread', _('Spread this') %> | 62 | <%= submit_button 'spread', _('Spread this') %> |
63 | <% end %> | 63 | <% end %> |
64 | <% end %> | 64 | <% end %> |
app/views/cms/publish_on_portal_community.html.erb
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | <%= hidden_field_tag :back_to, @back_to %> | 5 | <%= hidden_field_tag :back_to, @back_to %> |
6 | <%= labelled_text_field _('Title') + ': ', :name, @article.name, :style => 'width: 100%' %> | 6 | <%= labelled_text_field _('Title') + ': ', :name, @article.name, :style => 'width: 100%' %> |
7 | 7 | ||
8 | - <% button_bar do %> | 8 | + <%= button_bar do %> |
9 | <%= submit_button 'spread', _('Spread this'), :cancel => @back_to %> | 9 | <%= submit_button 'spread', _('Spread this'), :cancel => @back_to %> |
10 | <% end %> | 10 | <% end %> |
11 | <% end %> | 11 | <% end %> |
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | <%= _("There is no portal community in this environment.") %> | 14 | <%= _("There is no portal community in this environment.") %> |
15 | </div> | 15 | </div> |
16 | 16 | ||
17 | - <% button_bar do %> | 17 | + <%= button_bar do %> |
18 | <%= button :back, _('Back'), :controller => 'cms' %> | 18 | <%= button :back, _('Back'), :controller => 'cms' %> |
19 | <% end %> | 19 | <% end %> |
20 | <% end %> | 20 | <% end %> |
app/views/cms/suggest_an_article.html.erb
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | 23 | ||
24 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %> | 24 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %> |
25 | 25 | ||
26 | - <% button_bar do %> | 26 | + <%= button_bar do %> |
27 | <%= submit_button :save, _('Save') %> | 27 | <%= submit_button :save, _('Save') %> |
28 | <%= button :cancel, _('Cancel'), @back_to %> | 28 | <%= button :cancel, _('Cancel'), @back_to %> |
29 | <% end %> | 29 | <% end %> |
app/views/cms/view.html.erb
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | </div> | 14 | </div> |
15 | <% end %> | 15 | <% end %> |
16 | 16 | ||
17 | -<% button_bar(:style => 'margin-bottom: 1em;') do %> | 17 | +<%= button_bar(:style => 'margin-bottom: 1em;') do %> |
18 | <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> | 18 | <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> |
19 | 19 | ||
20 | <%= modal_button('new', _('New content'), url_for({:action => 'new', :parent_id => parent_id, :cms => true}).html_safe) %> | 20 | <%= modal_button('new', _('New content'), url_for({:action => 'new', :parent_id => parent_id, :cms => true}).html_safe) %> |
app/views/cms/why_categorize.html.erb
@@ -4,6 +4,6 @@ | @@ -4,6 +4,6 @@ | ||
4 | <%= _('By categorizing your content, you increase the possibility that other people access it. When they are looking for, say, articles about Bahia and you categorize your article in "Regions/Bahia", then there is a good change that your article is going to be found.') %> | 4 | <%= _('By categorizing your content, you increase the possibility that other people access it. When they are looking for, say, articles about Bahia and you categorize your article in "Regions/Bahia", then there is a good change that your article is going to be found.') %> |
5 | </p> | 5 | </p> |
6 | 6 | ||
7 | -<% button_bar do %> | 7 | +<%= button_bar do %> |
8 | <%= modal_close_button _('Close') %> | 8 | <%= modal_close_button _('Close') %> |
9 | <% end %> | 9 | <% end %> |
app/views/comment/_comment_form.html.erb
@@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
8 | <div id="recaptcha-container" style="display: none"> | 8 | <div id="recaptcha-container" style="display: none"> |
9 | <h3><%= _('Please type the two words below') %></h3> | 9 | <h3><%= _('Please type the two words below') %></h3> |
10 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> | 10 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> |
11 | - <% button_bar do %> | 11 | + <%= button_bar do %> |
12 | <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> | 12 | <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> |
13 | <%= button_to_function :cancel, _('Cancel'), "noosfero.modal.close()" %> | 13 | <%= button_to_function :cancel, _('Cancel'), "noosfero.modal.close()" %> |
14 | <% end %> | 14 | <% end %> |
@@ -87,7 +87,7 @@ function check_captcha(button, confirm_action) { | @@ -87,7 +87,7 @@ function check_captcha(button, confirm_action) { | ||
87 | 87 | ||
88 | <%= safe_join(@plugins.dispatch(:comment_form_extra_contents, local_assigns.merge(:comment => @comment)).collect { |content| instance_exec(&content) }, "") %> | 88 | <%= safe_join(@plugins.dispatch(:comment_form_extra_contents, local_assigns.merge(:comment => @comment)).collect { |content| instance_exec(&content) }, "") %> |
89 | 89 | ||
90 | - <% button_bar do %> | 90 | + <%= button_bar do %> |
91 | <%= submit_button('add', _('Post comment'), :onclick => "if(check_captcha(this)) { save_comment(this) } else { check_captcha(this, save_comment)};return false;") %> | 91 | <%= submit_button('add', _('Post comment'), :onclick => "if(check_captcha(this)) { save_comment(this) } else { check_captcha(this, save_comment)};return false;") %> |
92 | <% if !edition_mode %> | 92 | <% if !edition_mode %> |
93 | <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> | 93 | <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> |
app/views/content_viewer/_comment_form.html.erb
@@ -36,7 +36,7 @@ function submit_comment_form(button) { | @@ -36,7 +36,7 @@ function submit_comment_form(button) { | ||
36 | <div id="recaptcha-container" style="display: none"> | 36 | <div id="recaptcha-container" style="display: none"> |
37 | <h3><%= _('Please type the two words below') %></h3> | 37 | <h3><%= _('Please type the two words below') %></h3> |
38 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> | 38 | <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> |
39 | - <% button_bar do %> | 39 | + <%= button_bar do %> |
40 | <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> | 40 | <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> |
41 | <%= button_to_function :cancel, _('Cancel'), "noosfero.modal.close()" %> | 41 | <%= button_to_function :cancel, _('Cancel'), "noosfero.modal.close()" %> |
42 | <% end %> | 42 | <% end %> |
@@ -73,7 +73,7 @@ function submit_comment_form(button) { | @@ -73,7 +73,7 @@ function submit_comment_form(button) { | ||
73 | <%= hidden_field_tag(:confirm, 'false') %> | 73 | <%= hidden_field_tag(:confirm, 'false') %> |
74 | <%= hidden_field_tag(:view, params[:view])%> | 74 | <%= hidden_field_tag(:view, params[:view])%> |
75 | 75 | ||
76 | - <% button_bar do %> | 76 | + <%= button_bar do %> |
77 | <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %> | 77 | <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %> |
78 | <% if cancel_triggers_hide %> | 78 | <% if cancel_triggers_hide %> |
79 | <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> | 79 | <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> |
app/views/content_viewer/_confirm_unfollow.html.erb
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | <%= form_tag(@page.view_url.merge({:only_path => true}), {:method => 'post', :class => 'comment_form'}) do %> | 5 | <%= form_tag(@page.view_url.merge({:only_path => true}), {:method => 'post', :class => 'comment_form'}) do %> |
6 | <%= hidden_field_tag(:unfollow, 'commit') %> | 6 | <%= hidden_field_tag(:unfollow, 'commit') %> |
7 | <%= labelled_form_field(_('Enter your e-Mail'), text_field_tag(:email, nil, {:size => 40})) %> | 7 | <%= labelled_form_field(_('Enter your e-Mail'), text_field_tag(:email, nil, {:size => 40})) %> |
8 | - <% button_bar do %> | 8 | + <%= button_bar do %> |
9 | <%= submit_button(:ok, _('Cancel notifications for e-mail above') ) %> | 9 | <%= submit_button(:ok, _('Cancel notifications for e-mail above') ) %> |
10 | <% end %> | 10 | <% end %> |
11 | <% end %> | 11 | <% end %> |
app/views/content_viewer/blog_page.html.erb
app/views/content_viewer/forum_page.html.erb
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | <p><%= @page.terms_of_use %></p> | 16 | <p><%= @page.terms_of_use %></p> |
17 | 17 | ||
18 | <%= form_tag @page.url.merge(:terms_accepted => true) do %> | 18 | <%= form_tag @page.url.merge(:terms_accepted => true) do %> |
19 | - <% button_bar do %> | 19 | + <%= button_bar do %> |
20 | <% if user %> | 20 | <% if user %> |
21 | <%= submit_button :save, _("Accept") %> | 21 | <%= submit_button :save, _("Accept") %> |
22 | <% else %> | 22 | <% else %> |
app/views/enterprise_registration/basic_information.html.erb
@@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
8 | <%= _('There are no validators to validate the registration of this new enterprise. Contact your administrator for instructions.') %> | 8 | <%= _('There are no validators to validate the registration of this new enterprise. Contact your administrator for instructions.') %> |
9 | </div> | 9 | </div> |
10 | 10 | ||
11 | - <% button_bar do %> | 11 | + <%= button_bar do %> |
12 | <%= button :back, _('Go back'), { :profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile" }%> | 12 | <%= button :back, _('Go back'), { :profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile" }%> |
13 | <% end %> | 13 | <% end %> |
14 | <% else %> | 14 | <% else %> |
@@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
36 | 36 | ||
37 | <%= template_options(:enterprises, 'create_enterprise')%> | 37 | <%= template_options(:enterprises, 'create_enterprise')%> |
38 | 38 | ||
39 | - <% button_bar do %> | 39 | + <%= button_bar do %> |
40 | <%= submit_button('next', _('Next'), :cancel => {:profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile"}) %> | 40 | <%= submit_button('next', _('Next'), :cancel => {:profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile"}) %> |
41 | <% end %> | 41 | <% end %> |
42 | <% end %> | 42 | <% end %> |
app/views/enterprise_registration/creation.html.erb
@@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
4 | 4 | ||
5 | <%= render :partial => 'shared/template_welcome_page', :locals => {:template => @enterprise.template, :header => _("What can I do with a %s?")} %> | 5 | <%= render :partial => 'shared/template_welcome_page', :locals => {:template => @enterprise.template, :header => _("What can I do with a %s?")} %> |
6 | 6 | ||
7 | -<% button_bar do %> | 7 | +<%= button_bar do %> |
8 | <%= button :back, _('Back'), {:controller => 'memberships', :action => 'index', :profile => user.identifier} %> | 8 | <%= button :back, _('Back'), {:controller => 'memberships', :action => 'index', :profile => user.identifier} %> |
9 | <% end %> | 9 | <% end %> |
10 | 10 |
app/views/enterprise_registration/select_validator.html.erb
app/views/enterprise_validation/details.html.erb
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | <p><%= _('If this enterprise passes the criteria to be considered an solidarity enconomy enterprise, you can approve it by click the button below.') %></p> | 15 | <p><%= _('If this enterprise passes the criteria to be considered an solidarity enconomy enterprise, you can approve it by click the button below.') %></p> |
16 | 16 | ||
17 | <%= form_tag :action => 'approve', :id => @pending.code do %> | 17 | <%= form_tag :action => 'approve', :id => @pending.code do %> |
18 | - <% button_bar do %> | 18 | + <%= button_bar do %> |
19 | <%= submit_button('approve', _('Approve')) %> | 19 | <%= submit_button('approve', _('Approve')) %> |
20 | <% end %> | 20 | <% end %> |
21 | <% end %> | 21 | <% end %> |
@@ -27,7 +27,7 @@ | @@ -27,7 +27,7 @@ | ||
27 | <%= form_tag :action => 'reject', :id => @pending.code do %> | 27 | <%= form_tag :action => 'reject', :id => @pending.code do %> |
28 | <%= labelled_form_field(_('Please provide an explanation for the rejection. This explanation will be sent to the requestor (required).'), text_area_tag('reject_explanation'))%> | 28 | <%= labelled_form_field(_('Please provide an explanation for the rejection. This explanation will be sent to the requestor (required).'), text_area_tag('reject_explanation'))%> |
29 | <div> | 29 | <div> |
30 | - <% button_bar do %> | 30 | + <%= button_bar do %> |
31 | <%= submit_button('reject', _('Reject')) %> | 31 | <%= submit_button('reject', _('Reject')) %> |
32 | <% end %> | 32 | <% end %> |
33 | </div> | 33 | </div> |
app/views/enterprise_validation/edit_validation_info.html.erb
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | <%= labelled_form_for :info do |f| %> | 5 | <%= labelled_form_for :info do |f| %> |
6 | <%= f.text_area(:validation_methodology, :cols => 50, :rows => 10) %> | 6 | <%= f.text_area(:validation_methodology, :cols => 50, :rows => 10) %> |
7 | <%= f.text_area(:restrictions, :cols => 50, :rows => 7) %> | 7 | <%= f.text_area(:restrictions, :cols => 50, :rows => 7) %> |
8 | - <% button_bar do %> | 8 | + <%= button_bar do %> |
9 | <%= submit_button('save', _('Save'), :cancel => {:action => 'index'}) %> | 9 | <%= submit_button('save', _('Save'), :cancel => {:action => 'index'}) %> |
10 | <% end %> | 10 | <% end %> |
11 | <% end %> | 11 | <% end %> |
app/views/enterprise_validation/index.html.erb
1 | <h1><%= _('Enterprise validations') %></h1> | 1 | <h1><%= _('Enterprise validations') %></h1> |
2 | 2 | ||
3 | -<% button_bar do %> | 3 | +<%= button_bar do %> |
4 | <%= button(:edit, _('Edit validation info'), { :action => 'edit_validation_info' }) %> | 4 | <%= button(:edit, _('Edit validation info'), { :action => 'edit_validation_info' }) %> |
5 | <%= button(:back, _('Go Back'), { :controller => 'profile_editor' }) %> | 5 | <%= button(:back, _('Go Back'), { :controller => 'profile_editor' }) %> |
6 | <% end %> | 6 | <% end %> |
app/views/environment_role_manager/affiliate.html.erb
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | <%= form_tag( {:action => 'give_role'}, {:method => :post}) do %> | 3 | <%= form_tag( {:action => 'give_role'}, {:method => :post}) do %> |
4 | <%= select_tag 'role', options_for_select(@roles.map{|r|[r.name,r.id]}) %> | 4 | <%= select_tag 'role', options_for_select(@roles.map{|r|[r.name,r.id]}) %> |
5 | <%= hidden_field_tag 'person', current_user.person.id %> | 5 | <%= hidden_field_tag 'person', current_user.person.id %> |
6 | - <% button_bar do %> | 6 | + <%= button_bar do %> |
7 | <%= submit_button('affiliate', _('Affiliate', :cancel => {:action => 'index'}) %> | 7 | <%= submit_button('affiliate', _('Affiliate', :cancel => {:action => 'index'}) %> |
8 | <% end %> | 8 | <% end %> |
9 | <% end %> | 9 | <% end %> |
app/views/environment_role_manager/change_role.html.erb
@@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
7 | <% end %> | 7 | <% end %> |
8 | <%= hidden_field_tag 'person', @admin.id %> | 8 | <%= hidden_field_tag 'person', @admin.id %> |
9 | 9 | ||
10 | - <% button_bar do %> | 10 | + <%= button_bar do %> |
11 | <%= submit_button('save', _('Save changes'), :cancel => {:action => 'index'}) %> | 11 | <%= submit_button('save', _('Save changes'), :cancel => {:action => 'index'}) %> |
12 | <% end %> | 12 | <% end %> |
13 | <% end %> | 13 | <% end %> |
app/views/environment_role_manager/make_admin.html.erb
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | <% @roles.each do |r| %> | 9 | <% @roles.each do |r| %> |
10 | <%= labelled_form_field(r.name, (check_box_tag "roles[]", r.id)) %> | 10 | <%= labelled_form_field(r.name, (check_box_tag "roles[]", r.id)) %> |
11 | <% end %> | 11 | <% end %> |
12 | - <% button_bar do %> | 12 | + <%= button_bar do %> |
13 | <%= submit_button( 'save', _('Make'), :cancel => {:action => 'index'} ) %> | 13 | <%= submit_button( 'save', _('Make'), :cancel => {:action => 'index'} ) %> |
14 | <% end %> | 14 | <% end %> |
15 | <% end %> | 15 | <% end %> |
app/views/environment_themes/index.html.erb
@@ -3,6 +3,6 @@ | @@ -3,6 +3,6 @@ | ||
3 | 3 | ||
4 | <br style="clear:both" /> | 4 | <br style="clear:both" /> |
5 | 5 | ||
6 | -<% button_bar do %> | 6 | +<%= button_bar do %> |
7 | <%= button(:back, _('Back'), :controller => 'admin_panel', :action => 'index') %> | 7 | <%= button(:back, _('Back'), :controller => 'admin_panel', :action => 'index') %> |
8 | <% end %> | 8 | <% end %> |
app/views/favorite_enterprises/index.html.erb
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | </p> | 23 | </p> |
24 | <% end %> | 24 | <% end %> |
25 | 25 | ||
26 | -<% button_bar do %> | 26 | +<%= button_bar do %> |
27 | <%= button(:back, _('Go back'), :controller => 'profile_editor') %> | 27 | <%= button(:back, _('Go back'), :controller => 'profile_editor') %> |
28 | <% end %> | 28 | <% end %> |
29 | 29 |
app/views/features/_manage_community_fields.html.erb
@@ -55,7 +55,7 @@ | @@ -55,7 +55,7 @@ | ||
55 | </script> | 55 | </script> |
56 | 56 | ||
57 | <div> | 57 | <div> |
58 | - <% button_bar do %> | 58 | + <%= button_bar do %> |
59 | <%= submit_button('save', _('Save changes'), :id=>"save_community_fields") %> | 59 | <%= submit_button('save', _('Save changes'), :id=>"save_community_fields") %> |
60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> | 60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> |
61 | <% end %> | 61 | <% end %> |