Add cert setting.

This commit is contained in:
BoHung Chiu 2021-04-19 09:29:53 +08:00
parent bb35c3ee10
commit 951aef1b72
24 changed files with 772 additions and 112 deletions

View File

@ -1,10 +1,57 @@
class Admin::SitePanelController < OrbitAdminController class Admin::SitePanelController < OrbitAdminController
def initialize def initialize
super super
@app_title = "client_management" @app_title = "client_management"
end end
def upload_cert
@site_cert = SiteCert.new
end
def edit_cert
@site_cert = SiteCert.find(params[:site_panel_id])
end
def update_cert
@site_cert = SiteCert.find(params[:site_panel_id])
@site_cert.update_attributes(site_cert_params)
redirect_to cert_management_admin_site_panel_index_path
end
def create_cert
@site_cert = SiteCert.create(site_cert_params)
redirect_to cert_management_admin_site_panel_index_path
end
def destroy_cert
@site_cert = SiteCert.find(params[:site_panel_id])
@site_cert.destroy
redirect_to cert_management_admin_site_panel_index_path
end
def get_certs_for_site
site_construct = SiteConstruct.find(params[:id]) rescue nil
domain_name = site_construct.domain_name rescue ""
domain_names = domain_name.split(" ").select{|s| s.present?}
domain_names_count = domain_names.count
(0...domain_names_count).each do |i|
domain_names << domain_names[i].sub(/\w+\./,'\\*.')
end
if domain_names.count != 0
domain_name_search_text = "(" + domain_names.join("|") + ")"
else
domain_name_search_text = ""
end
@site_certs = SiteCert.all.where(:is_valid=>true,:domain_names=>/\A#{domain_name_search_text}/)
@site_certs = SiteCert.all
if site_construct
@enable_cert_id = site_construct.site_cert_id
end
render :layout => false
end
def cert_management
@site_certs = SiteCert.all.page(params[:page]).per(10)
@filter_fields = {}
params[:keywords] = params[:keywords].to_s.gsub("*","\\*")
@site_certs = search_data(@site_certs,[:domain_names])
if request.xhr?
render :partial => "certs_table"
end
end
def update_cert_setting def update_cert_setting
site_params = params.require('site').permit! site_params = params.require('site').permit!
if !site_params['cert_ver_file_content'].blank? if !site_params['cert_ver_file_content'].blank?
@ -52,8 +99,12 @@ class Admin::SitePanelController < OrbitAdminController
SiteServer.find(params[:id]).destroy SiteServer.find(params[:id]).destroy
redirect_to admin_site_panel_server_manager_path redirect_to admin_site_panel_server_manager_path
elsif params[:type] == 'detect_sites' elsif params[:type] == 'detect_sites'
extra_text = ""
if params[:key].present?
extra_text = "[#{params[:key]}]"
end
Thread.new do Thread.new do
system("bundle exec rake create_site:detect_sites") system("bundle exec rake create_site:detect_sites#{extra_text}")
end end
render :json => {"success"=>true} render :json => {"success"=>true}
elsif params[:type] == 'see_infos' elsif params[:type] == 'see_infos'
@ -95,7 +146,7 @@ class Admin::SitePanelController < OrbitAdminController
password = site_server.password password = site_server.password
site_name = site_construct.site_name site_name = site_construct.site_name
domain_name = site_construct.domain_name domain_name = site_construct.domain_name
port = site_construct.port port = site_construct.get_port
db_name = site_construct.db_name db_name = site_construct.db_name
path = site_construct.path path = site_construct.path
site_construct_id = site_construct.id.to_s site_construct_id = site_construct.id.to_s
@ -122,7 +173,7 @@ class Admin::SitePanelController < OrbitAdminController
password = site_server.password password = site_server.password
site_name = site_construct.site_name site_name = site_construct.site_name
domain_name = site_construct.domain_name domain_name = site_construct.domain_name
port = site_construct.port port = site_construct.get_port
db_name = site_construct.db_name db_name = site_construct.db_name
path = site_construct.path path = site_construct.path
site_construct_id = params[:id] site_construct_id = params[:id]
@ -154,12 +205,23 @@ class Admin::SitePanelController < OrbitAdminController
@site = SiteConstruct.find(params[:id]) @site = SiteConstruct.find(params[:id])
render 'see_detail_for_created_site' and return render 'see_detail_for_created_site' and return
elsif params[:type] == 'change_server_name' elsif params[:type] == 'change_server_name'
cmd = "bundle exec rake create_site:change_site_server_name[#{params[:id]},'#{params[:site_construct][:domain_name]}']" site_construct = SiteConstruct.find(params[:id])
system(cmd) site_construct.update(:domain_name=>params[:site_construct][:domain_name])
redirect_to :back and return cmd = "bundle exec rake create_site:change_site_server_name[#{params[:id]},'#{params[:site_construct][:domain_name]}','#{params[:site_construct][:port].to_a.join('////') }']"
site_construct.update(:status=>"execing",:infos=>["Execing change domain name task..."])
Thread.new do
Bundler.with_clean_env{system(cmd)}
end
redirect_to admin_site_panel_edit_site_path(:id=>params[:id],:type=>'detail',:status=>'changing') and return
elsif params[:type] == 'delete_from_list' elsif params[:type] == 'delete_from_list'
SiteConstruct.find(params[:id]).destroy SiteConstruct.find(params[:id]).destroy
redirect_to :back and return redirect_to :back and return
elsif params[:type] == 'select_cert'
@site_construct = SiteConstruct.find(params[:id])
@site_construct.update(:site_cert_id=>BSON::ObjectId(params[:site_cert_id]))
Thread.new do
system("bundle exec rake create_site:change_site_cert[#{params[:id]}]")
end
else else
Thread.new do Thread.new do
if params[:id].blank? && !params[:server_names].blank? if params[:id].blank? && !params[:server_names].blank?
@ -181,7 +243,7 @@ class Admin::SitePanelController < OrbitAdminController
@site_servers = SiteServer.all.with_categories(filters("category")) @site_servers = SiteServer.all.with_categories(filters("category"))
@sites = (params[:server_name].blank? ? @sites : @sites.where(:server_type=>params[:server_name])) @sites = (params[:server_name].blank? ? @sites : @sites.where(:server_type=>params[:server_name]))
@sites = @sites.any_in(:server_type => @site_servers.map{|s| s.server_name}) @sites = @sites.any_in(:server_type => @site_servers.map{|s| s.server_name})
@sites = search_data(@sites,[:domain_name,:site_name,:school_name,:status]).page(params[:page].to_i).per(10) @sites = search_data(@sites,[:domain_name,:site_name,:school_name,:status,:port]).page(params[:page].to_i).per(10)
if (params[:filters][:site_mode].present? rescue false) if (params[:filters][:site_mode].present? rescue false)
site_modes = params[:filters][:site_mode] site_modes = params[:filters][:site_mode]
if site_modes.include?("development") if site_modes.include?("development")
@ -202,11 +264,13 @@ class Admin::SitePanelController < OrbitAdminController
end end
end end
private private
def site_cert_params
site_cert_params = params.require(:site_cert).permit! rescue {}
end
def site_construct_params def site_construct_params
site_construct_params = params.require(:site_construct).permit! site_construct_params = params.require(:site_construct).permit! rescue {}
end end
def site_server_params def site_server_params
params.require(:site_server).permit! params.require(:site_server).permit! rescue {}
end end
end end

49
app/models/site_cert.rb Normal file
View File

@ -0,0 +1,49 @@
class SiteCert
include Mongoid::Document
include Mongoid::Timestamps
mount_uploader :cert_file, AssetUploader #Public key
mount_uploader :ca_bundle, AssetUploader
mount_uploader :private_key, AssetUploader
field :is_valid , type: Boolean ,default: false
field :domain_names , type: Array ,default: []
field :source_paths , type: Array ,default: []
field :start_date , type: DateTime
field :end_date , type: DateTime
has_many :site_constructs, :autosave => true
after_save :change_data
def upload_date
self.created_at.strftime("%Y/%m/%d %H:%M") rescue ""
end
def display_domain_names
self.domain_names.join("<br>").html_safe rescue ""
end
def generate_file_link(field_name)
f = self.send(field_name)
file_name = self[field_name]
"<a href=\"#{f.url}\" title=\"#{file_name}\">#{file_name}</a>".html_safe
end
def display_start_date
self.start_date.strftime("%Y-%m-%d") rescue ""
end
def display_end_date
self.end_date.strftime("%Y-%m-%d") rescue ""
end
def change_data
cert_file_md5 = `openssl x509 -noout -modulus -in #{self.cert_file.file.file} | openssl md5`
private_key_md5 = `openssl rsa -noout -modulus -in #{self.private_key.file.file} | openssl md5`
is_valid = (cert_file_md5 == private_key_md5)
domain_names = `openssl x509 -text < #{self.cert_file.file.file} | grep 'DNS:' | sed 's/\s*DNS:\([a-z0-9.\-]*\)[,\s]\?/\1 /g'`.split('DNS:').map{|s| s.strip}.select{|s| s.present?} rescue []
start_date_text = `openssl x509 -text < #{self.cert_file.file.file} -startdate -noout`.split('=').last.strip
end_date_text = `openssl x509 -text < #{self.cert_file.file.file} -enddate -noout`.split('=').last.strip
self.start_date = DateTime.parse(start_date_text) rescue nil
self.end_date = DateTime.parse(end_date_text) rescue nil
self.is_valid = is_valid
self.domain_names = domain_names
if !@skip_callback
@skip_callback = true
self.save(:validate=>false)
end
@skip_callback = false
false
end
end

View File

@ -11,7 +11,7 @@ class SiteConstruct
field :domain_name field :domain_name
field :nginx_file field :nginx_file
field :db_name field :db_name
field :port, type: String, :default => "80" field :port, type: Array, :default => ["80"]
field :path field :path
field :site_type field :site_type
field :school_name field :school_name
@ -25,39 +25,155 @@ class SiteConstruct
field :cert_ver_added_text field :cert_ver_added_text
field :cert_ver_file_content field :cert_ver_file_content
field :cert_ver_location_path field :cert_ver_location_path
belongs_to :site_cert
after_initialize do |record| after_initialize do |record|
unless record.new_record?
save_flag = false
if record.status.nil? if record.status.nil?
record.status = "" record.status = ""
record.save save_flag = true
end end
if record.infos.nil? if record.infos.nil?
record.infos = [] record.infos = []
record.save save_flag = true
end end
if record.nginx_file.nil? if record.nginx_file.nil?
record.nginx_file = "/etc/nginx/orbit_sites/"+record.site_name.to_s record.nginx_file = "/etc/nginx/orbit_sites/"+record.site_name.to_s
record.save save_flag = true
end end
if record.path.nil? if record.path.nil?
dir_path = ((record.site_type == "School" && !record.school_name.blank?) ? "school_sites/#{record.school_name}" : "orbit_sites") dir_path = ((record.site_type == "School" && !record.school_name.blank?) ? "school_sites/#{record.school_name}" : "orbit_sites")
record.path = "/home/rulingcom/#{dir_path}" record.path = "/home/rulingcom/#{dir_path}"
save_flag = true
end 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 parse_nginx_text_to_server_blocks(nginx_text,get_all_blocks=false)
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 = nginx_text_tmp.enum_for(:scan,/^(?:}+\s?)+/m).map { Regexp.last_match.offset(0).first + 1 }
start_index = 0
all_blocks = end_indices.map{|i| res = nginx_text_tmp[start_index..i];start_index = i + 1;res}
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[^;]+;/,'')
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"}
end
new_server_block = new_server_block.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" : '')+
' 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'+
' proxy_connect_timeout 360;\n'+
' proxy_pass http://'+self.get_site_name+'_sock;\n'+
' }\n'+
'}'
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_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 end
def get_site_name def get_site_name
return self.site_name.gsub(" ","\\ ") return self.site_name.to_s.gsub(" ","\\ ")
end end
def get_domain_name def get_domain_name(port=nil)
scheme = "" scheme = ""
extra_port = "" extra_port = ""
if self.port == "443" port = self.get_port if port.nil?
if port == "443"
scheme = "https://" scheme = "https://"
else else
scheme = "http://" scheme = "http://"
if self.port != "80" if port != "80"
extra_port = ":#{self.port}" extra_port = ":#{port}"
end end
end end
return (scheme + self.domain_name + extra_port) return (scheme + self.domain_name.split(" ").first + extra_port)
end end
def site_server def site_server
SiteServer.where(server_name: self.server_type).first SiteServer.where(server_name: self.server_type).first

View File

@ -0,0 +1,17 @@
<fieldset>
<!-- Input Area -->
<div class="input-area">
<!-- Module -->
<div class="tab-content module-area">
<!-- Basic Module -->
<div class="tab-pane fade in active" id="basic">
<!-- Category -->
<%=render :partial => "simple_form_file",:locals=>{:f=>f,:field_name=>'cert_file'}%>
<%=render :partial => "simple_form_file",:locals=>{:f=>f,:field_name=>'ca_bundle'}%>
<%=render :partial => "simple_form_file",:locals=>{:f=>f,:field_name=>'private_key'}%>
</div>
</div>
<div class="form-actions">
<%= f.submit t('submit'), class: 'btn btn-primary' %>
</div>
</fieldset>

View File

@ -0,0 +1,51 @@
<table class="table table-bordered main-list default">
<thead>
<tr>
<th><%=t('client_management.upload_date')%></th>
<th><%=t('client_management.status')%></th>
<th><%=t('client_management.start_date')%></th>
<th><%=t('client_management.end_date')%></th>
<th><%=t('client_management.domain_name')%></th>
<th><%=t('client_management.cert_file')%></th>
<th><%=t('client_management.ca_bundle')%></th>
<th><%=t('client_management.private_key')%></th>
<th><%=t('client_management.action')%></th>
</tr>
</thead>
<tbody>
<% @site_certs.each do |site_cert| %>
<tr>
<td><%=site_cert.upload_date %></td>
<td><span class="<%=site_cert.is_valid ? 'valid_icon' : 'invalid_icon' %>" aria-hidden="true"></span></td>
<td><%=site_cert.display_start_date %></td>
<td><%=site_cert.display_end_date %></td>
<td><%=site_cert.display_domain_names %></td>
<td><%=site_cert.generate_file_link('cert_file')%></td>
<td><%=site_cert.generate_file_link('ca_bundle')%></td>
<td><%=site_cert.generate_file_link('private_key')%></td>
<td>
<%= link_to t(:edit),admin_site_panel_edit_cert_path(site_cert.id),:class=>"btn btn-primary btn-small" %>
<%= link_to t(:delete_),admin_site_panel_destroy_cert_path(site_cert.id),:class=>"btn btn-danger btn-small",:data=>{:method=>"delete",:confirm=>t("client_management.confirm_delete")} %>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="bottomnav clearfix">
<div class="pagination pagination-centered"><%=paginate(@site_certs)%></div>
<a class="btn btn-primary pull-right" href="<%=upload_cert_admin_site_panel_index_path%>" title="<%=t('client_management.upload_cert')%>"><%=t('client_management.upload_cert')%></a>
</div>
<style type="text/css">
.valid_icon:before {
content: "✔";
font-weight: bold;
color: green;
font-size: 2em;
}
.invalid_icon:before {
content: "✖";
font-weight: bold;
color: red;
font-size: 2em;
}
</style>

View File

@ -103,7 +103,12 @@
<div class="control-group"> <div class="control-group">
<%= f.label :port ,"Port Number", :class => "control-label muted" %> <%= f.label :port ,"Port Number", :class => "control-label muted" %>
<div class="controls"> <div class="controls">
<%= f.number_field :port, :min => 1, :id => "port", :value => 80 %> <div class="port_block">
<%= number_field_tag("#{f.object_name}[port][]",f.object.port.first, :min => 1, :id => nil) %>
<div style="clear: both;"></div>
</div>
<div id="append_port_block"></div>
<button class="btn btn-primary" id="add_port" type="button">Add Port</button>
</div> </div>
</div> </div>
@ -120,6 +125,18 @@
</div> </div>
</div> </div>
</fieldset> </fieldset>
<style type="text/css">
.remove_btn{
float: left;
color: red;
line-height: 2rem;
cursor: pointer;
font-weight: bold;
}
.remove_btn:hover{
font-size: 1.3em;
}
</style>
<script type="text/javascript"> <script type="text/javascript">
var domain_name_relations = {}; var domain_name_relations = {};
var pre_site_name = ''; var pre_site_name = '';
@ -275,4 +292,13 @@
).join(' ')) ).join(' '))
console.log($("#path").val()); console.log($("#path").val());
}) })
$(document).on("click",".remove_btn",function(event){
$(this).parent().remove();
})
$("#add_port").click(function(){
var clone_input = $(this).siblings(".port_block").eq(0).clone();
var $div = $("<div></div>");
$div.append("<span class=\"remove_btn\">X</span>").append(clone_input);
$(this).siblings("#append_port_block").append($div)
})
</script> </script>

View File

@ -25,6 +25,7 @@
<a class="btn btn-primary" href = "<%= admin_site_panel_edit_server_info_path+"?id=#{site_server.id.to_s}" %>"><%=t(:edit)%></a> <a class="btn btn-primary" href = "<%= admin_site_panel_edit_server_info_path+"?id=#{site_server.id.to_s}" %>"><%=t(:edit)%></a>
<a class="btn btn-primary" href = "#" onclick="if(window.confirm('Do you really want to delete <%=site_server.server_name%>?')) { window.location.href = '<%= admin_site_panel_edit_server_info_path+"?id=#{site_server.id.to_s}&type=delete" %>';}"><%=t(:remove)%></a> <a class="btn btn-primary" href = "#" onclick="if(window.confirm('Do you really want to delete <%=site_server.server_name%>?')) { window.location.href = '<%= admin_site_panel_edit_server_info_path+"?id=#{site_server.id.to_s}&type=delete" %>';}"><%=t(:remove)%></a>
<a class="btn btn-primary" href = "<%= admin_site_panel_sites_list_path+"?server_name=#{site_server.server_name}" %>"><%= t('client_management.see_sites') %></a> <a class="btn btn-primary" href = "<%= admin_site_panel_sites_list_path+"?server_name=#{site_server.server_name}" %>"><%= t('client_management.see_sites') %></a>
<a class="btn btn-primary detect_sites" href="#" data-key="<%=site_server.server_name%>">Detect sites</a>
</td> </td>
</tr> </tr>
<% end %> <% end %>
@ -32,9 +33,10 @@
</table> </table>
<div class="bottomnav clearfix"> <div class="bottomnav clearfix">
<div class="pagination pagination-centered"><%=paginate(@site_servers)%></div> <div class="pagination pagination-centered"><%=paginate(@site_servers)%></div>
<a id="see_infos" class="btn btn-primary pull-right" href="#">See infos</a> <a class="btn btn-primary pull-right see_infos" href="#" data-key="detect_sites">See detect infos</a>
<a class="btn btn-primary pull-right see_infos" href="#" data-key="execing_commands">See exec infos</a>
<a class="btn btn-primary pull-right" href="<%=admin_site_panel_edit_server_info_path+"?type=create"%>"><%=t(:add)%></a> <a class="btn btn-primary pull-right" href="<%=admin_site_panel_edit_server_info_path+"?type=create"%>"><%=t(:add)%></a>
<a id="detect_sites" class="btn btn-primary pull-right" href="#">Detect sites</a> <a class="btn btn-primary pull-right detect_sites" href="#">Detect sites</a>
<a id="exec_commands" class="btn btn-primary pull-right" href="#">Exec commands</a> <a id="exec_commands" class="btn btn-primary pull-right" href="#">Exec commands</a>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
@ -79,7 +81,8 @@
show_infos_dialog("execing_commands"); show_infos_dialog("execing_commands");
}); });
} }
function see_infos(key=""){ function see_infos(key){
key = key || "";
if(!close_info){ if(!close_info){
var request = $.post("<%=admin_site_panel_edit_server_info_path%>",{"type":'see_infos',"key":key}); var request = $.post("<%=admin_site_panel_edit_server_info_path%>",{"type":'see_infos',"key":key});
request.done(function(data){ request.done(function(data){
@ -94,14 +97,15 @@
var status_text = status_relation[status]; var status_text = status_relation[status];
$("#info_texts").html(status_text+"<div style='clear:both;'></div>"+infos.join("<br>")); $("#info_texts").html(status_text+"<div style='clear:both;'></div>"+infos.join("<br>"));
msg_end.scrollIntoView(); msg_end.scrollIntoView();
timeout_id = window.setTimeout(see_infos(),1000); timeout_id = window.setTimeout(see_infos(key),1000);
} }
}) })
}else{ }else{
window.clearTimeout(timeout_id); window.clearTimeout(timeout_id);
} }
}; };
function show_infos_dialog(key=""){ function show_infos_dialog(key){
key = key || "";
close_info = true; close_info = true;
window.clearTimeout(timeout_id); window.clearTimeout(timeout_id);
close_info = false; close_info = false;
@ -129,9 +133,12 @@
}); });
} }
$(document).ready(function(){ $(document).ready(function(){
$("#detect_sites").off('click').on('click',function(){ $(".detect_sites").off('click').on('click',function(){
$.post("<%=admin_site_panel_edit_server_info_path%>",{"type":"detect_sites"}).done(function(){ var key = $(this).data("key");
show_infos_dialog(); if( key == undefined)
key = "";
$.post("<%=admin_site_panel_edit_server_info_path%>",{"type":"detect_sites","key":key}).done(function(){
show_infos_dialog("detect_sites");
}) })
}); });
$("#exec_commands").off('click').on('click',function(){ $("#exec_commands").off('click').on('click',function(){
@ -141,9 +148,12 @@
show_exec_commands_block(server_names); show_exec_commands_block(server_names);
}) })
}); });
$("#see_infos").off('click').on('click',function(){ $(".see_infos").off('click').on('click',function(){
$.post("<%=admin_site_panel_edit_server_info_path%>",{"type":"see_infos"}).done(function(){ var key = $(this).data("key")
show_infos_dialog(); if(key == undefined)
key = ""
$.post("<%=admin_site_panel_edit_server_info_path%>",{"type":"see_infos","key":key}).done(function(){
show_infos_dialog(key);
}) })
}); });
}) })

View File

@ -0,0 +1,23 @@
<div class="control-group">
<label class="control-label muted"><%= t("client_management.#{field_name}") %></label>
<div class="controls">
<label style="float: left;border-color: #666666" class="btn">
<%= f.file_field field_name , :style=>"position: absolute;width: 0.00000001em;",:class=>field_name %>
<% if f.object[field_name].blank?%>
<%= t('client_management.select_file') %>
<% else %>
<%= t('client_management.change_file') %>
<% end %>
</label>
<div class="filename <%=field_name%>" style="float: left;margin-left: 0.3em; "><%= f.object[field_name] %></div>
</div>
</div>
<script type="text/javascript">
$("input[type=\"file\"].<%=field_name%>").change(function(){
var file_name = "";
if($(this).prop("files").length != 0){
file_name = $(this).prop("files")[0].name;
}
$(this).parent().next(".filename.<%=field_name%>").text(file_name)
})
</script>

View File

@ -15,15 +15,15 @@
<td><%=site.server_type%></td> <td><%=site.server_type%></td>
<td> <td>
<% site.domain_name.split(" ").each_with_index do |domain_name,i| %> <% site.domain_name.split(" ").each_with_index do |domain_name,i| %>
<% domain_link = ((site.port.to_s == "443") ? "https" : "http") + '://' + domain_name + ((site.port.to_s != '80' && site.port.to_s != '443') ? ':'+site.port.to_s : '') %> <% domain_link = ((site.get_port.to_s == "443") ? "https" : "http") + '://' + domain_name + ((site.get_port.to_s != '80' && site.get_port.to_s != '443') ? ':'+site.get_port.to_s : '') %>
<% if i!=0 %> <% if i!=0 %>
<br> <br>
<% end %> <% end %>
<%= link_to domain_name, domain_link, :title => "open #{domain_link} to new window", :target=>"_blank" %> <%= link_to domain_name, domain_link, :title => "Open #{domain_link} in new window", :target=>"_blank" %>
<% end %> <% end %>
</td> </td>
<td><%=site.port%></td> <td><%=site.display_port%></td>
<td class="site_status"><%= (site.status.blank? ? "not yet create" : status_relation[site.status]) %></td> <td class="site_status"><%= (site.status.blank? ? "not yet create" : status_relation[site.status]) %></td>
<td> <td>
<a href="#" title="<%=t("client_management.see_logs_for_site",{:site=>site.domain_name})%>" class="btn btn-primary see_infos" data-id="<%=site.id.to_s%>"><%=t('client_management.see_logs')%></a> <a href="#" title="<%=t("client_management.see_logs_for_site",{:site=>site.domain_name})%>" class="btn btn-primary see_infos" data-id="<%=site.id.to_s%>"><%=t('client_management.see_logs')%></a>
@ -54,17 +54,20 @@
<%= form_for site, as: 'site', url: "/#{I18n.locale}/admin/site_panel/update_cert_setting",method: "post" do |f| %> <%= form_for site, as: 'site', url: "/#{I18n.locale}/admin/site_panel/update_cert_setting",method: "post" do |f| %>
<div> <div>
CSR txt path:&nbsp; CSR txt path:&nbsp;
<%= f.text_field 'cert_ver_location_path',style: 'width: calc(100% - 8em);margin: 0;' %> <%= f.text_field 'cert_ver_location_path',style: 'width: calc(100% - 8em);margin: 0;',:id=>nil %>
</div> </div>
<div> <div>
CSR txt content:&nbsp; CSR txt content:&nbsp;
<%= f.text_area 'cert_ver_file_content',class: 'ckeditor',value: site.cert_ver_file_content.to_s.gsub("\n",'<br>') %> <%= f.text_area 'cert_ver_file_content',class: 'ckeditor',value: site.cert_ver_file_content.to_s.gsub("\n",'<br>'),:id=>nil %>
</div> </div>
<%= f.hidden_field 'id' %> <%= f.hidden_field 'id',:id=>nil %>
<%= f.submit 'edit',class: 'btn btn-primary' %> <%= f.submit 'edit',class: 'btn btn-primary' %>
<% end %> <% end %>
</div> </div>
<% end %> <% end %>
<% if site.status != "" %>
<a data-id="<%= site.id %>" title="<%=t('client_management.https_setting')%>" class="btn btn-primary https_setting"><%=t('client_management.https_setting')%></a>
<% end %>
</td> </td>
</tr> </tr>
<% end %> <% end %>
@ -112,15 +115,19 @@
}); });
if(new_params_text[new_params_text.length -1] == "&") if(new_params_text[new_params_text.length -1] == "&")
new_params_text = new_params_text.substr(0,new_params_text.length - 1) new_params_text = new_params_text.substr(0,new_params_text.length - 1)
if(params["id"] == id){ if(params["id"] == id || window.refresh_flag){
close_info = true; close_info = true;
window.location.href = window.location.href.replace(window.location.search,new_params_text); window.location.href = window.location.href.replace(window.location.search,new_params_text);
} }
}else if(status == "changing"){
window.refresh_flag = true
} }
$(".see_infos[data-id="+id+"]").parent().siblings(".site_status").html(status_text); $(".see_infos[data-id="+id+"]").parent().siblings(".site_status").html(status_text);
//msg_end.scrollIntoView(); //msg_end.scrollIntoView();
timeout_id = window.setTimeout(see_infos(id),1000); timeout_id = window.setTimeout(see_infos(id),1000);
} }
}).fail(function() {
window.location.reload();
}) })
}else{ }else{
window.clearTimeout(timeout_id); window.clearTimeout(timeout_id);
@ -130,7 +137,7 @@
close_info = true; close_info = true;
window.clearTimeout(timeout_id); window.clearTimeout(timeout_id);
close_info = false; close_info = false;
var id = $(item).attr("data-id"); var id = $(item).data("id");
if($("#dialog-confirm").length == 0){ if($("#dialog-confirm").length == 0){
$("#main-wrap").before("<div id='dialog-confirm' title='site infos'>"+ $("#main-wrap").before("<div id='dialog-confirm' title='site infos'>"+
"<div style='clear:both;'></div><div id='info_texts'>"+see_infos(id)+"</div><div id='msg_end' style='height:0px; overflow:hidden'></div>"+ "<div style='clear:both;'></div><div id='info_texts'>"+see_infos(id)+"</div><div id='msg_end' style='height:0px; overflow:hidden'></div>"+
@ -160,6 +167,8 @@
var item = this; var item = this;
$.post("<%= admin_site_panel_create_site_path %>",{'id': id}).done(function(){ $.post("<%= admin_site_panel_create_site_path %>",{'id': id}).done(function(){
show_infos_dialog(item); show_infos_dialog(item);
}).fail(function() {
window.location.reload();
}) })
}); });
$('.recreate_site').click(function(){ $('.recreate_site').click(function(){
@ -172,6 +181,8 @@
var item = this; var item = this;
$.post("<%= admin_site_panel_create_site_path %>",{'id': id}).done(function(){ $.post("<%= admin_site_panel_create_site_path %>",{'id': id}).done(function(){
show_infos_dialog(item); show_infos_dialog(item);
}).fail(function() {
window.location.reload();
}) })
} }
} }
@ -224,6 +235,40 @@
} }
} }
}); });
$(".https_setting").click(function(){
var id = $(this).data("id");
var item = this;
if($("#https_setting-dialog-confirm").length == 0){
$("#main-wrap").before("<div id='https_setting-dialog-confirm' title='<%=t("client_management.https_setting")%>'>"
+"<div id='https_setting_area'></div>"+
"</div>");
}
$('#https_setting_area').attr('data-id',id);
$.get("<%=get_certs_for_site_admin_site_panel_index_path%>",{id: id}).done(function(html){
$('#https_setting_area').html(html);
$( "#https_setting-dialog-confirm" ).dialog({
resizable: true,
minHeight: 300,
maxHeight: 400,
modal: true,
width: '80%',
close: function(){$( this ).dialog( "close" );},
buttons: {
"<%= t(:submit) %>": function(){
var site_cert_id = $('#https_setting_area input:checked').eq(0).val();
if(site_cert_id != undefined){
console.log(site_cert_id);
$.post("<%=admin_site_panel_edit_site_path%>",{'id': id,'type':'select_cert','site_cert_id': site_cert_id}).done(function(response){
console.log(response);
show_infos_dialog(item);
});
}
$( this ).dialog( "close" );
},
}
});
})
})
$('.close_site').click(function(){ $('.close_site').click(function(){
var item = this; var item = this;
$.post("<%=admin_site_panel_edit_site_path%>",{'id':$(this).attr("data-id"),'type':'close'}).done(function(){ $.post("<%=admin_site_panel_edit_site_path%>",{'id':$(this).attr("data-id"),'type':'close'}).done(function(){

View File

@ -0,0 +1,25 @@
<%= javascript_include_tag "lib/jquery-ui-1.12.1/jquery-ui" %>
<%= stylesheet_link_tag "lib/jquery-ui-1.12.1/jquery-ui" %>
<% content_for :page_specific_javascript do %>
<%= javascript_include_tag "lib/module-area" %>
<% end %>
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<%= stylesheet_link_tag "lib/main-list" %>
<%= stylesheet_link_tag "lib/pageslide" %>
<style type="text/css">
.ui-dialog {
z-index: 100000000000 !important;
}
</style>
<% end %>
<% if !params[:id].blank? %>
<div id='dialog-confirm' title='site infos'>
<div style='clear:both;'></div>
<div id='info_texts'></div>
</div>
<% end %>
<%= render :partial => "sites_list_filter", :locals =>{:fields => @filter_fields, :search_dom_id=>"index_table", :quick_new=>false} %>
<span id="index_table">
<%= render :partial=>'certs_table' %>
</span>

View File

@ -0,0 +1,3 @@
<%= form_for @site_cert ,:url=>{:action=>"update_cert"},:method=>:post, :html => {:class=>"form-horizontal main-forms"} do |f|%>
<%= render :partial => 'cert_form',:locals=>{:f=>f} %>
<% end %>

View File

@ -0,0 +1,22 @@
<% if @site_certs.count == 0 %>
<%= link_to t('client_management.upload_cert'),upload_cert_admin_site_panel_index_path, :target=>"_blank" %>
<% else %>
<table class="table table-bordered main-list default">
<thead>
<th></th>
<th><%=t('client_management.upload_date')%></th>
<th><%=t('client_management.start_date')%>/<%=t('client_management.end_date')%></th>
<th><%=t('client_management.domain_name')%></th>
</thead>
<tbody>
<% @site_certs.each do |site_cert| %>
<tr>
<td><%=radio_button_tag("site_cert",site_cert.id,site_cert.id == @enable_cert_id)%></td>
<td><%=site_cert.upload_date %></td>
<td><%=site_cert.display_start_date %> / <%=site_cert.display_end_date %></td>
<td><%=site_cert.display_domain_names %></td>
</tr>
<% end %>
</tbody>
</table>
<% end %>

View File

@ -1,3 +1,5 @@
<%= javascript_include_tag "lib/jquery-ui-1.12.1/jquery-ui" %>
<%= stylesheet_link_tag "lib/jquery-ui-1.12.1/jquery-ui" %>
<div class="form-horizontal"> <div class="form-horizontal">
<form method="get" action="<%= "/#{I18n.locale}/admin/site_panel/edit_site" %>"> <form method="get" action="<%= "/#{I18n.locale}/admin/site_panel/edit_site" %>">
<div class="control-group"> <div class="control-group">
@ -23,7 +25,22 @@
</div> </div>
<div class="control-group"> <div class="control-group">
<label class="control-label">Port</label> <label class="control-label">Port</label>
<div class="controls"><%=@site.port%></div> <div class="controls">
<div class="port_block">
<%= number_field_tag("site_construct[port][]",@site.get_port, :min => 1, :id => nil) %>
<div style="clear: both;"></div>
</div>
<div id="append_port_block">
<% @site.port[1..-1].each do |port| %>
<div class="port_block">
<span class="remove_btn">X</span>
<%= number_field_tag("site_construct[port][]",port, :min => 1, :id => nil) %>
<div style="clear: both;"></div>
</div>
<% end %>
</div>
<button class="btn btn-primary" id="add_port" type="button">Add Port</button>
</div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label class="control-label">Site type</label> <label class="control-label">Site type</label>
@ -56,11 +73,84 @@
<%= hidden_field_tag 'id',@site.id %> <%= hidden_field_tag 'id',@site.id %>
<%= hidden_field_tag 'type','change_server_name' %> <%= hidden_field_tag 'type','change_server_name' %>
<a href="<%=admin_site_panel_sites_list_path%>" class="btn btn-primary"><%=t(:back)%></a> <a href="<%=admin_site_panel_sites_list_path%>" class="btn btn-primary"><%=t(:back)%></a>
<input type="submit" value="change domain" class="btn btn-primary"> <input type="submit" value="<%=t("client_management.change_setting")%>" class="btn btn-primary btn-danger">
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<% if params[:status] == "changing" %>
<script type="text/javascript">
var timeout_id;
var status_relation = {"creating":"<span style=\"color: skyblue;\">creating</span>","error":"<span style=\"color: red;\">error</span>","finish": "<span style=\"color: darkseagreen;\">finish</span>","closed":"<span style=\"color: red;\">closed</span>"};
function see_infos(id){
id = id || "<%=params[:id]%>";
if(!close_info){
var request = $.post("<%=admin_site_panel_site_infos_path%>",{"id":id});
request.done(function(data){
var infos = request.responseJSON.infos;
var status = request.responseJSON.status;
if($("#info_texts").length == 0)
return infos.join("<br>")
else{
$("#info_texts").html(infos.join("<br>"));
if(status == "")
var status_text = "not yet create";
else
var status_text = status_relation[status];
if(status == "finish"){
var new_params_text = window.location.search.replace(/[&?]status=[^&]*/,'');
close_info = true;
window.location.href = window.location.href.replace(window.location.search,new_params_text);
}
$(".see_infos[data-id="+id+"]").parent().siblings(".site_status").html(status_text);
timeout_id = window.setTimeout(see_infos(id),1000);
}
}).fail(function() {
window.location.reload();
})
}else{
window.clearTimeout(timeout_id);
}
};
function show_infos_dialog(){
close_info = true;
window.clearTimeout(timeout_id);
close_info = false;
if($("#dialog-confirm").length == 0){
$("#main-wrap").before("<div id='dialog-confirm' title='site infos'>"+
"<div style='clear:both;'></div><div id='info_texts'>"+see_infos()+"</div><div id='msg_end' style='height:0px; overflow:hidden'></div>"+
"</div>");
}else{
see_infos();
};
$( "#dialog-confirm" ).dialog({
resizable: true,
minHeight: 300,
maxHeight: 400,
modal: true,
width: '80%',
close: function(){$( this ).dialog( "close" );close_info = true;},
buttons: {
"<%= t('client_management.confirm') %>": function(){$( this ).dialog( "close" );close_info = true;},
"stop update": function(){close_info = true;}
}
});
}
show_infos_dialog();
</script>
<% end %>
<style type="text/css">
.remove_btn{
float: left;
color: red;
line-height: 2rem;
cursor: pointer;
font-weight: bold;
}
.remove_btn:hover{
font-size: 1.3em;
}
</style>
<script type="text/javascript"> <script type="text/javascript">
function unique(array) { function unique(array) {
return $.grep(array, function(el, index) { return $.grep(array, function(el, index) {
@ -89,4 +179,13 @@
var correct_val = $(ele).val().match(/([0-9]||[a-z]||[-_.])*/gi).join(""); var correct_val = $(ele).val().match(/([0-9]||[a-z]||[-_.])*/gi).join("");
$(ele).val(correct_val.replace("_","-")); $(ele).val(correct_val.replace("_","-"));
} }
$(document).on("click",".remove_btn",function(event){
$(this).parent().remove();
})
$("#add_port").click(function(){
var clone_input = $(this).siblings(".port_block").eq(0).clone();
var $div = $("<div></div>");
$div.append("<span class=\"remove_btn\">X</span>").append(clone_input);
$(this).siblings("#append_port_block").append($div)
})
</script> </script>

View File

@ -0,0 +1,3 @@
<%= form_for @site_cert ,:url=>{:action=>"create_cert"},:method=>:post, :html => {:class=>"form-horizontal main-forms"} do |f|%>
<%= render :partial => 'cert_form',:locals=>{:f=>f} %>
<% end %>

View File

@ -3,8 +3,22 @@ en:
client_management: Client Management client_management: Client Management
restful_actions: restful_actions:
server_manager: Server Manager server_manager: Server Manager
site_list: Site List sites_list: Site List
upload_cert: Upload Cert
cert_management: Cert Management
client_management: client_management:
start_date: Start Date
end_date: End Date
change_setting: Change Setting
upload_cert: Upload Cert
https_setting: https Setting
change_file: Change File
select_file: Select File
upload_date: Upload date
private_key: Private key
cert_file: Public key
ca_bundle: Ca Bundle
cert_management: Cert Management
development: Development development: Development
production: Production production: Production
site_mode: Site mode site_mode: Site mode

View File

@ -3,8 +3,22 @@ zh_tw:
client_management: 網站管理系統 client_management: 網站管理系統
restful_actions: restful_actions:
server_manager: 伺服器管理 server_manager: 伺服器管理
site_list: 網站列表 sites_list: 網站列表
upload_cert: 上傳憑證
cert_management: 憑證管理
client_management: client_management:
start_date: 開始日期
end_date: 結束日期
change_setting: 變更設定
upload_cert: 上傳憑證
https_setting: https設定
change_file: 更換檔案
select_file: 選擇檔案
upload_date: 上傳日期
private_key: 私鑰(Private keykey檔案)
cert_file: 憑證檔案(Public keycrt檔案)
ca_bundle: 中繼憑證(Ca Bundlecrt檔案)
cert_management: 憑證管理
development: 開發者模式 development: 開發者模式
production: 產品模式 production: 產品模式
site_mode: 網站模式 site_mode: 網站模式

View File

@ -49,7 +49,19 @@ Rails.application.routes.draw do
get "site_panel/edit_server_info" => "site_panel#edit_server_info" get "site_panel/edit_server_info" => "site_panel#edit_server_info"
post "site_panel/edit_server_info" => "site_panel#edit_server_info" post "site_panel/edit_server_info" => "site_panel#edit_server_info"
post "site_panel/update_cert_setting" => "site_panel#update_cert_setting" post "site_panel/update_cert_setting" => "site_panel#update_cert_setting"
resources :site_panel resources :site_panel do
delete 'destroy_cert'
get 'edit_cert'
post 'update_cert'
patch 'update_cert'
collection do
get 'cert_management'
get 'upload_cert'
get 'get_certs_for_site'
post 'create_cert'
patch 'create_cert'
end
end
end end

View File

@ -20,37 +20,42 @@ module ClientManagement
:link_path=>"admin_client_managements_path" , :link_path=>"admin_client_managements_path" ,
:priority=>1, :priority=>1,
:active_for_action=>{'admin/client_managements'=>"index"}, :active_for_action=>{'admin/client_managements'=>"index"},
:available_for => 'users' :available_for => 'admin'
context_link 'client_management.completed_requests', context_link 'client_management.completed_requests',
:link_path=>"completed_requests_admin_client_managements_path" , :link_path=>"completed_requests_admin_client_managements_path" ,
:priority=>1, :priority=>1,
:active_for_action=>{'admin/client_managements'=>"completed_requests"}, :active_for_action=>{'admin/client_managements'=>"completed_requests"},
:available_for => 'users' :available_for => 'admin'
context_link 'client_management.contracts', context_link 'client_management.contracts',
:link_path=>"contracts_admin_client_managements_path" , :link_path=>"contracts_admin_client_managements_path" ,
:priority=>1, :priority=>1,
:active_for_action=>{'admin/client_managements'=>"contracts"}, :active_for_action=>{'admin/client_managements'=>"contracts"},
:available_for => 'users' :available_for => 'admin'
context_link 'client_management.cert_management',
:link_path=>"cert_management_admin_site_panel_index_path" ,
:priority=>1,
:active_for_action=>{'admin/site_panel'=>"cert_management"},
:available_for => 'admin'
context_link 'client_management.create_site', context_link 'client_management.create_site',
:link_path=>"admin_site_panel_path" , :link_path=>"admin_site_panel_path" ,
:priority=>1, :priority=>1,
:active_for_action=>{'admin/site_panel'=>"index"}, :active_for_action=>{'admin/site_panel'=>"index"},
:available_for => 'users' :available_for => 'admin'
context_link 'client_management.sites_list', context_link 'client_management.sites_list',
:link_path=>"admin_site_panel_sites_list_path" , :link_path=>"admin_site_panel_sites_list_path" ,
:priority=>1, :priority=>1,
:active_for_action=>{'admin/site_panel'=>"sites_list"}, :active_for_action=>{'admin/site_panel'=>"sites_list"},
:available_for => 'users' :available_for => 'admin'
context_link 'client_management.server_manager', context_link 'client_management.server_manager',
:link_path=>"admin_site_panel_server_manager_path" , :link_path=>"admin_site_panel_server_manager_path" ,
:priority=>1, :priority=>1,
:active_for_action=>{'admin/site_panel'=>"server_manager"}, :active_for_action=>{'admin/site_panel'=>"server_manager"},
:available_for => 'users' :available_for => 'admin'
end end
end end
end end

View File

@ -20,7 +20,7 @@ namespace :create_site do
file_path = "#{site_construct.path}/#{site_construct.site_name}/tmp/#{file_name}" file_path = "#{site_construct.path}/#{site_construct.site_name}/tmp/#{file_name}"
site_construct.cert_ver_added_text = " location #{location_path}{#add_by_site_module\n alias #{file_path};\n }" site_construct.cert_ver_added_text = " location #{location_path}{#add_by_site_module\n alias #{file_path};\n }"
site_construct.save site_construct.save
server_array = nginx_config.scan(/^[ \t]*server[ \t]*{(?:(?!server[ \t]*{).)+}/m) server_array = site_construct.parse_nginx_text_to_server_blocks(nginx_config)
server_array.each do |server| server_array.each do |server|
tmp = server[0...-1] + site_construct.cert_ver_added_text + "\n}" tmp = server[0...-1] + site_construct.cert_ver_added_text + "\n}"
nginx_config = nginx_config.sub(server,tmp) nginx_config = nginx_config.sub(server,tmp)

View File

@ -0,0 +1,58 @@
require 'net/ssh'
require 'pathname'
require 'json'
namespace :create_site do
desc "Change Site Cert"
task :change_site_cert,[:id] => :environment do |task,args|
begin
@site_construct = SiteConstruct.find(args.id)
@site_cert = @site_construct.site_cert
site_server = @site_construct.site_server
@site_construct.update(:infos=>[],:status=>"changing")
if !site_server.nil? && !@site_cert.nil?
@password = site_server.password
Net::SSH.start(site_server.ip , site_server.account , password: site_server.password) do |ssh|
update_infos("Copying Cert to #{@site_construct.server_type}...")
cert_file_content = [(@site_cert.cert_file.file.read.strip rescue ""),(@site_cert.ca_bundle.file.read.strip rescue "")].join("\n").strip
private_key_content = @site_cert.private_key.file.read
cert_file_store_path = @site_construct.cert_file_remote_store_path
exec_ssh_command_by_sudo(ssh,"mkdir -p #{File.dirname(cert_file_store_path)}")
exec_command_by_user(ssh,"x='#{cert_file_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{cert_file_store_path}\"")
private_key_store_path = @site_construct.private_key_remote_store_path
exec_ssh_command_by_sudo(ssh,"mkdir -p #{File.dirname(private_key_store_path)}")
exec_command_by_user(ssh,"x='#{private_key_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{private_key_store_path}\"")
update_infos("Finish copy.")
update_infos("Setting Cert...")
nginx_file_content = exec_command_by_user(ssh,"cat #{@site_construct.nginx_file}")
all_ports = (@site_construct.port + ["443"]).uniq
@site_construct.update(:port=> all_ports )
nginx_file_content = @site_construct.generate_nginx_text(nginx_file_content)
cmd = "x='#{nginx_file_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{@site_construct.nginx_file}\""
exec_command_by_user(ssh,cmd)
puts nginx_file_content
exec_ssh_command_by_sudo(ssh,"service nginx restart")
update_infos("Finish!")
@site_construct.update(:status=>"finish")
end
else
update_infos("Cert not found!")
@site_construct.update(:status=>"error")
end
rescue => e
puts [e,e.backtrace]
update_infos(e.to_s)
@site_construct.update(:status=>"error")
end
end
def exec_command_by_user(session,command)
output = session.exec!(command)
return output[0...-1].gsub(/^\n[\n]+/,'')
end
def exec_ssh_command_by_sudo(session,command)
output = session.exec!("echo '#{@password}' | sudo -S #{command}")
if output.include?("sudo:") && output.include?("command not found")
output = session.exec!(command)
end
return output
end
end

View File

@ -1,24 +1,35 @@
require 'net/ssh' require 'net/ssh'
require 'pathname' require 'pathname'
require 'json'
namespace :create_site do namespace :create_site do
desc "Change Site Server Name" desc "Change Site Server Name"
task :change_site_server_name,[:id,:server_name] => :environment do |task,args| task :change_site_server_name,[:id,:server_name,:port] => :environment do |task,args|
begin begin
site_construct = SiteConstruct.find(args.id) @site_construct = SiteConstruct.find(args.id)
site_server = site_construct.site_server site_server = @site_construct.site_server
if !site_server.nil? if !site_server.nil?
@password = site_server.password @password = site_server.password
update_infos("Starting change domain name and ports.")
Net::SSH.start(site_server.ip , site_server.account , password: site_server.password) do |ssh| Net::SSH.start(site_server.ip , site_server.account , password: site_server.password) do |ssh|
nginx_file_content = exec_command_by_user(ssh,"cat #{site_construct.nginx_file}") @site_construct.update(:domain_name=>args.server_name)
nginx_file_content = nginx_file_content.gsub(/^[ \t]*server_name[ \t]+.*;/," server_name #{args.server_name};") update_infos("Reading setting file.")
puts nginx_file_content nginx_file_content = exec_command_by_user(ssh,"cat #{@site_construct.nginx_file}")
cmd = "x='#{nginx_file_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{site_construct.nginx_file}\"" if args.port.present?
all_ports = args.port.split('////')
@site_construct.update(:port=> all_ports )
end
nginx_file_content = @site_construct.generate_nginx_text(nginx_file_content)
update_infos("Writing...")
cmd = "x='#{nginx_file_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{@site_construct.nginx_file}\""
exec_command_by_user(ssh,cmd) exec_command_by_user(ssh,cmd)
exec_ssh_command_by_sudo(ssh,"service nginx restart") exec_ssh_command_by_sudo(ssh,"service nginx restart")
update_infos("Finish!")
@site_construct.update(:status=>'finish')
end end
site_construct.update(:domain_name=>args.server_name)
end end
rescue => e rescue => e
update_infos(e.to_s)
@site_construct.update(:status=>'error')
puts [e,e.backtrace] puts [e,e.backtrace]
end end
end end

View File

@ -32,25 +32,7 @@ namespace :create_site do
end end
Net::SSH.start(args.ip , args.user , password: args.password) do |ssh| Net::SSH.start(args.ip , args.user , password: args.password) do |ssh|
update_infos("setting nginx for #{args.site_name}") update_infos("setting nginx for #{args.site_name}")
nginx_setting_texts = ('upstream '+@site_construct.get_site_name+'_sock {\n'+ nginx_setting_texts = @site_construct.generate_nginx_text
' server unix:'+args.path+'/'+@site_construct.get_site_name+'/tmp/unicorn.sock;\n'+
'}\n'+
'server {\n'+
' listen '+args.port+';\n\n'+
' root '+args.path+'/'+@site_construct.get_site_name+'/public;\n\n'+
'server_name '+args.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'+
' proxy_connect_timeout 360;\n'+
'proxy_pass http://'+@site_construct.get_site_name+'_sock;\n'+
' }\n'+
'}')
exec_ssh_command_by_sudo_for_create(ssh,"touch /etc/nginx/orbit_sites/#{@site_construct.get_site_name}") exec_ssh_command_by_sudo_for_create(ssh,"touch /etc/nginx/orbit_sites/#{@site_construct.get_site_name}")
exec_ssh_command_by_sudo_for_create(ssh,"sh -c \"echo '#{nginx_setting_texts}' > /etc/nginx/orbit_sites/#{@site_construct.get_site_name}\"") exec_ssh_command_by_sudo_for_create(ssh,"sh -c \"echo '#{nginx_setting_texts}' > /etc/nginx/orbit_sites/#{@site_construct.get_site_name}\"")
update_infos("restarting nginx") update_infos("restarting nginx")

View File

@ -31,25 +31,7 @@ namespace :create_site do
end end
Net::SSH.start(args.ip , args.user , password: args.password) do |ssh| Net::SSH.start(args.ip , args.user , password: args.password) do |ssh|
update_infos("setting nginx for #{args.site_name}") update_infos("setting nginx for #{args.site_name}")
nginx_setting_texts = ('upstream '+@site_construct.get_site_name+'_sock {\n'+ nginx_setting_texts = @site_construct.generate_nginx_text
' server unix:'+args.path+'/'+@site_construct.get_site_name+'/tmp/unicorn.sock;\n'+
'}\n'+
'server {\n'+
' listen '+args.port+';\n\n'+
' root '+args.path+'/'+@site_construct.get_site_name+'/public;\n\n'+
'server_name '+args.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'+
' proxy_connect_timeout 360;\n'+
'proxy_pass http://'+@site_construct.get_site_name+'_sock;\n'+
' }\n'+
'}')
exec_ssh_command_by_sudo_for_create(ssh,"touch /etc/nginx/orbit_sites/#{@site_construct.get_site_name}") exec_ssh_command_by_sudo_for_create(ssh,"touch /etc/nginx/orbit_sites/#{@site_construct.get_site_name}")
exec_ssh_command_by_sudo_for_create(ssh,"sh -c \"echo '#{nginx_setting_texts}' > /etc/nginx/orbit_sites/#{@site_construct.get_site_name}\"") exec_ssh_command_by_sudo_for_create(ssh,"sh -c \"echo '#{nginx_setting_texts}' > /etc/nginx/orbit_sites/#{@site_construct.get_site_name}\"")
update_infos("restarting nginx") update_infos("restarting nginx")

View File

@ -1,10 +1,12 @@
require 'net/ssh' require 'net/ssh'
require 'pathname' require 'pathname'
require 'fileutils'
namespace :create_site do namespace :create_site do
desc "Detect sites" desc "Detect sites"
task :detect_sites,[:detect_name] => :environment do |task,args| task :detect_sites,[:detect_name] => :environment do |task,args|
#Multithread.where(:key=>'detect_sites').destroy #Multithread.where(:key=>'detect_sites').destroy
Multithread.where(:key=>'detect_sites').each{|thread| thread.destroy if (thread.status["status"] == "error" || thread.status["status"] == "finish")} Multithread.where(:key=>'detect_sites').each{|thread| thread.destroy if (thread.status["status"] == "error" || thread.status["status"] == "finish")}
Multithread.where(:key=>'detect_sites').destroy
@thread = Multithread.where(:key=>'detect_sites').first @thread = Multithread.where(:key=>'detect_sites').first
if @thread.nil? if @thread.nil?
begin begin
@ -47,6 +49,8 @@ namespace :create_site do
server_name_list << server_name_for_site server_name_list << server_name_for_site
end end
server_name = server_name_list.join(' ') server_name = server_name_list.join(' ')
nginx_file_content = exec_ssh_command_by_sudo_and_see_output(ssh,"cat #{nginx_file}",false)
nginx_file_content = nginx_file_content.join('\n') if nginx_file_content.class == Array
site_path = Pathname.new(exec_ssh_command_by_sudo(ssh,"echo `grep root #{nginx_file} | grep -v -e '#.*root'`").to_s.split("\n").first.to_s.strip.split("root").last.to_s.gsub(";","").strip).dirname.to_s site_path = Pathname.new(exec_ssh_command_by_sudo(ssh,"echo `grep root #{nginx_file} | grep -v -e '#.*root'`").to_s.split("\n").first.to_s.strip.split("root").last.to_s.gsub(";","").strip).dirname.to_s
if site_path.present? && exec_ssh_command_by_sudo(ssh,"ls #{site_path}").split.length != 0 && exec_ssh_command_by_sudo(ssh,"ls #{site_path}/Gemfile").include?("No such file or directory") if site_path.present? && exec_ssh_command_by_sudo(ssh,"ls #{site_path}").split.length != 0 && exec_ssh_command_by_sudo(ssh,"ls #{site_path}/Gemfile").include?("No such file or directory")
SiteConstruct.where(:server_type => @site_server.server_name , :domain_name=>server_name).destroy SiteConstruct.where(:server_type => @site_server.server_name , :domain_name=>server_name).destroy
@ -55,7 +59,7 @@ namespace :create_site do
path = Pathname.new(site_path).dirname.to_s path = Pathname.new(site_path).dirname.to_s
site_name = Pathname.new(site_path).basename.to_s site_name = Pathname.new(site_path).basename.to_s
server_type = @site_server.server_name server_type = @site_server.server_name
port = exec_ssh_command_by_sudo(ssh,"echo `grep 'listen' #{nginx_file} | grep -v -e '#.*listen'`").split("\n").first.strip.split("listen").last.strip.split(";").first.split.select{|p| p.strip == p.strip.to_i.to_s}.first.strip rescue "80" port = exec_ssh_command_by_sudo_and_see_output(ssh,"grep 'listen' #{nginx_file} | grep -v -e '#.*listen'",false).flat_map{|s| s.split(/(\r\n|\n)/)}.map{|s| s.match(/listen\s+(\d+)/)[1] rescue nil}.select{|s| s.present?}.uniq
db_name = exec_ssh_command_by_sudo(ssh,"echo `cat #{site_path}/config/mongoid.yml | grep 'database'`").split("database:").last.strip db_name = exec_ssh_command_by_sudo(ssh,"echo `cat #{site_path}/config/mongoid.yml | grep 'database'`").split("database:").last.strip
db_name = site_name.gsub("-","_") if db_name.include?("No such file or directory") db_name = site_name.gsub("-","_") if db_name.include?("No such file or directory")
unicorn_sock_path = exec_ssh_command_by_sudo(ssh,"echo `grep 'server unix' #{nginx_file} | grep -v -e '#.*server unix'`").strip.split("server unix").last.strip.split(":").last.strip rescue (site_path+"/tmp/unicorn.sock") unicorn_sock_path = exec_ssh_command_by_sudo(ssh,"echo `grep 'server unix' #{nginx_file} | grep -v -e '#.*server unix'`").strip.split("server unix").last.strip.split(":").last.strip rescue (site_path+"/tmp/unicorn.sock")
@ -77,13 +81,13 @@ namespace :create_site do
status = "closed" status = "closed"
end end
end end
site_constructs = SiteConstruct.where(:server_type => server_type , :domain_name.in => [server_name,*server_name_list]).to_a site_constructs = SiteConstruct.where(:server_type => server_type , :nginx_file=>nginx_file).to_a
site_construct = site_constructs[0] site_construct = site_constructs[0]
Array(site_constructs[1..-1]).each do |s| Array(site_constructs[1..-1]).each do |s|
s.destroy s.destroy
end end
cert_ver_added_text = exec_command_by_user(ssh,"cat #{nginx_file}").scan(/[ \t]*location(?:(?!location.*{).)+{#add_by_site_module.*}/m)[0] cert_ver_added_text = exec_command_by_user(ssh,"cat #{nginx_file}").scan(/[ \t]*location(?:(?!location.*{).)+{#add_by_site_module.*}/m)[0]
update_thread_infos("Detect <a href='#{((port == "443") ? "https" : "http")}://#{server_name}#{((port=="80" || port=="443") ? "" : (':'+port))}'>#{server_name}</a>".html_safe) update_thread_infos("Detect <a href='#{((port[0] == "443") ? "https" : "http")}://#{server_name}#{((port[0]=="80" || port[0]=="443") ? "" : (':'+port[0]))}'>#{server_name}</a>".html_safe)
if site_construct.nil? if site_construct.nil?
site_construct = SiteConstruct.create(:server_type=>server_type,:site_name=>site_name,:domain_name=>server_name,:nginx_file=>nginx_file,:db_name=>db_name,:port=>port,:path=>path,:site_type=>site_type,:school_name=>school_name,:user_id=>User.first.id,:status=>status,:cert_ver_added_text=>cert_ver_added_text) site_construct = SiteConstruct.create(:server_type=>server_type,:site_name=>site_name,:domain_name=>server_name,:nginx_file=>nginx_file,:db_name=>db_name,:port=>port,:path=>path,:site_type=>site_type,:school_name=>school_name,:user_id=>User.first.id,:status=>status,:cert_ver_added_text=>cert_ver_added_text)
else else
@ -103,6 +107,31 @@ namespace :create_site do
end end
end end
site_construct.update(:rails_env => rails_env) site_construct.update(:rails_env => rails_env)
crt_file_path = nginx_file_content.match(/ssl_certificate\s+(.*)/)[1].split(';').first rescue ''
private_key_path = nginx_file_content.match(/ssl_certificate_key\s+(.*)/)[1].split(';').first rescue ''
site_cert = nil
if crt_file_path.present? || private_key_path.present?
site_cert = site_construct.site_cert
if site_cert.nil?
site_cert = SiteCert.where(:source_paths=>[crt_file_path,private_key_path]).first
site_cert = SiteCert.new if site_cert.nil?
end
if true #site_cert.source_paths.count == 0
site_cert["cert_file"] = File.basename(crt_file_path)
cert_file_store_path = site_cert.cert_file.file.file
crt_file_content = exec_ssh_command_by_sudo_and_see_output(ssh,"cat #{crt_file_path}",false).select{|s| s.present?}.join("\n").strip.split(/(\r\n|\n)/).select{|s| s.present?}.join("\n")
FileUtils.mkdir_p(File.dirname(cert_file_store_path)) unless Dir.exist?(File.dirname(cert_file_store_path))
File.open(site_cert.cert_file.file.file,'w+'){|f| f.write(crt_file_content)}
site_cert["private_key"] = File.basename(private_key_path)
private_key_store_path = site_cert.private_key.file.file
private_key_content = exec_ssh_command_by_sudo_and_see_output(ssh,"cat #{private_key_path}",false).select{|s| s.present?}.join("\n").strip.split(/(\r\n|\n)/).select{|s| s.present?}.join("\n")
FileUtils.mkdir_p(File.dirname(private_key_store_path)) unless Dir.exist?(File.dirname(private_key_path))
File.open(site_cert.private_key.file.file,'w+'){|f| f.write(private_key_content)}
site_cert.source_paths = [crt_file_path,private_key_path]
site_cert.save
site_construct.update(:site_cert=>site_cert)
end
end
end end
end end
end end