Add Super User Management feature.

This commit is contained in:
BoHung Chiu 2022-11-14 12:56:29 +08:00
parent 4869c3274c
commit 5a3b5c895c
13 changed files with 678 additions and 13 deletions

File diff suppressed because one or more lines are too long

View File

@ -45,6 +45,65 @@ class Admin::SitePanelController < OrbitAdminController
return super return super
end end
end end
def super_manager_management
@site_server = SiteServer.find(params[:id])
end
def update_super_manager_management
@site_server = SiteServer.find(params[:id])
site_server_params = params.require(:site_server).permit! rescue {}
removed_super_users = []
site_server_params["site_super_users_attributes"].each do |k, v|
if v["_destroy"] == 'true'
super_user = SiteSuperUser.find(v["id"])
if super_user.old_user_name.nil?
removed_super_users << super_user.user_name
elsif super_user.old_user_name != ''
removed_super_users << super_user.old_user_name
end
end
end if site_server_params["site_super_users_attributes"]
@site_server.update_attributes(site_server_params)
@site_server.check_super_user_changed
if removed_super_users.count != 0
@site_server.removed_super_users += removed_super_users
@site_server.super_user_changed = true
@site_server.save
end
redirect_back_custom
end
def super_manager_management_for_site
@site_construct = SiteConstruct.find(params[:id])
end
def update_super_manager_management_for_site
@site_construct = SiteConstruct.find(params[:id])
site_construct_params = params.require(:site_construct).permit! rescue {}
removed_super_users = []
site_construct_params["site_super_users_attributes"].each do |k, v|
if v["_destroy"] == 'true'
super_user = SiteSuperUser.find(v["id"])
if super_user.old_user_name.nil?
removed_super_users << super_user.user_name
elsif super_user.old_user_name != ''
removed_super_users << super_user.old_user_name
end
end
end if site_construct_params["site_super_users_attributes"]
@site_construct.update_attributes(site_construct_params)
@site_construct.check_super_user_changed
if removed_super_users.count != 0
@site_construct.removed_super_users += removed_super_users
@site_construct.super_user_changed = true
@site_construct.save
end
redirect_back_custom
end
def redirect_back_custom
if Is_Rails5
redirect_back(fallback_location: { action: "setting"})
else
redirect_to :back
end
end
def setting def setting
ClientManagerSetting.create if ClientManagerSetting.count == 0 ClientManagerSetting.create if ClientManagerSetting.count == 0
@setting = ClientManagerSetting.first @setting = ClientManagerSetting.first
@ -53,11 +112,7 @@ class Admin::SitePanelController < OrbitAdminController
setting_params = params.require(:client_manager_setting).permit! setting_params = params.require(:client_manager_setting).permit!
setting = ClientManagerSetting.first setting = ClientManagerSetting.first
setting.update_attributes(setting_params) setting.update_attributes(setting_params)
if Is_Rails5 redirect_back_custom
redirect_back(fallback_location: { action: "setting"})
else
redirect_to :back and return
end
end end
def upload_cert def upload_cert
@site_cert = SiteCert.new @site_cert = SiteCert.new
@ -331,24 +386,101 @@ class Admin::SitePanelController < OrbitAdminController
system("bundle exec rake create_site:change_site_cert[#{params[:id]},#{is_certbot},#{params[:is_server]}]") system("bundle exec rake create_site:change_site_cert[#{params[:id]},#{is_certbot},#{params[:is_server]}]")
end end
end end
elsif params[:type] == 'apply_change_users'
Thread.new do
exec_commands_args = {}
site_server = nil
site_construct = nil
if params[:is_server] == 'true'
site_server = SiteServer.find(params[:id])
site_super_users = site_server.site_super_users.where(:is_changed=>true).to_a
removed_super_users = site_server.removed_super_users
exec_commands_args = {:type=>'exec_all', :server_name=>site_server.server_name}
clean_thread_execing_info
else
site_construct = SiteConstruct.find(params[:id])
site_super_users = site_construct.site_super_users.where(:is_changed=>true).to_a
removed_super_users = site_construct.removed_super_users
exec_commands_args = {:site_construct_id=>params[:id], :type=>'exec_commands'}
end
commands = []
commands_i18n = []
removed_super_users.uniq.each do |user_name|
commands << remove_user_mongo_eval_cmd(user_name)
commands_i18n << "Delete Super Manager: #{user_name}"
end
site_super_users.each do |super_user|
user_attrs = super_user.get_attrs
old_user_name = super_user.old_user_name
member_profile = MemberProfile.new(id: nil, is_hidden: true, position: 0)
member_profile.send(:generate_uid)
member_attrs = member_profile.attributes
member_attrs.delete('_id')
commands << user_mongo_eval_cmd(user_attrs, member_attrs, (old_user_name.blank? ? nil : old_user_name))
if old_user_name == ''
commands_i18n << "Create Super Manager: #{super_user.user_name}"
else
commands_i18n << "Update Super Manager: #{super_user.user_name}"
end
end
if commands.count > 0
site_construct.update(:status=>"execing",:infos=>[""]) if site_construct
exec_commands_args[:commands] = commands
exec_commands_args[:commands_i18n] = commands_i18n
if system("bundle exec rake exec_commands:exec_commands[\"#{Base64.strict_encode64(exec_commands_args.to_json)}\"]")
SiteSuperUser.where(:id.in=>site_super_users.map{|u| u.id}).clear_changed
if site_server
site_server.update(:super_user_changed => false, :removed_super_users => [])
end
if site_construct
site_construct.update(:super_user_changed => false, :removed_super_users => [])
end
end
end
end
else else
Thread.new do Thread.new do
cmds = params[:commands].split('////') cmds = params[:commands].split('////')
commands_i18n = (0...cmds.count).collect{nil}
if cmds.include?('{{create_super_manager}}') && !params[:account].blank? && !params[:password].blank? if cmds.include?('{{create_super_manager}}') && !params[:account].blank? && !params[:password].blank?
site_server_ids = []
site_construct_id = nil
if params[:id].blank? && !params[:server_names].blank?
site_server_ids = SiteServer.where(:server_name.in=>params[:server_names]).pluck(:id)
else
site_construct = SiteConstruct.find(params[:id])
site_construct.update(:status=>"execing",:infos=>[""])
site_construct_id = site_construct.id rescue nil
end
idx = cmds.index('{{create_super_manager}}') idx = cmds.index('{{create_super_manager}}')
cmds[idx] = create_super_manager_cmd(params[:account],params[:password]) cmds[idx] = create_super_manager_cmd(params[:account],params[:password], site_server_ids, site_construct_id)
commands_i18n[idx] = "#{@create_super_user ? 'Create' : 'Update'} Super Manager: #{params[:account]}"
end
if commands_i18n.compact.count == 0
commands_i18n = nil
end end
exec_commands_args = {} exec_commands_args = {}
if params[:id].blank? && !params[:server_names].blank? if params[:id].blank? && !params[:server_names].blank?
exec_commands_args = {:commands=>cmds.join('////'), :type=>'exec_all', :server_name=>params[:server_names].join('////')} exec_commands_args = {:commands=>cmds.join('////'), :type=>'exec_all', :server_name=>params[:server_names].join('////')}
clean_thread_execing_info
else else
exec_commands_args = {:site_construct_id=>params[:id], :commands=>cmds.join('////'), :type=>'exec_commands'} exec_commands_args = {:site_construct_id=>params[:id], :commands=>cmds.join('////'), :type=>'exec_commands'}
end end
exec_commands_args[:commands_i18n] = commands_i18n
system("bundle exec rake exec_commands:exec_commands[\"#{Base64.strict_encode64(exec_commands_args.to_json)}\"]") system("bundle exec rake exec_commands:exec_commands[\"#{Base64.strict_encode64(exec_commands_args.to_json)}\"]")
end end
end end
render :json =>{"success"=>true} render :json =>{"success"=>true}
end end
def clean_thread_execing_info
Multithread.where(:key=>'execing_commands').each do |thread|
if thread.status["status"] == "error" || thread.status["status"] == "finish"
thread.destroy
elsif thread.updated_at < (Time.now - 5.minute)
thread.destroy
end
end
end
def sites_list def sites_list
@module_app = ModuleApp.where(:title=>@app_title).first @module_app = ModuleApp.where(:title=>@app_title).first
@categories = @module_app.categories @categories = @module_app.categories
@ -419,17 +551,50 @@ class Admin::SitePanelController < OrbitAdminController
site_params = params.require(:site_construct).permit! site_params = params.require(:site_construct).permit!
site_params.except(:domain_name,:port) site_params.except(:domain_name,:port)
end end
def create_super_manager_cmd(user_name, password) def create_super_manager_cmd(user_name, password, site_server_ids, site_construct_id)
user = User.new(id: nil, user_name: user_name, password: password, beta_tester: true, approved: true) password_digest = SiteSuperUser.generate_password_digest(password)
member_profile = user.build_member_profile(id: nil, is_hidden: true) user_attrs = nil
user_attrs = user.attributes super_user = nil
user_attrs.delete('_id') if site_server_ids.present?
user_attrs.delete('member_profile_id') site_server_ids.each_with_index do |site_server_id, i|
super_user = SiteSuperUser.where(:site_construct_id=>site_construct_id, :user_name=>user_name).first
if super_user.nil?
super_user = SiteSuperUser.new(:site_construct_id=>site_construct_id, :user_name=>user_name)
@create_super_user = true
end
super_user.update_password_digest(password_digest)
if i == 0
user_attrs = super_user.get_attrs
end
end
elsif site_construct_id.present?
super_user = SiteSuperUser.where(:site_construct_id=>site_construct_id, :user_name=>user_name).first
if super_user.nil?
super_user = SiteSuperUser.new(:site_construct_id=>site_construct_id, :user_name=>user_name)
@create_super_user = true
end
super_user.update_password_digest(password_digest)
user_attrs = super_user.get_attrs
end
member_profile = MemberProfile.new(id: nil, is_hidden: true, position: 0)
member_profile.send(:generate_uid) member_profile.send(:generate_uid)
member_attrs = member_profile.attributes member_attrs = member_profile.attributes
member_attrs.delete('_id') member_attrs.delete('_id')
user_mongo_eval_cmd(user_attrs, member_attrs)
end
def remove_user_mongo_eval_cmd(user_name)
cmd = """mongo --eval 'a=function(){ cmd = """mongo --eval 'a=function(){
var user_query = {user_name: \"#{user_attrs['user_name']}\"}; var user_query = {user_name: \"#{user_name}\"};
user = db.users.findOne(user_query);
if (user) {
db.member_profiles.deleteOne({_id: user[\"member_profile_id\"]});
db.users.deleteOne(user_query);
}
}()' {{db_name}}""".gsub(/\n|^ */,"")
end
def user_mongo_eval_cmd(user_attrs, member_attrs, old_user_name=nil)
cmd = """mongo --eval 'a=function(){
var user_query = {user_name: \"#{old_user_name ? old_user_name : user_attrs['user_name']}\"};
var user = db.users.findOne(user_query); var user = db.users.findOne(user_query);
var user_id; var user_id;
var user_data = #{user_attrs.to_json}; var user_data = #{user_attrs.to_json};
@ -443,6 +608,7 @@ class Admin::SitePanelController < OrbitAdminController
}else{ }else{
db.users.insertOne(user_data); db.users.insertOne(user_data);
} }
user_query = {user_name: \"#{user_attrs['user_name']}\"};
user = db.users.findOne(user_query); user = db.users.findOne(user_query);
var member_query = {_id: user.member_profile_id}; var member_query = {_id: user.member_profile_id};
var member = user.member_profile_id ? db.member_profiles.findOne(member_query) : null; var member = user.member_profile_id ? db.member_profiles.findOne(member_query) : null;

View File

@ -28,7 +28,11 @@ 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
field :super_user_changed, type: Boolean, type: false
field :removed_super_users, type: Array, default: []
belongs_to :site_cert belongs_to :site_cert
has_many :site_super_users, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :site_super_users, :allow_destroy => true
after_initialize do |record| after_initialize do |record|
unless record.new_record? unless record.new_record?
save_flag = false save_flag = false
@ -60,6 +64,9 @@ class SiteConstruct
@skip_callback = false @skip_callback = false
end end
end end
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
def generate_nginx_text(old_nginx_text="") def generate_nginx_text(old_nginx_text="")
sock_text = "upstream #{self.get_site_name}_sock {\n"+ sock_text = "upstream #{self.get_site_name}_sock {\n"+
" server unix:#{self.full_site_path}/tmp/unicorn.sock;\n"+ " server unix:#{self.full_site_path}/tmp/unicorn.sock;\n"+

View File

@ -15,6 +15,13 @@ class SiteServer
field :active , type: Boolean ,default: true field :active , type: Boolean ,default: true
field :has_certbot, type: Boolean , default: false field :has_certbot, type: Boolean , default: false
field :need_update_site_ids, type: Array, default: [] field :need_update_site_ids, type: Array, default: []
field :super_user_changed, type: Boolean, type: false
field :removed_super_users, type: Array, default: []
has_many :site_super_users, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :site_super_users, :allow_destroy => true
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
def domain_names def domain_names
if self.domain_name != '' if self.domain_name != ''
[self.domain_name] [self.domain_name]

View File

@ -0,0 +1,118 @@
class SiteSuperUser
include Mongoid::Document
include Mongoid::Timestamps
require_dependency 'bcrypt'
begin
require_or_load 'bcrypt/engine'
rescue
Object.send(:remove_const, 'BCrypt') rescue nil
$LOADED_FEATURES.select!{|p| !p.include? 'bcrypt'}
require 'bcrypt'
end
require_dependency 'active_model/secure_password'
include ActiveModel::SecurePassword
field :is_changed, type: Boolean, default: true
field :old_user_name, type: String, default: ''
field :user_name, type: String
field :password_high_security, type: Boolean, default: false
field :password_updated_at, type: Time
field :password_digest, type: String
field :old_password_digest_list, type: Array, default: []
field :beta_tester, type: Boolean, default: true
field :approved, type: Boolean, default: true
belongs_to :site_server
belongs_to :site_construct
has_secure_password
CurrentSite = Site.first
PasswordValidRegex = ::Regexp.new("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})")
CurrentSite.password_change_constrained = 5
before_save do
if self.user_name_changed? && self.user_name_was
self.old_user_name = self.user_name_was if !(self.is_changed) || self.old_user_name.blank?
self.is_changed = true
end
end
before_destroy do
if self.site_server
self.site_server.removed_super_users << (self.old_user_name.blank? ? self.user_name : self.old_user_name)
self.site_server.super_user_changed = true
self.site_server.save
elsif self.site_construct
self.site_construct.removed_super_users << (self.old_user_name.blank? ? self.user_name : self.old_user_name)
self.site_construct.super_user_changed = true
self.site_construct.save
end
end
def self.clear_changed
self.update_all(:is_changed=>false, :old_user_name=>nil)
end
def clear_changed
self.is_changed = false
self.old_user_name = nil
self.save
end
def self.generate_password_digest(password)
if password.length < 8
raise StandardError.new('Password too short!')
end
BCrypt::Password.create(password)
end
def old_password_digest_list_check(password)
tmps = self.old_password_digest_list + [self.password_digest]
tmps = tmps.compact.uniq
if tmps.length>0
tmp_len = self.class::CurrentSite.password_change_constrained+1
tmp_len = tmps.length<tmp_len ? tmps.length : tmp_len
@old_password_index = tmps[-tmp_len..-1].index{|pwd| BCrypt::Password.new(pwd)==password}
if @old_password_index.nil?
true
else
@old_password_index = -tmp_len + @old_password_index
false
end
else
true
end
end
def get_attrs
user_attrs = self.attributes
user_attrs.except('_id', 'site_server_id', 'site_construct_id', 'is_changed', 'old_user_name')
end
def update_password_digest(new_password_digest)
self.old_password_digest_list << self.password_digest if self.password_digest
self.password_digest = new_password_digest
self.save
end
def password=(value)
if self.old_password_digest_list_check(value)
if self.password_digest != self.old_password_digest_list[-1]
self.password_updated_at = Time.zone.now
if PasswordValidRegex.match(value)
self.password_high_security = true
else
self.password_high_security = false
end
if self.class::CurrentSite.password_change_constrained
self.old_password_digest_list << self.password_digest
end
self.is_changed = true
end
super(value)
if !self.new_record?
self.save
end
else
unless @old_password_index == -1 # @old_password_index = -1 -> the same as current password
self.is_changed = true
puts "@old_password_index: #{@old_password_index}"
self.old_password_digest_list << self.password_digest
self.old_password_digest_list.delete_at(@old_password_index)
super(value)
if !self.new_record?
self.save
end
end
end
self
end
end

View File

@ -70,6 +70,7 @@
<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-success" href = "<%= backup_setting_admin_site_panel_path(site_server) %>"><%= t('client_management.backup_setting') %></a> <a class="btn btn-success" href = "<%= backup_setting_admin_site_panel_path(site_server) %>"><%= t('client_management.backup_setting') %></a>
<a class="btn btn-dark btn-inverse detect_sites" href="javascript:void(0)" data-key="<%=site_server.server_name%>">Detect sites</a> <a class="btn btn-dark btn-inverse detect_sites" href="javascript:void(0)" data-key="<%=site_server.server_name%>">Detect sites</a>
<a title="<%=t('client_management.super_manager_management')%>" class="btn btn-primary super_manager_management" href="<%=super_manager_management_admin_site_panel_path(:id=>site_server.id) %>"><%=t('client_management.super_manager_management')%></a>
</td> </td>
</tr> </tr>
<% end %> <% end %>

View File

@ -0,0 +1,85 @@
<%= javascript_include_tag('/assets/client_management/jquery.validate.min') %>
<%
relation_field = "#{type.pluralize}"
records = f.object.send(relation_field)
%>
<div id="<%=type%>">
<!-- Add -->
<div>
<% if f.object.super_user_changed %>
<a href="javascript:void(0)" class="btn btn-success apply_change_users" data-id="<%=f.object.id%>" data-is-server="<%=f.object.class == SiteServer%>"><%= t('client_management.apply_change') %></a>
<hr>
<% end %>
</div>
<div class="add-target">
<% records.each do |record| %>
<%= f.fields_for relation_field, record do |f| %>
<%= render :partial => "super_manager_form_block", :locals=>{:f=>f} %>
<% end %>
<% end %>
</div>
<p class="add-btn">
<%= hidden_field_tag "#{relation_field}_count", records.count %>
<a class="btn btn-primary create_super_manager <%=type%>" href="#"><%= t("client_management.create_super_manager") %></a>
</p>
</div>
<style type="text/css">
.block_remove_btn{
color: red;
margin-right: 0.3em;
background: transparent;
border: 1px solid red;
margin-bottom: 1em;
padding: 0.4em 0.8em;
cursor: pointer;
}
.block_remove_btn:hover{
font-size: 1.3em;
top: 0.3em;
position: relative;
}
.user_form_block{
border: 0.3em solid #666;
margin-bottom: 0.5em;
padding-bottom: 1em;
}
.main-forms fieldset .form-actions{
background: #fff;
}
#info_texts{
white-space: pre;
}
</style>
<script type="text/javascript">
$(document).ready(function(){
function validate_password(){
$('.super_manager_form').validate();
}
validate_password();
$(document).on('click', ".create_super_manager.<%=type%>", function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_<%=relation_field%>", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'super_manager_form_block', f, relation_field) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.input-append').find('.tab-content').each(function() {
$(this).children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
});
formTip();
validate_password();
});
$(document).on('click','.block_remove_btn',function(){
var user_form_block = $(this).parents('.user_form_block').eq(0);
if(user_form_block.hasClass("new_record")){
user_form_block.remove()
}else{
if(window.confirm('<%=t("client_management.are_you_sure_to_delete")%>')){
user_form_block.addClass('hide');
user_form_block.find('.should_destroy').val('true');
}
}
})
})
</script>

View File

@ -0,0 +1,27 @@
<% object_name_underscore = f.object_name.gsub(/[\[\]]/,'_') %>
<div class="user_form_block <%= f.object.new_record? ? 'new_record' : '' %>">
<span class="block_remove_btn">X</span>
<div style="clear: both;"></div>
<div class="control-group">
<%= f.label :user_name ,t("client_management.user_name"), :class => "control-label muted" %>
<div class="controls">
<%= f.text_field :user_name, :placeholder => t("client_management.user_name") %>
</div>
</div>
<div class="control-group">
<%= f.label :new_password ,t("client_management.new_password"), :class => "control-label muted", :for=>"#{object_name_underscore}_new_password" %>
<div class="controls">
<%= f.password_field_tag "#{f.object_name}[password]", nil, :placeholder => t("client_management.new_password"), :id=>"#{object_name_underscore}_new_password", :data => {"rule-password"=> true} %>
</div>
</div>
<div class="control-group">
<%= f.label :confirm_new_password ,t("client_management.confirm_new_password"), :class => "control-label muted", :for=>"#{object_name_underscore}_confirm_new_password" %>
<div class="controls">
<%= f.password_field_tag "#{f.object_name}[password_confirmation]", nil, :placeholder => t("client_management.confirm_new_password"), :id=>"#{object_name_underscore}_confirm_new_password", :data => {"rule-password"=> true, "rule-equalTo"=>"##{object_name_underscore}_new_password"} %>
</div>
</div>
<% unless f.object.new_record? %>
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
<% end %>
</div>

View File

@ -0,0 +1,108 @@
<%= form_for @site_server, :url => {:action=>"update_super_manager_management"}, :html => {:class => 'form-horizontal main-forms super_manager_form'} do |f| %>
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<% end %>
<% content_for :page_specific_javascript do %>
<% end %>
<%#= f.error_messages %>
<fieldset>
<h3><%= "#{f.object.server_name} (IP: #{f.object.ip}) " %></h3>
<!-- Input Area -->
<div class="input-area">
<%= render :partial => "super_manager_form", :locals=>{:f=>f,:type=>"site_super_user"} %>
<div class="form-actions">
<%= f.submit t('submit'), class: 'btn btn-primary' %>
</div>
</div>
</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">
var close_info = false;
var timeout_id;
var status_relation = {"starting":"<span style=\"color: skyblue;\">starting</span>","execing":"<span style=\"color: skyblue;\">execing</span>","detecting":"<span style=\"color: skyblue;\">detecting</span>","error":"<span style=\"color: red;\">error</span>","finish": "<span style=\"color: darkseagreen;\">finish</span>","closed":"<span style=\"color: red;\">closed</span>"};
var need_close_info = false;
function see_infos(key){
key = key || "";
if(!close_info){
var request = $.post("<%=admin_site_panel_edit_server_info_path%>",{"type":'see_infos',"key":key});
request.done(function(data){
var infos = request.responseJSON.infos;
var status = request.responseJSON.status;
if($("#info_texts").length == 0)
return infos.join("\n")
else{
if(status == "")
var status_text = "not yet create";
else
var status_text = status_relation[status];
if(!status_text){
status_text = "<span style=\"color: skyblue;\">"+status+"</span>";
}
$("#info_texts").html(status_text+"<div style='clear:both;'></div>"+infos.join("\n"));
msg_end.scrollIntoView();
if(need_close_info && status != 'execing'){
close_info = true;
window.setTimeout(function(){
window.location.reload();
},1000);
}else{
if(status == 'execing'){
need_close_info = true;
}
timeout_id = window.setTimeout(see_infos(key),1000);
}
}
})
}else{
window.clearTimeout(timeout_id);
}
};
function show_infos_dialog(key){
key = key || "";
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(key)+"</div><div id='msg_end' style='height:0px; overflow:hidden'></div>"+
"</div>");
}else{
see_infos(key);
};
$( "#dialog-confirm" ).dialog({
resizable: true,
minHeight: 100,
maxHeight: 400,
width: '80%',
modal: true,
open: function(){
$(this).parent().css("top",$(document).height() - $(window).height() + "px");
},
close: function(){close_info = true;},
buttons: {
"<%= t('client_management.confirm') %>": function(){$( this ).dialog( "close" );close_info = true;},
"stop update": function(){close_info = true;}
}
});
}
$(document).ready(function(){
$('.apply_change_users').click(function(){
var item = $(this);
$.post("<%=admin_site_panel_edit_site_path%>",{'id': item.attr("data-id"),'type':'apply_change_users','is_server': item.data('is-server')}).done(function(){
show_infos_dialog("execing_commands");
});
});
})
</script>
<% end %>

View File

@ -0,0 +1,124 @@
<%= form_for @site_construct, :url => {:action=>"update_super_manager_management_for_site"}, :html => {:class => 'form-horizontal main-forms super_manager_form'} do |f| %>
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<% end %>
<% content_for :page_specific_javascript do %>
<% end %>
<%#= f.error_messages %>
<fieldset>
<h3><%= "#{f.object.site_name} (Domain: #{f.object.get_default_domain(true)}) " %></h3>
<!-- Input Area -->
<div class="input-area">
<%= render :partial => "super_manager_form", :locals=>{:f=>f,:type=>"site_super_user"} %>
<div class="form-actions">
<%= f.submit t('submit'), class: 'btn btn-primary' %>
</div>
</div>
</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">
var close_info = false;
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>"};
var need_close_info = false;
function see_infos(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("\n");
else{
$("#info_texts").html(infos.join("\n"));
if(status == "")
var status_text = "not yet create";
else
var status_text = status_relation[status];
if(status == "finish"){
var params = {}
var params_text = window.location.search.split(/[?&]/).slice(1);
params_text.forEach(function(text){
if(text.split("=")[0] != "")
params[text.split("=")[0]] = text.split("=")[1].split("#")[0].split("&")[0];
});
var new_params_text = "?";
Object.keys(params).forEach(function(key){
var value = params[key];
if(key == "id"){
if(value != id){
new_params_text += (key+"="+value+"&");
}
}else
new_params_text += (key+"="+value+"&");
});
if(new_params_text[new_params_text.length -1] == "&")
new_params_text = new_params_text.substr(0,new_params_text.length - 1);
if(params["id"] == id || window.refresh_flag || need_close_info){
close_info = true;
window.setTimeout(function(){
window.location.search = new_params_text;
}, 1000);
}
}else if(status == "changing"){
window.refresh_flag = true
}else{
need_close_info = true;
}
$(".see_infos[data-id="+id+"]").parent().siblings(".site_status").html(status_text);
//msg_end.scrollIntoView();
timeout_id = window.setTimeout(see_infos(id),1000);
}
}).fail(function() {
window.location.reload();
})
}else{
window.clearTimeout(timeout_id);
}
};
function show_infos_dialog(item){
close_info = true;
window.clearTimeout(timeout_id);
close_info = false;
var id = item.data("id");
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(id)+"</div><div id='msg_end' style='height:0px; overflow:hidden'></div>"+
"</div>");
}else{
see_infos(id);
};
$( "#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;}
}
});
}
$(document).ready(function(){
$('.apply_change_users').click(function(){
var item = $(this);
$.post("<%=admin_site_panel_edit_site_path%>",{'id': item.attr("data-id"),'type':'apply_change_users','is_server': item.data('is-server')}).done(function(){
show_infos_dialog(item);
});
});
})
</script>
<% end %>

View File

@ -7,6 +7,12 @@ en:
upload_cert: Upload Cert upload_cert: Upload Cert
cert_management: Cert Management cert_management: Cert Management
client_management: client_management:
apply_change: "Apply Change"
are_you_sure_to_delete: "Are you sure to delete?"
user_name: "User Account"
new_password: "New Password"
confirm_new_password: "Confirm new password"
super_manager_management: "Super Manager Management"
create_super_manager: Create Super Manager For Site create_super_manager: Create Super Manager For Site
enable_api: Enable API enable_api: Enable API
api_key: API Key api_key: API Key

View File

@ -7,6 +7,12 @@ zh_tw:
upload_cert: 上傳憑證 upload_cert: 上傳憑證
cert_management: 憑證管理 cert_management: 憑證管理
client_management: client_management:
apply_change: "設定生效"
are_you_sure_to_delete: "您確定要刪除嗎?"
user_name: "使用者帳號"
new_password: "新密碼"
confirm_new_password: "確認新密碼"
super_manager_management: "管理網站超級管理者"
create_super_manager: 創建網站超級管理者 create_super_manager: 創建網站超級管理者
enable_api: 開啟API enable_api: 開啟API
api_key: API Key api_key: API Key

View File

@ -67,6 +67,12 @@ Rails.application.routes.draw do
post 'create_cert' post 'create_cert'
patch 'create_cert' patch 'create_cert'
end end
member do
get "super_manager_management"
patch "update_super_manager_management"
get "super_manager_management_for_site"
patch "update_super_manager_management_for_site"
end
end end
end end