2017-11-30 09:00:26 +00:00
|
|
|
class SiteConstruct
|
|
|
|
include Mongoid::Document
|
|
|
|
include Mongoid::Timestamps
|
2021-01-28 03:10:41 +00:00
|
|
|
def self.server_types
|
2023-02-03 05:45:11 +00:00
|
|
|
SiteServer.where(:active.ne=>false).map{|s| s.server_name}
|
2021-01-28 03:10:41 +00:00
|
|
|
end
|
2017-11-30 09:00:26 +00:00
|
|
|
SITE_TYPES = ["School","Gravity"]
|
2021-10-08 12:04:38 +00:00
|
|
|
field :enable_redirect_default_domain, type: Integer, default: 0 #0 => use default, 1 => disable, 2 => enable
|
|
|
|
field :default_domain_idx, type: Integer, default: -1 #-1 present use default
|
2021-04-14 10:55:07 +00:00
|
|
|
field :rails_env, type: String, :default => "development"
|
2017-11-30 09:00:26 +00:00
|
|
|
field :server_type
|
|
|
|
field :site_name
|
|
|
|
field :domain_name
|
2021-01-19 04:48:03 +00:00
|
|
|
field :nginx_file
|
2017-11-30 09:00:26 +00:00
|
|
|
field :db_name
|
2021-04-19 01:29:53 +00:00
|
|
|
field :port, type: Array, :default => ["80"]
|
2017-11-30 09:00:26 +00:00
|
|
|
field :path
|
|
|
|
field :site_type
|
|
|
|
field :school_name
|
|
|
|
field :user_id
|
|
|
|
field :constructed, type: Boolean, :default => false
|
2020-04-24 14:38:28 +00:00
|
|
|
field :status, type: String, :default => ""
|
|
|
|
field :infos, type: Array, :default => []
|
2021-01-19 04:48:03 +00:00
|
|
|
field :hidden, type: Boolean, :default => false
|
2021-02-23 06:18:25 +00:00
|
|
|
field :copy_id
|
2021-04-13 03:06:09 +00:00
|
|
|
field :only_copy_installed_module, type: Boolean, :default => false
|
2021-04-19 12:35:16 +00:00
|
|
|
field :redirect_to_https, type: Boolean, :default => false
|
2021-02-24 10:44:09 +00:00
|
|
|
field :cert_ver_added_text
|
|
|
|
field :cert_ver_file_content
|
|
|
|
field :cert_ver_location_path
|
2022-11-14 04:56:29 +00:00
|
|
|
field :super_user_changed, type: Boolean, type: false
|
|
|
|
field :removed_super_users, type: Array, default: []
|
2021-04-19 01:29:53 +00:00
|
|
|
belongs_to :site_cert
|
2022-11-14 04:56:29 +00:00
|
|
|
has_many :site_super_users, :autosave => true, :dependent => :destroy
|
|
|
|
accepts_nested_attributes_for :site_super_users, :allow_destroy => true
|
2020-04-28 13:26:49 +00:00
|
|
|
after_initialize do |record|
|
2021-04-19 01:29:53 +00:00
|
|
|
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
|
2020-04-28 13:26:49 +00:00
|
|
|
end
|
2021-04-19 01:29:53 +00:00
|
|
|
end
|
2022-11-14 04:56:29 +00:00
|
|
|
def check_super_user_changed
|
|
|
|
self.update(:super_user_changed => (self.site_super_users.where(:is_changed=>true).count != 0 || self.removed_super_users.count != 0))
|
|
|
|
end
|
2021-04-19 01:29:53 +00:00
|
|
|
def generate_nginx_text(old_nginx_text="")
|
2022-09-08 06:48:32 +00:00
|
|
|
sock_text = "upstream #{self.get_site_name}_sock {\n"+
|
|
|
|
" server unix:#{self.full_site_path}/tmp/unicorn.sock;\n"+
|
|
|
|
"}\n"
|
2021-04-19 01:29:53 +00:00
|
|
|
all_ports = self.port.uniq
|
|
|
|
server_blocks = []
|
2022-11-14 04:48:04 +00:00
|
|
|
port_server_blocks_relation = {}
|
2021-04-19 01:29:53 +00:00
|
|
|
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?
|
2022-09-08 06:48:32 +00:00
|
|
|
sock_text = upstream_block + "\n"
|
2021-04-19 01:29:53 +00:00
|
|
|
end
|
2022-11-14 04:48:04 +00:00
|
|
|
server_blocks.each_with_index do |server_block, i|
|
|
|
|
tmp_ports = server_block.gsub(/(^|\s+|;)listen\s+(\d+)/).map{$2}
|
|
|
|
tmp_ports.each do |port|
|
|
|
|
port_server_blocks_relation[port] = i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
all_ports.each do |port|
|
|
|
|
tmp = port_server_blocks_relation[port]
|
|
|
|
if tmp.nil?
|
|
|
|
port_server_blocks_relation[port] = 0
|
|
|
|
end
|
2020-04-28 13:26:49 +00:00
|
|
|
end
|
2022-11-14 04:48:04 +00:00
|
|
|
nginx_text = sock_text + port_server_blocks_relation.map{|port,i|
|
2021-04-19 01:29:53 +00:00
|
|
|
if server_blocks[i].present?
|
|
|
|
generate_server_block(port,server_blocks[i])
|
|
|
|
else
|
|
|
|
generate_server_block(port,server_blocks[0])
|
|
|
|
end
|
2022-09-08 06:48:32 +00:00
|
|
|
}.join("\n").gsub("\n", '\n')
|
2021-04-19 01:29:53 +00:00
|
|
|
end
|
2021-04-19 12:35:16 +00:00
|
|
|
def match_exact_index(text,match_character,level=1)
|
2021-12-09 09:59:15 +00:00
|
|
|
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}
|
2021-04-19 12:35:16 +00:00
|
|
|
end
|
|
|
|
def parse_nginx_text_to_server_blocks(nginx_text,get_all_blocks=false,level=1)
|
2021-04-19 01:29:53 +00:00
|
|
|
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}
|
2021-04-19 12:35:16 +00:00
|
|
|
end_indices = match_exact_index(nginx_text_tmp,'}',level)
|
|
|
|
start_indices = match_exact_index(nginx_text_tmp,'{',level)
|
2022-11-14 04:48:04 +00:00
|
|
|
start_indices = start_indices.map.with_index{|i, j| (i - nginx_text_tmp[(j == 0 ? 0 : start_indices[j-1])...i].reverse.index(/(}|;|\n)/m)) rescue 0}
|
2021-04-19 12:35:16 +00:00
|
|
|
all_blocks = (0...end_indices.count).map{|i| nginx_text_tmp[start_indices[i]..end_indices[i]]}
|
2021-04-19 01:29:53 +00:00
|
|
|
all_blocks = all_blocks.map{|s| s.gsub(/[{}]+/){|ff| ff[0]}.strip}
|
|
|
|
if get_all_blocks
|
|
|
|
all_blocks
|
|
|
|
else
|
2022-11-14 04:48:04 +00:00
|
|
|
server_blocks = all_blocks.select{|s| s.match(/\A[\s\r\n]*server\s*{/)}
|
2021-04-19 01:29:53 +00:00
|
|
|
server_blocks
|
2021-01-19 04:48:03 +00:00
|
|
|
end
|
2021-04-19 01:29:53 +00:00
|
|
|
end
|
|
|
|
def generate_server_block(port,old_server_block="")
|
|
|
|
if port.blank?
|
|
|
|
port = "80"
|
|
|
|
else
|
|
|
|
port = port.to_s
|
2021-01-19 04:48:03 +00:00
|
|
|
end
|
2021-12-30 07:32:07 +00:00
|
|
|
default_domain = get_default_domain
|
|
|
|
redirect_default_text = get_redirect_default_text(port, default_domain)
|
2021-04-19 01:29:53 +00:00
|
|
|
port_text = port
|
|
|
|
if port.to_i == 443
|
|
|
|
if self.site_cert.nil?
|
|
|
|
return ""
|
|
|
|
end
|
|
|
|
port_text += " ssl"
|
|
|
|
end
|
2021-12-30 07:32:07 +00:00
|
|
|
domain_name_str = self.domain_name
|
|
|
|
if default_domain.present?
|
2021-12-30 07:49:56 +00:00
|
|
|
domain_name_str = ((domain_name_str.split(/\s+/) - [default_domain]) + [default_domain]).join(" ")
|
2021-12-30 07:32:07 +00:00
|
|
|
end
|
2021-04-19 01:29:53 +00:00
|
|
|
if old_server_block.present?
|
2022-10-16 07:13:12 +00:00
|
|
|
new_server_block = old_server_block.gsub('\n',"\n").gsub(/(listen\s+)[^;]+/){|ff| "#{$1}#{port_text}"}
|
|
|
|
if port_text == "80"
|
2023-05-20 02:56:15 +00:00
|
|
|
new_server_block = new_server_block.gsub(/^(?:(?!{|}).)*#\s*managed by Certbot(\n|$)/,'')
|
2022-10-16 07:13:12 +00:00
|
|
|
else
|
|
|
|
if self.site_cert && !(self.site_cert.is_certbot)
|
2023-05-20 02:41:26 +00:00
|
|
|
new_server_block = new_server_block.gsub(/[ \t]*#\s*managed by Certbot/,'')
|
2022-10-16 07:13:12 +00:00
|
|
|
end
|
|
|
|
end
|
2021-12-30 07:32:07 +00:00
|
|
|
new_server_block = new_server_block.gsub(/(server_name\s+)[^;]+/m){|ff| "#{$1}#{domain_name_str}"}
|
2021-04-19 01:29:53 +00:00
|
|
|
new_server_block = new_server_block.gsub(/\s*ssl_certificate[^;]+;/,'')
|
2021-04-29 06:50:03 +00:00
|
|
|
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*;/)}
|
2021-10-08 12:04:38 +00:00
|
|
|
get_redirect_to_default_block = level_2_block.select{|t| t.match(/\s*return\s+30[12]\s+http(s|):\/\/[^\$]+\$request_uri\s*;/)}
|
2021-04-29 06:50:03 +00:00
|
|
|
location_app_block = level_2_block.select{|t| t.match(/location\s+@app/)}
|
2021-04-26 01:54:52 +00:00
|
|
|
if get_redirect_block.count > 0
|
|
|
|
get_redirect_block.each do |redirect_block|
|
|
|
|
new_server_block = new_server_block.gsub(redirect_block,'')
|
|
|
|
end
|
|
|
|
end
|
2021-10-08 12:04:38 +00:00
|
|
|
if get_redirect_to_default_block.count > 0
|
|
|
|
get_redirect_to_default_block.each do |redirect_block|
|
|
|
|
new_server_block = new_server_block.gsub(redirect_block,'')
|
|
|
|
end
|
|
|
|
end
|
2021-04-29 06:50:03 +00:00
|
|
|
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
|
2021-04-19 01:29:53 +00:00
|
|
|
if port == "443"
|
2021-04-19 12:35:16 +00:00
|
|
|
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"}
|
2021-04-29 06:50:03 +00:00
|
|
|
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
|
2021-04-19 12:35:16 +00:00
|
|
|
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
|
2021-04-19 01:29:53 +00:00
|
|
|
end
|
2021-10-08 12:04:38 +00:00
|
|
|
if redirect_default_text.present?
|
|
|
|
new_server_block = new_server_block.sub(/\s*root/){|ff| redirect_default_text + ff}
|
|
|
|
end
|
2022-09-08 06:48:32 +00:00
|
|
|
new_server_block = new_server_block.gsub(/[\s]+\n/,"\n\n").gsub(/\n{3,}/,"\n\n").gsub("\n", '\n')
|
2021-04-19 01:29:53 +00:00
|
|
|
else
|
2022-09-08 06:48:32 +00:00
|
|
|
new_server_block = "server {\n"+
|
|
|
|
" listen #{port_text};\n\n"+
|
2021-04-19 12:35:16 +00:00
|
|
|
(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"+
|
2022-09-08 06:48:32 +00:00
|
|
|
" }\n" : '') : '')+
|
2021-10-08 12:04:38 +00:00
|
|
|
redirect_default_text +
|
2022-09-08 06:48:32 +00:00
|
|
|
" root #{self.full_site_path}/public;\n\n"+
|
|
|
|
" server_name #{domain_name_str};\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"+
|
|
|
|
"}"
|
|
|
|
new_server_block.gsub("\n", '\n')
|
2021-04-19 01:29:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
def display_port
|
|
|
|
self.port.map{|port| "<a href=\"#{get_domain_name(port)}\" title=\"#{port}\" target=\"_blank\">#{port}</a>"}.join("<br>").html_safe
|
|
|
|
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
|
2022-10-16 07:13:12 +00:00
|
|
|
if site_cert.source_paths.present? && site_cert.source_paths.count == 2
|
|
|
|
site_cert.source_paths[0]
|
|
|
|
else
|
|
|
|
"#{self.full_site_path}/ssl_certs/#{site_cert.id}/#{site_cert["cert_file"]}"
|
|
|
|
end
|
2021-04-19 01:29:53 +00:00
|
|
|
end
|
|
|
|
def private_key_remote_store_path
|
|
|
|
site_cert = self.site_cert
|
2022-10-16 07:13:12 +00:00
|
|
|
if site_cert.source_paths.present? && site_cert.source_paths.count == 2
|
|
|
|
site_cert.source_paths[1]
|
|
|
|
else
|
|
|
|
"#{self.full_site_path}/ssl_certs/#{site_cert.id}/#{site_cert["private_key"]}"
|
|
|
|
end
|
2021-04-19 01:29:53 +00:00
|
|
|
end
|
|
|
|
def get_path
|
|
|
|
return self.path.to_s.gsub(" ","\\ ")
|
2020-04-28 13:26:49 +00:00
|
|
|
end
|
2021-02-21 03:59:36 +00:00
|
|
|
def get_site_name
|
2021-04-19 01:29:53 +00:00
|
|
|
return self.site_name.to_s.gsub(" ","\\ ")
|
2021-02-21 03:59:36 +00:00
|
|
|
end
|
2021-04-19 01:29:53 +00:00
|
|
|
def get_domain_name(port=nil)
|
2021-02-16 08:49:58 +00:00
|
|
|
scheme = ""
|
|
|
|
extra_port = ""
|
2021-04-19 01:29:53 +00:00
|
|
|
port = self.get_port if port.nil?
|
|
|
|
if port == "443"
|
2021-02-16 08:49:58 +00:00
|
|
|
scheme = "https://"
|
|
|
|
else
|
|
|
|
scheme = "http://"
|
2021-04-19 01:29:53 +00:00
|
|
|
if port != "80"
|
|
|
|
extra_port = ":#{port}"
|
2021-02-16 08:49:58 +00:00
|
|
|
end
|
|
|
|
end
|
2021-04-19 01:29:53 +00:00
|
|
|
return (scheme + self.domain_name.split(" ").first + extra_port)
|
2021-02-16 08:49:58 +00:00
|
|
|
end
|
2021-02-17 16:59:11 +00:00
|
|
|
def site_server
|
|
|
|
SiteServer.where(server_name: self.server_type).first
|
|
|
|
end
|
2022-11-14 04:48:04 +00:00
|
|
|
def get_default_domain(force_get=false)
|
2021-10-08 12:04:38 +00:00
|
|
|
custom_default_domain_name = ""
|
|
|
|
domain_names = domain_name.strip().split(" ")
|
|
|
|
if default_domain_idx == -1
|
2021-10-08 12:12:01 +00:00
|
|
|
site_server.default_domain_names.each do |default_domain_name|
|
2021-12-09 09:59:15 +00:00
|
|
|
default_domain_name = ::Regexp.new("\\A"+default_domain_name.gsub(".","\\.").gsub("*","[^.]*"))
|
2021-10-08 12:12:01 +00:00
|
|
|
custom_default_domain_name = domain_names.select{|n| n.match(default_domain_name) }.first
|
|
|
|
break if custom_default_domain_name.present?
|
|
|
|
end
|
2022-11-14 04:48:04 +00:00
|
|
|
if force_get && custom_default_domain_name.blank?
|
|
|
|
custom_default_domain_name = domain_names[0]
|
|
|
|
end
|
2021-10-08 12:04:38 +00:00
|
|
|
else
|
|
|
|
custom_default_domain_name = domain_names[default_domain_idx]
|
|
|
|
end
|
|
|
|
custom_default_domain_name
|
|
|
|
end
|
|
|
|
def get_enable_redirect_default_domain
|
|
|
|
(self.enable_redirect_default_domain == 0 ? site_server.enable_redirect_default_domain : ((self.enable_redirect_default_domain - 1) == 1) rescue false)
|
|
|
|
end
|
|
|
|
def default_enable_redirect_default_domain
|
|
|
|
site_server.enable_redirect_default_domain rescue false
|
|
|
|
end
|
2021-12-30 07:32:07 +00:00
|
|
|
def get_redirect_default_text(port=80,default_domain=nil)
|
2021-10-08 12:04:38 +00:00
|
|
|
port = port.to_i
|
|
|
|
is_enable = get_enable_redirect_default_domain
|
|
|
|
scheme = (port == 443 ? "https" : "http")
|
|
|
|
port_text = ((port == 80 || port == 443 || port.blank?) ? "" : ":#{port}")
|
|
|
|
text = ""
|
|
|
|
if is_enable
|
2021-12-30 07:32:07 +00:00
|
|
|
default_domain = get_default_domain if default_domain.nil?
|
2021-10-08 12:04:38 +00:00
|
|
|
if default_domain.present?
|
|
|
|
text = "\n\n if ($host !~* (^#{default_domain.gsub('.','\.')}$) ) {\n"+
|
|
|
|
" return 302 #{scheme}://#{default_domain}#{port_text}$request_uri;\n"+
|
|
|
|
" }\n\n"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
text
|
|
|
|
end
|
2017-11-30 09:00:26 +00:00
|
|
|
end
|