From e05a1b0f5ae40a2aa17976b3009cd563b8e4660a Mon Sep 17 00:00:00 2001 From: Azul Date: Sun, 1 May 2016 10:55:33 -0300 Subject: api: allow version bumping - bump to 2 --- app/controllers/api/certs_controller.rb | 31 +++++++ app/controllers/api/configs_controller.rb | 37 +++++++++ app/controllers/api/identities_controller.rb | 16 ++++ app/controllers/api/messages_controller.rb | 119 +++++++++++++++++++++++++++ app/controllers/api/services_controller.rb | 8 ++ app/controllers/api/sessions_controller.rb | 44 ++++++++++ app/controllers/api/smtp_certs_controller.rb | 42 ++++++++++ app/controllers/api/users_controller.rb | 83 +++++++++++++++++++ app/controllers/v1/certs_controller.rb | 31 ------- app/controllers/v1/configs_controller.rb | 37 --------- app/controllers/v1/identities_controller.rb | 16 ---- app/controllers/v1/messages_controller.rb | 119 --------------------------- app/controllers/v1/services_controller.rb | 8 -- app/controllers/v1/sessions_controller.rb | 44 ---------- app/controllers/v1/smtp_certs_controller.rb | 42 ---------- app/controllers/v1/users_controller.rb | 83 ------------------- app/views/api/sessions/new.json.erb | 3 + app/views/v1/sessions/new.json.erb | 3 - 18 files changed, 383 insertions(+), 383 deletions(-) create mode 100644 app/controllers/api/certs_controller.rb create mode 100644 app/controllers/api/configs_controller.rb create mode 100644 app/controllers/api/identities_controller.rb create mode 100644 app/controllers/api/messages_controller.rb create mode 100644 app/controllers/api/services_controller.rb create mode 100644 app/controllers/api/sessions_controller.rb create mode 100644 app/controllers/api/smtp_certs_controller.rb create mode 100644 app/controllers/api/users_controller.rb delete mode 100644 app/controllers/v1/certs_controller.rb delete mode 100644 app/controllers/v1/configs_controller.rb delete mode 100644 app/controllers/v1/identities_controller.rb delete mode 100644 app/controllers/v1/messages_controller.rb delete mode 100644 app/controllers/v1/services_controller.rb delete mode 100644 app/controllers/v1/sessions_controller.rb delete mode 100644 app/controllers/v1/smtp_certs_controller.rb delete mode 100644 app/controllers/v1/users_controller.rb create mode 100644 app/views/api/sessions/new.json.erb delete mode 100644 app/views/v1/sessions/new.json.erb (limited to 'app') diff --git a/app/controllers/api/certs_controller.rb b/app/controllers/api/certs_controller.rb new file mode 100644 index 0000000..46a84d3 --- /dev/null +++ b/app/controllers/api/certs_controller.rb @@ -0,0 +1,31 @@ +class Api::CertsController < ApiController + + before_filter :require_login, :unless => :anonymous_access_allowed? + before_filter :require_enabled + + # GET /cert + # deprecated - we actually create a new cert and that can + # be reflected in the action. GET /cert will eventually go + # away and be replaced by POST /cert + def show + create + end + + # POST /cert + def create + @cert = ClientCertificate.new(:prefix => service_level.cert_prefix) + render text: @cert.to_s, content_type: 'text/plain' + end + + protected + + def require_enabled + if !current_user.is_anonymous? && !current_user.enabled? + access_denied + end + end + + def service_level + current_user.effective_service_level + end +end diff --git a/app/controllers/api/configs_controller.rb b/app/controllers/api/configs_controller.rb new file mode 100644 index 0000000..55ceb4f --- /dev/null +++ b/app/controllers/api/configs_controller.rb @@ -0,0 +1,37 @@ +class Api::ConfigsController < ApiController + include ControllerExtension::JsonFile + + before_filter :require_login, :unless => :anonymous_access_allowed? + before_filter :sanitize_id, only: :show + + def index + render json: {services: service_paths} + end + + def show + send_file lookup_file + end + + protected + + SERVICE_IDS = { + soledad: "soledad-service", + eip: "eip-service", + smtp: "smtp-service" + } + + def service_paths + Hash[SERVICE_IDS.map{|k,v| [k,"/1/configs/#{v}.json"] } ] + end + + def sanitize_id + @id = params[:id].downcase + access_denied unless SERVICE_IDS.values.include? @id + end + + def lookup_file + path = APP_CONFIG[:config_file_paths][@id] + not_found if path.blank? + Rails.root.join path + end +end diff --git a/app/controllers/api/identities_controller.rb b/app/controllers/api/identities_controller.rb new file mode 100644 index 0000000..ab2ac00 --- /dev/null +++ b/app/controllers/api/identities_controller.rb @@ -0,0 +1,16 @@ +module Api + class IdentitiesController < ApiController + before_filter :token_authenticate + before_filter :require_monitor + + def show + @identity = Identity.find_by_address(params[:id]) + if @identity + respond_with @identity + else + render_not_found + end + end + + end +end diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb new file mode 100644 index 0000000..a69a40a --- /dev/null +++ b/app/controllers/api/messages_controller.rb @@ -0,0 +1,119 @@ +module Api + class MessagesController < ApiController + + before_filter :require_login + + def index + if Dir.exist?(motd_dir) + if !CommonLanguages::available_code?(params[:locale]) + locale = 'en' + else + locale = params[:locale] + end + render json: motd_files_for_locale(locale) + else + render json: [] + end + end + + # disable per-user messages for now, not supported in the client + #def update + # if message = Message.find(params[:id]) + # message.mark_as_read_by(current_user) + # message.save + # render json: success(:marked_as_read) + # else + # render json: error(:not_found), status: :not_found + # end + #end + + private + + # + # returns list of messages, for example: + # + # [ + # {"id": 1, "locale": "en", "text": ""}, + # {"id": 2, "locale": "en", "text": ""} + # ] + # + # Each message is present only once, using the best choice + # for the locale. The order is determined by the id. + # + def motd_files_for_locale(locale) + files = [] + motd_files.keys.each do |id| + if motd_files[id].key?(locale) + msg_locale = locale + elsif motd_files[id].key?('en') + msg_locale = 'en' + else + msg_locale = motd_files[id].keys.first + end + files << { + "id" => id, + "locale" => msg_locale, + "text" => motd_files[id][msg_locale] + } + end + files.sort! {|a,b| a["id"].to_i <=> b["id"].to_i } + return files + end + + # + # returns messages of the day as a hash: + # { "1": {"en": "message"}, "2": {"en": "message"} } + # + def motd_files + if motd_changed? || @motd_files.nil? + @motd_files = load_motd_files + else + @motd_files + end + end + + def motd_changed? + newest = Dir.glob(File.join(motd_dir, '*.{html,md}')).collect{|file| File.mtime(file)}.max + if @timestamp.nil? + @timestamp = newest + return true + elsif @timestamp < newest + @timestamp = newest + return true + else + return false + end + end + + def load_motd_files + files = {} + Dir.glob(File.join(motd_dir, '*.{html,md}')).each do |file| + id, locale, msg = parse_motd_file(file) + next unless id + files[id] ||= {} + files[id][locale] = msg + end + files + end + + def parse_motd_file(file) + id, locale, ext = File.basename(file).split('.') + if id.nil? || locale.nil? || ext.nil? || id.to_i.to_s != id || !['md', 'html'].include?(ext) + Rails.logger.error "ERROR: Could not parse MOTD file #{file}" + return nil + end + contents = File.read(file) + if ext == "md" + msg = RDiscount.new(contents, :autolink).to_html + elsif ext == "html" + msg = File.read(file) + end + return id, locale, msg + end + + def motd_dir + File.join(APP_CONFIG['customization_directory'], 'motd') + end + + end +end diff --git a/app/controllers/api/services_controller.rb b/app/controllers/api/services_controller.rb new file mode 100644 index 0000000..da2774b --- /dev/null +++ b/app/controllers/api/services_controller.rb @@ -0,0 +1,8 @@ +class Api::ServicesController < ApiController + + before_filter :require_login, :unless => :anonymous_access_allowed? + + def show + respond_with current_user.effective_service_level + end +end diff --git a/app/controllers/api/sessions_controller.rb b/app/controllers/api/sessions_controller.rb new file mode 100644 index 0000000..c8deb7a --- /dev/null +++ b/app/controllers/api/sessions_controller.rb @@ -0,0 +1,44 @@ +module Api + class SessionsController < ApiController + + before_filter :require_login, only: :destroy + + def new + @session = Session.new + if authentication_errors + @errors = authentication_errors + render :status => 422 + end + end + + def create + logout if logged_in? + if params['A'] + authenticate! + else + @user = User.find_by_login(params['login']) + render :json => {salt: @user.salt} + end + end + + def update + authenticate! + @token = Token.create(:user_id => current_user.id) + session[:token] = @token.id + render :json => login_response + end + + def destroy + logout + head :no_content + end + + protected + + def login_response + handshake = session.delete(:handshake) || {} + handshake.to_hash.merge(:id => current_user.id, :token => @token.to_s) + end + + end +end diff --git a/app/controllers/api/smtp_certs_controller.rb b/app/controllers/api/smtp_certs_controller.rb new file mode 100644 index 0000000..d9eab7d --- /dev/null +++ b/app/controllers/api/smtp_certs_controller.rb @@ -0,0 +1,42 @@ +class Api::SmtpCertsController < ApiController + + before_filter :require_login + before_filter :require_email_account + before_filter :fetch_identity + before_filter :require_enabled + + # POST /1/smtp_cert + def create + @cert = ClientCertificate.new common_name: current_user.email_address + @identity.register_cert(@cert) + @identity.save + render text: @cert.to_s, content_type: 'text/plain' + end + + protected + + # + # Filters + # + + def require_email_account + access_denied unless service_level.provides? 'email' + end + + def require_enabled + access_denied unless current_user.enabled? + end + + def fetch_identity + @identity = current_user.identity + end + + # + # Helper methods + # + + def service_level + current_user.effective_service_level + end + +end diff --git a/app/controllers/api/users_controller.rb b/app/controllers/api/users_controller.rb new file mode 100644 index 0000000..e64d21f --- /dev/null +++ b/app/controllers/api/users_controller.rb @@ -0,0 +1,83 @@ +module Api + class UsersController < ApiController + include ControllerExtension::FetchUser + + # allow optional access to this controller using API auth tokens: + before_filter :token_authenticate + + before_filter :fetch_user, :only => [:update, :destroy] + before_filter :require_monitor, :only => [:index, :show] + before_filter :require_login, :only => [:index, :update, :destroy] + + respond_to :json + + # used for autocomplete for admins in the web ui + def index + if params[:query] + @users = User.login_starts_with(params[:query]) + respond_with @users.map(&:login).sort + else + render :json => {'error' => 'query required', 'status' => :unprocessable_entity} + end + end + + def show + if params[:login] + @user = User.find_by_login(params[:login]) + elsif params[:id] + @user = User.find(params[:id]) + end + if @user + respond_with @user + else + not_found + end + end + + def create + if current_user.is_monitor? + create_test_account + elsif APP_CONFIG[:allow_registration] + create_account + else + head :forbidden + end + end + + def update + @user.account.update params[:user] + respond_with @user + end + + def destroy + destroy_identity = current_user.is_monitor? || params[:identities] == "destroy" + @user.account.destroy(destroy_identity) + if @user == current_user + logout + end + render :json => {'success' => 'user deleted'} + end + + private + + # tester auth can only create test users. + def create_test_account + if User::is_test?(params[:user][:login]) + @user = Account.create(params[:user], :invite_required => false) + respond_with @user + else + head :forbidden + end + end + + def create_account + if APP_CONFIG[:allow_registration] + @user = Account.create(params[:user]) + respond_with @user # return ID instead? + else + head :forbidden + end + end + + end +end diff --git a/app/controllers/v1/certs_controller.rb b/app/controllers/v1/certs_controller.rb deleted file mode 100644 index ffa6e35..0000000 --- a/app/controllers/v1/certs_controller.rb +++ /dev/null @@ -1,31 +0,0 @@ -class V1::CertsController < ApiController - - before_filter :require_login, :unless => :anonymous_access_allowed? - before_filter :require_enabled - - # GET /cert - # deprecated - we actually create a new cert and that can - # be reflected in the action. GET /cert will eventually go - # away and be replaced by POST /cert - def show - create - end - - # POST /cert - def create - @cert = ClientCertificate.new(:prefix => service_level.cert_prefix) - render text: @cert.to_s, content_type: 'text/plain' - end - - protected - - def require_enabled - if !current_user.is_anonymous? && !current_user.enabled? - access_denied - end - end - - def service_level - current_user.effective_service_level - end -end diff --git a/app/controllers/v1/configs_controller.rb b/app/controllers/v1/configs_controller.rb deleted file mode 100644 index f0b284e..0000000 --- a/app/controllers/v1/configs_controller.rb +++ /dev/null @@ -1,37 +0,0 @@ -class V1::ConfigsController < ApiController - include ControllerExtension::JsonFile - - before_filter :require_login, :unless => :anonymous_access_allowed? - before_filter :sanitize_id, only: :show - - def index - render json: {services: service_paths} - end - - def show - send_file lookup_file - end - - protected - - SERVICE_IDS = { - soledad: "soledad-service", - eip: "eip-service", - smtp: "smtp-service" - } - - def service_paths - Hash[SERVICE_IDS.map{|k,v| [k,"/1/configs/#{v}.json"] } ] - end - - def sanitize_id - @id = params[:id].downcase - access_denied unless SERVICE_IDS.values.include? @id - end - - def lookup_file - path = APP_CONFIG[:config_file_paths][@id] - not_found if path.blank? - Rails.root.join path - end -end diff --git a/app/controllers/v1/identities_controller.rb b/app/controllers/v1/identities_controller.rb deleted file mode 100644 index 4efd1f5..0000000 --- a/app/controllers/v1/identities_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -module V1 - class IdentitiesController < ApiController - before_filter :token_authenticate - before_filter :require_monitor - - def show - @identity = Identity.find_by_address(params[:id]) - if @identity - respond_with @identity - else - render_not_found - end - end - - end -end diff --git a/app/controllers/v1/messages_controller.rb b/app/controllers/v1/messages_controller.rb deleted file mode 100644 index c0ca0c7..0000000 --- a/app/controllers/v1/messages_controller.rb +++ /dev/null @@ -1,119 +0,0 @@ -module V1 - class MessagesController < ApiController - - before_filter :require_login - - def index - if Dir.exist?(motd_dir) - if !CommonLanguages::available_code?(params[:locale]) - locale = 'en' - else - locale = params[:locale] - end - render json: motd_files_for_locale(locale) - else - render json: [] - end - end - - # disable per-user messages for now, not supported in the client - #def update - # if message = Message.find(params[:id]) - # message.mark_as_read_by(current_user) - # message.save - # render json: success(:marked_as_read) - # else - # render json: error(:not_found), status: :not_found - # end - #end - - private - - # - # returns list of messages, for example: - # - # [ - # {"id": 1, "locale": "en", "text": ""}, - # {"id": 2, "locale": "en", "text": ""} - # ] - # - # Each message is present only once, using the best choice - # for the locale. The order is determined by the id. - # - def motd_files_for_locale(locale) - files = [] - motd_files.keys.each do |id| - if motd_files[id].key?(locale) - msg_locale = locale - elsif motd_files[id].key?('en') - msg_locale = 'en' - else - msg_locale = motd_files[id].keys.first - end - files << { - "id" => id, - "locale" => msg_locale, - "text" => motd_files[id][msg_locale] - } - end - files.sort! {|a,b| a["id"].to_i <=> b["id"].to_i } - return files - end - - # - # returns messages of the day as a hash: - # { "1": {"en": "message"}, "2": {"en": "message"} } - # - def motd_files - if motd_changed? || @motd_files.nil? - @motd_files = load_motd_files - else - @motd_files - end - end - - def motd_changed? - newest = Dir.glob(File.join(motd_dir, '*.{html,md}')).collect{|file| File.mtime(file)}.max - if @timestamp.nil? - @timestamp = newest - return true - elsif @timestamp < newest - @timestamp = newest - return true - else - return false - end - end - - def load_motd_files - files = {} - Dir.glob(File.join(motd_dir, '*.{html,md}')).each do |file| - id, locale, msg = parse_motd_file(file) - next unless id - files[id] ||= {} - files[id][locale] = msg - end - files - end - - def parse_motd_file(file) - id, locale, ext = File.basename(file).split('.') - if id.nil? || locale.nil? || ext.nil? || id.to_i.to_s != id || !['md', 'html'].include?(ext) - Rails.logger.error "ERROR: Could not parse MOTD file #{file}" - return nil - end - contents = File.read(file) - if ext == "md" - msg = RDiscount.new(contents, :autolink).to_html - elsif ext == "html" - msg = File.read(file) - end - return id, locale, msg - end - - def motd_dir - File.join(APP_CONFIG['customization_directory'], 'motd') - end - - end -end diff --git a/app/controllers/v1/services_controller.rb b/app/controllers/v1/services_controller.rb deleted file mode 100644 index 523eb44..0000000 --- a/app/controllers/v1/services_controller.rb +++ /dev/null @@ -1,8 +0,0 @@ -class V1::ServicesController < ApiController - - before_filter :require_login, :unless => :anonymous_access_allowed? - - def show - respond_with current_user.effective_service_level - end -end diff --git a/app/controllers/v1/sessions_controller.rb b/app/controllers/v1/sessions_controller.rb deleted file mode 100644 index a343d9b..0000000 --- a/app/controllers/v1/sessions_controller.rb +++ /dev/null @@ -1,44 +0,0 @@ -module V1 - class SessionsController < ApiController - - before_filter :require_login, only: :destroy - - def new - @session = Session.new - if authentication_errors - @errors = authentication_errors - render :status => 422 - end - end - - def create - logout if logged_in? - if params['A'] - authenticate! - else - @user = User.find_by_login(params['login']) - render :json => {salt: @user.salt} - end - end - - def update - authenticate! - @token = Token.create(:user_id => current_user.id) - session[:token] = @token.id - render :json => login_response - end - - def destroy - logout - head :no_content - end - - protected - - def login_response - handshake = session.delete(:handshake) || {} - handshake.to_hash.merge(:id => current_user.id, :token => @token.to_s) - end - - end -end diff --git a/app/controllers/v1/smtp_certs_controller.rb b/app/controllers/v1/smtp_certs_controller.rb deleted file mode 100644 index 5760645..0000000 --- a/app/controllers/v1/smtp_certs_controller.rb +++ /dev/null @@ -1,42 +0,0 @@ -class V1::SmtpCertsController < ApiController - - before_filter :require_login - before_filter :require_email_account - before_filter :fetch_identity - before_filter :require_enabled - - # POST /1/smtp_cert - def create - @cert = ClientCertificate.new common_name: current_user.email_address - @identity.register_cert(@cert) - @identity.save - render text: @cert.to_s, content_type: 'text/plain' - end - - protected - - # - # Filters - # - - def require_email_account - access_denied unless service_level.provides? 'email' - end - - def require_enabled - access_denied unless current_user.enabled? - end - - def fetch_identity - @identity = current_user.identity - end - - # - # Helper methods - # - - def service_level - current_user.effective_service_level - end - -end diff --git a/app/controllers/v1/users_controller.rb b/app/controllers/v1/users_controller.rb deleted file mode 100644 index 6640d10..0000000 --- a/app/controllers/v1/users_controller.rb +++ /dev/null @@ -1,83 +0,0 @@ -module V1 - class UsersController < ApiController - include ControllerExtension::FetchUser - - # allow optional access to this controller using API auth tokens: - before_filter :token_authenticate - - before_filter :fetch_user, :only => [:update, :destroy] - before_filter :require_monitor, :only => [:index, :show] - before_filter :require_login, :only => [:index, :update, :destroy] - - respond_to :json - - # used for autocomplete for admins in the web ui - def index - if params[:query] - @users = User.login_starts_with(params[:query]) - respond_with @users.map(&:login).sort - else - render :json => {'error' => 'query required', 'status' => :unprocessable_entity} - end - end - - def show - if params[:login] - @user = User.find_by_login(params[:login]) - elsif params[:id] - @user = User.find(params[:id]) - end - if @user - respond_with @user - else - not_found - end - end - - def create - if current_user.is_monitor? - create_test_account - elsif APP_CONFIG[:allow_registration] - create_account - else - head :forbidden - end - end - - def update - @user.account.update params[:user] - respond_with @user - end - - def destroy - destroy_identity = current_user.is_monitor? || params[:identities] == "destroy" - @user.account.destroy(destroy_identity) - if @user == current_user - logout - end - render :json => {'success' => 'user deleted'} - end - - private - - # tester auth can only create test users. - def create_test_account - if User::is_test?(params[:user][:login]) - @user = Account.create(params[:user], :invite_required => false) - respond_with @user - else - head :forbidden - end - end - - def create_account - if APP_CONFIG[:allow_registration] - @user = Account.create(params[:user]) - respond_with @user # return ID instead? - else - head :forbidden - end - end - - end -end diff --git a/app/views/api/sessions/new.json.erb b/app/views/api/sessions/new.json.erb new file mode 100644 index 0000000..36154b8 --- /dev/null +++ b/app/views/api/sessions/new.json.erb @@ -0,0 +1,3 @@ +{ +"errors": <%= raw @errors.to_json %> +} diff --git a/app/views/v1/sessions/new.json.erb b/app/views/v1/sessions/new.json.erb deleted file mode 100644 index 36154b8..0000000 --- a/app/views/v1/sessions/new.json.erb +++ /dev/null @@ -1,3 +0,0 @@ -{ -"errors": <%= raw @errors.to_json %> -} -- cgit v1.2.3