<commit_before>require "pathname"
require "shellwords"
require "uri"

require_relative "../git_providers/bitbucket"
require_relative "../git_providers/git_providers"
require_relative "../git_providers/github"
require_relative "../git_providers/gitlab"
require_relative "../site"
require_relative "../wordlist"
require_relative "base"

module Tint
	module Controllers
		class Site < Base
			get "/" do
				if ENV['SITE_PATH']
					authorize site, :index?
					slim :"site/index", locals: { site: site }
				else
					authorize Tint::Site, :index?

					git_providers = Tint.db[:identities].where(user_id: pundit_user.user_id).map do |identity|
						GitProviders.build(identity[:provider], identity[:omniauth])
					end.compact

					sites = policy_scope(Tint::Site)
					repos = sites.map { |site| site.remote }

					slim :index, locals: { sites: sites, repos: repos, git_providers: git_providers }
				end
			end

			post "/" do
				authorize Tint::Site, :create?

				site_id = Tint.db.transaction do
					begin
						subdomain = WORDLIST.sample(3).join('-')
						site_id = Tint.db[:sites].insert(
							fn: params[:fn],
							remote: params[:remote],
							domain: DOMAIN && "#{subdomain}.#{DOMAIN}"
						)
						Tint.db[:site_users].insert(
							site_id: site_id,
							user_id: pundit_user.user_id,
							role: "owner"
						)
					rescue Sequel::UniqueConstraintViolation
						retry
					end

					if params[:provider]
						identity = Tint.db[:identities][user_id: pundit_user.user_id, provider: params[:provider]]
						if identity && (provider = GitProviders.build(identity[:provider], identity[:omniauth]))
							provider.add_deploy_key(params[:remote], Tint::Site.new(site_id: site_id).ssh_public_key_path.read)
							provider.subscribe(params[:remote], "#{ENV.fetch("APP_URL")}/#{site_id}/sync")
						end
					end

					site_id
				end

				redirect to("/#{site_id}/")
			end

			namespace "/:site" do
				get "/", params: :invite do
					authorize site, :accept_invitation?

					invite = Tint.db[:site_invites].
						where(site_id: params[:site], invite_code: params[:invite]).
						where("expires_at > ?", Time.now.utc).first

					if invite
						Tint.db[:site_users].insert(
							site_id: params[:site].to_i,
							user_id: pundit_user.user_id,
							role: invite[:role]
						)

						redirect(site.route)
					else
						status 404
						slim :error, locals: { message: "Not a valid invite code." }
					end
				end

				get "/" do
					authorize site, :index?

					unless site.git?
						Thread.new { site.clone }
					end

					slim :"site/index", locals: { site: site }
				end

				put "/" do
					authorize site, :update?

					params["domain"] = "#{params[:subdomain]}.#{DOMAIN}" if params[:subdomain]

					updated_attributes = [:fn, :remote, :domain, :show_config_warning].select { |key|
						params.has_key?(key.to_s)
					}.each_with_object({}) { |key, update|
						update[key] = translate(params[key])
					}

					Tint.db[:sites].where(site_id: params[:site]).update(updated_attributes)

					site.clear_cache!

					redirect to(site.route)
				end

				delete "/" do
					authorize site, :destroy?

					site.clear_cache!
					Tint.db[:sites].where(site_id: params[:site]).delete

					redirect to("/")
				end
			end

			namespace "/:site/users" do
				get "/" do
					authorize site, :manage_users?
					users = Tint.db[:users].where(user_id: site.users.map { |u| u[:user_id] }).map do |user|
						role = site.users.find { |u| u[:user_id] == user[:user_id] }
						user.merge(role: role[:role])
					end

					slim :"site/users", locals: {
						site: site,
						users: users,
						owner_invite: invite_for("owner"),
						client_invite: invite_for("client")
					}
				end
			end

		protected

			def invite_for(role)
				invite = Tint.db[:site_invites].
							where(site_id: params["site"].to_i, role: role).
							where("expires_at > ?", Time.now.utc + 432000 - 3600).first
				unless invite
					invite = {
						invite_code: SecureRandom.urlsafe_base64,
						expires_at: Time.now.utc + 432000,
						site_id: params["site"].to_i,
						role: role
					}

					Tint.db[:site_invites].insert(invite)
				end

				invite
			end

			def translate(value)
				case value
				when "false"
					false
				when "true"
					true
				else
					value
				end
			end
		end
	end
end
<commit_msg>Remove SSH key when removing a site<commit_after>require "pathname"
require "shellwords"
require "uri"

require_relative "../git_providers/bitbucket"
require_relative "../git_providers/git_providers"
require_relative "../git_providers/github"
require_relative "../git_providers/gitlab"
require_relative "../site"
require_relative "../wordlist"
require_relative "base"

module Tint
	module Controllers
		class Site < Base
			get "/" do
				if ENV['SITE_PATH']
					authorize site, :index?
					slim :"site/index", locals: { site: site }
				else
					authorize Tint::Site, :index?

					git_providers = Tint.db[:identities].where(user_id: pundit_user.user_id).map do |identity|
						GitProviders.build(identity[:provider], identity[:omniauth])
					end.compact

					sites = policy_scope(Tint::Site)
					repos = sites.map { |site| site.remote }

					slim :index, locals: { sites: sites, repos: repos, git_providers: git_providers }
				end
			end

			post "/" do
				authorize Tint::Site, :create?

				site_id = Tint.db.transaction do
					begin
						subdomain = WORDLIST.sample(3).join('-')
						site_id = Tint.db[:sites].insert(
							fn: params[:fn],
							remote: params[:remote],
							domain: DOMAIN && "#{subdomain}.#{DOMAIN}"
						)
						Tint.db[:site_users].insert(
							site_id: site_id,
							user_id: pundit_user.user_id,
							role: "owner"
						)
					rescue Sequel::UniqueConstraintViolation
						retry
					end

					if params[:provider]
						identity = Tint.db[:identities][user_id: pundit_user.user_id, provider: params[:provider]]
						if identity && (provider = GitProviders.build(identity[:provider], identity[:omniauth]))
							provider.add_deploy_key(params[:remote], Tint::Site.new(site_id: site_id).ssh_public_key_path.read)
							provider.subscribe(params[:remote], "#{ENV.fetch("APP_URL")}/#{site_id}/sync")
						end
					end

					site_id
				end

				redirect to("/#{site_id}/")
			end

			namespace "/:site" do
				get "/", params: :invite do
					authorize site, :accept_invitation?

					invite = Tint.db[:site_invites].
						where(site_id: params[:site], invite_code: params[:invite]).
						where("expires_at > ?", Time.now.utc).first

					if invite
						Tint.db[:site_users].insert(
							site_id: params[:site].to_i,
							user_id: pundit_user.user_id,
							role: invite[:role]
						)

						redirect(site.route)
					else
						status 404
						slim :error, locals: { message: "Not a valid invite code." }
					end
				end

				get "/" do
					authorize site, :index?

					unless site.git?
						Thread.new { site.clone }
					end

					slim :"site/index", locals: { site: site }
				end

				put "/" do
					authorize site, :update?

					params["domain"] = "#{params[:subdomain]}.#{DOMAIN}" if params[:subdomain]

					updated_attributes = [:fn, :remote, :domain, :show_config_warning].select { |key|
						params.has_key?(key.to_s)
					}.each_with_object({}) { |key, update|
						update[key] = translate(params[key])
					}

					Tint.db[:sites].where(site_id: params[:site]).update(updated_attributes)

					site.clear_cache!

					redirect to(site.route)
				end

				delete "/" do
					authorize site, :destroy?

					site.clear_cache!
					site.ssh_public_key_path.unlink
					site.ssh_private_key_path.unlink
					Tint.db[:sites].where(site_id: params[:site]).delete

					redirect to("/")
				end
			end

			namespace "/:site/users" do
				get "/" do
					authorize site, :manage_users?
					users = Tint.db[:users].where(user_id: site.users.map { |u| u[:user_id] }).map do |user|
						role = site.users.find { |u| u[:user_id] == user[:user_id] }
						user.merge(role: role[:role])
					end

					slim :"site/users", locals: {
						site: site,
						users: users,
						owner_invite: invite_for("owner"),
						client_invite: invite_for("client")
					}
				end
			end

		protected

			def invite_for(role)
				invite = Tint.db[:site_invites].
							where(site_id: params["site"].to_i, role: role).
							where("expires_at > ?", Time.now.utc + 432000 - 3600).first
				unless invite
					invite = {
						invite_code: SecureRandom.urlsafe_base64,
						expires_at: Time.now.utc + 432000,
						site_id: params["site"].to_i,
						role: role
					}

					Tint.db[:site_invites].insert(invite)
				end

				invite
			end

			def translate(value)
				case value
				when "false"
					false
				when "true"
					true
				else
					value
				end
			end
		end
	end
end

{'fraction_non_alphanumeric': 0.13757816941444, 'fraction_numerical': 0.005002842524161455, 'mean_word_length': 2.744572158365262, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6682529', 'n_tokens_mistral': 4116, 'n_tokens_neox': 2960, 'n_words': 614}