require 'sinatra/base' require 'git_fusion/util' require 'git_fusion/config_service' require 'tempfile' module GitFusion class App < Sinatra::Base include Util include ConfigParser # # repositories # get '/git-fusion/v1/repos' do require_p4 p4 = env['p4'] hws_settings = env['hws_settings'] results = p4.run_files('-e', "//#{hws_settings.GIT_FUSION_DEPOT}/repos/*/p4gf_config") repo_names = results.map do |result| m = %r{^//#{hws_settings.GIT_FUSION_DEPOT}/repos/(.*)/p4gf_config}.match(result['depotFile']) {'id'=> m[1], 'name' => HWSStrings.gf_decode(m[1])} if m end repo_names.to_json end get '/git-fusion/v1/repos/:repo' do # # Grab config for specific repo # require_p4 p4 = env['p4'] hws_settings = env['hws_settings'] result = p4.run('print', "//#{hws_settings.GIT_FUSION_DEPOT}/repos/#{params[:repo]}/p4gf_config") result.shift halt 404 if result.empty? parse_to_hash(result).to_json end put '/git-fusion/v1/repos/:repo' do # # Replace config or add a new one if specified repo does not exist # # Config is in JSON - translate that to plain and save/replace repo = HWSStrings.gf_decode(params[:repo]) validate_json_config(params[:config], repo) # at this point depot_path point to chosen repo require_p4 hws_settings = env['hws_settings'] p4 = env['p4'] current_config = p4.run('print', "//#{hws_settings.GIT_FUSION_DEPOT}/repos/#{params[:repo]}/p4gf_config") config = parse_from_json(params[:repo], params[:config]) if current_config.empty? or current_config[0]['action'] == 'delete' # repo does not exist yet or the configuration file was removed p4, file, change_id = modified_temp_client_with_a_file( "repos/#{params[:repo]}/p4gf_config", config, "Added #{repo} p4gf_config" ) p4.run('add', '-c', change_id, file.path) else # instead of an add we will perform edit p4, file, change_id = modified_temp_client_with_a_file( "repos/#{params[:repo]}/p4gf_config", config, "Modified #{repo} p4gf_config" ) p4.run('sync', '-f') p4.run('edit', '-c', change_id, file.path) File.open("#{p4.fetch_client["Root"]}/p4gf_config", 'w') do | out | out.write config end end p4.at_exception_level(P4::RAISE_NONE) do p4.run_submit( '-c', change_id ) last_error = P4Util.make_p4_error(p4) error = P4Error.error?(p4) clean_up(p4, change_id) if last_error.user_error? raise last_error if error end result = p4.run('print', "//#{hws_settings.GIT_FUSION_DEPOT}/repos/#{params[:repo]}/p4gf_config") parse_to_hash(result).to_json end patch '/git-fusion/v1/repos/:repo' do # # Replace parts of p4gf_config for specified repo # require_p4 hws_settings = env['hws_settings'] repo = HWSStrings.gf_decode(params[:repo]) p4, change_id = modified_temp_client( "repos/#{repo}/p4gf_config", 'p4gf_config', "Modified p4gf_config for #{repo}" ) p4.run('sync', '-f') p4.run('edit', '-c', change_id, "//#{p4.client}/p4gf_config") old_config = p4.run('print', "//#{hws_settings.GIT_FUSION_DEPOT}/repos/#{repo}/p4gf_config") old_config.shift config = parse_from_json(params[:repo], modify_config(old_config, params[:config], change_id, p4)) File.open("#{p4.fetch_client['Root']}/p4gf_config", 'w+') do | out | out.write config end p4.at_exception_level(P4::RAISE_NONE) do p4.run_submit( '-c', change_id ) last_error = P4Util.make_p4_error(p4) error = P4Error.error?(p4) clean_up(p4, change_id) if last_error.user_error? raise last_error if error end '' end delete '/git-fusion/v1/repos/:repo' do repo = HWSStrings.gf_decode(params[:repo]) p4 = modified_temp_client( "repos/#{repo}/...", "..." ) p4.at_exception_level(P4::RAISE_NONE) do p4.run('delete', '-v', "//#{env['hws_settings'].GIT_FUSION_DEPOT}/repos/#{repo}/...") p4.run_submit( '-d', "Removed repo config for #{repo}") end '' end # # ssh keys # get '/git-fusion/v1/keys' do # get all keys for all users with names and contents # Until we will support adding keys for another user, this method returns the same data # as the next method down. # keys = get_all_keys keys = get_keys_for_user(user) keys.to_json end get '/git-fusion/v1/keys/:user' do # get all keys for a user with names and contents user = HWSStrings.component_decode(params[:user], '%', HWSStrings::URI_ILLEGAL_CHARACTERS) raise P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user keys = get_keys_for_user(user) keys.to_json end put '/git-fusion/v1/keys/:user/*' do # add a key to user # if user already has the key under different name - exit with error # if user already had the key under the same name - exit with success # if key exists for a different user - exit with error # if a different key exists under the name - exit with error user = HWSStrings.component_decode(params[:user], '%', HWSStrings::URI_ILLEGAL_CHARACTERS) raise P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user key_name = HWSStrings.component_decode(params[:splat].first, '%', HWSStrings::URI_ILLEGAL_CHARACTERS) unless check_if_key_exists(params[:key]) # key doesn't exist anywhere in depot but file with the same name for the same user still might if check_if_key_name_exists(key_name, user) # if it does, throw error raise P4Error.default_error(KEY_ALREADY_EXISTS) end p4, file, change_id = modified_temp_client_with_a_file( "users/#{user}/keys/#{key_name}", params[:key], "Added SSH key for #{user}" ) p4.at_exception_level(P4::RAISE_NONE) do p4.run('add', '-c', change_id, file.path) p4.run_submit('-c', change_id ) last_error = P4Util.make_p4_error(p4) error = P4Error.error?(p4) clean_up(p4, change_id) if last_error.user_error? raise last_error if error end else # key is assigned to some other user or our user owner = get_by_key(params[:key], 'user') filename = get_by_key(params[:key], 'key_name') unless owner == user message = "Key is already assigned to another user (#{owner})" else if owner == user && filename != key_name message = "Key already assigned to user #{user} under name #{filename}" else # in other case - key already exists for user under the same name, skip next end end raise P4Error.default_error(message) # error_and_clean_up(message) end get_keys_for_user(user).to_json end delete '/git-fusion/v1/key/:user/*' do user = HWSStrings.component_decode(params[:user], '%', HWSStrings::URI_ILLEGAL_CHARACTERS) raise P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user key_name = HWSStrings.component_decode(params[:splat].first, '%', HWSStrings::URI_ILLEGAL_CHARACTERS) p4 = modified_temp_client( "users/#{user}/keys/#{key_name}", "#{key_name}" ) p4.at_exception_level(P4::RAISE_NONE) do p4.run('delete', '-v', "//#{env['hws_settings'].GIT_FUSION_DEPOT}/users/#{user}/keys/#{key_name}") p4.run_submit( '-d', "Removed SSH key") end '' end delete '/git-fusion/v1/key' do # Undocumented remove by SSH key key_name = get_by_key(params[:key], 'key_name') user = get_by_key(params[:key], 'user') raise P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user p4 = modified_temp_client( "users/#{user}/keys/#{key_name}", "#{key_name}" ) p4.at_exception_level(P4::RAISE_NONE) do p4.run('delete', '-v', "//#{env['hws_settings'].GIT_FUSION_DEPOT}/users/#{user}/keys/#{key_name}") p4.run_submit( '-d', "Removed SSH key") end '' end delete '/git-fusion/v1/keys/:user' do # delete all keys for user user = HWSStrings.component_decode(params[:user], '%', HWSStrings::URI_ILLEGAL_CHARACTERS) raise P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user p4 = modified_temp_client( "users/#{params[:user]}/keys/...", "..." ) p4.at_exception_level(P4::RAISE_NONE) do p4.run('delete', '-v', "//#{env['hws_settings'].GIT_FUSION_DEPOT}/users/#{user}/keys/...") p4.run_submit( '-d', "Removed SSH keys for #{user}") end '' end end end