class SiteConstruct include Mongoid::Document include Mongoid::Timestamps def self.server_types SiteServer.all.map{|s| s.server_name} end SITE_TYPES = ["School","Gravity"] field :rails_env, type: String, :default => "development" field :server_type field :site_name field :domain_name field :nginx_file field :db_name field :port, type: Array, :default => ["80"] field :path field :site_type field :school_name field :user_id field :constructed, type: Boolean, :default => false field :status, type: String, :default => "" field :infos, type: Array, :default => [] field :hidden, type: Boolean, :default => false field :copy_id field :only_copy_installed_module, type: Boolean, :default => false field :redirect_to_https, type: Boolean, :default => false field :cert_ver_added_text field :cert_ver_file_content field :cert_ver_location_path belongs_to :site_cert after_initialize do |record| unless record.new_record? save_flag = false if record.status.nil? record.status = "" save_flag = true end if record.infos.nil? record.infos = [] save_flag = true end if record.nginx_file.nil? record.nginx_file = "/etc/nginx/orbit_sites/"+record.site_name.to_s save_flag = true end if record.path.nil? dir_path = ((record.site_type == "School" && !record.school_name.blank?) ? "school_sites/#{record.school_name}" : "orbit_sites") record.path = "/home/rulingcom/#{dir_path}" save_flag = true end if record["port"].class == String record["port"] = Array(record["port"]) save_flag = true end if save_flag && !@skip_callback @skip_callback = true record.save(:validate=>false) end @skip_callback = false end end def generate_nginx_text(old_nginx_text="") sock_text = 'upstream '+self.get_site_name+'_sock {\n'+ ' server unix:'+self.full_site_path+'/tmp/unicorn.sock;\n'+ '}\n' all_ports = self.port.uniq server_blocks = [] if old_nginx_text.present? all_blocks = parse_nginx_text_to_server_blocks(old_nginx_text,true) server_blocks = all_blocks.select{|s| s.match(/\A[\s\r\n]*server\s*{/)} upstream_block = all_blocks.select{|s| s.match(/\A[\s\r\n]*upstream/)}.first rescue nil if upstream_block.present? sock_text = upstream_block + '\n' end end nginx_text = sock_text + all_ports.map.with_index{|port,i| if server_blocks[i].present? generate_server_block(port,server_blocks[i]) else generate_server_block(port,server_blocks[0]) end }.join('\n') end def match_exact_index(text,match_character,level=1) text.enum_for(:scan,/(?:[^#{match_character}])#{match_character}{#{level}}(?!#{match_character})/m).map { offset_index=Regexp.last_match.to_s.index(match_character);Regexp.last_match.offset(0).first + offset_index} end def parse_nginx_text_to_server_blocks(nginx_text,get_all_blocks=false,level=1) num = 1 nginx_text_tmp = nginx_text.gsub(/({|})/m){|ff| res = ff;((ff == '{') ? (res = ff * num;num = num + 1) : (num = num - 1;res = ff * num;)); res} end_indices = match_exact_index(nginx_text_tmp,'}',level) start_indices = match_exact_index(nginx_text_tmp,'{',level) start_indices = start_indices.map{|i| (i - nginx_text_tmp[0...i].reverse.index(/(}|;)/m)) rescue 0} all_blocks = (0...end_indices.count).map{|i| nginx_text_tmp[start_indices[i]..end_indices[i]]} all_blocks = all_blocks.map{|s| s.gsub(/[{}]+/){|ff| ff[0]}.strip} server_blocks = all_blocks.select{|s| s.match(/\A[\s\r\n]*server\s*{/)} if get_all_blocks all_blocks else server_blocks end end def generate_server_block(port,old_server_block="") if port.blank? port = "80" else port = port.to_s end port_text = port if port.to_i == 443 if self.site_cert.nil? return "" end port_text += " ssl" end if old_server_block.present? new_server_block = old_server_block.gsub(/(listen\s+)[^;]+/){|ff| "#{$1}#{port_text}"} domain_name = self.domain_name new_server_block = new_server_block.gsub(/(server_name\s+)[^;]+/m){|ff| "#{$1}#{domain_name}"} new_server_block = new_server_block.gsub(/\s*ssl_certificate[^;]+;/,'') level_2_block = parse_nginx_text_to_server_blocks(old_server_block,true,2) get_redirect_block = level_2_block.select{|t| t.match(/\s*return\s+30[12]\s+https:\/\/\$host\$request_uri\s*;/)} location_app_block = level_2_block.select{|t| t.match(/location\s+@app/)} if get_redirect_block.count > 0 get_redirect_block.each do |redirect_block| new_server_block = new_server_block.gsub(redirect_block,'') end end if location_app_block.count > 0 location_app_block = location_app_block.map do |app_block| new_app_block = app_block.gsub(/proxy_set_header\s+X-Forwarded-Proto\s+https\s*;/,"") new_server_block = new_server_block.gsub(app_block,new_app_block) new_app_block end end if port == "443" new_server_block = new_server_block.gsub(/(listen\s+)[^;]+;/){|ff| ff + "\n\n ssl_certificate #{self.cert_file_remote_store_path};\n\n ssl_certificate_key #{self.private_key_remote_store_path};\n\n"} location_app_block.each do |app_block| new_app_block = app_block.gsub(/proxy_set_header\s+Host\s+\$http_host\s*;/){|ff| ff + "\n proxy_set_header X-Forwarded-Proto https;"} new_server_block = new_server_block.gsub(app_block,new_app_block) end else if self.redirect_to_https && !self.site_cert.nil? new_server_block = new_server_block.sub(/(listen\s+)[^;]+;[\s\r\n]*/){|ff| ff + " if ($host ~ (#{self.site_cert.domain_names.map{|s| '^'+s.gsub('.','\.').gsub('*','[^.]*').gsub(',','')}.join('|')}) ) {\n"+ " return 301 https://$host$request_uri;\n"+ " }\n"} end end new_server_block = new_server_block.gsub(/[ \t\s]+\n/,"\n\n").gsub(/\n{3,}/,'\n\n') else 'server {\n'+ ' listen '+port_text+';\n\n'+ (port == "443" ? " ssl_certificate #{self.cert_file_remote_store_path};\n\n"+ " ssl_certificate_key #{self.private_key_remote_store_path};\n\n"+ ((self.redirect_to_https && !self.site_cert.nil?) ? " if ($host ~ (#{self.site_cert.domain_names.map{|s| '^'+s.gsub('.','\.').gsub('*','[^.]*').gsub(',','')}.join('|')}) ) {\n"+ " return 301 https://$host$request_uri;\n"+ "}\n" : '') : '')+ ' root '+self.full_site_path+'/public;\n\n'+ ' server_name '+self.domain_name+';\n\n'+ ' client_max_body_size 500m;\n\n'+ ' location / {\n'+ ' try_files \$uri \$uri/index.html \$uri.html @app;\n'+ ' }\n\n'+ ' location @app {\n'+ ' proxy_redirect off;\n'+ ' proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;\n'+ ' proxy_set_header Host \$http_host;\n'+ (port == "443" ? ' proxy_set_header X-Forwarded-Proto https;\n' : '')+ ' proxy_connect_timeout 360;\n'+ ' proxy_pass http://'+self.get_site_name+'_sock;\n'+ ' }\n'+ '}' end end def display_port self.port.map{|port| "#{port}"}.join("
").html_safe end def get_host_with_port(port) self.domain_name.split().first end def get_port(idx=0) self.port[idx] rescue "80" end def full_site_path return "#{self.get_path}/#{self.get_site_name}" end def cert_file_remote_store_path site_cert = self.site_cert "#{self.full_site_path}/ssl_certs/#{site_cert.id}/#{site_cert["cert_file"]}" end def private_key_remote_store_path site_cert = self.site_cert "#{self.full_site_path}/ssl_certs/#{site_cert.id}/#{site_cert["private_key"]}" end def get_path return self.path.to_s.gsub(" ","\\ ") end def get_site_name return self.site_name.to_s.gsub(" ","\\ ") end def get_domain_name(port=nil) scheme = "" extra_port = "" port = self.get_port if port.nil? if port == "443" scheme = "https://" else scheme = "http://" if port != "80" extra_port = ":#{port}" end end return (scheme + self.domain_name.split(" ").first + extra_port) end def site_server SiteServer.where(server_name: self.server_type).first end end