| @@ -141,6 +141,7 @@ class AccountsController < ApplicationController | |||||
| Register::Form.new(register_params).validate! | Register::Form.new(register_params).validate! | ||||
| user = Users::RegisterService.call(register_params) | user = Users::RegisterService.call(register_params) | ||||
| user.mail = "#{user.login}@example.org" if user.mail.blank? | |||||
| password = register_params[:password].strip | password = register_params[:password].strip | ||||
| # gitea用户注册, email, username, password | # gitea用户注册, email, username, password | ||||
| @@ -53,6 +53,6 @@ class Admins::Topic::BannersController < Admins::Topic::BaseController | |||||
| end | end | ||||
| def banner_params | def banner_params | ||||
| params.require(:topic_banner).permit(:title, :order_index) | |||||
| params.require(:topic_banner).permit(:title, :order_index, :url) | |||||
| end | end | ||||
| end | end | ||||
| @@ -103,8 +103,10 @@ class ApplicationController < ActionController::Base | |||||
| when 1, 2, 4, 9 | when 1, 2, 4, 9 | ||||
| # 手机类型的发送 | # 手机类型的发送 | ||||
| sigle_para = {phone: value} | sigle_para = {phone: value} | ||||
| status = Gitlink::Sms.send(mobile: value, code: code) | |||||
| tip_exception(-2, code_msg(status)) if status != 0 | |||||
| # status = Gitlink::Sms.send(mobile: value, code: code) | |||||
| # tip_exception(-2, code_msg(status)) if status != 0 | |||||
| status = Sms::UcloudService.call(value, code) | |||||
| tip_exception(-2, ucloud_code_msg(status)) if status != 0 | |||||
| when 8, 3, 5 | when 8, 3, 5 | ||||
| # 邮箱类型的发送 | # 邮箱类型的发送 | ||||
| sigle_para = {email: value} | sigle_para = {email: value} | ||||
| @@ -116,8 +118,13 @@ class ApplicationController < ActionController::Base | |||||
| send_email_control = LimitForbidControl::SendEmailCode.new(value) | send_email_control = LimitForbidControl::SendEmailCode.new(value) | ||||
| tip_exception(-1, '邮件发送太频繁,请稍后再试') if send_email_control.forbid? | tip_exception(-1, '邮件发送太频繁,请稍后再试') if send_email_control.forbid? | ||||
| begin | begin | ||||
| UserMailer.register_email(value, code).deliver_now | |||||
| if send_type == 3 | |||||
| UserMailer.find_password(value, code).deliver_now | |||||
| elsif send_type == 5 | |||||
| UserMailer.bind_email(value, code).deliver_now | |||||
| else | |||||
| UserMailer.register_email(value, code).deliver_now | |||||
| end | |||||
| Rails.cache.write(send_email_limit_cache_key, 1, expires_in: 1.minute) | Rails.cache.write(send_email_limit_cache_key, 1, expires_in: 1.minute) | ||||
| send_email_control.increment! | send_email_control.increment! | ||||
| # Mailer.run.email_register(code, value) | # Mailer.run.email_register(code, value) | ||||
| @@ -149,6 +156,27 @@ class ApplicationController < ActionController::Base | |||||
| end | end | ||||
| end | end | ||||
| def ucloud_code_msg status | |||||
| case status | |||||
| when 0 | |||||
| "验证码已经发送到您的手机,请注意查收" | |||||
| when 171 | |||||
| "API签名错误" | |||||
| when 18014 | |||||
| "无效手机号码" | |||||
| when 18017 | |||||
| "无效模板" | |||||
| when 18018 | |||||
| "短信模板参数与短信模板不匹配" | |||||
| when 18023 | |||||
| "短信内容中含有运营商拦截的关键词" | |||||
| when 18033 | |||||
| "变量内容不符合规范" | |||||
| else | |||||
| "错误码#{status}" | |||||
| end | |||||
| end | |||||
| def validate_type(object_type) | def validate_type(object_type) | ||||
| normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip) | normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip) | ||||
| end | end | ||||
| @@ -213,20 +213,17 @@ class AttachmentsController < ApplicationController | |||||
| def attachment_candown | def attachment_candown | ||||
| unless current_user.admin? || current_user.business? | unless current_user.admin? || current_user.business? | ||||
| candown = true | candown = true | ||||
| unless params[:type] == 'history' | |||||
| if @file.container && current_user.logged? | |||||
| if @file.container.is_a?(Issue) | |||||
| course = @file.container.project | |||||
| candown = course.member?(current_user) || course.is_public | |||||
| elsif @file.container.is_a?(Journal) | |||||
| course = @file.container.issue.project | |||||
| candown = course.member?(current_user) || course.is_public | |||||
| else | |||||
| course = nil | |||||
| end | |||||
| tip_exception(403, "您没有权限进入") if course.present? && !candown | |||||
| tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication) | |||||
| if @file.container | |||||
| if @file.container.is_a?(Issue) | |||||
| project = @file.container.project | |||||
| candown = project.is_public || (current_user.logged? && project.member?(current_user)) | |||||
| elsif @file.container.is_a?(Journal) | |||||
| project = @file.container.issue.project | |||||
| candown = project.is_public || (current_user.logged? && project.member?(current_user)) | |||||
| else | |||||
| project = nil | |||||
| end | end | ||||
| tip_exception(403, "您没有权限进入") if project.present? && !candown | |||||
| end | end | ||||
| end | end | ||||
| end | end | ||||
| @@ -10,7 +10,7 @@ class ProjectCategoriesController < ApplicationController | |||||
| end | end | ||||
| def group_list | def group_list | ||||
| @project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc) | |||||
| @project_categories = ProjectCategory.select("id, name, projects_count, private_projects_count, (projects_count - private_projects_count) as public_projects_count").having('public_projects_count > 0').order(public_projects_count: :desc) | |||||
| # projects = Project.no_anomory_projects.visible | # projects = Project.no_anomory_projects.visible | ||||
| # @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size | # @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size | ||||
| end | end | ||||
| @@ -155,6 +155,15 @@ class ProjectsController < ApplicationController | |||||
| } | } | ||||
| gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params) | gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params) | ||||
| @project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]}) | @project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]}) | ||||
| # 更新对应所属分类下的项目数量(私有) | |||||
| before_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][0] : @project.is_public | |||||
| after_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][1] : @project.is_public | |||||
| before_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][0] : @project.project_category_id | |||||
| after_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][1] : @project.project_category_id | |||||
| before_pc = ProjectCategory.find_by_id(before_pc_id) | |||||
| after_pc = ProjectCategory.find_by_id(after_pc_id) | |||||
| before_pc.decrement!(:private_projects_count, 1) if before_pc.present? && !before_is_public | |||||
| after_pc.increment!(:private_projects_count, 1) if after_pc.present? && !after_is_public | |||||
| end | end | ||||
| SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu? | SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu? | ||||
| end | end | ||||
| @@ -172,6 +181,8 @@ class ProjectsController < ApplicationController | |||||
| Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call | Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call | ||||
| @project.destroy! | @project.destroy! | ||||
| @project.forked_projects.update_all(forked_from_project_id: nil) | @project.forked_projects.update_all(forked_from_project_id: nil) | ||||
| # 如果该项目有所属的项目分类以及为私有项目,需要更新对应数量 | |||||
| @project.project_category.decrement!(:private_projects_count, 1) if @project.project_category.present? && !@project.is_public | |||||
| render_ok | render_ok | ||||
| end | end | ||||
| else | else | ||||
| @@ -10,6 +10,18 @@ class UserMailer < ApplicationMailer | |||||
| mail(to: mail, subject: 'Gitink | 注册验证码') | mail(to: mail, subject: 'Gitink | 注册验证码') | ||||
| end | end | ||||
| # 用户找回密码 | |||||
| def find_password(mail, code) | |||||
| @code = code | |||||
| mail(to: mail, subject: 'Gitink | 找回密码验证码') | |||||
| end | |||||
| # 用户绑定邮箱 | |||||
| def bind_email(mail, code) | |||||
| @code = code | |||||
| mail(to: mail, subject: 'Gitink | 绑定邮箱验证码') | |||||
| end | |||||
| def update_email(mail, code) | def update_email(mail, code) | ||||
| @code = code | @code = code | ||||
| mail(to: mail, subject: 'Gitink | 更改邮箱验证码') | mail(to: mail, subject: 'Gitink | 更改邮箱验证码') | ||||
| @@ -2,14 +2,15 @@ | |||||
| # | # | ||||
| # Table name: project_categories | # Table name: project_categories | ||||
| # | # | ||||
| # id :integer not null, primary key | |||||
| # name :string(255) | |||||
| # position :integer | |||||
| # projects_count :integer default("0") | |||||
| # created_at :datetime not null | |||||
| # updated_at :datetime not null | |||||
| # ancestry :string(255) | |||||
| # pinned_index :integer default("0") | |||||
| # id :integer not null, primary key | |||||
| # name :string(255) | |||||
| # position :integer | |||||
| # projects_count :integer default("0") | |||||
| # created_at :datetime not null | |||||
| # updated_at :datetime not null | |||||
| # ancestry :string(255) | |||||
| # pinned_index :integer default("0") | |||||
| # private_projects_count :integer default("0") | |||||
| # | # | ||||
| # Indexes | # Indexes | ||||
| # | # | ||||
| @@ -16,6 +16,7 @@ class Projects::CreateService < ApplicationService | |||||
| Project.update_common_projects_count! | Project.update_common_projects_count! | ||||
| ProjectUnit.init_types(@project.id) | ProjectUnit.init_types(@project.id) | ||||
| Repositories::CreateService.new(user, @project, repository_params).call | Repositories::CreateService.new(user, @project, repository_params).call | ||||
| upgrade_project_category_private_projects_count | |||||
| else | else | ||||
| Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}") | Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}") | ||||
| end | end | ||||
| @@ -28,6 +29,14 @@ class Projects::CreateService < ApplicationService | |||||
| private | private | ||||
| def upgrade_project_category_private_projects_count | |||||
| # 如果为空或者项目为公有项目直接返回 | |||||
| return unless params[:project_category_id].present? | |||||
| return if repo_is_public | |||||
| project_category = ProjectCategory.find_by_id(params[:project_category_id]) | |||||
| project_category.increment!(:private_projects_count, 1) | |||||
| end | |||||
| def authroize_user_id_success | def authroize_user_id_success | ||||
| (user.id == params[:user_id].to_i) || (user.organizations.find_by_id(params[:user_id]).present?) | (user.id == params[:user_id].to_i) || (user.organizations.find_by_id(params[:user_id]).present?) | ||||
| end | end | ||||
| @@ -0,0 +1,98 @@ | |||||
| class Sms::UcloudService < ApplicationService | |||||
| attr_reader :phone, :code | |||||
| def initialize(phone, code) | |||||
| @phone = phone | |||||
| @code = code | |||||
| end | |||||
| def call | |||||
| public_key = EduSetting.get("ucloud_public_key") || "4Z7QYDY0SumplMtmNmd9PERgPPFiMpR1R" | |||||
| private_key = EduSetting.get("ucloud_private_key") || "7wxMoGoaQ1DtcQjDxgJrOGOXnIiZq4amEWvmi7eBtm2d" | |||||
| project_id = "org-3ozbh2" | |||||
| sign_params = { | |||||
| "Action" => "SendUSMSMessage", | |||||
| "ProjectId" => project_id, | |||||
| "TemplateId" => "UTA221114S2MGTY", | |||||
| "PublicKey" => public_key, | |||||
| "PhoneNumbers.0" => @phone, | |||||
| "TemplateParams.0" => "#{@code}", | |||||
| "SigContent" => "GitLink确实开源" | |||||
| } | |||||
| sequence = sign_params.sort.map { |k, v| "#{k}#{v}" }.join('') | |||||
| # Rails.logger.info("create_signature=========#{sequence}#{private_key}") | |||||
| req_params = sign_params.merge("Signature" => Digest::SHA1.hexdigest("#{sequence}#{private_key}")) | |||||
| uri = URI("https://api.ucloud.cn") | |||||
| uri.query = req_params.map { |k, v| "#{k}=#{URI.escape(v.to_s)}" }.join('&') | |||||
| # Rails.logger.info("uri.query=========#{uri.query}") | |||||
| Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http| | |||||
| req = Net::HTTP::Get.new uri.request_uri | |||||
| response = http.request(req) | |||||
| # Rails.logger.info("ucloud sms response.body=========#{response.body}") | |||||
| result = ActiveSupport::JSON.decode(response.body) | |||||
| result['RetCode'] | |||||
| end | |||||
| end | |||||
| def send_by_params(opt={}) | |||||
| public_key = "4Z7QYDY0SumplMtmNmd9PERgPPFiMpRR" | |||||
| private_key = "7wxMoGoaQ1DtcQjDxgJrOGOXnIiZq4amEWvmi7eBtmd" | |||||
| project_id = "org-3ozbh2" | |||||
| sign_params = { | |||||
| "Action" => "SendUSMSMessage", | |||||
| "ProjectId" => project_id, | |||||
| "TemplateId" => "#{opt[:TemplateId]}", | |||||
| "PublicKey" => public_key, | |||||
| "PhoneNumbers.0" => "#{opt[:PhoneNumbers]}", | |||||
| "TemplateParams.0" => "#{opt[:TemplateParams]}", | |||||
| "SigContent" => "GitLink确实开源" | |||||
| } | |||||
| sequence = sign_params.sort.map { |k, v| "#{k}#{v}" }.join('') | |||||
| # Rails.logger.info("create_signature=========#{sequence}#{private_key}") | |||||
| req_params = sign_params.merge("Signature" => Digest::SHA1.hexdigest("#{sequence}#{private_key}")) | |||||
| uri = URI("https://api.ucloud.cn") | |||||
| uri.query = req_params.map { |k, v| "#{k}=#{URI.escape(v.to_s)}" }.join('&') | |||||
| # Rails.logger.info("uri.query=========#{uri.query}") | |||||
| Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http| | |||||
| req = Net::HTTP::Get.new uri.request_uri | |||||
| response = http.request(req) | |||||
| # Rails.logger.info("ucloud sms response.body=========#{response.body}") | |||||
| ActiveSupport::JSON.decode(response.body) | |||||
| end | |||||
| end | |||||
| def send_sms(template_id) | |||||
| end | |||||
| def GetProjectList | |||||
| public_key = "4Z7QYDY0SumplMtmNmd9PERgPPFiMpRR" | |||||
| private_key = "7wxMoGoaQ1DtcQjDxgJrOGOXnIiZq4amEWvmi7eBtmd" | |||||
| sign_params = { | |||||
| "Action" => "GetProjectList", | |||||
| "PublicKey" => public_key | |||||
| } | |||||
| sequence = sign_params.sort.map { |k, v| "#{k}#{v}" }.join('') | |||||
| Rails.logger.info("create_signature=========#{sequence}#{private_key}") | |||||
| req_params = sign_params.merge("Signature" => Digest::SHA1.hexdigest("#{sequence}#{private_key}")) | |||||
| uri = URI("https://api.ucloud.cn") | |||||
| uri.query = req_params.map { |k, v| "#{k}=#{URI.escape(v.to_s)}" }.join('&') | |||||
| Rails.logger.info("uri.query=========#{uri.query}") | |||||
| Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http| | |||||
| req = Net::HTTP::Get.new uri.request_uri | |||||
| response = http.request(req) | |||||
| Rails.logger.info("ucloud sms response.body=========#{response.body}") | |||||
| response.body | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -4,7 +4,8 @@ | |||||
| <th width="5%">序号</th> | <th width="5%">序号</th> | ||||
| <th width="30%">名称</th> | <th width="30%">名称</th> | ||||
| <th width="20%"><%= sort_tag('精选', name: 'pinned_index', path: admins_project_categories_path) %></th> | <th width="20%"><%= sort_tag('精选', name: 'pinned_index', path: admins_project_categories_path) %></th> | ||||
| <th width="20%"><%= sort_tag('项目数', name: 'projects_count', path: admins_project_categories_path) %></th> | |||||
| <th width="10%"><%= sort_tag('项目数', name: 'projects_count', path: admins_project_categories_path) %></th> | |||||
| <th width="10%"><%= sort_tag('私有项目数', name: 'private_projects_count', path: admins_project_categories_path) %></th> | |||||
| <th width="20%">精选项目数</th> | <th width="20%">精选项目数</th> | ||||
| <th width="20%"><%= sort_tag('创建时间', name: 'created_at', path: admins_project_categories_path) %></th> | <th width="20%"><%= sort_tag('创建时间', name: 'created_at', path: admins_project_categories_path) %></th> | ||||
| <th width="25%">操作</th> | <th width="25%">操作</th> | ||||
| @@ -20,6 +21,7 @@ | |||||
| </td> | </td> | ||||
| <td><%= project_category.pinned_index == 0 ? "" : "√" %></td> | <td><%= project_category.pinned_index == 0 ? "" : "√" %></td> | ||||
| <td><%= project_category.projects_count %></td> | <td><%= project_category.projects_count %></td> | ||||
| <td><%= project_category.private_projects_count %></td> | |||||
| <td><%= project_category.projects.select(:id).where(is_pinned: true).size %></td> | <td><%= project_category.projects.select(:id).where(is_pinned: true).size %></td> | ||||
| <td><%= project_category.created_at&.strftime('%Y-%m-%d %H:%M') %></td> | <td><%= project_category.created_at&.strftime('%Y-%m-%d %H:%M') %></td> | ||||
| <td class="action-container"> | <td class="action-container"> | ||||
| @@ -15,6 +15,12 @@ | |||||
| </label> | </label> | ||||
| <%= p.text_field :title,class: "form-control input-lg",required: true%> | <%= p.text_field :title,class: "form-control input-lg",required: true%> | ||||
| </div> | </div> | ||||
| <div class="form-group"> | |||||
| <label> | |||||
| 跳转URL | |||||
| </label> | |||||
| <%= p.text_field :url, class: "form-control",placeholder: ""%> | |||||
| </div> | |||||
| <div class="form-group"> | <div class="form-group"> | ||||
| <label> | <label> | ||||
| 排序等级 | 排序等级 | ||||
| @@ -4,8 +4,9 @@ | |||||
| <th width="5%">序号</th> | <th width="5%">序号</th> | ||||
| <th width="20%">标题</th> | <th width="20%">标题</th> | ||||
| <th width="20%">图片</th> | <th width="20%">图片</th> | ||||
| <th width="20%">排序等级</th> | |||||
| <th width="25%">操作</th> | |||||
| <th width="25%">跳转URL</th> | |||||
| <th width="10%">排序等级</th> | |||||
| <th width="20%">操作</th> | |||||
| </tr> | </tr> | ||||
| </thead> | </thead> | ||||
| <tbody> | <tbody> | ||||
| @@ -15,6 +16,7 @@ | |||||
| <td><%= list_index_no((params[:page] || 1).to_i, index) %></td> | <td><%= list_index_no((params[:page] || 1).to_i, index) %></td> | ||||
| <td><%= banner.title %></td> | <td><%= banner.title %></td> | ||||
| <td><img style="width:150px" src="<%= banner.image %>" /></td> | <td><img style="width:150px" src="<%= banner.image %>" /></td> | ||||
| <td><a href="<%= banner.url %>" target="_blank"><%= banner.url %></a> </td> | |||||
| <td><%= banner.order_index %></td> | <td><%= banner.order_index %></td> | ||||
| <td class="action-container"> | <td class="action-container"> | ||||
| <%= link_to "编辑", edit_admins_topic_banner_path(banner), remote: true, class: "action" %> | <%= link_to "编辑", edit_admins_topic_banner_path(banner), remote: true, class: "action" %> | ||||
| @@ -1,5 +1,5 @@ | |||||
| json.array! @project_categories do |category| | json.array! @project_categories do |category| | ||||
| json.id category.id | json.id category.id | ||||
| json.name category.name | json.name category.name | ||||
| json.projects_count category.projects_count | |||||
| json.projects_count category.public_projects_count | |||||
| end | end | ||||
| @@ -1 +1 @@ | |||||
| json.(banner, :id, :title, :image) | |||||
| json.(banner, :id, :title, :image, :url) | |||||
| @@ -0,0 +1,5 @@ | |||||
| class AddPrivateProjectsCountToProjectCategory < ActiveRecord::Migration[5.2] | |||||
| def change | |||||
| add_column :project_categories, :private_projects_count, :integer, default: 0 | |||||
| end | |||||
| end | |||||