diff --git a/app/forms/organizations/create_form.rb b/app/forms/organizations/create_form.rb index 2163f477e..1f40350b3 100644 --- a/app/forms/organizations/create_form.rb +++ b/app/forms/organizations/create_form.rb @@ -1,12 +1,12 @@ class Organizations::CreateForm < BaseForm - NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 + NAME_REGEX = /^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*$/ #只含有数字、字母、下划线不能以下划线开头和结尾 attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname, :original_name validates :name, :nickname, :visibility, presence: true validates :name, :nickname, length: { maximum: 100 } validates :location, length: { maximum: 50 } validates :description, length: { maximum: 200 } - validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能以数字或字母开头,仅支持横杠、下划线、点三种符号,不允许符号连续排列,长度4-50个字符" } validate do check_name(name) unless name.blank? || name == original_name diff --git a/app/jobs/delay_expired_issue_and_milestone_job.rb b/app/jobs/delay_expired_issue_and_milestone_job.rb new file mode 100644 index 000000000..4bba7aaf1 --- /dev/null +++ b/app/jobs/delay_expired_issue_and_milestone_job.rb @@ -0,0 +1,16 @@ +class DelayExpiredIssueAndMilestoneJob < ApplicationJob + queue_as :message + + def perform + Issue.where(due_date: Date.today + 1.days).find_each do |issue| + SendTemplateMessageJob.perform_later('IssueExpire', issue.id) if Site.has_notice_menu? + end + Version.where(effective_date: Date.today + 1.days).find_each do |version| + SendTemplateMessageJob.perform_later('ProjectMilestoneEarlyExpired', version.id) if Site.has_notice_menu? + end + Version.where(effective_date: Date.today - 1.days).find_each do |version| + SendTemplateMessageJob.perform_later('ProjectMilestoneExpired', version.id) if Site.has_notice_menu? + end + end + +end \ No newline at end of file diff --git a/app/jobs/delay_expired_issue_job.rb b/app/jobs/delay_expired_issue_job.rb deleted file mode 100644 index ed390e15b..000000000 --- a/app/jobs/delay_expired_issue_job.rb +++ /dev/null @@ -1,10 +0,0 @@ -class DelayExpiredIssueJob < ApplicationJob - queue_as :message - - def perform - Issue.where(due_date: Date.today + 1.days).find_each do |issue| - SendTemplateMessageJob.perform_later('IssueExpire', issue.id) if Site.has_notice_menu? - end - end - -end \ No newline at end of file diff --git a/app/jobs/send_template_message_job.rb b/app/jobs/send_template_message_job.rb index 05572d451..82f41cad2 100644 --- a/app/jobs/send_template_message_job.rb +++ b/app/jobs/send_template_message_job.rb @@ -221,6 +221,20 @@ class SendTemplateMessageJob < ApplicationJob receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestone.get_email_message_content(receiver, operator, milestone) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) end + when 'ProjectMilestoneExpired' + milestone_id = args[0] + milestone = Version.find_by_id(milestone_id) + return unless milestone.present? && milestone&.project.present? + receivers = User.where(id: milestone.user_id) + receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneExpired.get_message_content(receivers, milestone) + Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id}) + when 'ProjectMilestoneEarlyExpired' + milestone_id = args[0] + milestone = Version.find_by_id(milestone_id) + return unless milestone.present? && milestone&.project.present? + receivers = User.where(id: milestone.user_id) + receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneEarlyExpired.get_message_content(receivers, milestone) + Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id}) when 'ProjectPraised' operator_id, project_id = args[0], args[1] operator = User.find_by_id(operator_id) diff --git a/app/models/message_template.rb b/app/models/message_template.rb index 7ab7fdad8..75d64fa95 100644 --- a/app/models/message_template.rb +++ b/app/models/message_template.rb @@ -52,6 +52,8 @@ class MessageTemplate < ApplicationRecord self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 {nickname2}/{repository} 创建了一个里程碑:{name}', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 新建了一个里程碑") email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html") self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 {nickname}/{repository} 仓库,里程碑 {name} 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成") + self.create(type: 'MessageTemplate::ProjectMilestoneEarlyExpired', sys_notice: '您创建的里程碑 {name} 已临近截止日期,请尽快处理.', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}') + self.create(type: 'MessageTemplate::ProjectMilestoneExpired', sys_notice: '您创建的里程碑 {name} 已逾期,请及时更新进度或联系项目团队.', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}') self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '{nickname1} 点赞了你管理的仓库 {nickname2}/{repository}', notification_url: '{baseurl}/{login}') self.create(type: 'MessageTemplate::ProjectOpenDevOps', sys_notice: '您的仓库 {repository} 已成功开通引擎服务,可通过简单的节点编排完成自动化集成与部署。欢迎体验!', notification_url: '{baseurl}/{owner}/{identifier}/devops') email_html = File.read("#{email_template_html_dir}/project_pull_request.html") diff --git a/app/models/message_template/project_milestone_early_expired.rb b/app/models/message_template/project_milestone_early_expired.rb new file mode 100644 index 000000000..5539fc362 --- /dev/null +++ b/app/models/message_template/project_milestone_early_expired.rb @@ -0,0 +1,70 @@ +# == Schema Information +# +# Table name: message_templates +# +# id :integer not null, primary key +# type :string(255) +# sys_notice :text(65535) +# email :text(65535) +# created_at :datetime not null +# updated_at :datetime not null +# notification_url :string(255) +# email_title :string(255) +# + +# 我管理的仓库有里程碑完成 +class MessageTemplate::ProjectMilestoneEarlyExpired < MessageTemplate + + # MessageTemplate::ProjectMilestoneEarlyExpired.get_message_content(User.where(login: 'yystopf'), Version.find(7)) + def self.get_message_content(receivers, milestone) + receivers.each do |receiver| + if receiver.user_template_message_setting.present? + send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneEarlyExpired"] + send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneEarlyExpired"] : send_setting + receivers = receivers.where.not(id: receiver.id) unless send_setting + end + end + return '', '', '' if receivers.blank? + project = milestone&.project + owner = project&.owner + content = sys_notice.gsub('{nickname}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name) + url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s) + + return receivers_string(receivers), content, url + rescue => e + Rails.logger.info("MessageTemplate::MilestoneEarlyExpired.get_message_content [ERROR] #{e}") + return '', '', '' + end + + def self.get_email_message_content(receiver, milestone) + if receiver.user_template_message_setting.present? + send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneEarlyExpired"] + send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneEarlyExpired"] : send_setting + return '', '', '' unless send_setting + project = milestone&.project + owner = project&.owner + title = email_title + title.gsub!('{nickname}', owner&.real_name) + title.gsub!('{repository}', project&.name) + + content = email + content.gsub!('{receiver}', receiver&.real_name) + content.gsub!('{baseurl}', base_url) + content.gsub!('{nickname}', owner&.real_name) + content.gsub!('{repository}', project&.name) + content.gsub!('{login}', owner&.login) + content.gsub!('{identifier}', project&.identifier) + content.gsub!('{id}', milestone&.id.to_s) + content.gsub!('{name}', milestone&.name) + content.gsub!('{platform}', PLATFORM) + + return receiver&.mail, title, content + else + return '', '', '' + end + + rescue => e + Rails.logger.info("MessageTemplate::MilestoneEarlyExpired.get_email_message_content [ERROR] #{e}") + return '', '', '' + end +end diff --git a/app/models/message_template/project_milestone_expired.rb b/app/models/message_template/project_milestone_expired.rb new file mode 100644 index 000000000..de6b8c10c --- /dev/null +++ b/app/models/message_template/project_milestone_expired.rb @@ -0,0 +1,70 @@ +# == Schema Information +# +# Table name: message_templates +# +# id :integer not null, primary key +# type :string(255) +# sys_notice :text(65535) +# email :text(65535) +# created_at :datetime not null +# updated_at :datetime not null +# notification_url :string(255) +# email_title :string(255) +# + +# 我管理的仓库有里程碑完成 +class MessageTemplate::ProjectMilestoneExpired < MessageTemplate + + # MessageTemplate::ProjectMilestoneExpired.get_message_content(User.where(login: 'yystopf'), Version.find(7)) + def self.get_message_content(receivers, milestone) + receivers.each do |receiver| + if receiver.user_template_message_setting.present? + send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneExpired"] + send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneExpired"] : send_setting + receivers = receivers.where.not(id: receiver.id) unless send_setting + end + end + return '', '', '' if receivers.blank? + project = milestone&.project + owner = project&.owner + content = sys_notice.gsub('{nickname}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name) + url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s) + + return receivers_string(receivers), content, url + rescue => e + Rails.logger.info("MessageTemplate::ProjectMilestoneExpired.get_message_content [ERROR] #{e}") + return '', '', '' + end + + def self.get_email_message_content(receiver, milestone) + if receiver.user_template_message_setting.present? + send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneExpired"] + send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneExpired"] : send_setting + return '', '', '' unless send_setting + project = milestone&.project + owner = project&.owner + title = email_title + title.gsub!('{nickname}', owner&.real_name) + title.gsub!('{repository}', project&.name) + + content = email + content.gsub!('{receiver}', receiver&.real_name) + content.gsub!('{baseurl}', base_url) + content.gsub!('{nickname}', owner&.real_name) + content.gsub!('{repository}', project&.name) + content.gsub!('{login}', owner&.login) + content.gsub!('{identifier}', project&.identifier) + content.gsub!('{id}', milestone&.id.to_s) + content.gsub!('{name}', milestone&.name) + content.gsub!('{platform}', PLATFORM) + + return receiver&.mail, title, content + else + return '', '', '' + end + + rescue => e + Rails.logger.info("MessageTemplate::ProjectMilestoneExpired.get_email_message_content [ERROR] #{e}") + return '', '', '' + end +end diff --git a/app/models/organization.rb b/app/models/organization.rb index d61dda567..f6c14298d 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -63,7 +63,7 @@ class Organization < Owner alias_attribute :name, :login - NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 + NAME_REGEX = /^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*$/ #只含有数字、字母、下划线不能以下划线开头和结尾 default_scope { where(type: "Organization") } @@ -74,7 +74,7 @@ class Organization < Owner validates :login, presence: true validates_uniqueness_of :login, :if => Proc.new { |user| user.login_changed? && user.login.present? }, case_sensitive: false - validates :login, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + validates :login, format: { with: NAME_REGEX, multiline: true, message: "只能以数字或字母开头,仅支持横杠、下划线、点三种符号,不允许符号连续排列,长度4-50个字符" } delegate :description, :website, :location, :repo_admin_change_team_access, :recommend, :visibility, :max_repo_creation, :num_projects, :num_users, :num_teams, to: :organization_extension, allow_nil: true diff --git a/app/models/user_template_message_setting.rb b/app/models/user_template_message_setting.rb index 49db51d4d..7e855b768 100644 --- a/app/models/user_template_message_setting.rb +++ b/app/models/user_template_message_setting.rb @@ -44,6 +44,8 @@ class UserTemplateMessageSetting < ApplicationRecord "ManageProject::Forked": true, "ManageProject::Milestone": true, "ManageProject::MilestoneCompleted": true, + "ManageProject::MilestoneExpired": true, + "ManageProject::MilestoneEarlyExpired": true, }.stringify_keys! end @@ -65,6 +67,8 @@ class UserTemplateMessageSetting < ApplicationRecord "ManageProject::Forked": false, "ManageProject::Milestone": false, "ManageProject::MilestoneCompleted": false, + "ManageProject::MilestoneExpired": false, + "ManageProject::MilestoneEarlyExpired": false, }.stringify_keys! end diff --git a/app/models/version.rb b/app/models/version.rb index 82474f55e..5787116db 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -68,5 +68,7 @@ class Version < ApplicationRecord def send_update_message_to_notice_system SendTemplateMessageJob.perform_later('ProjectMilestoneCompleted', self.id) if Site.has_notice_menu? && self.issue_percent == 1.0 + SendTemplateMessageJob.perform_later('ProjectMilestoneEarlyExpired', self.id) if Site.has_notice_menu? && self.effective_date == Date.today + 1.days + SendTemplateMessageJob.perform_later('ProjectMilestoneExpired', self.id) if Site.has_notice_menu? && self.effective_date == Date.today - 1.days end end diff --git a/config/sidekiq_cron.yml b/config/sidekiq_cron.yml index 448e9c945..c31ce2575 100644 --- a/config/sidekiq_cron.yml +++ b/config/sidekiq_cron.yml @@ -5,5 +5,5 @@ sync_gitea_repo_update_time: delay_expired_issue: cron: "0 0 * * *" - class: "DelayExpiredIssueJob" + class: "DelayExpiredIssueAndMilestoneJob" queue: message