require 'base64' require 'tempfile' require 'sinatra/base' require 'git_fusion/util' require 'git_fusion/config_parser' module GitFusion # # This web application is mostly an easy way to communicate with specified # p4d and perform operations on git-fusion repos and SSH keys # class App < Sinatra::Base include Util include ConfigParser # # repositories # get '/git-fusion/v1/repos' do p4, hws_settings = temp_client results = p4.run_files('-e', "//#{hws_settings.GIT_FUSION_DEPOT}/repos/*/p4gf_config") repo_names = results.map do |result| config_regex = %r{^//#{hws_settings.GIT_FUSION_DEPOT}/repos/(.*)/p4gf_config} m = config_regex.match(result['depotFile']) { 'id' => m[1], 'name' => GitFusionStrings.decode(m[1]) } if m end repo_names.to_json end get %r{/git-fusion/v1/repos/(.*)} do |repo| # # Grab config for specific repo # file = "//#{env['hws_settings'].GIT_FUSION_DEPOT}/repos/#{repo}/p4gf_config" result = print_result(file) halt 404 if result.empty? parse_to_hash(result).to_json end put %r{/git-fusion/v1/repos/(.*)} do |repo| # # Replace config or add a new one if specified repo does not exist # # Config is in JSON - translate that to plain and save/replace decoded_repo_name = GitFusionStrings.decode(repo) validate_json_config(params[:config], decoded_repo_name) require_p4_with_temp_client p4 = env['p4'] hws_settings = env['hws_settings'] file_path = "//#{hws_settings.GIT_FUSION_DEPOT}/repos/#{repo}/p4gf_config" config = parse_from_json(repo, params[:config]) submit_file(p4, file_path, config, "Latest p4fg_config for #{decoded_repo_name}") result = print_result(file_path, p4: p4) parse_to_hash(result).to_json end patch %r{/git-fusion/v1/repos/(.*)} do |repo| # # Replace parts of p4gf_config for specified repo # p4, hws_settings = temp_client file_path = "//#{hws_settings.GIT_FUSION_DEPOT}/repos/#{repo}/p4gf_config" decoded_repo_name = GitFusionStrings.decode(repo) old_config = print_result(file_path, p4: p4) config = parse_from_json(repo, modify_config(old_config, params[:config])) submit_file(p4, file_path, config, "Modified p4fg_config for #{decoded_repo_name}") '' end delete %r{/git-fusion/v1/repos/(.*)} do |repo| p4, hws_settings = temp_client decoded_repo_name = GitFusionStrings.decode(repo) p4.at_exception_level(P4::RAISE_NONE) do file = "//#{hws_settings.GIT_FUSION_DEPOT}/repos/#{repo}/p4gf_config" p4.run('delete', '-v', file) p4.run_submit('-d', "Removed repo config for #{decoded_repo_name}") end '' end # # user ssh keys # get %r{/git-fusion/v1/users/(.*)/keys} do |user| # get all keys for a user with names and contents user = decode_from_uri(user).first fail P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user keys = keys_for_user(user) keys.to_json end put %r{/git-fusion/v1/users/(.*)/keys/(.*)} do |user, key_name| # add a key to user user, key_name = decode_from_uri(user, key_name) fail P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user user, key_name = encode_to_gf_format(user, key_name) 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 fail P4Error.default_error(KEY_ALREADY_EXISTS) end require_p4_with_temp_client p4 = env['p4'] key_path = "//#{env['hws_settings'].GIT_FUSION_DEPOT}/users/#{user}/keys/#{key_name}" submit_file(p4, key_path, params[:key], "Added SSH key for #{user}") 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') if owner == user if 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 next end else message = "Key is already assigned to another user (#{owner})" end fail P4Error.default_error(message) end keys_for_user(user).to_json end delete %r{/git-fusion/v1/users/(.*)/keys/(.*)} do |user, key_name| # delete a key for a user by its name # decode username and key_name form URL user, key_name = decode_from_uri(user, key_name) fail P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user p4, hws_settings = temp_client # encode it into git-fusion format so we get a valid perforce path user, key_name = encode_to_gf_format(user, key_name) p4.at_exception_level(P4::RAISE_NONE) do file = "//#{hws_settings.GIT_FUSION_DEPOT}/users/#{user}/keys/#{key_name}" p4.run('delete', '-v', file) p4.run_submit('-d', 'Removed SSH key') end '' end delete %r{/git-fusion/v1/users/(.*)/keys} do |user| # decode username and key_name form URL user = decode_from_uri(user).first fail P4Error.default_error(USER_NOT_MATCHING) if user != env['p4'].user p4, hws_settings = temp_client # encode it into git-fusion format so we get a valid perforce path user = encode_to_gf_format(user).first p4.at_exception_level(P4::RAISE_NONE) do file = "//#{hws_settings.GIT_FUSION_DEPOT}/users/#{user}/keys/..." p4.run('delete', '-v', file) p4.run_submit('-d', "Removed SSH keys for #{user}") end end end end