diff options
author | Heiko Bernloehr <Heiko.Bernloehr@FreeIT.de> | 2017-03-07 11:59:22 +0100 |
---|---|---|
committer | Heiko Bernloehr <Heiko.Bernloehr@FreeIT.de> | 2017-03-07 11:59:22 +0100 |
commit | dbaaad343f4abd6ca7904f6dfd0165ac0207b20e (patch) | |
tree | 07de54ff3ddfee48b5161a68b85e7767fd7e9d4b /app | |
parent | c21d238a97502eb252756722084e73b3f264c0dd (diff) | |
download | ecs-dbaaad343f4abd6ca7904f6dfd0165ac0207b20e.tar.gz ecs-dbaaad343f4abd6ca7904f6dfd0165ac0207b20e.zip |
Initial controllers.
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/admin/communities_controller.rb | 98 | ||||
-rw-r--r-- | app/controllers/admin/helper.rb | 41 | ||||
-rw-r--r-- | app/controllers/admin/identities_controller.rb | 21 | ||||
-rw-r--r-- | app/controllers/admin/organizations_controller.rb | 75 | ||||
-rw-r--r-- | app/controllers/admin/participants_controller.rb | 176 | ||||
-rw-r--r-- | app/controllers/admin/ressources_controller.rb | 77 | ||||
-rw-r--r-- | app/controllers/application_controller.rb | 237 | ||||
-rw-r--r-- | app/controllers/config_controller_bak.rb | 34 | ||||
-rw-r--r-- | app/controllers/configs_controller.rb | 64 | ||||
-rw-r--r-- | app/controllers/events_controller.rb | 87 | ||||
-rw-r--r-- | app/controllers/memberships_controller.rb | 64 | ||||
-rw-r--r-- | app/controllers/messages_controller.rb | 288 | ||||
-rw-r--r-- | app/controllers/subparticipants_controller.rb | 122 |
13 files changed, 1381 insertions, 3 deletions
diff --git a/app/controllers/admin/communities_controller.rb b/app/controllers/admin/communities_controller.rb new file mode 100644 index 0000000..7c02725 --- /dev/null +++ b/app/controllers/admin/communities_controller.rb @@ -0,0 +1,98 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +class Admin::CommunitiesController < ApplicationController + + include Admin::Helper + + # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) + verify :method => [ :post, :put, :delete ], :only => [ :destroy, :create, :update, :destroy_participant ], + :add_flash => { :notice => "Failed to execute last action" }, + :redirect_to => :index_admin_communities_path + + def index + list + render :action => 'list' + end + + def list + @communities=Community.find(:all).uniq + end + + def show + @community = Community.find(params[:id]) + end + + def new + @community = Community.new + end + + def create + @community = Community.new(params[:community]) + if @community.save + flash[:notice] = 'Community was successfully created.' + redirect_to admin_community_path(@community) + else + render :action => 'new' + end + end + + def edit + @community = Community.find(params[:id]) + end + + def update + @community = Community.find(params[:id]) + if @community.update_attributes(params[:community]) + flash[:notice] = 'Community was successfully updated.' + redirect_to admin_community_path(@community) + else + render :action => 'edit' + end + end + + def destroy + Community.find(params[:id]).destroy + redirect_to admin_communities_path + end + + # lists all participants of the community + def index_participants + @community = Community.find(params[:id]) + @participants=Community.find(params[:id]).memberships.collect {|i| i.participant }.uniq.sort{|x,y| x.id <=> y.id } + end + + # lists all those participants which has not joined the community + def index_nonparticipants + index_participants + @participants=(Participant.find(:all) - @participants).sort{|x,y| x.id <=> y.id } + end + + # community releases a participant + def destroy_participant + destroy_membership(params[:id], params[:p_id]) + redirect_to admin_community_participants_path(:id=>params[:id]) + end + + # community invites a participant + def create_participant + create_membership(params[:id], params[:p_id]) + redirect_to index_admin_community_nonparticipants_path(:id=>params[:id]) + end + +end diff --git a/app/controllers/admin/helper.rb b/app/controllers/admin/helper.rb new file mode 100644 index 0000000..bd5516f --- /dev/null +++ b/app/controllers/admin/helper.rb @@ -0,0 +1,41 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +module Admin::Helper + + # defining a RouteSet + #rs=ActionController::Routing::Routes + + + # Participant leaves Community or Community releases Participant + def destroy_membership(community_id, participant_id) + membership=Membership.find_by_community_id_and_participant_id(community_id, participant_id) + if membership.destroy + flash[:notice] = "Participant \"#{Participant.find(participant_id).name}\" successfully left Community \"#{Community.find(community_id).name}\"." + else + flash[:notice] = "Participant \"#{Participant.find(participant_id).name}\" could not leave Community \"#{Community.find(community_id).name}\"." + end + end + + # Participant joins Community or Community invites Participant + def create_membership(community_id, participant_id) + Participant.find(participant_id).communities << Community.find(community_id) + flash[:notice] = "Participant \"#{Participant.find(participant_id).name}\" successfully joined Community \"#{Community.find(community_id).name}\"." + end + +end diff --git a/app/controllers/admin/identities_controller.rb b/app/controllers/admin/identities_controller.rb new file mode 100644 index 0000000..a4424bb --- /dev/null +++ b/app/controllers/admin/identities_controller.rb @@ -0,0 +1,21 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +class Admin::IdentitiesController < ApplicationController + +end diff --git a/app/controllers/admin/organizations_controller.rb b/app/controllers/admin/organizations_controller.rb new file mode 100644 index 0000000..d16d07d --- /dev/null +++ b/app/controllers/admin/organizations_controller.rb @@ -0,0 +1,75 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +class Admin::OrganizationsController < ApplicationController + + include Admin::Helper + + # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) + verify :method => [ :post, :put, :delete ], :only => [ :destroy, :create, :update ], + :add_flash => { :notice => "Failed to execute last action" }, + :redirect_to => :admin_organization_path + + def index + list + render :action => 'list' + end + + def list + @organizations=Organization.find(:all).uniq + end + + def show + @organization = Organization.find(params[:id]) + end + + def new + @organization = Organization.new + end + + def create + @organization = Organization.new(params[:organization]) + if @organization.save + flash[:notice] = 'Organization was successfully created.' + redirect_to :action => 'index' + else + render :action => 'new' + end + end + + def edit + @organization = Organization.find(params[:id]) + end + + def update + @organization = Organization.find(params[:id]) + if @organization.update_attributes(params[:organization]) + flash[:notice] = 'Organization was successfully updated.' + redirect_to :action => 'index' + else + render :action => 'edit' + end + end + + def destroy + Organization.find(params[:id]).destroy + redirect_to :action => 'index' + end + +end + diff --git a/app/controllers/admin/participants_controller.rb b/app/controllers/admin/participants_controller.rb new file mode 100644 index 0000000..e6babf9 --- /dev/null +++ b/app/controllers/admin/participants_controller.rb @@ -0,0 +1,176 @@ +# Copyright (C) 2007, 2008, 2009, 2010, 2016 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +class Admin::ParticipantsController < ApplicationController + + require 'pp' + + include Admin::Helper + + # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) + verify :method => [ :post, :put, :delete ], :only => [ :destroy, :create, :update, :destroy_participant, :reset ], + :add_flash => { :notice => "Failed to execute last action" }, + :redirect_to => :admin_participants_path + + def default + redirect_to admin_participants_path + end + + def index + list + render :action => 'list' + end + + def list + @list_participants_anonymous_count = Participant.all.count - Participant.without_anonymous.count + @participants = case params[:anonymous] + when "true" + @list_anonymous=true + @list_participants_count = Participant.all.count + Participant.find(:all).uniq + when "false" + @list_anonymous=false + @list_participants_count = Participant.all.count - @list_participants_anonymous_count + Participant.without_anonymous.uniq + else + @list_anonymous=false + @list_participants_count = Participant.all.count - @list_participants_anonymous_count + Participant.without_anonymous.uniq + end + @action_buttons = case params[:actionbuttons] + when "true" + true + when "false" + false + else + false + end + end + + def show + @participant = Participant.find(params[:id]) + end + + def new + @participant = Participant.new + @organizations = Organization.find(:all, :order => :id) + @participant.identities.build + end + + def create + @participant = Participant.new(params[:participant]) + @participant.ptype = Participant::TYPE[:main] + if @participant.save + flash[:notice] = "Participant \"#{CGI.escapeHTML @participant.name}\" was successfully created." + redirect_to admin_participants_path + else + @organizations = Organization.find(:all, :order => :id) + render :action => 'new' + end + end + + def edit + @participant = Participant.find(params[:id]) + @organizations = Organization.find(:all, :order => :id) + end + + def reset + @participant = Participant.find(params[:id]) + @participant.destroy_receiver_messages + @participant.destroy_sender_messages + @participant.destroy_events + flash[:notice] = "Successfully cleared all sent and received messages and events of participant \"#{CGI.escapeHTML @participant.name}\"." + redirect_to_admin_participants_path + end + + def update + params[:participant][:community_ids] ||= [] + @organizations = Organization.find(:all, :order => :id) + @participant = Participant.find(params[:id]) + lmsgs= leaved_messages(@participant, params[:participant][:community_ids]) + if @participant.update_attributes(params[:participant]) + generate_destroyed_events_by_leaving_a_community(@participant,lmsgs) unless lmsgs.blank? + flash[:notice] = 'Participant was successfully updated.' + redirect_to admin_participant_path(:id => @participant) + else + render :action => 'edit' + end + end + + def destroy + p = Participant.find(params[:id]) + p.destroy + flash[:notice] = "Participant \"#{CGI.escapeHTML p.name}\" was successfully destroyed." + redirect_to_admin_participants_path + end + + def index_communities + @participant = Participant.find(params[:id]) + @communities=Participant.find(params[:id]).memberships.collect {|i| i.community }.uniq.sort{|x,y| x.id <=> y.id } + end + + # lists all those communities which the participant has not yet joined + def index_noncommunities + index_communities + @communities=(Community.find(:all) - @communities).sort{|x,y| x.id <=> y.id } + end + + def destroy_community + destroy_membership(params[:c_id], params[:id]) + redirect_to admin_participant_communities_path(params[:id]) + end + + + # join to a community + def create_community + create_membership(params[:c_id], params[:id]) + redirect_to admin_participant_communities_path(params[:id]) + end + +private + + def redirect_to_admin_participants_path + queryparams={} + if params[:anonymous] + queryparams[:anonymous]=true + end + if params[:actionbuttons] + queryparams[:actionbuttons]=true + end + redirect_to admin_participants_path(queryparams) + end + + # Generate destroyed events for all messages unconnected in respect to the + # leaving communities. + def generate_destroyed_events_by_leaving_a_community(participant, messages ) + messages.each do |msg| + Event.make(:event_type_name => EvType.find_by_name("destroyed").name, :participant => participant, :message => msg) + logger.info "destroyed event for message.id=#{msg.id}, participant:#{participant.name} (pid:#{participant.id})" + end + end + + def leaved_messages(participant, community_ids) + leaved_community_ids= participant.communities.map{|c| c.id} - community_ids.map{|p| p.to_i} + leaved_messages= [] + leaved_community_ids.each do |cid| + leaved_messages << Membership.find_by_participant_id_and_community_id(participant.id, cid).messages + leaved_messages << Community.find(cid).messages + end + leaved_messages.flatten.compact.uniq + end +end diff --git a/app/controllers/admin/ressources_controller.rb b/app/controllers/admin/ressources_controller.rb new file mode 100644 index 0000000..2975839 --- /dev/null +++ b/app/controllers/admin/ressources_controller.rb @@ -0,0 +1,77 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +class Admin::RessourcesController < ApplicationController + require 'pp' + + include Admin::Helper + + # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) + verify :method => [ :post, :put, :delete ], :only => [ :destroy, :create, :update ], + :add_flash => { :notice => "Failed to execute last action" }, + :redirect_to => :admin_ressources_path + + def index + list + render :action => 'list' + end + + def list + @ressources = Ressource.list + @list_ressources_count = @ressources.count + end + + def show + @ressource = Ressource.find(params[:id]) + end + + def new + @ressource = Ressource.new + end + + def create + @ressource = Ressource.new(params[:ressource]) + if @ressource.save + flash[:notice] = 'Ressource was successfully created.' + redirect_to admin_ressources_path + else + render :action => 'new' + end + end + + def edit + @ressource = Ressource.find(params[:id]) + end + + def update + #params[:participant][:community_ids] ||= [] + @ressource = Ressource.find(params[:id]) + if @ressource.update_attributes(params[:ressource]) + flash[:notice] = 'Ressource was successfully updated.' + redirect_to admin_ressource_path(:id => @ressource) + else + render :action => 'edit' + end + end + + def destroy + Ressource.find(params[:id]).destroy + redirect_to admin_ressources_path + end + +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e..6c3e6bd 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,236 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +# Filters added to this controller apply to all controllers in the application. +# Likewise, all the methods added will be available for all controllers. + + class ApplicationController < ActionController::Base - # Prevent CSRF attacks by raising an exception. - # For APIs, you may want to use :null_session instead. - protect_from_forgery with: :exception + + require 'exceptions' + require 'pp' + require 'json/add/rails' + + #rescue_from Exception, :with => :rescue_body_500 + rescue_from Ecs::InvalidMessageException, :with => :rescue_body_400 + rescue_from Ecs::MissingReceiverHeaderException, :with => :rescue_body_400 + rescue_from Ecs::AuthenticationException, :with => :rescue_body_401 + rescue_from Ecs::AuthorizationException, :with => :rescue_body_403 + rescue_from Ecs::InvalidRessourceUriException, :with => :rescue_body_404 + rescue_from ActiveRecord::RecordNotFound, :with => :rescue_body_404 + rescue_from ActionController::RoutingError , :with => :rescue_body_404 + rescue_from Ecs::NoReceiverOfMessageException, :with => :rescue_body_404 + rescue_from Ecs::OuttimedAuthsException, :with => :rescue_body_409 + rescue_from ActiveRecord::StaleObjectError, :with => :rescue_body_409 + rescue_from ActiveRecord::StatementInvalid, :with => :rescue_body_415 + rescue_from Ecs::InvalidMimetypeException, :with => :rescue_body_415 + + #helper :all # include all helpers, all the time + protect_from_forgery # See ActionController::RequestForgeryProtection for details + # session :on + + # Scrub sensitive parameters from your log + # filter_parameter_logging :password + # + + def initialize + super + #@ar_model_name = nil + #@ar_model = nil + @list = nil + @record = nil + @app_namespace = nil + @ressource_name = nil + @ressource_path = nil + @body = "" + @participant = nil + @memberships = nil + @cookie = nil + @outdated_auth_token = nil + end + +protected + + def authentication + # authenticated subparticipants + participant = subparticipant? + if participant + logger.info "X-EcsAuthId: #{participant.identities[0].name} -- Subparticipant-ID: #{participant.id}" + return @participant= participant + end + if ECS_CONFIG["participants"]["allow_anonymous"] + # new anonymous participant + if new_anonymous_participant? + @participant, @cookie = Participant.generate_anonymous_participant + logger.info "Cookie (new anonymous participant): #{@cookie} -- Participant-ID: #{@participant.id}" + return @participant + end + # anonymous participants + if (participant= anonymous_participant) + logger.info "Cookie: #{@cookie} -- Participant-ID: #{participant.id}" + return @participant = participant + end + end + # authenticated participants + auth_id, participant = authenticated_participant + if participant + logger.info "X-EcsAuthId: #{auth_id} -- Participant-ID: #{participant.id}" + return @participant= participant + end + false + end + + def new_anonymous_participant? + request.headers["X-EcsAuthId"].blank? and request.headers["Cookie"].blank? + end + + def anonymous_participant + if !(@cookie = cookies[:ecs_anonymous]).blank? + if (identity = Identity.find_by_name(@cookie)).blank? + raise Ecs::AuthenticationException, "No valid identity found for cookie: #{@cookie}" + elsif (participant = identity.participant).blank? or !participant.anonymous + raise Ecs::AuthenticationException, "Cookie: #{@cookie}\" is not assigned any anonymous participant" + else + return participant + end + else + false + end + end + + def subparticipant? + if !(@cookie = cookies[:ecs_subparticipant]).blank? + if (identity = Identity.find_by_name(@cookie)).blank? + raise Ecs::AuthenticationException, "No valid identity found for subparticipant cookie: #{@cookie}" + elsif (participant = identity.participant).blank? or !participant.subparticipant + raise Ecs::AuthenticationException, "Subparticipant-Cookie: #{@cookie}\" is not assigned any subparticipant" + else + return participant + end + else + false + end + end + + def authenticated_participant + if (auth_id = request.headers["X-EcsAuthId"]).blank? + raise Ecs::AuthenticationException, "No \"X-EcsAuthId\" http header" + elsif (identity = Identity.find_by_name(auth_id)).blank? + raise Ecs::AuthenticationException, "No \"X-EcsAuthId: #{auth_id}\" identity found" + elsif (participant = identity.participant).blank? + raise Ecs::AuthenticationException, "\"X-EcsAuthId: #{auth_id}\" is not assigned any participant" + else + return auth_id, participant + end + end + + # set the cookie header + def add_cookie_header + case + when @participant.anonymous? + cookies[:ecs_anonymous] = \ + { + :value => @cookie, + :path => "/", + :expires => Participant::TTL.seconds.from_now + } + when @participant.subparticipant? + cookies[:ecs_subparticipant] = \ + { + :value => @cookie, + :path => "/", + :expires => Subparticipant::TTL.seconds.from_now + } + end + end + + def touch_participant_ttl + Participant.touch_ttl(@participant) if @participant.anonymous + end + + def block_anonymous_participants + if @participant.anonymous + raise Ecs::AuthenticationException, "Anonymous participants not allowed." + end + end + + def block_subparticipants + if @participant.subparticipant + raise Ecs::AuthenticationException, "Subparticipants not allowed." + end + end + + def check_json_contenttype + unless Mime::Type.lookup(request.headers["CONTENT_TYPE"]) =~ "application/json" + raise Ecs::InvalidMimetypeException, "Please provide \"Content-Type: application/json\" header for json data." + end unless request.raw_post.empty? + end + + + # error pages + def rescue_body_401 + @http_error= $! + logger.error $!.to_s + render :text => "#{$!.to_s}\n", :layout => false, :status => 401 + end + + def rescue_body_500 + @http_error= $! + logger.error $!.to_s + render :text => "#{$!.to_s}\n", :layout => false, :status => 500 + end + + def rescue_body_400 + @http_error= $! + logger.error $!.to_s + render :text => "#{$!.to_s}\n" , :layout => false, :status => 400 + end + + def rescue_body_403 + @http_error= $! + logger.error $!.to_s + render :text => "#{$!.to_s}\n" , :layout => false, :status => 403 + end + + def rescue_body_404 + @http_error= $! + logger.error $!.to_s + if $!.to_s.blank? + render :text => "The server does not know the ressource\nor the message queue in question is empty.\n" , :layout => false, :status => 404 + else + render :text => "#{$!.to_s}\n" , :layout => false, :status => 404 + end + end + + def rescue_body_409 + @http_error= $! + logger.error $!.to_s + render :text => "#{$!.to_s}\n" , :layout => false, :status => 409 + end + + def rescue_body_415(controller_binding) + @http_error= $! + logger.error $!.to_s + if $!.to_s.blank? + render :text => "The format of the client data is not supported by the server.\nIf your format is right please doublecheck the encoding !\nIt has to be UTF8 !\n", :layout => false, :status => 415 + else + render :text => "#{$!.to_s}\n" , :layout => false, :status => 415 + end + + end end diff --git a/app/controllers/config_controller_bak.rb b/app/controllers/config_controller_bak.rb new file mode 100644 index 0000000..d2cc3ce --- /dev/null +++ b/app/controllers/config_controller_bak.rb @@ -0,0 +1,34 @@ +class ConfigController < ApplicationController + + require 'json/add/rails' + + before_filter :authentication + before_filter :add_cookie_header # only for anonymous participants + + def initialize + super + end + + def index + config_render + end + + def create + end + +private + + def config_render + config = nil + config_txt = "" + config= \ + { + :events => @participant.events?.to_s + } + respond_to do |format| + format.json { render :json => JSON.pretty_generate(config) } + format.xml { render :xml => config } + end + end + +end diff --git a/app/controllers/configs_controller.rb b/app/controllers/configs_controller.rb new file mode 100644 index 0000000..0b516e9 --- /dev/null +++ b/app/controllers/configs_controller.rb @@ -0,0 +1,64 @@ +class ConfigsController < ApplicationController + + require 'json/add/rails' + + before_filter :authentication + before_filter :add_cookie_header # only for anonymous participants + + def initialize + super + end + + def index + config_render + end + + def create + unless Mime::Type.lookup(request.headers["CONTENT_TYPE"]) =~ "application/json" + raise Ecs::InvalidMimetypeException, "Please provide \"Content-Type:\" header. Data format has to be in JSON (application/json)" + end + + config= ActiveSupport::JSON.decode request.raw_post + + if config["participant_events"] == true + @participant.events_= true + else + @participant.events_= false + end unless config["participant_events"].nil? + + if config["selfrouting"] == true + @participant.community_selfrouting= true + else + @participant.community_selfrouting= false + end unless config["selfrouting"].nil? + + @participant.save! + config_render + #rescue ActiveSupport::OkJson::Error + rescue Ecs::InvalidMimetypeException + raise + rescue ActiveRecord::RecordInvalid + raise Ecs::InvalidMessageException, "Data could not be saved (ConfigsController#create)." + rescue StandardError + raise Ecs::InvalidMessageException, "You have provided invalid JSON data (ConfigsController#create)." + end + +private + + def config_render + config = nil + config_txt = "" + res_ev={};Ressource.all.each {|r| res_ev["/#{r.namespace}/#{r.ressource}"] = r.events} + config= \ + { + :participant_events => @participant.events?, + :resource_events => res_ev, + :selfrouting => @participant.community_selfrouting + } + respond_to do |format| + format.json { render :json => JSON.pretty_generate(config) + "\r\n" } + format.xml { render :xml => config } + end + end + +end diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb new file mode 100644 index 0000000..1e8ec1d --- /dev/null +++ b/app/controllers/events_controller.rb @@ -0,0 +1,87 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +class EventsController < ApplicationController + + require 'json/add/rails' + + before_filter :authentication + before_filter :add_cookie_header # only for anonymous participants + + def initialize + super + end + + def index + count = params["count"].blank? ? -1 : params["count"].to_i + events_render(@participant.id, count) + end + + def fifo + max_tries = 5 + begin + Event.transaction do + count = params["count"].blank? ? 1 : params["count"].to_i + events_render(@participant.id, count) + end + rescue ActiveRecord::StaleObjectError, ActiveRecord::RecordNotFound => error + logger.info "**** Concurrent access at events queue (max_tries=#{max_tries})." + max_tries-= 1 + retry unless max_tries <= 0 + raise + end + end + +private + + def events_render(participant_id, count) + events = [] + events_txt = "" + Event.for_participant(participant_id,count).each do |event| + if request.post? + event.destroy + # do not destroy message if another reference in events to the message + # exists or the message is not marked as removed + unless Event.find_by_message_id(event.message.id) or !event.message.removed + event.message.destroy + end + end + events << + { + :ressource => event.message.ressource.namespace + "/" + + event.message.ressource.ressource + "/" + + event.message.id.to_s, + :status => event.ev_type.name + } + end + respond_to do |format| + format.json { render :json => JSON.pretty_generate(events) } + format.xml { render :xml => events } + format.text { render :text => events_render_txt(events) } + end + end + + def events_render_txt(events) + events_txt = "" + events.each do |event| + events_txt << event[:ressource] + " " + event[:status] + "\r\n" + end + events_txt + end + +end diff --git a/app/controllers/memberships_controller.rb b/app/controllers/memberships_controller.rb new file mode 100644 index 0000000..dbd60ca --- /dev/null +++ b/app/controllers/memberships_controller.rb @@ -0,0 +1,64 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +class MembershipsController < ApplicationController + + require 'json/add/rails' + + before_filter :authentication + before_filter :add_cookie_header # only for anonymous participants + + def initialize + super + end + + def index + memberships= index_querystring_list + if memberships.empty? + render :text => "", :content_type => "application/json", :layout => false + else + respond_to do |format| + format.json { render :json => JSON.pretty_generate(memberships) } + format.xml { render :xml => memberships } + end + end + end + + private + + def index_querystring_list + header_querystrings = request.headers["X-EcsQueryStrings"] + if header_querystrings + hqs = header_querystrings.split(",").map{|s| s.strip}.map{|s| s.split("=").map{|s| s.strip}} + mainparticipants = (m=hqs.assoc("mainparticipants")) ? m[1] : nil + subparticipants = (m=hqs.assoc("subparticipants")) ? m[1] : nil + anonymous = (m=hqs.assoc("anonymous")) ? m[1] : nil + all = (m=hqs.assoc("all")) ? m[1] : nil + end + mainparticipants ||= params["mainparticipants"] ? params["mainparticipants"] : nil + subparticipants ||= params["subparticipants"] ? params["subparticipants"] : nil + anonymous ||= params["anonymous"] ? params["anonymous"] : nil + all ||= params["all"] ? params["all"] : nil + Membership.memberships(@participant,false, + { :mainparticipants => mainparticipants, + :subparticipants => subparticipants, + :anonymous => anonymous, + :all => all }) + end + +end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb new file mode 100644 index 0000000..deb01a6 --- /dev/null +++ b/app/controllers/messages_controller.rb @@ -0,0 +1,288 @@ +# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + + +class MessagesController < ApplicationController + + before_filter :late_initialize + before_filter :authentication + before_filter :add_cookie_header + before_filter :get_record, :only => [:show, :update, :destroy] + after_filter :touch_participant_ttl + + def initialize + super + @render_cmd=nil + end + + def index + index_querystring_list + @list.each do |li| + @body << @ressource_name << "/" << li.id.to_s << "\n" + end unless @list.empty? + index_render + end + + def show + @memberships = Membership.receiver(@participant.id, @record.id) + case + when @record.outtimed_auths_resource_by_non_owner?(@app_namespace, @resource_name, @participant) + raise Ecs::OuttimedAuthsException, 'Authorization token outtimed' + when (!@memberships.empty? or @participant.sender?(@record)) + @record.filter(__method__, @app_namespace, @ressource_name, params) + @body = @record.body + show_render + eval(@render_cmd) unless @render_cmd.blank? + else + raise Ecs::AuthorizationException, + "You are not allowed to access this resource, " + + "because you are not the original sender or a receiver." + end + end + + + # Create and save a new message. Then render "Created 201" response. + # - todo: exceptions for: create, constantize + def create + @record= Message.create__(request, @app_namespace, @ressource_name, @participant) + @body = @record.body + create_render + end + + def update + @record.update__(request, @app_namespace, @ressource_name, @participant) + update_render + end + + def destroy + @body = @record.body + @memberships = Membership.receiver(@participant.id, @record.id) + show_render + case + when @record.outtimed_auths_resource_by_non_owner?(@app_namespace, @resource_name, @participant) + @record.destroy_as_receiver(@participant) + raise Ecs::OuttimedAuthsException, 'Authorization token outtimed' + when (@participant.sender?(@record) and not @participant.receiver?(@record)) + @record.destroy_as_sender + else + @record.destroy_as_receiver(@participant) + end + eval(@render_cmd) unless @render_cmd.blank? + end + + def fifo + queue(:queue_type => :fifo) + end + + def lifo + queue(:queue_type => :lifo) + end + + def details + details = nil + no_data_to_render = false + if params["id"] + # member subresource + details = member_subresource_details(params["id"]) + if !details[:receivers] then no_data_to_render = true end + else + index_querystring_list + # collection subresource + details ||= [] + @list.each do |li| + details << member_subresource_details(li.id) + end unless @list.empty? + if details.empty? then no_data_to_render = true end + end + if no_data_to_render + render :text => "", :content_type => "application/json", :layout => false + else + respond_to do |format| + format.json { render :json => JSON.pretty_generate(details) } + format.xml { render :xml => details } + end + end + end + +protected + + def member_subresource_details(record_id) + get_record(record_id) + if @participant.sender?(@record) or @participant.receiver?(@record) + receivers=[] + senders=[] + Membership.receivers(@record.id).each do |recv| + receivers << { :pid => recv.participant.id, :mid => recv.id, :cid => recv.community_id, + :itsyou => recv.participant_id == @participant.id } + senders << { :mid => Membership.find_by_participant_id_and_community_id(@record.sender, recv.community_id).id } + end + content_type = @record.content_type + url = @ressource_name + "/" + record_id.to_s + { :receivers => receivers, + :senders => senders, + :content_type => content_type, + :url => url, + :owner => { :itsyou => @participant.id == @record.sender, + :pid => @record.sender } + } + else + raise Ecs::AuthorizationException, + "You are not allowed to access this resource, " + + "because you are not the original sender or a receiver." + end + end + + def index_querystring_list + header_querystrings = request.headers["X-EcsQueryStrings"] + if header_querystrings + hqs = header_querystrings.split(",").map{|s| s.strip}.map{|s| s.split("=").map{|s| s.strip}} + sender = (m=hqs.assoc("sender")) ? m[1] : nil + receiver = (m=hqs.assoc("receiver")) ? m[1] : nil + all = (m=hqs.assoc("all")) ? m[1] : nil + end + sender ||= params["sender"] ? params["sender"] : nil + receiver ||= params["receiver"] ? params["receiver"] : nil + all ||= params["all"] ? params["all"] : nil + case + when sender == "true" + @list = Message.for_participant_sender(@participant).for_resource(@app_namespace,@ressource_name).for_not_removed.uniq + when receiver == "true" + @list = Message.for_participant_receiver(@participant).for_resource(@app_namespace,@ressource_name).for_not_removed.uniq + when all == "true" + list1 = Message.for_participant_sender(@participant).for_resource(@app_namespace,@ressource_name).for_not_removed + list2 = Message.for_participant_receiver(@participant).for_resource(@app_namespace,@ressource_name).for_not_removed + @list = list1.concat(list2).uniq + else + @list = Message.for_participant_receiver(@participant).for_resource(@app_namespace,@ressource_name).for_not_removed.uniq + end + end + + def queue(queue_options = {:queue_type => :fifo}) + begin + Message.transaction do + # returned record holds a lock (pessimistic locking) + @record = Message.fifo_lifo_rest(@app_namespace, @ressource_name,@participant.id, queue_options) + if @record + @memberships = Membership.receiver(@participant.id, @record.id) + @body = @record.body + if request.post? + if @record + show_render + @record.destroy_as_receiver(@participant) + eval(@render_cmd) unless @render_cmd.blank? + else + raise ActiveRecord::RecordNotFound + end + else + show_render + eval(@render_cmd) unless @render_cmd.blank? + end + else + empty_render + end + end + rescue ActiveRecord::StaleObjectError, ActiveRecord::RecordNotFound => error + logger.info "Concurrent access at queue resource" + raise + end + end + + # inititialize instance variables dependent from request object + def late_initialize + @app_namespace= request.path.sub(/^\//,'').sub(/\/.*/,'') + @ressource_name= $&.sub(/\//,'').sub(/\/.*/,'') + #@ar_model_name= "#{@app_namespace}_#{@ressource_name}".pluralize.classify + #@ar_model= @ar_model_name.constantize + end + + # get a record out of the message table + def get_record(record_id = params["id"], app_namespace=@app_namespace, ressource_name=@ressource_name) + @record, @outdated_auth_token = Message.get_record(record_id, app_namespace, ressource_name) + end + + def empty_render + render :text => "", :content_type => "application/json" + end + + def index_render + render :text => @body, :content_type => "text/uri-list" + end + + def show_render + #expires_in 3.hours, 'max-stale' => 5.hours, :public => true + headers["Cache-Control"] = "private, max-age=5" + x_ecs_receiver_communities= "" + x_ecs_sender= "" + @memberships.each do |memb| + x_ecs_receiver_communities << memb.community.id.to_s + x_ecs_sender << Membership.find_by_participant_id_and_community_id(Participant.find(@record.sender).id, memb.community.id).id.to_s + unless @memberships.last == memb + x_ecs_receiver_communities << "," + x_ecs_sender << "," + end + end unless @memberships.blank? + headers["X-EcsReceiverCommunities"]= x_ecs_receiver_communities unless x_ecs_receiver_communities.blank? + headers["X-EcsSender"]= x_ecs_sender unless x_ecs_sender.blank? + if stale?(:etag => @record, :last_modified => @record.updated_at.utc, + :x_ecs_receiver_communities => x_ecs_receiver_communities, + :x_ecs_sender => x_ecs_sender) + @render_cmd='render :text => @body, :layout => false, :status => 200, :content_type => Mime::Type.lookup(@record.content_type)' + end + end + + def create_render + location = request.protocol + request.host + location += ":" + request.headers["SERVER_PORT"] unless [80,443].include? request.headers["SERVER_PORT"] + location += request.headers["SCRIPT_NAME"] if request.headers.has_key?("SCRIPT_NAME") + location += request.path.gsub(/\/*$/,'') + "/" + @record.id.to_s + if @app_namespace == 'sys' and @ressource_name == 'auths' + render :text => @body, :layout => false, :status => 201, :location => location, :content_type => Mime::Type.lookup_by_extension("json") + else + render :text => "", :layout => false, :status => 201, :location => location, :content_type => Mime::Type.lookup(@record.content_type) + end + end + + def update_render + location = request.protocol + request.host + location += request.headers["SCRIPT_NAME"] if request.headers.has_key?("SCRIPT_NAME") + location += request.path.gsub(/\/*$/,'') + render :text => "", :layout => false, :status => 200, + :location => location + end + + def destroy_render + render :nothing => true, :layout => false, :status => 200, + :content_type => "application/json" + end + + # this is a custom fresh_when function, which is called by stale? + # see http://www.themomorohoax.com/2009/01/07/using-stale-with-rails-to-return-304-not-modified + def fresh_when(options) + options.assert_valid_keys(:etag, :last_modified, :x_ecs_receiver_communities, :x_ecs_sender) + + response.etag = options[:etag] if options[:etag] + response.last_modified = options[:last_modified] if options[:last_modified] + response.headers["X-EcsReceiverCommunities"] = options[:x_ecs_receiver_communities] unless options[:x_ecs_receiver_communities].blank? + response.headers["X-EcsSender"] = options[:x_ecs_sender] unless options[:x_ecs_sender].blank? + + if request.fresh?(response) + head :not_modified + end + end + + +end diff --git a/app/controllers/subparticipants_controller.rb b/app/controllers/subparticipants_controller.rb new file mode 100644 index 0000000..6284536 --- /dev/null +++ b/app/controllers/subparticipants_controller.rb @@ -0,0 +1,122 @@ +# Copyright (C) 2014 Heiko Bernloehr (FreeIT.de). +# +# This file is part of ECS. +# +# ECS is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# ECS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with ECS. If not, see <http://www.gnu.org/licenses/>. + +class SubparticipantsController < ApplicationController + + require 'json/add/rails' + + before_filter :authentication + before_filter :block_anonymous_participants + before_filter :block_subparticipants + before_filter :check_json_contenttype, :only => :create + before_filter :check_parent, :only => [:show, :destroy, :update] + + def initialize + super + end + + def index + childs= @participant.childs + childs.each do |child| + @body << "subparticipants/" << child.id.to_s << "\n" + end unless childs.empty? + respond_to do |format| + format.text { render :text => @body, :content_type => "text/uri-list" } + end + end + + def show + subparticipant= Subparticipant.find(params[:id]) + body= show_render(subparticipant) + respond_to do |format| + format.json { render :json => JSON.pretty_generate(body) + "\r\n" } + format.xml { render :xml => body } + end + end + + def create + begin + json_data= ActiveSupport::JSON.decode request.raw_post + rescue ActiveSupport::OkJson::Error, StandardError + raise Ecs::InvalidMessageException, "You have provided invalid JSON data (SubparticipantsController#create)." + end unless request.raw_post.empty? + logger.debug "request raw post: #{(request.raw_post.empty?)?'<empty>':request.raw_post}" + subparticipant= Subparticipant.generate(@participant, json_data) + body= show_render(subparticipant) + respond_to do |format| + format.json { render :json => JSON.pretty_generate(body) + "\r\n", :location => location(subparticipant) } + format.xml { render :xml => body, :location => location(subparticipant) } + end + end + + def update + begin + json_data= ActiveSupport::JSON.decode request.raw_post + rescue StandardError + raise Ecs::InvalidMessageException, "You have provided invalid JSON data (SubparticipantsController#update)." + end unless request.raw_post.empty? + subparticipant= Subparticipant.find(params[:id]) + subparticipant.update__(@participant, json_data, subparticipant) + body= show_render(subparticipant) + respond_to do |format| + format.json { render :json => JSON.pretty_generate(body) + "\r\n", :location => location(subparticipant) } + format.xml { render :xml => body, :location => location(subparticipant) } + end + end + + def destroy + subparticipant= Subparticipant.find(params[:id]) + subparticipant.participant.destroy + render :text => "", :layout => false, :status => 200, :content_type => :json + end + +private + + def show_render(subparticipant) + participant= subparticipant.participant + data = nil + data= \ + { + :name => participant.name, + :description => participant.description, + :auth_ids => participant.identities.map{|ident| {:auth_id=>ident.name, :desc=>ident.description}}, + :dns => participant.dns, + :email => participant.email, + :community_selfrouting => participant.community_selfrouting, + :events => participant.events_, + :memberships => Membership.memberships(participant,true), + :realm => subparticipant.realm, + } + data + end + + def check_parent + subparticipant= Subparticipant.find(params[:id]) + unless @participant.childs.include?(subparticipant) + raise Ecs::AuthorizationException, "You are not allowed to access this subparticipant because you are not its parent/creator." + end + end + + def location(subparticipant) + location = request.protocol + request.host + location += ":" + request.port.to_s unless [80, 443].include?(request.port) + location += request.headers["SCRIPT_NAME"] if request.headers.has_key?("SCRIPT_NAME") + location += request.path.gsub(/\/*$/,'') + "/" + subparticipant.id.to_s + location + end + +end |