Merge pull request '发布V3.1.0版本' (#139) from dev_trustie_server into trustie_server

This commit is contained in:
jasder 2021-09-03 18:16:51 +08:00
commit 86c98a1716
60 changed files with 703 additions and 32 deletions

View File

@ -1,7 +1,7 @@
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() {
if ($('body.admins-courses-index-page').length > 0) { if ($('body.admins-courses-index-page').length > 0) {
let searchContainer = $(".course-list-form"); var searchContainer = $(".course-list-form");
let searchForm = $("form.search-form",searchContainer); var searchForm = $("form.search-form",searchContainer);
searchContainer.on('change', '.course-homepage-show', function(){ searchContainer.on('change', '.course-homepage-show', function(){
searchForm.find('input[type="submit"]').trigger('click'); searchForm.find('input[type="submit"]').trigger('click');

View File

@ -0,0 +1,76 @@
/*
* @Description: Do not edit
* @Date: 2021-08-31 11:16:45
* @LastEditors: viletyy
* @Author: viletyy
* @LastEditTime: 2021-08-31 14:19:46
* @FilePath: /forgeplus/app/assets/javascripts/admins/reversed_keywords/index.js
*/
$(document).on('turbolinks:load', function(){
var showSuccessNotify = function() {
$.notify({
message: '操作成功'
},{
type: 'success'
});
}
// close user
$('.reversed-keyword-list-container').on('click', '.close-action', function(){
var $closeAction = $(this);
var $uncloseAction = $closeAction.siblings('.unclose-action');
var keywordID = $closeAction.data('id');
customConfirm({
content: '确认关闭限制吗?',
ok: function(){
$.ajax({
url: '/admins/reversed_keywords/' + keywordID,
method: 'PUT',
dataType: 'json',
data: {
reversed_keyword: {
closed: true
}
},
success: function() {
showSuccessNotify();
$closeAction.hide();
$uncloseAction.show();
$(".reversed-keyword-item-"+keywordID).children('td').eq(3).text("")
}
});
}
});
});
// unclose user
$('.reversed-keyword-list-container').on('click', '.unclose-action', function(){
var $uncloseAction = $(this);
var $closeAction = $uncloseAction.siblings('.close-action');
var keywordID = $uncloseAction.data('id');
customConfirm({
content: '确认开启限制吗?',
ok: function () {
$.ajax({
url: '/admins/reversed_keywords/' + keywordID,
method: 'PUT',
dataType: 'json',
data: {
reversed_keyword: {
closed: false
}
},
success: function() {
showSuccessNotify();
$closeAction.show();
$uncloseAction.hide();
$(".reversed-keyword-item-"+keywordID).children('td').eq(3).text("√")
}
});
}
})
});
})

View File

@ -1,7 +1,15 @@
/*
* @Description: Do not edit
* @Date: 2021-07-16 11:58:16
* @LastEditors: viletyy
* @Author: viletyy
* @LastEditTime: 2021-08-31 14:48:59
* @FilePath: /forgeplus/app/assets/javascripts/admins/shixun_settings/index.js
*/
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function() {
if ($('body.admins-shixun-settings-index-page').length > 0) { if ($('body.admins-shixun-settings-index-page').length > 0) {
let searchContainer = $(".shixun-settings-list-form"); var searchContainer = $(".shixun-settings-list-form");
let searchForm = $("form.search-form",searchContainer); var searchForm = $("form.search-form",searchContainer);
searchContainer.on('change', '.shixun-settings-select', function(){ searchContainer.on('change', '.shixun-settings-select', function(){
searchForm.find('input[type="submit"]').trigger('click'); searchForm.find('input[type="submit"]').trigger('click');

View File

@ -9,6 +9,7 @@ class AccountsController < ApplicationController
# 其他平台同步注册的用户 # 其他平台同步注册的用户
def remote_register def remote_register
username = params[:username]&.gsub(/\s+/, "") username = params[:username]&.gsub(/\s+/, "")
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.is_reversed(username).present?
email = params[:email]&.gsub(/\s+/, "") email = params[:email]&.gsub(/\s+/, "")
password = params[:password] password = params[:password]
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "") platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")

View File

@ -0,0 +1,84 @@
class Admins::ReversedKeywordsController < Admins::BaseController
before_action :get_keyword, only: [:edit,:update, :destroy]
# before_action :validate_identifer, only: [:create, :update]
def index
sort_by = ReversedKeyword.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
q = ReversedKeyword.ransack(identifier_cont: params[:search])
keywords = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@keywords = paginate(keywords)
end
def new
@keyword = ReversedKeyword.new
end
def edit
end
def create
@keyword = ReversedKeyword.new(keyword_params)
if @keyword.save
redirect_to admins_reversed_keywords_path
flash[:success] = '系统保留关键词创建成功'
else
redirect_to admins_reversed_keywords_path
flash[:danger] = @keyword.errors.full_messages.join(",")
end
end
def update
respond_to do |format|
if @keyword.update_attributes(keyword_params)
format.html do
redirect_to admins_reversed_keywords_path
flash[:success] = '系统保留关键词更新成功'
end
format.js {render_ok}
else
format.html do
redirect_to admins_reversed_keywords_path
flash[:danger] = @keyword.errors.full_messages.join(",")
end
format.js {render_js_error}
end
end
end
def destroy
if @keyword.destroy
redirect_to admins_reversed_keywords_path
flash[:success] = "系统保留关键词删除成功"
else
redirect_to admins_reversed_keywords_path
flash[:danger] = "系统保留关键词删除失败"
end
end
private
def keyword_params
params.require(:reversed_keyword).permit!
end
def get_keyword
@keyword = ReversedKeyword.find_by(id: params[:id])
unless @keyword.present?
redirect_to admins_reversed_keywords_path
flash[:danger] = "系统保留关键词不存在"
end
end
def validate_identifer
identifer = keyword_params[:identifier].to_s.downcase
if identifer.blank?
redirect_to admins_reversed_keywords_path
flash[:danger] = '系统保留关键词标识不能为空'
elsif ProjectLanguage.exists?(name: identifer)
redirect_to admins_reversed_keywords_path
flash[:danger] = '系统保留关键词已存在'
end
end
end

View File

@ -246,6 +246,14 @@ class ApplicationController < ActionController::Base
tip_exception(401, "请登录后再操作") unless User.current.logged? tip_exception(401, "请登录后再操作") unless User.current.logged?
end end
def require_profile_completed
tip_exception(411, "请完善资料后再操作") unless User.current.profile_completed
end
def require_user_profile_completed(user)
tip_exception(412, "请用户完善资料后再操作") unless user.profile_completed
end
# 异常提醒 # 异常提醒
def tip_exception(status = -1, message) def tip_exception(status = -1, message)
raise Educoder::TipException.new(status, message) raise Educoder::TipException.new(status, message)

View File

@ -1,5 +1,6 @@
class ForksController < ApplicationController class ForksController < ApplicationController
before_action :require_login before_action :require_login
before_action :require_profile_completed, only: [:create]
before_action :load_project before_action :load_project
before_action :authenticate_project!, :authenticate_user! before_action :authenticate_project!, :authenticate_user!

View File

@ -1,7 +1,9 @@
class IssuesController < ApplicationController class IssuesController < ApplicationController
before_action :require_login, except: [:index, :show, :index_chosen] before_action :require_login, except: [:index, :show, :index_chosen]
before_action :require_profile_completed, only: [:create]
before_action :load_project before_action :load_project
before_action :set_user before_action :set_user
before_action :check_menu_authorize, except: [:index_chosen]
before_action :check_issue_permission before_action :check_issue_permission
before_action :operate_issue_permission, only:[:create, :update, :destroy, :clean, :series_update, :copy] before_action :operate_issue_permission, only:[:create, :update, :destroy, :clean, :series_update, :copy]
before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue] before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue]
@ -13,7 +15,6 @@ class IssuesController < ApplicationController
include TagChosenHelper include TagChosenHelper
def index def index
return render_not_found unless @project.has_menu_permission("issues")
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user)) @user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
issues = @project.issues.issue_issue.issue_index_includes issues = @project.issues.issue_issue.issue_index_includes
issues = issues.where(is_private: false) unless @user_admin_or_member issues = issues.where(is_private: false) unless @user_admin_or_member
@ -499,4 +500,8 @@ class IssuesController < ApplicationController
return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i
end end
end end
def check_menu_authorize
return render_not_found unless @project.has_menu_permission("issues")
end
end end

View File

@ -1,5 +1,6 @@
class JournalsController < ApplicationController class JournalsController < ApplicationController
before_action :require_login, except: [:index, :get_children_journals] before_action :require_login, except: [:index, :get_children_journals]
before_action :require_profile_completed, only: [:create]
before_action :set_issue before_action :set_issue
before_action :check_issue_permission before_action :check_issue_permission
before_action :set_journal, only: [:destroy, :edit, :update] before_action :set_journal, only: [:destroy, :edit, :update]

View File

@ -2,6 +2,7 @@ class MembersController < ApplicationController
before_action :require_login before_action :require_login
before_action :load_project before_action :load_project
before_action :find_user_with_id, only: %i[create remove change_role] before_action :find_user_with_id, only: %i[create remove change_role]
before_action :check_user_profile_completed, only: [:create]
before_action :operate!, except: %i[index] before_action :operate!, except: %i[index]
before_action :check_member_exists!, only: %i[create] before_action :check_member_exists!, only: %i[create]
before_action :check_member_not_exists!, only: %i[remove change_role] before_action :check_member_not_exists!, only: %i[remove change_role]
@ -61,4 +62,8 @@ class MembersController < ApplicationController
def check_member_not_exists! def check_member_not_exists!
return render_error("user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists? return render_error("user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists?
end end
def check_user_profile_completed
require_user_profile_completed(@user)
end
end end

View File

@ -1,5 +1,6 @@
class Organizations::OrganizationsController < Organizations::BaseController class Organizations::OrganizationsController < Organizations::BaseController
before_action :require_login, except: [:index, :show, :recommend] before_action :require_login, except: [:index, :show, :recommend]
before_action :require_profile_completed, only: [:create]
before_action :convert_image!, only: [:create, :update] before_action :convert_image!, only: [:create, :update]
before_action :load_organization, only: [:show, :update, :destroy] before_action :load_organization, only: [:show, :update, :destroy]
before_action :check_user_can_edit_org, only: [:update, :destroy] before_action :check_user_can_edit_org, only: [:update, :destroy]
@ -25,6 +26,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
def create def create
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.is_reversed(organization_params[:name]).present?
Organizations::CreateForm.new(organization_params).validate! Organizations::CreateForm.new(organization_params).validate!
@organization = Organizations::CreateService.call(current_user, organization_params) @organization = Organizations::CreateService.call(current_user, organization_params)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present? Util.write_file(@image, avatar_path(@organization)) if params[:image].present?

View File

@ -1,6 +1,7 @@
class Organizations::TeamUsersController < Organizations::BaseController class Organizations::TeamUsersController < Organizations::BaseController
before_action :load_organization, :load_team before_action :load_organization, :load_team
before_action :load_operate_user, only: [:create, :destroy] before_action :load_operate_user, only: [:create, :destroy]
before_action :check_user_profile_completed, only: [:create]
before_action :load_team_user, only: [:destroy] before_action :load_team_user, only: [:destroy]
before_action :check_user_can_edit_org, only: [:create, :destroy] before_action :check_user_can_edit_org, only: [:create, :destroy]
@ -83,4 +84,8 @@ class Organizations::TeamUsersController < Organizations::BaseController
tip_exception("组织团队成员不存在") if @team_user.nil? tip_exception("组织团队成员不存在") if @team_user.nil?
end end
def check_user_profile_completed
require_user_profile_completed(@operate_user)
end
end end

View File

@ -1,5 +1,5 @@
class OwnersController < ApplicationController class OwnersController < ApplicationController
before_action :require_login before_action :require_login, only: [:index]
def index def index
@owners = [] @owners = []
@ -9,4 +9,53 @@ class OwnersController < ApplicationController
teams: {can_create_org_project: true}) teams: {can_create_org_project: true})
.distinct .distinct
end end
def show
@owner = Owner.find_by(login: params[:id]) || Owner.find_by(id: params[:id])
return render_not_found unless @owner.present?
# 组织
if @owner.is_a?(Organization)
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
@can_create_project = @owner.can_create_project?(current_user.id)
@is_admin = current_user.admin? || @owner.is_owner?(current_user.id)
@is_member = @owner.is_member?(current_user.id)
# 用户
else
#待办事项,现在未做
if User.current.admin? || User.current.login == @owner.login
@waiting_applied_messages = @owner.applied_messages.waiting
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @owner.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @owner.id}, teams: {authorize: %w(admin owner)} )).common
@common_applied_projects = AppliedProject.where(project_id: @owner.full_admin_projects).common
@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
else
@waiting_applied_messages = AppliedMessage.none
@common_applied_transfer_projects = AppliedTransferProject.none
@common_applied_projects = AppliedProject.none
@undo_events = 0
end
#用户的组织数量
# @user_composes_count = @user.composes.size
@user_composes_count = 0
user_organizations = User.current.logged? ? @owner.organizations.with_visibility(%w(common limited)) + @owner.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @owner.organizations.with_visibility("common")
@user_org_count = user_organizations.size
normal_projects = Project.members_projects(@owner.id).to_sql
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @owner.id}).to_sql
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @owner.login) ? projects : projects.visible
@projects_common_count = user_projects.common.size
@projects_mirrior_count = user_projects.mirror.size
@projects_sync_mirrior_count = user_projects.sync_mirror.size
puts @owner.as_json
end
end
private
def org_limited_condition
@owner.organization_extension.limited? && !current_user.logged?
end
def org_privacy_condition
return false if current_user.admin?
@owner.organization_extension.privacy? && @owner.organization_users.where(user_id: current_user.id).blank?
end
end end

View File

@ -1,5 +1,6 @@
class PraiseTreadController < ApplicationController class PraiseTreadController < ApplicationController
before_action :require_login, except: %i[index] before_action :require_login, except: %i[index]
before_action :require_profile_completed, only: [:like]
before_action :find_project_with_id before_action :find_project_with_id
def index def index

View File

@ -1,5 +1,6 @@
class Projects::AppliedTransferProjectsController < Projects::BaseController class Projects::AppliedTransferProjectsController < Projects::BaseController
before_action :check_auth before_action :check_auth
before_action :check_user_profile_completed, only: [:create]
def organizations def organizations
@organizations = Organization.includes(:organization_extension).joins(team_users: :team).where(team_users: {user_id: current_user.id}, teams: {authorize: %w(admin owner)}) @organizations = Organization.includes(:organization_extension).joins(team_users: :team).where(team_users: {user_id: current_user.id}, teams: {authorize: %w(admin owner)})
@ -23,4 +24,10 @@ class Projects::AppliedTransferProjectsController < Projects::BaseController
def check_auth def check_auth
return render_forbidden unless current_user.admin? ||@project.owner?(current_user) return render_forbidden unless current_user.admin? ||@project.owner?(current_user)
end end
def check_user_profile_completed
@owner = Owner.find_by(login: params[:owner_name])
return if @owner.is_a?(Organization)
require_user_profile_completed(@owner)
end
end end

View File

@ -1,4 +1,5 @@
class Projects::ProjectAppliesController < Projects::BaseController class Projects::ProjectAppliesController < Projects::BaseController
before_action :require_profile_completed, only: [:create]
def create def create
project = Projects::ApplyJoinService.call(current_user, create_params) project = Projects::ApplyJoinService.call(current_user, create_params)
render_ok(project_id: project.id) render_ok(project_id: project.id)

View File

@ -5,6 +5,7 @@ class ProjectsController < ApplicationController
include Acceleratorable include Acceleratorable
before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about menu_list] before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about menu_list]
before_action :require_profile_completed, only: [:create, :migrate]
before_action :load_repository, except: %i[index group_type_list migrate create recommend] before_action :load_repository, except: %i[index group_type_list migrate create recommend]
before_action :authorizate_user_can_edit_project!, only: %i[update] before_action :authorizate_user_can_edit_project!, only: %i[update]
before_action :project_public?, only: %i[fork_users praise_users watch_users] before_action :project_public?, only: %i[fork_users praise_users watch_users]
@ -21,7 +22,7 @@ class ProjectsController < ApplicationController
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources")
menu.append(menu_hash_by_name("activity")) menu.append(menu_hash_by_name("activity"))
menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.manager?(current_user) menu.append(menu_hash_by_name("settings")) if current_user.admin? || @project.manager?(current_user)
render json: menu render json: menu
end end
@ -45,6 +46,7 @@ class ProjectsController < ApplicationController
def create def create
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
tip_exception("无法使用以下关键词:#{project_params[:repository_name]},请重新命名") if ReversedKeyword.is_reversed(project_params[:repository_name]).present?
Projects::CreateForm.new(project_params).validate! Projects::CreateForm.new(project_params).validate!
@project = Projects::CreateService.new(current_user, project_params).call @project = Projects::CreateService.new(current_user, project_params).call
@ -55,6 +57,7 @@ class ProjectsController < ApplicationController
end end
def migrate def migrate
tip_exception("无法使用以下关键词:#{mirror_params[:repository_name]},请重新命名") if ReversedKeyword.is_reversed(mirror_params[:repository_name]).present?
Projects::MigrateForm.new(mirror_params).validate! Projects::MigrateForm.new(mirror_params).validate!
@project = @project =

View File

@ -1,6 +1,8 @@
class PullRequestsController < ApplicationController class PullRequestsController < ApplicationController
before_action :require_login, except: [:index, :show, :files, :commits] before_action :require_login, except: [:index, :show, :files, :commits]
before_action :require_profile_completed, only: [:create]
before_action :load_repository before_action :load_repository
before_action :check_menu_authorize
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits] before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
before_action :load_pull_request, only: [:files, :commits] before_action :load_pull_request, only: [:files, :commits]
include TagChosenHelper include TagChosenHelper
@ -8,7 +10,6 @@ class PullRequestsController < ApplicationController
def index def index
return render_not_found unless @project.has_menu_permission("pulls")
# @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取 # @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取
issues = @project.issues.issue_pull_request.issue_index_includes.includes(pull_request: :user) issues = @project.issues.issue_pull_request.issue_index_includes.includes(pull_request: :user)
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user)) issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
@ -260,4 +261,8 @@ class PullRequestsController < ApplicationController
status_id: 1, status_id: 1,
} }
end end
def check_menu_authorize
return render_not_found unless @project.has_menu_permission("pulls")
end
end end

View File

@ -4,6 +4,7 @@ class RepositoriesController < ApplicationController
include Repository::LanguagesPercentagable include Repository::LanguagesPercentagable
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror] before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
before_action :require_profile_completed, only: [:create_file]
before_action :load_repository before_action :load_repository
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive] before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror] before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]

View File

@ -74,7 +74,7 @@ class UsersController < ApplicationController
end end
def update def update
return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id]) return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id) return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
@user.attributes = user_params.except(:image) @user.attributes = user_params.except(:image)

View File

@ -7,7 +7,7 @@ class VersionReleasesController < ApplicationController
def index def index
version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call
@version_releases = version_releases @version_releases = version_releases
@user_permission = current_user.present? && (current_user == @user || current_user.admin?) @user_permission = current_user.present? && (@repository.project.all_developers.include?(current_user) || current_user.admin?)
@forge_releases = @repository.version_releases.select(:id,:version_gid, :created_at).includes(:attachments) @forge_releases = @repository.version_releases.select(:id,:version_gid, :created_at).includes(:attachments)
end end

View File

@ -1,11 +1,12 @@
class VersionsController < ApplicationController class VersionsController < ApplicationController
before_action :require_login, except: [:index, :show] before_action :require_login, except: [:index, :show]
before_action :require_profile_completed, only: [:create]
before_action :load_repository before_action :load_repository
before_action :check_menu_authorize
before_action :check_issue_permission, except: [:show, :index] before_action :check_issue_permission, except: [:show, :index]
before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status] before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status]
def index def index
return render_not_found unless @project.has_menu_permission("versions")
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user)) @user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
status = params[:status] status = params[:status]
versions = @project.versions.version_includes versions = @project.versions.version_includes
@ -182,4 +183,8 @@ class VersionsController < ApplicationController
%w(desc asc).include?(params[:order_type]) ? params[:order_type] : 'desc' %w(desc asc).include?(params[:order_type]) ? params[:order_type] : 'desc'
end end
def check_menu_authorize
return render_not_found unless @project.has_menu_permission("versions")
end
end end

View File

@ -1,5 +1,6 @@
class WatchersController < ApplicationController class WatchersController < ApplicationController
before_action :require_login, except: %i[index] before_action :require_login, except: %i[index]
before_action :require_profile_completed, only: [:follow]
# before_action :find_project_with_id # before_action :find_project_with_id
before_action :get_target before_action :get_target

View File

@ -15,6 +15,8 @@ class Projects::CreateForm < BaseForm
validate do validate do
check_project_category(project_category_id) check_project_category(project_category_id)
check_project_language(project_language_id) check_project_language(project_language_id)
check_project_name(user_id, name) unless name.blank?
check_repository_name(user_id, repository_name) unless repository_name.blank?
end end
def check_license def check_license

View File

@ -0,0 +1,26 @@
# == Schema Information
#
# Table name: reversed_keywords
#
# id :integer not null, primary key
# identifier :string(255)
# description :text(65535)
# closed :boolean default("0")
# created_at :datetime not null
# updated_at :datetime not null
#
class ReversedKeyword < ApplicationRecord
scope :is_reversed, -> (identifier){where(identifier: identifier.downcase, closed: false) if identifier.present?}
validates :identifier, presence: true, uniqueness: true
before_validation :set_identifier
private
def set_identifier
self.identifier = self.identifier.downcase
end
end

View File

@ -187,7 +187,7 @@ class User < Owner
:show_email, :show_location, :show_department, :show_email, :show_location, :show_department,
:technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true
before_save :update_hashed_password, :set_lastname before_save :update_hashed_password, :set_lastname, :set_profile_completed
after_create do after_create do
SyncTrustieJob.perform_later("user", 1) if allow_sync_to_trustie? SyncTrustieJob.perform_later("user", 1) if allow_sync_to_trustie?
end end
@ -796,6 +796,10 @@ class User < Owner
def set_lastname def set_lastname
self.lastname = self.nickname if changes[:nickname].present? self.lastname = self.nickname if changes[:nickname].present?
end end
def set_profile_completed
self.profile_completed = self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present?
end
end end

View File

@ -24,6 +24,7 @@ class Projects::ApplyTransferService < ApplicationService
raise Error, '仓库标识不正确' if @project.identifier != params[:identifier] raise Error, '仓库标识不正确' if @project.identifier != params[:identifier]
raise Error, '该仓库正在迁移' if @project.is_transfering raise Error, '该仓库正在迁移' if @project.is_transfering
raise Error, '新拥有者不存在' unless @owner.present? raise Error, '新拥有者不存在' unless @owner.present?
raise Error, '新拥有者资料不完善' unless @owner.profile_completed
raise Error, '新拥有者已经存在同名仓库!' if Project.where(user_id: @owner.id, identifier: params[:identifier]).present? raise Error, '新拥有者已经存在同名仓库!' if Project.where(user_id: @owner.id, identifier: params[:identifier]).present?
raise Error, '未拥有转移权限' unless is_permit_owner raise Error, '未拥有转移权限' unless is_permit_owner
end end

View File

@ -0,0 +1,32 @@
<div class="modal fade reversed-keyword-change-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><%= type == "create" ? "新增" : "编辑" %></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<%= form_for @keyword, url: {controller: "reversed_keywords", action: "#{type}"} do |p| %>
<div class="modal-body">
<div class="form-group">
<label>
系统保留关键词标识 <span class="ml10 color-orange mr20">*</span>
</label>
<%= p.text_field :identifier,class: "form-control input-lg",required: true%>
</div>
<div class="form-group">
<label>
系统保留关键词描述
</label>
<%= p.text_area :description,class: "form-control",placeholder: ""%>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<%= p.submit "确认", class: "btn btn-primary submit-btn" %>
</div>
<% end %>
</div>
</div>
</div>

View File

@ -0,0 +1,37 @@
<table class="table table-hover text-center subject-list-table">
<thead class="thead-light">
<tr>
<th width="5%">序号</th>
<th width="30%"><%= sort_tag('标识', name: 'identifier', path: admins_reversed_keywords_path) %></th>
<th width="20%">描述</th>
<th width="20%"><%= sort_tag('限制是否开启', name: 'closed', path: admins_reversed_keywords_path) %></th>
<th width="20%"><%= sort_tag('创建时间', name: 'created_at', path: admins_reversed_keywords_path) %></th>
<th width="25%">操作</th>
</tr>
</thead>
<tbody>
<% if keywords.present? %>
<% keywords.each_with_index do |keyword, index| %>
<tr class="reversed-keyword-item-<%= keyword.id %>">
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
<td>
<%= link_to(keyword.identifier, "javascript:void(0)") %>
</td>
<td><%= keyword.description %></td>
<td class="keyword_closed"><%= !keyword.closed ? '√' : '' %></td>
<td><%= keyword.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
<td class="action-container">
<%= javascript_void_link '开启限制', class: 'action unclose-action', data: { id: keyword.id }, style: keyword.closed? ? '' : 'display: none;' %>
<%= javascript_void_link '关闭限制', class: 'action close-action', data: { id: keyword.id }, style: keyword.closed? ? 'display: none;' : '' %>
<%= link_to "编辑", edit_admins_reversed_keyword_path(keyword), remote: true, class: "action" %>
<%= link_to "删除", admins_reversed_keyword_path(keyword), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: keywords } %>

View File

@ -0,0 +1,2 @@
$("#reversed-keyword-modals").html("<%= j render(partial: 'admins/reversed_keywords/form_modal', locals: {type: 'update'}) %>")
$(".reversed-keyword-change-modal").modal('show');

View File

@ -0,0 +1,18 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('系统保留关键词') %>
<% end %>
<div class="box search-form-container project-list-form">
<%= form_tag(admins_reversed_keywords_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标识检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
<% end %>
<%= link_to "新增", new_admins_reversed_keyword_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
</div>
<div class="box admin-list-container reversed-keyword-list-container">
<%= render partial: 'admins/reversed_keywords/list', locals: { keywords: @keywords } %>
</div>
<div id="reversed-keyword-modals">
</div>

View File

@ -0,0 +1 @@
$('.reversed-keyword-list-container').html("<%= j( render partial: 'admins/reversed_keywords/list', locals: { keywords: @keywords } ) %>");

View File

@ -0,0 +1,2 @@
$("#reversed-keyword-modals").html("<%= j render(partial: 'admins/reversed_keywords/form_modal', locals: {type: 'create'}) %>")
$(".reversed-keyword-change-modal").modal('show');

View File

@ -26,6 +26,7 @@
<li><%= sidebar_item(admins_project_categories_path, '分类列表', icon: 'sitemap', controller: 'admins-project_categories') %></li> <li><%= sidebar_item(admins_project_categories_path, '分类列表', icon: 'sitemap', controller: 'admins-project_categories') %></li>
<li><%= sidebar_item(admins_project_licenses_path, '开源许可证', icon: 'file-text-o', controller: 'admins-project_licenses') %></li> <li><%= sidebar_item(admins_project_licenses_path, '开源许可证', icon: 'file-text-o', controller: 'admins-project_licenses') %></li>
<li><%= sidebar_item(admins_project_ignores_path, '忽略文件', icon: 'git', controller: 'admins-project_ignores') %></li> <li><%= sidebar_item(admins_project_ignores_path, '忽略文件', icon: 'git', controller: 'admins-project_ignores') %></li>
<li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li>
<% end %> <% end %>
</li> </li>

View File

@ -0,0 +1,24 @@
json.type @owner.type
if @owner.is_a?(Organization)
json.partial! "organizations/organizations/detail", organization: @owner
json.can_create_project @can_create_project
json.is_admin @is_admin
json.is_member @is_member
else
json.partial! 'users/user', locals: { user: @owner }
json.undo_messages @waiting_applied_messages.size
json.undo_transfer_projects @common_applied_transfer_projects.size
json.undo_join_projects @common_applied_projects.size
json.undo_events @undo_events
json.user_composes_count @user_composes_count
json.user_org_count @user_org_count
json.common_projects_count @projects_common_count
json.mirror_projects_count @projects_mirrior_count
json.sync_mirror_projects_count @projects_sync_mirrior_count
json.created_time format_time(@owner.created_on)
json.email @owner.show_email ? @owner.mail : nil
json.province @owner.show_location ? @owner.province : nil
json.city @owner.show_location ? @owner.city : nil
json.custom_department @owner.show_department ? @owner.custom_department : nil
json.description @owner.description
end

View File

@ -1,20 +1,20 @@
json.user_id user.id json.user_id user.id
json.name user.full_name json.name user.full_name
json.username @user.full_name json.username user.full_name
json.real_name @user.real_name json.real_name user.real_name
json.grade user.grade json.grade user.grade
json.gender @user.gender json.gender user.gender
json.login @user.login json.login user.login
json.user_id @user.id json.user_id user.id
json.image_url url_to_avatar(@user) json.image_url url_to_avatar(user)
json.admin @user.admin? json.admin user.admin?
json.user_identity @user.identity json.user_identity user.identity
json.is_watch current_user&.watched?(@user) json.is_watch current_user&.watched?(user)
json.watched_count @user.fan_count #粉丝 json.watched_count user.fan_count #粉丝
json.watching_count @user.follow_count #关注数 json.watching_count user.follow_count #关注数
json.created_time format_time(@user.created_on) json.created_time format_time(user.created_on)
json.email @user.show_email ? @user.mail : nil json.email user.show_email ? user.mail : nil
json.province @user.show_location ? @user.province : nil json.province user.show_location ? user.province : nil
json.city @user.show_location ? @user.city : nil json.city user.show_location ? user.city : nil
json.custom_department @user.show_department ? @user.custom_department : nil json.custom_department user.show_department ? user.custom_department : nil
json.description @user.description json.description user.description

View File

@ -4,5 +4,6 @@ json.array! users do |user|
json.login user.login json.login user.login
json.user_id user.id json.user_id user.id
json.image_url url_to_avatar(user) json.image_url url_to_avatar(user)
json.profile_completed user.profile_completed
end end

View File

@ -1,5 +1,6 @@
json.username @user.full_name json.username @user.full_name
json.real_name @user.real_name json.real_name @user.real_name
json.nickname @user.nickname
json.gender @user.gender json.gender @user.gender
json.login @user.login json.login @user.login
json.user_id @user.id json.user_id @user.id

View File

@ -107,7 +107,7 @@ Rails.application.routes.draw do
put 'commons/unhidden', to: 'commons#unhidden' put 'commons/unhidden', to: 'commons#unhidden'
delete 'commons/delete', to: 'commons#delete' delete 'commons/delete', to: 'commons#delete'
resources :owners, only: [:index] resources :owners, only: [:index, :show]
scope module: :organizations do scope module: :organizations do
resources :organizations, except: [:edit, :new] do resources :organizations, except: [:edit, :new] do
@ -655,6 +655,7 @@ Rails.application.routes.draw do
resources :project_categories resources :project_categories
resources :project_licenses resources :project_licenses
resources :project_ignores resources :project_ignores
resources :reversed_keywords
resources :major_informations, only: [:index] resources :major_informations, only: [:index]
resources :ec_templates, only: [:index, :destroy] do resources :ec_templates, only: [:index, :destroy] do
collection do collection do

View File

@ -0,0 +1,11 @@
class CreateReversedKeywords < ActiveRecord::Migration[5.2]
def change
create_table :reversed_keywords do |t|
t.string :identifier, comment: '保留关键字'
t.text :description, comment: '描述'
t.boolean :closed, default: false, comment: '是否关闭'
t.timestamps
end
end
end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
html{margin:0px;padding:0px;font-size:14px;font-family:"微软雅黑","宋体"}body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{margin:0;padding:0}.IndexContent{height:100vh;width:100%;position:relative;background-image:url("/images/oauth/backImg.png");background-repeat:no-repeat;background-size:cover;display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column}.indexLogo{width:80px;margin-bottom:35px}.indexPanel{width:580px;min-height:400px;background-color:#fff;box-shadow:0px 2px 10px 5px rgba(0,0,0,0.05);border-radius:5px;box-sizing:border-box}.indexTitle{height:75px;line-height:75px;font-size:18px;color:#333;text-align:center;border-bottom:1px solid #eee}.indexInfo{display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;-webkit-box-align:start;align-items:flex-start}.indexInfos{padding:40px 60px}.indexInfo>span{color:#333;font-size:16px;margin-top:5px}.indexInfo input{width:100%;height:40px;border-radius:2px;border:1px solid #eee;margin-top:5px;padding:0px 0px 0px 8px;outline:none}.indexInfo .checkInfo{height:15px;color:red}.indexBtn{text-align:center;margin-top:20px}.indexSubmit{width:50%;height:32px;line-height:32px;background-color:#1890FF;border:none;color:#fff;border-radius:2px;cursor:pointer;outline:none}

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe ReversedKeyword, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end