| @@ -1,4 +1,35 @@ | |||
| # Changelog | |||
| ## [v3.2.0](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-06-09 | |||
| ### ENHANCEMENTS | |||
| * ADD 集成邮件和平台站内信等通知系统 | |||
| * Fix 代码库二级页面-优化文件子目录浏览功能(#50388) | |||
| * Fix 代码库二级页面-优化commit提交详情页页面排版及数据显示(#50372) | |||
| * Fix 代码库二级页面-优化commit提交信息列表页加载方式和数据排序功能(#50348) | |||
| * Fix 代码库二级页面-优化创建发行版功能(#50346) | |||
| * Fix 代码库二级页面-优化标签列表页功能(#50344) | |||
| * Fix 代码库二级页面-优化发行版本列表页功能(#50345) | |||
| * Fix 代码库二级页面-优化分支列表页功能(#50343) | |||
| * Fix 其他问题优化(#51581) (#51343) (#51108) | |||
| --- | |||
| ### BUGFIXES | |||
| * Fix 发行版—标签跳转链接错误(#51666) | |||
| * Fix 文件预览报错(#51660) | |||
| * Fix 标签创建时间显示错误(#51658) | |||
| * Fix 分支列表中头像显示问题(#51656) | |||
| * Fix 文本信息过长(#51630) (#51626) | |||
| * Fix 版本库中附件下载400(#51625) | |||
| * Fix loading页面优化(#51588) | |||
| * Fix 提交详情页面优化(#51577) | |||
| * Fix 修复易修复制功能(#51569) | |||
| * Fix 修复新建发行版用户信息显示错误的问题(#51665) | |||
| * Fix 修复查看文件详细信息报错的问题(#51561) | |||
| * Fix 修复提交记录中时间显示格式问题(#51526) | |||
| * Fix 组织下项目更加更新时间倒序排序(#50833) | |||
| ## [v3.1.0](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-06-09 | |||
| * ENHANCEMENTS | |||
| @@ -0,0 +1,44 @@ | |||
| class Admins::MessageTemplatesController < Admins::BaseController | |||
| before_action :get_template, only: [:edit, :update, :destroy] | |||
| def index | |||
| message_templates = MessageTemplate.group(:type).count.keys | |||
| @message_templates = kaminari_array_paginate(message_templates) | |||
| end | |||
| def edit | |||
| end | |||
| def update | |||
| if @message_template.update_attributes(message_template_params) | |||
| redirect_to admins_message_templates_path | |||
| flash[:success] = '消息模版更新成功' | |||
| else | |||
| redirect_to admins_message_templates_path | |||
| flash[:danger] = @message_template.errors.full_messages.join(",") | |||
| end | |||
| end | |||
| def init_data | |||
| if MessageTemplate.build_init_data | |||
| redirect_to admins_message_templates_path | |||
| flash[:success] = '消息模版初始化成功' | |||
| else | |||
| redirect_to admins_message_templates_path | |||
| flash[:danger] = '消息模版初始化失败' | |||
| end | |||
| end | |||
| private | |||
| def message_template_params | |||
| params.require(@message_template.type.split("::").join("_").underscore.to_sym).permit! | |||
| end | |||
| def get_template | |||
| @message_template = MessageTemplate.find_by(id: params[:id]) | |||
| unless @message_template.present? | |||
| redirect_to admins_message_templates_path | |||
| flash[:danger] = "消息模版不存在" | |||
| end | |||
| end | |||
| end | |||
| @@ -247,11 +247,11 @@ class ApplicationController < ActionController::Base | |||
| end | |||
| def require_profile_completed | |||
| tip_exception(411, "请完善资料后再操作") unless User.current.profile_completed | |||
| tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed? | |||
| end | |||
| def require_user_profile_completed(user) | |||
| tip_exception(412, "请用户完善资料后再操作") unless user.profile_completed | |||
| tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed? | |||
| end | |||
| # 异常提醒 | |||
| @@ -280,7 +280,7 @@ class ApplicationController < ActionController::Base | |||
| # 资料是否完善 | |||
| def check_account | |||
| if !current_user.profile_completed? | |||
| if !current_user. profile_is_completed? | |||
| #info_url = '/account/profile' | |||
| tip_exception(402, nil) | |||
| end | |||
| @@ -24,7 +24,7 @@ class CompareController < ApplicationController | |||
| @exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).take | |||
| end | |||
| if @exist_pullrequest.present? | |||
| return -2, "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}/Messagecount'>#{@exist_pullrequest.try(:title)}</a>" | |||
| return -2, "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}/Messagecount'>#{@exist_pullrequest.try(:title)}</a>" | |||
| else | |||
| if @compare_result["Commits"].blank? && @compare_result["Diff"].blank? | |||
| return -2, "分支内容相同,无需创建合并请求" | |||
| @@ -15,7 +15,7 @@ class IssuesController < ApplicationController | |||
| include TagChosenHelper | |||
| def index | |||
| @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) || @project.is_public?) | |||
| issues = @project.issues.issue_issue.issue_index_includes | |||
| issues = issues.where(is_private: false) unless @user_admin_or_member | |||
| @@ -111,6 +111,8 @@ class IssuesController < ApplicationController | |||
| Issues::CreateForm.new({subject:issue_params[:subject]}).validate! | |||
| @issue = Issue.new(issue_params) | |||
| if @issue.save! | |||
| SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) | |||
| SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @issue&.id) | |||
| if params[:attachment_ids].present? | |||
| params[:attachment_ids].each do |id| | |||
| attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | |||
| @@ -158,6 +160,7 @@ class IssuesController < ApplicationController | |||
| def update | |||
| last_token = @issue.token | |||
| last_status_id = @issue.status_id | |||
| @issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank? | |||
| if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? | |||
| @issue&.issue_tags_relates&.destroy_all | |||
| params[:issue_tag_ids].each do |tag| | |||
| @@ -202,6 +205,20 @@ class IssuesController < ApplicationController | |||
| issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id) | |||
| Issues::UpdateForm.new({subject:issue_params[:subject]}).validate! | |||
| if @issue.update_attributes(issue_params) | |||
| if @issue&.pull_request.present? | |||
| SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) | |||
| SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @issue&.pull_request&.id ) if @issue.previous_changes[:assigned_to_id].present? | |||
| else | |||
| previous_changes = @issue.previous_changes.slice(:status_id, :assigned_to_id, :tracker_id, :priority_id, :fixed_version_id, :done_ratio, :issue_tags_value, :branch_name) | |||
| if @issue.previous_changes[:start_date].present? | |||
| previous_changes.merge!(start_date: [@issue.previous_changes[:start_date][0].to_s, @issue.previous_changes[:start_date][1].to_s]) | |||
| end | |||
| if @issue.previous_changes[:due_date].present? | |||
| previous_changes.merge!(due_date: [@issue.previous_changes[:due_date][0].to_s, @issue.previous_changes[:due_date][1].to_s]) | |||
| end | |||
| SendTemplateMessageJob.perform_later('IssueChanged', current_user.id, @issue&.id, previous_changes) | |||
| SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if @issue.previous_changes[:assigned_to_id].present? | |||
| end | |||
| if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时 | |||
| @issue.issue_times.update_all(end_time: Time.now) | |||
| @issue.update_closed_issues_count_in_project! | |||
| @@ -253,6 +270,7 @@ class IssuesController < ApplicationController | |||
| status_id = @issue.status_id | |||
| token = @issue.token | |||
| login = @issue.user.try(:login) | |||
| SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, @issue&.subject, @issue.assigned_to_id, @issue.author_id) | |||
| if @issue.destroy | |||
| if issue_type == "2" && status_id != 5 | |||
| post_to_chain("add", token, login) | |||
| @@ -272,8 +290,12 @@ class IssuesController < ApplicationController | |||
| def clean | |||
| #批量删除,暂时只能删除未悬赏的 | |||
| issue_ids = params[:ids] | |||
| if issue_ids.present? | |||
| if Issue.where(id: issue_ids, issue_type: "1").destroy_all | |||
| issues = Issue.where(id: issue_ids, issue_type: "1") | |||
| if issues.present? | |||
| issues.find_each do |i| | |||
| SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, i&.subject, i.assigned_to_id, i.author_id) | |||
| end | |||
| if issues.destroy_all | |||
| normal_status(0, "删除成功") | |||
| else | |||
| normal_status(-1, "删除失败") | |||
| @@ -307,7 +329,18 @@ class IssuesController < ApplicationController | |||
| if update_hash.blank? | |||
| normal_status(-1, "请选择批量更新内容") | |||
| elsif issues&.update(update_hash) | |||
| issues.map{|i| i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present?} | |||
| issues.each do |i| | |||
| i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present? | |||
| previous_changes = i.previous_changes.slice(:status_id, :assigned_to_id, :tracker_id, :priority_id, :fixed_version_id, :done_ratio, :issue_tags_value, :branch_name) | |||
| if i.previous_changes[:start_date].present? | |||
| previous_changes.merge!(start_date: [i.previous_changes[:start_date][0].to_s, i.previous_changes[:start_date][1].to_s]) | |||
| end | |||
| if i.previous_changes[:due_date].present? | |||
| previous_changes.merge!(due_date: [i.previous_changes[:due_date][0].to_s, i.previous_changes[:due_date][1].to_s]) | |||
| end | |||
| SendTemplateMessageJob.perform_later('IssueChanged', current_user.id, i&.id, previous_changes) | |||
| SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, i&.id) if i.previous_changes[:assigned_to_id].present? | |||
| end | |||
| normal_status(0, "批量更新成功") | |||
| else | |||
| normal_status(-1, "批量更新失败") | |||
| @@ -321,6 +354,8 @@ class IssuesController < ApplicationController | |||
| @new_issue = @issue.dup | |||
| @new_issue.author_id = current_user.id | |||
| if @new_issue.save | |||
| SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @new_issue&.id) | |||
| SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @new_issue&.id) | |||
| issue_tags = @issue.issue_tags.pluck(:id) | |||
| if issue_tags.present? | |||
| issue_tags.each do |tag| | |||
| @@ -398,27 +433,27 @@ class IssuesController < ApplicationController | |||
| def check_project_public | |||
| unless @project.is_public || @project.member?(current_user) || current_user.admin? || (@project.user_id == current_user.id) | |||
| normal_status(-1, "您没有权限") | |||
| return render_forbidden | |||
| end | |||
| end | |||
| def set_issue | |||
| @issue = Issue.find_by_id(params[:id]) | |||
| if @issue.blank? | |||
| normal_status(-1, "标签不存在") | |||
| elsif @issue.is_lock &&!(@project.member?(current_user) || current_user.admin?) | |||
| normal_status(-1, "您没有权限") | |||
| return render_not_found | |||
| elsif !(@project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id)))) | |||
| return render_forbidden | |||
| end | |||
| end | |||
| def check_issue_permission | |||
| unless @project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id))) | |||
| normal_status(-1, "您没有权限") | |||
| return render_forbidden | |||
| end | |||
| end | |||
| def operate_issue_permission | |||
| return render_forbidden("您没有权限进行此操作.") unless current_user.admin? || @project.member?(current_user) | |||
| return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?) | |||
| end | |||
| def export_issues(issues) | |||
| @@ -23,9 +23,9 @@ class MainController < ApplicationController | |||
| # TODO: 这块之后需要整合,者架构重新变化,统一跳转到index后再路由分发 | |||
| if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild" | |||
| render file: 'public/h5educoderbuild/index.html', :layout => false | |||
| render file: 'public/h5educoderbuild/index.html', :layout => false, :content_type=> 'text/html' | |||
| else | |||
| render file: 'public/react/build/index.html', :layout => false | |||
| render file: 'public/react/build/index.html', :layout => false, :content_type=> 'text/html' | |||
| end | |||
| end | |||
| @@ -9,6 +9,8 @@ class MembersController < ApplicationController | |||
| def create | |||
| interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user) | |||
| SendTemplateMessageJob.perform_later('ProjectJoined', current_user.id, @user.id, @project.id) | |||
| SendTemplateMessageJob.perform_later('ProjectMemberJoined', current_user.id, @user.id, @project.id) | |||
| render_response(interactor) | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -28,6 +30,8 @@ class MembersController < ApplicationController | |||
| def remove | |||
| interactor = Projects::DeleteMemberInteractor.call(@project.owner, @project, @user) | |||
| SendTemplateMessageJob.perform_later('ProjectLeft', current_user.id, @user.id, @project.id) | |||
| SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, @user.id, @project.id) | |||
| render_response(interactor) | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -36,6 +40,7 @@ class MembersController < ApplicationController | |||
| def change_role | |||
| interactor = Projects::ChangeMemberRoleInteractor.call(@project.owner, @project, @user, params[:role]) | |||
| SendTemplateMessageJob.perform_later('ProjectRole', current_user.id, @user.id, @project.id, message_role_name) | |||
| render_response(interactor) | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -66,4 +71,14 @@ class MembersController < ApplicationController | |||
| def check_user_profile_completed | |||
| require_user_profile_completed(@user) | |||
| end | |||
| def message_role_name | |||
| case params[:role] | |||
| when 'Manager' then '管理员' | |||
| when 'Developer' then '开发者' | |||
| when 'Reporter' then '报告者' | |||
| else | |||
| '' | |||
| end | |||
| end | |||
| end | |||
| @@ -18,6 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController | |||
| ActiveRecord::Base.transaction do | |||
| @team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id) | |||
| @organization_user = OrganizationUser.build(@organization.id, @operate_user.id) | |||
| SendTemplateMessageJob.perform_later('OrganizationRole', @operate_user.id, @organization.id, @team.authorize_name) | |||
| Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login) | |||
| end | |||
| rescue Exception => e | |||
| @@ -6,7 +6,8 @@ class Projects::ProjectUnitsController < Projects::BaseController | |||
| def create | |||
| if current_user.admin? || @project.manager?(current_user) | |||
| ActiveRecord::Base.transaction do | |||
| ProjectUnit.update_by_unit_types!(@project, unit_types) | |||
| before_units, after_units = ProjectUnit.update_by_unit_types!(@project, unit_types) | |||
| SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, {navbar: true}) unless before_units.eql?(after_units) | |||
| render_ok | |||
| end | |||
| else | |||
| @@ -4,7 +4,7 @@ class ProjectsController < ApplicationController | |||
| include ProjectsHelper | |||
| 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 branches_slice 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 :authorizate_user_can_edit_project!, only: %i[update] | |||
| @@ -86,6 +86,13 @@ class ProjectsController < ApplicationController | |||
| @branches = result.is_a?(Hash) && result.key?(:status) ? [] : result | |||
| end | |||
| def branches_slice | |||
| return @branches = [] unless @project.forge? | |||
| slice_result = Gitea::Repository::Branches::ListSliceService.call(@owner, @project.identifier) | |||
| @branches_slice = slice_result.is_a?(Hash) && slice_result.key?(:status) ? [] : slice_result | |||
| end | |||
| def group_type_list | |||
| project_statics = ProjectStatistic.first | |||
| @@ -139,6 +146,7 @@ class ProjectsController < ApplicationController | |||
| @project.repository.update_column(:hidden, private) | |||
| 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)) | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -58,8 +58,9 @@ class PullRequestsController < ApplicationController | |||
| ActiveRecord::Base.transaction do | |||
| @pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params) | |||
| if @gitea_pull_request[:status] == :success | |||
| @pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"]) | |||
| render_ok | |||
| @pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"]) | |||
| SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) | |||
| SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) | |||
| else | |||
| render_error("create pull request error: #{@gitea_pull_request[:status]}") | |||
| raise ActiveRecord::Rollback | |||
| @@ -77,12 +78,13 @@ class PullRequestsController < ApplicationController | |||
| if params[:title].nil? | |||
| normal_status(-1, "名称不能为空") | |||
| elsif params[:issue_tag_ids].nil? | |||
| normal_status(-1, "标签不能为空") | |||
| normal_status(-1, "标记不能为空") | |||
| else | |||
| ActiveRecord::Base.transaction do | |||
| begin | |||
| merge_params | |||
| @issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank? | |||
| if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? | |||
| @issue&.issue_tags_relates&.destroy_all | |||
| params[:issue_tag_ids].each do |tag| | |||
| @@ -116,6 +118,8 @@ class PullRequestsController < ApplicationController | |||
| normal_status(-1, e.message) | |||
| raise ActiveRecord::Rollback | |||
| end | |||
| SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) | |||
| SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id ) if @issue.previous_changes[:assigned_to_id].present? | |||
| end | |||
| end | |||
| @@ -125,7 +129,12 @@ class PullRequestsController < ApplicationController | |||
| ActiveRecord::Base.transaction do | |||
| begin | |||
| colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user) | |||
| colsed === true ? normal_status(1, "已拒绝") : normal_status(-1, '合并失败') | |||
| if colsed === true | |||
| SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) | |||
| normal_status(1, "已拒绝") | |||
| else | |||
| normal_status(-1, '合并失败') | |||
| end | |||
| rescue => e | |||
| normal_status(-1, e.message) | |||
| raise ActiveRecord::Rollback | |||
| @@ -164,6 +173,7 @@ class PullRequestsController < ApplicationController | |||
| if success_condition && @pull_request.merge! | |||
| @pull_request.project_trend_status! | |||
| @issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id) | |||
| SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) | |||
| normal_status(1, "合并成功") | |||
| else | |||
| normal_status(-1, result.message) | |||
| @@ -190,7 +200,7 @@ class PullRequestsController < ApplicationController | |||
| if can_merge.present? | |||
| render json: { | |||
| status: -2, | |||
| message: "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}/Messagecount''>#{can_merge.first.try(:title)}</a>", | |||
| message: "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}''>#{can_merge.first.try(:title)}</a>", | |||
| } | |||
| else | |||
| normal_status(0, "可以合并") | |||
| @@ -1,4 +1,5 @@ | |||
| class RepositoriesController < ApplicationController | |||
| include RepositoriesHelper | |||
| include ApplicationHelper | |||
| include OperateProjectAbilityAble | |||
| include Repository::LanguagesPercentagable | |||
| @@ -54,16 +55,6 @@ class RepositoriesController < ApplicationController | |||
| @entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call | |||
| @entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : [] | |||
| @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" | |||
| # TODO | |||
| # 临时处理readme文件问题 | |||
| result = Gitea::Repository::Readme::GetService.call(@owner.login, @project.identifier, @ref, @owner&.gitea_token) | |||
| @readme = | |||
| if result[:status] == :success | |||
| result[:body] | |||
| else | |||
| {} | |||
| end | |||
| end | |||
| end | |||
| @@ -73,6 +64,7 @@ class RepositoriesController < ApplicationController | |||
| def sub_entries | |||
| file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) | |||
| @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" | |||
| if @project.educoder? | |||
| if params[:type] === 'file' | |||
| @@ -103,10 +95,21 @@ class RepositoriesController < ApplicationController | |||
| end | |||
| def commits | |||
| @hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier, | |||
| sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call | |||
| if params[:filepath].present? | |||
| file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) | |||
| @hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri, | |||
| sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call | |||
| else | |||
| @hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier, | |||
| sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call | |||
| end | |||
| end | |||
| def commits_slice | |||
| @hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier, | |||
| sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token) | |||
| end | |||
| def commit | |||
| @sha = params[:sha] | |||
| @commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token) | |||
| @@ -120,7 +123,11 @@ class RepositoriesController < ApplicationController | |||
| end | |||
| def contributors | |||
| @contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier) | |||
| if params[:filepath].present? | |||
| @contributors = [] | |||
| else | |||
| @contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier) | |||
| end | |||
| end | |||
| def edit | |||
| @@ -183,10 +190,16 @@ class RepositoriesController < ApplicationController | |||
| end | |||
| def readme | |||
| result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token) | |||
| if params[:filepath].present? | |||
| result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token) | |||
| else | |||
| result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token) | |||
| end | |||
| @readme = result[:status] === :success ? result[:body] : nil | |||
| render json: @readme | |||
| @readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref]) | |||
| render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha") | |||
| rescue | |||
| render json: nil | |||
| end | |||
| def languages | |||
| @@ -214,7 +227,7 @@ class RepositoriesController < ApplicationController | |||
| file_path = [domain, api_url, url].join | |||
| file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") if @repository.hidden? | |||
| redirect_to file_path | |||
| redirect_to URI.escape(file_path) | |||
| end | |||
| private | |||
| @@ -237,8 +250,14 @@ class RepositoriesController < ApplicationController | |||
| # TODO 获取最新commit信息 | |||
| def project_commits | |||
| Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier, | |||
| sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call | |||
| if params[:filepath].present? | |||
| file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) | |||
| Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri, | |||
| sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call | |||
| else | |||
| Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier, | |||
| sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call | |||
| end | |||
| end | |||
| def get_statistics | |||
| @@ -0,0 +1,96 @@ | |||
| class Users::MessagesController < Users::BaseController | |||
| before_action :private_user_resources! | |||
| before_action :find_receivers, only: [:create] | |||
| def index | |||
| limit = params[:limit] || params[:per_page] | |||
| limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i | |||
| page = params[:page].to_i.zero? ? 1 : params[:page].to_i | |||
| result = Notice::Read::ListService.call(observed_user.id, message_type, message_status, page, limit) | |||
| return render_error if result.nil? | |||
| @data = result[2] | |||
| end | |||
| def create | |||
| return render_forbidden unless %w(atme).include?(params[:type]) | |||
| case params[:type] | |||
| when 'atme' | |||
| Notice::Write::CreateAtmeForm.new(atme_params).validate! | |||
| case atme_params[:atmeable_type] | |||
| when 'Issue' | |||
| SendTemplateMessageJob.perform_now('IssueAtme', @receivers, current_user.id, atme_params[:atmeable_id]) | |||
| when 'PullRequest' | |||
| SendTemplateMessageJob.perform_now('PullRequestAtme', @receivers, current_user.id, atme_params[:atmeable_id]) | |||
| when 'Journal' | |||
| journal = Journal.find_by_id(atme_params[:atmeable_id]) | |||
| if journal.present? | |||
| if journal&.issue&.pull_request.present? | |||
| SendTemplateMessageJob.perform_now('PullRequestAtme', @receivers, current_user.id, atme_params[:atmeable_id]) | |||
| else | |||
| SendTemplateMessageJob.perform_now('IssueAtme', @receivers, current_user.id, atme_params[:atmeable_id]) | |||
| end | |||
| end | |||
| end | |||
| end | |||
| render_ok | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def delete | |||
| return render_forbidden unless %w(atme).include?(params[:type]) | |||
| result = Notice::Write::DeleteService.call(params[:ids], observed_user.id, message_type) | |||
| return render_error if result.nil? | |||
| render_ok | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def read | |||
| return render_forbidden unless %w(notification atme).include?(params[:type]) | |||
| result = Notice::Write::ChangeStatusService.call(params[:ids], observed_user.id, message_type) | |||
| if result.nil? | |||
| render_error | |||
| else | |||
| render_ok | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| private | |||
| def message_type | |||
| @message_type = begin | |||
| case params[:type] | |||
| when "notification" then 1 | |||
| when "atme" then 2 | |||
| else | |||
| -1 | |||
| end | |||
| end | |||
| end | |||
| def message_status | |||
| @message_status = begin | |||
| case params[:status] | |||
| when "1" then 1 | |||
| when "2" then 2 | |||
| else | |||
| -1 | |||
| end | |||
| end | |||
| end | |||
| def atme_params | |||
| params.permit(:atmeable_type, :atmeable_id, receivers_login: []) | |||
| end | |||
| def find_receivers | |||
| @receivers = User.where(login: params[:receivers_login]) | |||
| return render_not_found if @receivers.size == 0 | |||
| end | |||
| end | |||
| @@ -91,6 +91,12 @@ class UsersController < ApplicationController | |||
| def get_user_info | |||
| begin | |||
| @user = current_user | |||
| begin | |||
| result = Notice::Read::CountService.call(current_user.id) | |||
| @message_unread_total = result.nil? ? 0 : result[2]["unread_notification"] | |||
| rescue | |||
| @message_unread_total = 0 | |||
| end | |||
| # TODO 等消息上线再打开注释 | |||
| #@tidding_count = unviewed_tiddings(current_user) if current_user.present? | |||
| rescue Exception => e | |||
| @@ -1,14 +1,14 @@ | |||
| class VersionReleasesController < ApplicationController | |||
| before_action :load_repository | |||
| before_action :set_user | |||
| before_action :require_login, except: [:index] | |||
| before_action :find_version , only: [:edit, :update, :destroy] | |||
| before_action :require_login, except: [:index, :show] | |||
| before_action :check_release_authorize, except: [:index, :show] | |||
| before_action :find_version , only: [:show, :edit, :update, :destroy] | |||
| def index | |||
| version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call | |||
| @version_releases = version_releases | |||
| @version_releases = kaminari_paginate(@repository.version_releases.order(created_at: :desc)) | |||
| @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) | |||
| @user_admin_permission = current_user.present? && (@repository.project.all_managers.include?(current_user) || current_user.admin?) | |||
| end | |||
| def new | |||
| @@ -22,6 +22,10 @@ class VersionReleasesController < ApplicationController | |||
| end | |||
| end | |||
| def show | |||
| # @release = Gitea::Versions::GetService.call(current_user.gitea_token, @user&.login, @repository&.identifier, @version&.version_gid) | |||
| end | |||
| def create | |||
| if params[:name].nil? | |||
| normal_status(-1, "名称不能为空") | |||
| @@ -37,13 +41,14 @@ class VersionReleasesController < ApplicationController | |||
| version_params = releases_params | |||
| version_release = VersionRelease.new(version_params.merge(user_id: current_user.id, repository_id: @repository.id)) | |||
| if version_release.save! | |||
| git_version_release = Gitea::Versions::CreateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params).call | |||
| git_version_release = Gitea::Versions::CreateService.new(current_user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params).call | |||
| if git_version_release | |||
| update_params = { | |||
| tarball_url: git_version_release["tarball_url"], | |||
| zipball_url: git_version_release["zipball_url"], | |||
| url: git_version_release["url"], | |||
| version_gid: git_version_release["id"], | |||
| sha: git_version_release["sha"] | |||
| } | |||
| version_release.update_attributes!(update_params) | |||
| version_release.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") | |||
| @@ -81,7 +86,7 @@ class VersionReleasesController < ApplicationController | |||
| if @version.update_attributes!(version_params) | |||
| create_attachments(params[:attachment_ids], @version) if params[:attachment_ids].present? | |||
| git_version_release = Gitea::Versions::UpdateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call | |||
| git_version_release = Gitea::Versions::UpdateService.new(current_user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call | |||
| unless git_version_release | |||
| raise Error, "更新失败" | |||
| end | |||
| @@ -102,7 +107,7 @@ class VersionReleasesController < ApplicationController | |||
| ActiveRecord::Base.transaction do | |||
| begin | |||
| if @version.destroy | |||
| git_version_release = Gitea::Versions::DeleteService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), @version.try(:version_gid)).call | |||
| git_version_release = Gitea::Versions::DeleteService.new(current_user.gitea_token, @user.try(:login), @repository.try(:identifier), @version.try(:version_gid)).call | |||
| if git_version_release.status == 204 | |||
| normal_status(0, "删除成功") | |||
| @@ -157,4 +162,8 @@ class VersionReleasesController < ApplicationController | |||
| end | |||
| end | |||
| def check_release_authorize | |||
| return render_forbidden("您没有权限进行此操作.") unless current_user.admin? || @project.manager?(current_user) | |||
| end | |||
| end | |||
| @@ -1 +1,502 @@ | |||
| # Pulls | |||
| ## Get a pull request | |||
| 获取合并请求详情接口 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET http://localhost:3000/api/Jasder/gitlink/pulls/88.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/Jasder/gitlink/pulls/88.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/pulls/:id.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| |string |用户登录名 | | |||
| |repo |是| |string |项目标识identifier | | |||
| |id |是| | integer | pull id值 | | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "响应成功", | |||
| "project_name": "Gitlink", | |||
| "identifier": "forgeplus", | |||
| "project_identifier": "forgeplus", | |||
| "pr_time": "52分钟前", | |||
| "commits_count": 229, | |||
| "files_count": 328, | |||
| "comments_count": 0, | |||
| "comments_total_count": 0, | |||
| "pull_request": { | |||
| "id": 1189, | |||
| "base": "master", | |||
| "head": "develop", | |||
| "status": 0, | |||
| "fork_project_id": null, | |||
| "is_original": false, | |||
| "pull_request_staus": "open", | |||
| "fork_project_user": null, | |||
| "create_user": "jasder", | |||
| "mergeable": true, | |||
| "state": "open" | |||
| }, | |||
| "issue": { | |||
| "id": 51888, | |||
| "subject": "FIx release v3.2.0", | |||
| "description": null, | |||
| "is_private": false, | |||
| "branch_name": null, | |||
| "project_author_name": "Gitlink", | |||
| "closed_on": "", | |||
| "created_at": "2021-10-12 15:51", | |||
| "assign_user_name": "victor", | |||
| "assign_user_login": "moshenglv", | |||
| "author_name": "段甲生", | |||
| "author_login": "jasder", | |||
| "author_picture": "images/avatars/User/36480?t=1615520120", | |||
| "issue_status": "新增", | |||
| "priority": "正常", | |||
| "version": null, | |||
| "issue_tags": null | |||
| }, | |||
| "conflict_files": [] | |||
| } | |||
| ``` | |||
| ## 获取pull request文件列表 | |||
| 获取pull request文件列表 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET \ | |||
| http://localhost:3000/api/Jason/gitlink/pulls/1/files.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/jasder/gitlink/pulls/1/files.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/pulls/:id/files.json` | |||
| ### 请求参数: | |||
| |参数名|必选|类型|说明| | |||
| |-|-|-|-| | |||
| |owner |是|string |用户登录名 | | |||
| |repo |是|string |project's identifier | | |||
| |id |是|int |pull request's id | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |-|-|-| | |||
| |files_count |int|文件更改的总数量| | |||
| |total_addition |int|添加代码总行数| | |||
| |total_deletion |int|删除代码总行数| | |||
| |files |array|| | |||
| |-- sha |string|commit's sha value| | |||
| |-- name |string|当前文件名| | |||
| |-- old_name |string| 修改之前的文件名称,与name相同的话,说明文件名未更改| | |||
| |-- addition |int|文件添加的行数| | |||
| |-- deletion |int|文件删除的行数| | |||
| |-- type |int|文件类型, 1: 表示该文件只添加了内容,2: 表示该文件内容有修改, 3: 表示文件被删除或者改文件只删除了内容| | |||
| |-- isCreated |boolean|当前文件是否为新增文件, true: 是, false: 否| | |||
| |-- isDeleted |boolean|当前文件是否被删除, true: 是,false: 否| | |||
| |-- isBin |boolean|当前文件是否为二进制文件,true: 是,false: 否| | |||
| |-- isLFSFile |boolean|当前文件是否为LFS文件,true: 是,false: 否| | |||
| |-- isRenamed |boolean|当前文件是否被重命名,true: 是,false: 否| | |||
| |-- sections |array|| | |||
| |---- fileName |string|文件名称| | |||
| |---- lines |array|| | |||
| |------ leftIdx |string|文件变动之前所在行数| | |||
| |------ rightIdx |string|文件更改后所在行数| | |||
| |------ type |string|文件变更类型,1: 新增,2: 修改, 3: 删除, 4: diff统计信息| | |||
| |------ content |string|文件变更的内容| | |||
| |------ sectionInfo |object|| | |||
| |-------- path |string|文件相对仓库的路径| | |||
| |-------- lastLeftIdx |int|| | |||
| |-------- lastRightIdx |int|| | |||
| |-------- leftHunkSize |int|文件变更之前的行数| | |||
| |-------- rightHunkSize |int|文件变更之后的行数(及当前页面编辑器显示的总行数)| | |||
| |-------- leftIdx |int|文件变更之前所在行数| | |||
| |-------- rightIdx |int|文件变更之后所在行数(即:页面编辑器开始显示的行数)| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "files_count": 6, | |||
| "total_addition": 447, | |||
| "total_deletion": 0, | |||
| "files": [ | |||
| { | |||
| "sha": "xefenisnii", | |||
| "name": "文件.txt", | |||
| "old_name": "文件.txt", | |||
| "index": 6, | |||
| "addition": 2, | |||
| "deletion": 0, | |||
| "type": 1, | |||
| "isCreated": true, | |||
| "isDeleted": false, | |||
| "isBin": false, | |||
| "isLFSFile": false, | |||
| "isRenamed": false, | |||
| "isSubmodule": false, | |||
| "sections": [ | |||
| { | |||
| "fileName": "文件.txt", | |||
| "name": "", | |||
| "lines": [ | |||
| { | |||
| "leftIdx": 0, | |||
| "rightIdx": 0, | |||
| "type": 4, | |||
| "content": "@@ -0,0 +1,2 @@", | |||
| "sectionInfo": { | |||
| "path": null, | |||
| "lastLeftIdx": null, | |||
| "lastRightIdx": null, | |||
| "leftIdx": 0, | |||
| "rightIdx": 0, | |||
| "leftHunkSize": null, | |||
| "rightHunkSize": null | |||
| } | |||
| }, | |||
| { | |||
| "leftIdx": 0, | |||
| "rightIdx": 1, | |||
| "type": 2, | |||
| "content": "+用例图一致性更新", | |||
| "sectionInfo": null | |||
| }, | |||
| { | |||
| "leftIdx": 0, | |||
| "rightIdx": 2, | |||
| "type": 2, | |||
| "content": "+工程文件直接上传会有文件缺失,现在压缩后上传", | |||
| "sectionInfo": null | |||
| } | |||
| ] | |||
| } | |||
| ] | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| ## 获取pull request的commits列表 | |||
| 获取pull request的commits列表 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET http://localhost:3000/api/jasder/jasder_test/pulls/1/commits.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/jasder/jasder_test/pulls/1/commits.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/pulls/:id/commits.json` | |||
| ### 请求参数: | |||
| |参数名|必选|类型|说明| | |||
| |-|-|-|-| | |||
| |owner |是|string |用户登录名 | | |||
| |repo |是|string |project's identifier | | |||
| |id |是|int |pull request's id | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |commits_count |int|commits总数量| | |||
| |commits |array|| | |||
| |-- author |object|项目作者| | |||
| |---- login |string|用户login| | |||
| |---- name |string|用户姓名| | |||
| |---- image_url |string|用户头像| | |||
| |-- committer |object|commit提交用户| | |||
| |---- login |string|用户login| | |||
| |---- name |string|用户姓名| | |||
| |---- image_url |string|用户头像| | |||
| |-- timestamp |int|commit的unix时间戳| | |||
| |-- time_from_now|string|commit’s 提交时间距当前时间的时间值| | |||
| |-- message |string|commit说明信息| | |||
| |-- sha |string|commit’s sha值| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "commits_count": 1, | |||
| "commits": [ | |||
| { | |||
| "author": { | |||
| "id": 36480, | |||
| "login": "jasder", | |||
| "name": "段甲生", | |||
| "image_url": "avatars/User/b" | |||
| }, | |||
| "committer": { | |||
| "id": 36480, | |||
| "login": "jasder", | |||
| "name": "段甲生", | |||
| "image_url": "avatars/User/b" | |||
| }, | |||
| "timestamp": 1604382982, | |||
| "time_from_now": "3小时前", | |||
| "message": "add some file\n* Add the tag list page to the release page\n* Apply suggestions from code review\n* Add the tags list view\n* Add the delete tag way on ui\n* Not delete tag and clear message when delete a release\n", | |||
| "sha": "8f5faee0d3b3be1b8063e84da0c79dd75327b968" | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| ## Compare two commits | |||
| Compare two commits | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET \ | |||
| http://localhost:3000/api/Jason/test-txt/compare/master...develop | |||
| curl -X GET \ | |||
| http://localhost:3000/api/Jason/test-txt/compare/master...Jason/test-txt:develop | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/Jason/test-txt/compare/master...Jason/test-txt:develop') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/compare/{base}...{head}.json` | |||
| ### 请求参数: | |||
| |参数名|必选|类型|说明| | |||
| |-|-|-|-| | |||
| |owner |是|string |用户登录名 | | |||
| |repo |是|string |project's identifier | | |||
| |base |是|string |pull request's id | | |||
| |head |是|string |pull request's id | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |-|-|-| | |||
| |commits_count |int|commits总数量| | |||
| |commits |array|| | |||
| |-- author |object|项目作者| | |||
| |---- login |string|用户login| | |||
| |---- name |string|用户姓名| | |||
| |---- image_url |string|用户头像| | |||
| |-- committer |object|commit提交用户| | |||
| |---- login |string|用户login| | |||
| |---- name |string|用户姓名| | |||
| |---- image_url |string|用户头像| | |||
| |-- timestamp |int|commit的unix时间戳| | |||
| |-- time_from_now|string|commit’s 提交时间距当前时间的时间值| | |||
| |-- message |string|commit说明信息| | |||
| |-- sha |string|commit’s sha值| | |||
| |diff |object|| | |||
| |-- files_count |int|文件更改的总数量| | |||
| |-- total_addition |int|添加代码总行数| | |||
| |-- total_deletion |int|删除代码总行数| | |||
| |-- files |Array|| | |||
| |-- sha |string|commit's sha | | |||
| |-- name |string|当前文件名| | |||
| |-- old_name |string| 修改之前的文件名称,与name相同的话,说明文件名未更改| | |||
| |-- addition |int|文件添加的行数| | |||
| |-- deletion |int|文件删除的行数| | |||
| |-- type |int|文件类型, 1: 表示该文件只添加了内容,2: 表示该文件内容有修改, 3: 表示文件被删除或者改文件只删除了内容| | |||
| |-- isCreated |boolean|当前文件是否为新增文件, true: 是, false: 否| | |||
| |-- isDeleted |boolean|当前文件是否被删除, true: 是,false: 否| | |||
| |-- isBin |boolean|当前文件是否为二进制文件,true: 是,false: 否| | |||
| |-- isLFSFile |boolean|当前文件是否为LFS文件,true: 是,false: 否| | |||
| |-- isRenamed |boolean|当前文件是否被重命名,true: 是,false: 否| | |||
| |-- sections |array|| | |||
| |---- fileName |string|文件名称| | |||
| |---- lines |array|| | |||
| |------ leftIdx |string|文件变动之前所在行数| | |||
| |------ rightIdx |string|文件更改后所在行数| | |||
| |------ type |string|文件变更类型,1: 内容未改动,2: 添加, 3: 删除, 4: diff统计信息| | |||
| |------ content |string|文件变更的内容| | |||
| |------ sectionInfo |object|| | |||
| |-------- path |string|文件相对仓库的路径| | |||
| |-------- lastLeftIdx |int|| | |||
| |-------- lastRightIdx |int|| | |||
| |-------- leftHunkSize |int|文件变更之前的行数| | |||
| |-------- rightHunkSize |int|文件变更之后的行数(及当前页面编辑器显示的总行数)| | |||
| |-------- leftIdx |int|文件变更之前所在行数| | |||
| |-------- rightIdx |int|文件变更之后所在行数| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "commits_count": 1, | |||
| "commits": [ | |||
| { | |||
| "author": { | |||
| "id": 36480, | |||
| "login": "jasder", | |||
| "name": "段甲生", | |||
| "image_url": "avatars/User/b" | |||
| }, | |||
| "committer": { | |||
| "id": 36480, | |||
| "login": "jasder", | |||
| "name": "段甲生", | |||
| "image_url": "avatars/User/b" | |||
| }, | |||
| "timestamp": 1604382982, | |||
| "time_from_now": "4小时前", | |||
| "message": "add some file\n* Add the tag list page to the release page\n* Apply suggestions from code review\n* Add the tags list view\n* Add the delete tag way on ui\n* Not delete tag and clear message when delete a release\n", | |||
| "sha": "8f5faee0d3b3be1b8063e84da0c79dd75327b968" | |||
| } | |||
| ], | |||
| "diff": { | |||
| "files_count": 6, | |||
| "total_addition": 447, | |||
| "total_deletion": 0, | |||
| "files": [ | |||
| { | |||
| "name": "build.go", | |||
| "old_name": "build.go", | |||
| "index": 1, | |||
| "addition": 33, | |||
| "deletion": 0, | |||
| "type": 1, | |||
| "isCreated": true, | |||
| "isDeleted": false, | |||
| "isBin": false, | |||
| "isLFSFile": false, | |||
| "isRenamed": false, | |||
| "isSubmodule": false, | |||
| "sections": [ | |||
| { | |||
| "fileName": "build.go", | |||
| "name": "", | |||
| "lines": [ | |||
| { | |||
| "leftIdx": 0, | |||
| "rightIdx": 0, | |||
| "type": 4, | |||
| "content": "@@ -0,0 +1,33 @@", | |||
| "sectionInfo": { | |||
| "path": "build.go", | |||
| "lastLeftIdx": 0, | |||
| "lastRightIdx": 0, | |||
| "leftIdx": 0, | |||
| "rightIdx": 1, | |||
| "leftHunkSize": 0, | |||
| "rightHunkSize": 33 | |||
| } | |||
| }, | |||
| { | |||
| "leftIdx": 0, | |||
| "rightIdx": 1, | |||
| "type": 2, | |||
| "content": "+// Copyright 2020 The Gitea Authors. All rights reserved.", | |||
| "sectionInfo": null | |||
| } | |||
| ] | |||
| } | |||
| ] | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| ## List pull requests | |||
| 获取合并请求列表 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET http://localhost:3000/api/Jasder/gitlink/pulls.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/Jasder/gitlink/pulls.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/pulls.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| |string |用户登录名 | | |||
| |repo |是| |string |项目标识identifier | | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "响应成功", | |||
| "open_count": 4, | |||
| "close_count": 51, | |||
| "merged_issues_size": 123, | |||
| "search_count": 4, | |||
| "limit": null, | |||
| "user_admin_or_member": true, | |||
| "user_admin_or_developer": true, | |||
| "project_name": "Gitlink", | |||
| "project_author_name": "Gitlink", | |||
| "issues": [ | |||
| { | |||
| "pull_request_id": 1189, | |||
| "pull_request_status": 0, | |||
| "pull_request_head": "develop", | |||
| "pull_request_base": "master", | |||
| "pull_request_staus": "open", | |||
| "is_original": false, | |||
| "fork_project_id": null, | |||
| "fork_project_identifier": null, | |||
| "fork_project_user": null, | |||
| "id": 51888, | |||
| "name": "FIx release v3.2.0", | |||
| "pr_time": "59分钟前", | |||
| "assign_user_name": "victor", | |||
| "assign_user_login": "moshenglv", | |||
| "author_name": "段甲生", | |||
| "author_login": "jasder", | |||
| "avatar_url": "images/avatars/User/36480?t=1615520120", | |||
| "priority": "正常", | |||
| "version": null, | |||
| "journals_count": 0, | |||
| "issue_tags": null | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| @@ -274,6 +274,124 @@ await octokit.request('GET /api/yystopf/ceshi/detail.json') | |||
| } | |||
| ``` | |||
| ## 仓库标签列表 | |||
| 仓库标签列表 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET http://localhost:3000/api/yystopf/csfjkkj/tags.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/yystopf/csfjkkj/tags.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/tags.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| |string |用户登录名 | | |||
| |repo |是| |string |项目标识identifier | | |||
| |page |否| 1 | integer | 页码 | | |||
| |limit |否| 20| integer | 每页个数 | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |id |int |标签id | | |||
| |name |string|标签名称| | |||
| |zipball_url |string|标签zip包下载地址| | |||
| |tarball_url |string|标签tar包下载地址| | |||
| |tagger |object|打标签的人| | |||
| |time_ago |string|打标签的时间| | |||
| |created_at_unix|string|打标签的时间戳| | |||
| |message |string|标签信息| | |||
| |commit |object|标签最后一个commit| | |||
| |commit.sha |string|commit的id| | |||
| |commit.message |string|commit的提交信息| | |||
| |commit.time_ago|string|commit的提交时间| | |||
| |commit.created_at_unix|string|commit的提交时间戳| | |||
| |commit.committer|object|commit的提交者| | |||
| |commit.author|object|commit的作者| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| [ | |||
| { | |||
| "name": "v2.0.0", | |||
| "id": "c7d0873ee41796d1a0e193063095ccf539a9bf31", | |||
| "zipball_url": "http://localhost:3000/api/yystopf/csfjkkj/archive/v2.0.0.zip", | |||
| "tarball_url": "http://localhost:3000/api/yystopf/csfjkkj/archive/v2.0.0.tar.gz", | |||
| "tagger": { | |||
| "id": 4, | |||
| "login": "testforge1", | |||
| "name": "testforge1", | |||
| "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" | |||
| }, | |||
| "time_ago": "1天前", | |||
| "created_at_unix": 1632376903, | |||
| "message": "jdfkls", | |||
| "commit": { | |||
| "sha": "08fe383f1e5ebe2e2a384a8ea3ee890a758c7cd7", | |||
| "message": "add\n", | |||
| "time_ago": "1天前", | |||
| "created_at_unix": 1632376186, | |||
| "committer": { | |||
| "id": 4, | |||
| "login": "testforge1", | |||
| "name": "testforge1", | |||
| "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" | |||
| }, | |||
| "author": { | |||
| "id": 4, | |||
| "login": "testforge1", | |||
| "name": "testforge1", | |||
| "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" | |||
| } | |||
| } | |||
| }, | |||
| { | |||
| "name": "v1.0.0", | |||
| "id": "12168ad39c3ef201a445a2db181a3e43d50e40dd", | |||
| "zipball_url": "http://localhost:3000/api/yystopf/csfjkkj/archive/v1.0.0.zip", | |||
| "tarball_url": "http://localhost:3000/api/yystopf/csfjkkj/archive/v1.0.0.tar.gz", | |||
| "tagger": { | |||
| "id": null, | |||
| "login": "viletyy", | |||
| "name": "viletyy", | |||
| "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" | |||
| }, | |||
| "time_ago": "10天前", | |||
| "created_at_unix": 1631588042, | |||
| "message": "dfks", | |||
| "commit": { | |||
| "sha": "5291b5e45a377c1f7710cc6647259887ed7aaccf", | |||
| "message": "ADD file via upload\n", | |||
| "time_ago": "21天前", | |||
| "created_at_unix": 1630648417, | |||
| "committer": { | |||
| "id": null, | |||
| "login": "yystopf", | |||
| "name": "yystopf", | |||
| "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" | |||
| }, | |||
| "author": { | |||
| "id": null, | |||
| "login": "yystopf", | |||
| "name": "yystopf", | |||
| "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" | |||
| } | |||
| } | |||
| } | |||
| ] | |||
| ``` | |||
| ## 编辑仓库信息 | |||
| 编辑仓库信息 | |||
| @@ -868,6 +986,128 @@ await octokit.request('GET /api/jasder/jasder_test/sub_entries.json') | |||
| Success Data. | |||
| </aside> | |||
| ## 获取仓库README文件 | |||
| 获取仓库README文件 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET \ | |||
| -d "ref=master" \ | |||
| -d "filepath=lib" \ | |||
| http://localhost:3000/api/yystopf/csfjkkj/readme.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/yystopf/csfjkkj/readme.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/readme.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| |string |用户登录名 | | |||
| |repo |是| |string |项目标识identifier | | |||
| |ref |否| | string |分支名称、tag名称或是提交记录id,默认为默认分支 | | |||
| |filepath |否| | string |子目录名称,默认为空 | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type |string|文件类型, file:文件,dir:文件目录 | |||
| |encoding |string |编码 | | |||
| |size |int|文件夹或文件大小 单位B | |||
| |name |string|文件夹或文件名称| | |||
| |path |string|文件夹或文件相对路径| | |||
| |content |string|文件内容 | |||
| |sha |string|文件commitid | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "type": "file", | |||
| "encoding": "base64", | |||
| "size": 24, | |||
| "name": "README.md", | |||
| "path": "lib/README.md", | |||
| "content": "ZGZhc2RhZGpmIGRrZnNsCgpzZGZkZnMK", | |||
| "sha": "860962cd21c60b1a9e07d723080c87c32c18d44a" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 获取仓库贡献者 | |||
| 获取仓库贡献者 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET \ | |||
| -d "ref=master" \ | |||
| -d "filepath=lib" \ | |||
| http://localhost:3000/api/yystopf/csfjkkj/contributors.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/yystopf/csfjkkj/contributors.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/contributors.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| |string |用户登录名 | | |||
| |repo |是| |string |项目标识identifier | | |||
| |ref |否| | string |分支名称、tag名称或是提交记录id,默认为整个仓库 | | |||
| |filepath |否| | string |子目录名称,默认为空 | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |total_count |integer|贡献者数量| | |||
| |contributions |integer|贡献数量| | |||
| |login |string |用户登录名 | | |||
| |type |string|用户类型 | | |||
| |name |string|用户昵称| | |||
| |image_url |string|用户头像| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "contributors": [ | |||
| { | |||
| "contributions": 5, | |||
| "login": "testforge2", | |||
| "type": "User", | |||
| "name": "testforge2", | |||
| "image_url": "system/lets/letter_avatars/2/T/236_177_85/120.png" | |||
| }, | |||
| { | |||
| "contributions": 79, | |||
| "login": "yystopf", | |||
| "type": "User", | |||
| "name": "yystopf", | |||
| "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" | |||
| } | |||
| ], | |||
| "total_count": 2 | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 获取仓库webhooks列表 | |||
| 获取仓库webhooks列表 | |||
| @@ -1,7 +1,7 @@ | |||
| <!-- | |||
| * @Date: 2021-03-01 10:35:21 | |||
| * @LastEditors: viletyy | |||
| * @LastEditTime: 2021-06-11 16:28:51 | |||
| * @LastEditTime: 2021-09-15 18:00:10 | |||
| * @FilePath: /forgeplus/app/docs/slate/source/includes/_users.md | |||
| --> | |||
| # Users | |||
| @@ -47,6 +47,275 @@ await octokit.request('GET /api/users/me.json') | |||
| Success Data. | |||
| </aside> | |||
| ## 用户消息列表 | |||
| 获取用户消息列表 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET http://localhost:3000/api/users/:login/messages.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/users/:login/messages.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET api/users/yystopf/messages.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type | string | 消息类型,不传为所有消息,notification为系统消息,atme为@我消息| | |||
| |status | integer | 是否已读,不传为所有消息,1为未读,2为已读 | | |||
| |limit | integer | 每页个数 | | |||
| |page | integer | 页码 | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |total_count | integer | 消息总数 | | |||
| |type | string | 消息类型 | | |||
| |unread_notification | integer | 未读系统通知数量 | | |||
| |unread_atme | integer | 未读@我数量 | | |||
| |messages.id | integer | 消息id | | |||
| |messages.status | integer | 消息是否已读,1为未读,2为已读 | | |||
| |messages.content | string | 消息内容 | | |||
| |messages.notification_url | string | 消息跳转地址 | | |||
| |messages.source | string | 消息来源 | | |||
| |messages.timeago | string | 消息时间 | | |||
| |messages.type | string | 消息类型,notification为系统消息,atme为@我消息| | |||
| |sender | object | 消息发送者 | | |||
| #### 消息来源source字段说明 | |||
| 类型|说明 | |||
| --------- | ----------- | |||
| |IssueAssigned | 有新指派给我的易修 | | |||
| |IssueAssignerExpire | 我负责的易修截止日期到达最后一天 | | |||
| |IssueAtme | 在易修中@我 | | |||
| |IssueChanged | 我创建或负责的易修状态变更 | | |||
| |IssueCreatorExpire | 我创建的易修截止日期到达最后一天 | | |||
| |IssueDeleted | 我创建或负责的易修删除 | | |||
| |IssueJournal | 我创建或负责的易修有新的评论 | | |||
| |LoginIpTip | 登录异常提示 | | |||
| |OrganizationJoined | 账号被拉入组织 | | |||
| |OrganizationLeft | 账号被移出组织 | | |||
| |OrganizationRole | 账号组织权限变更 | | |||
| |ProjectDeleted | 我关注的仓库被删除 | | |||
| |ProjectFollowed | 我管理的仓库被关注 | | |||
| |ProjectForked | 我管理的仓库被复刻 | | |||
| |ProjectIssue | 我管理/关注的仓库有新的易修 | | |||
| |ProjectJoined | 账号被拉入项目 | | |||
| |ProjectLeft | 账号被移出项目 | | |||
| |ProjectMemberJoined | 我管理的仓库有成员加入 | | |||
| |ProjectMemberLeft | 我管理的仓库有成员移出 | | |||
| |ProjectMilestone | 我管理的仓库有新的里程碑 | | |||
| |ProjectPraised | 我管理的仓库被点赞 | | |||
| |ProjectPullRequest | 我管理/关注的仓库有新的合并请求 | | |||
| |ProjectRole | 账号仓库权限变更 | | |||
| |ProjectSettingChanged | 我管理的仓库项目设置被更改 | | |||
| |ProjectTransfer | 我关注的仓库被转移 | | |||
| |ProjectVersion | 我关注的仓库有新的发行版 | | |||
| |PullRequestAssigned | 有新指派给我的合并请求 | | |||
| |PullReuqestAtme | 在合并请求中@我 | | |||
| |PullRequestChanged | 我创建或负责的合并请求状态变更 | | |||
| |PullRequestClosed | 我创建或负责的合并请求被关闭 | | |||
| |PullRequestJournal | 我创建或负责的合并请求有新的评论 | | |||
| |PullRequestMerged | 我创建或负责的合并请求被合并 | | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "total_count": 5, | |||
| "type": "", | |||
| "unread_notification": 3, | |||
| "unread_atme": 2, | |||
| "messages": [ | |||
| { | |||
| "id": 1, | |||
| "status": 1, | |||
| "content": "Atme Message Content 1", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "PullRequestAtme", | |||
| "time_ago": "1天前", | |||
| "type": "atme", | |||
| "sender": { | |||
| "id": 5, | |||
| "type": "User", | |||
| "name": "testforge2", | |||
| "login": "testforge2", | |||
| "image_url": "system/lets/letter_avatars/2/T/236_177_85/120.png" | |||
| } | |||
| }, | |||
| { | |||
| "id": 2, | |||
| "status": 0, | |||
| "content": "Atme Message Content 2", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "IssueAtme", | |||
| "time_ago": "1天前", | |||
| "type": "atme", | |||
| "sender": { | |||
| "id": 4, | |||
| "type": "User", | |||
| "name": "testforge1", | |||
| "login": "testforge1", | |||
| "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" | |||
| } | |||
| }, | |||
| { | |||
| "id": 3, | |||
| "status": 1, | |||
| "content": "Notification Message Content 1", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "IssueDelete", | |||
| "time_ago": "1天前", | |||
| "type": "notification" | |||
| }, | |||
| { | |||
| "id": 4, | |||
| "status": 0, | |||
| "content": "Notification Message Content 2", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "IssueChanged", | |||
| "time_ago": "1天前", | |||
| "type": "notification" | |||
| }, | |||
| { | |||
| "id": 5, | |||
| "status": 0, | |||
| "content": "Notification Message Content 3", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "ProjectJoined", | |||
| "time_ago": "1天前", | |||
| "type": "notification" | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 发送消息 | |||
| 发送消息, 目前只支持atme | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST http://localhost:3000/api/users/:login/messages.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/users/:login/messages.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST api/users/yystopf/messages.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type | string | 消息类型 | | |||
| |receivers_login | array | 需要发送消息的用户名数组| | |||
| |atmeable_type | string | atme消息对象,是从哪里@我的,比如评论:Journal、易修:Issue、合并请求:PullRequest | | |||
| |atmeable_id | integer | atme消息对象id | | |||
| > 请求的JSON示例: | |||
| ```json | |||
| { | |||
| "type": "atme", | |||
| "receivers_login": ["yystopf", "testforge1"], | |||
| "atmeable_type": "Journal", | |||
| "atmeable_id": 67 | |||
| } | |||
| ``` | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 阅读消息 | |||
| 阅读消息 | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST http://localhost:3000/api/users/:login/messages/read.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/users/:login/messages/read.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST api/users/yystopf/messages/read.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type | string | 消息类型,不传为所有消息,notification为系统消息,atme为@我消息| | |||
| |ids | array | 消息id数组,包含-1则把所有未读消息标记为已读| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 删除消息 | |||
| 删除消息 | |||
| > 示例: | |||
| ```shell | |||
| curl -X DELETE http://localhost:3000/api/users/:login/messages.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('DELETE /api/users/:login/messages.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `DELETE api/users/yystopf/messages.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type | string | 消息类型,atme为@我消息| | |||
| |ids | array | 消息id数组,包含-1则把所有消息删除| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 更改用户信息 | |||
| 更改用户信息 | |||
| @@ -2,11 +2,15 @@ class BaseForm | |||
| include ActiveModel::Model | |||
| def check_project_category(project_category_id) | |||
| raise "project_category_id参数值无效." if project_category_id && !ProjectCategory.exists?(project_category_id) | |||
| unless project_category_id == '' | |||
| raise "project_category_id参数值无效." if project_category_id && !ProjectCategory.exists?(project_category_id) | |||
| end | |||
| end | |||
| def check_project_language(project_language_id) | |||
| raise "project_language_id参数值无效." if project_language_id && !ProjectLanguage.exists?(project_language_id) | |||
| unless project_language_id == '' | |||
| raise "project_language_id参数值无效." if project_language_id && !ProjectLanguage.exists?(project_language_id) | |||
| end | |||
| end | |||
| def check_repository_name(user_id, repository_name) | |||
| @@ -0,0 +1,23 @@ | |||
| class Notice::Write::CreateAtmeForm | |||
| include ActiveModel::Model | |||
| attr_accessor :receivers_login, :atmeable_type, :atmeable_id | |||
| validate :check_receivers | |||
| def check_receivers | |||
| receivers_login.each do |login| | |||
| receiver = User.find_by(login: login) || User.find_by_id(login) | |||
| raise 'receivers_login值无效.' unless receiver.present? | |||
| end | |||
| end | |||
| def check_atmeable | |||
| begin | |||
| raise 'atmeable对象无效.' unless atmeable_type.constantize.find_by_id(atmeable_id).present? | |||
| rescue => exception | |||
| raise 'atmeable对象无效.' | |||
| end | |||
| end | |||
| end | |||
| @@ -1,6 +1,6 @@ | |||
| class Projects::UpdateForm < BaseForm | |||
| attr_accessor :name, :description, :project_category_id, :project_language_id, :private | |||
| validates :name, :description, :project_category_id, :project_language_id, presence: true | |||
| validates :name, presence: true | |||
| validates :name, length: { maximum: 50 } | |||
| validates :description, length: { maximum: 200 } | |||
| validate do | |||
| @@ -434,6 +434,10 @@ module ApplicationHelper | |||
| User.find_by_login login | |||
| end | |||
| def find_user_by_login_and_mail(login, mail) | |||
| User.find_by(login: login, mail: mail) | |||
| end | |||
| def find_user_by_gitea_uid(gitea_uid) | |||
| User.find_by(gitea_uid: gitea_uid) | |||
| end | |||
| @@ -6,16 +6,16 @@ module RepositoriesHelper | |||
| def render_decode64_content(str) | |||
| return nil if str.blank? | |||
| Base64.decode64(str).force_encoding("UTF-8") | |||
| Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace) | |||
| end | |||
| def download_type(str) | |||
| default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2) | |||
| default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2) | |||
| default_type.include?(str&.downcase) | |||
| end | |||
| def image_type?(str) | |||
| default_type = %w(png jpg gif tif psd svg gif bmp webp jpeg) | |||
| default_type = %w(png jpg gif tif psd svg bmp webp jpeg) | |||
| default_type.include?(str&.downcase) | |||
| end | |||
| @@ -26,9 +26,13 @@ module RepositoriesHelper | |||
| end | |||
| def render_commit_author(author_json) | |||
| return nil if author_json.blank? || author_json["id"].blank? | |||
| # find_user_by_login author_json['name'] | |||
| find_user_by_gitea_uid author_json['id'] | |||
| return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?) | |||
| if author_json["id"].present? | |||
| return find_user_by_gitea_uid author_json['id'] | |||
| end | |||
| if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?) | |||
| return find_user_by_login_and_mail(author_json['name'], author_json["email"]) | |||
| end | |||
| end | |||
| def readme_render_decode64_content(str, path) | |||
| @@ -79,12 +83,15 @@ module RepositoriesHelper | |||
| def decode64_content(entry, owner, repo, ref, path=nil) | |||
| if is_readme?(entry['type'], entry['name']) | |||
| content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content'] | |||
| content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] | |||
| readme_render_decode64_content(content, path) | |||
| else | |||
| file_type = File.extname(entry['name'].to_s)[1..-1] | |||
| if image_type?(file_type) | |||
| return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content'] | |||
| end | |||
| if download_type(file_type) | |||
| return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content'] : entry['content'] | |||
| return entry['content'] | |||
| end | |||
| render_decode64_content(entry['content']) | |||
| end | |||
| @@ -18,12 +18,30 @@ class BroadcastMirrorRepoMsgJob < ApplicationJob | |||
| id: project.id, | |||
| type: project.numerical_for_project_type | |||
| } | |||
| # 新增失败重试机制, 重试三次 | |||
| result = broadcast(project, json_data) | |||
| if result == 0 | |||
| count = 3 | |||
| while count > 0 | |||
| sleep 3.seconds | |||
| result = broadcast(project, json_data) | |||
| if result > 0 | |||
| break | |||
| end | |||
| count -= 1 | |||
| end | |||
| end | |||
| end | |||
| def broadcast(project, json_data) | |||
| puts "############ broadcast start.......... " | |||
| puts "############ broadcast channel_name: channel_room_#{project.id}" | |||
| puts "############ broadcast project data: #{json_data} " | |||
| cable_result = ActionCable.server.broadcast "channel_room_#{project.id}", project: json_data | |||
| puts "############ broadcast result: #{cable_result == 1 ? 'successed' : 'failed'} " | |||
| puts "############ broadcast result: #{cable_result > 0 ? 'successed' : 'failed'} " | |||
| return cable_result | |||
| end | |||
| end | |||
| @@ -0,0 +1,11 @@ | |||
| class DelayExpiredIssueJob < ApplicationJob | |||
| queue_as :message | |||
| def perform | |||
| Issue.where(due_date: Date.today + 1.days).find_each do |issue| | |||
| SendTemplateMessageJob.perform_later('IssueAssignerExpire', issue.id) | |||
| SendTemplateMessageJob.perform_later('IssueCreatorExpire', issue.id) | |||
| end | |||
| end | |||
| end | |||
| @@ -16,5 +16,6 @@ class MigrateRemoteRepositoryJob < ApplicationJob | |||
| else | |||
| repo&.mirror&.failed! | |||
| end | |||
| BroadcastMirrorRepoMsgJob.perform_later(repo.id) unless repo&.mirror.waiting? | |||
| end | |||
| end | |||
| @@ -0,0 +1,259 @@ | |||
| class SendTemplateMessageJob < ApplicationJob | |||
| queue_as :message | |||
| def perform(source, *args) | |||
| Rails.logger.info "SendTemplateMessageJob [args] #{args}" | |||
| case source | |||
| when 'FollowTip' | |||
| watcher_id = args[0] | |||
| watcher = Watcher.find_by_id(watcher_id) | |||
| return unless watcher.present? | |||
| receivers = User.where(id: watcher.watchable_id) | |||
| followeder = User.find_by_id(watcher.user_id) | |||
| receivers_string, content, notification_url = MessageTemplate::FollowedTip.get_message_content(receivers, followeder) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {watcher_id: watcher.id}) | |||
| when 'IssueAssigned' | |||
| operator_id, issue_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless operator.present? && issue.present? | |||
| receivers = User.where(id: issue&.assigned_to_id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueAssigned.get_message_content(receivers, operator, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::IssueAssigned.get_email_message_content(receiver, operator, issue) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'IssueAssignerExpire' | |||
| issue_id = args[0] | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless issue.present? | |||
| receivers = User.where(id: issue&.assigned_to_id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueAssignerExpire.get_message_content(receivers, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id}) | |||
| when 'IssueAtme' | |||
| receivers, operator_id, issue_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless operator.present? && issue.present? | |||
| receivers = receivers.where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueAtme.get_message_content(receivers, operator, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}, 2) | |||
| when 'IssueChanged' | |||
| operator_id, issue_id, change_params = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless operator.present? && issue.present? | |||
| receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueChanged.get_message_content(receivers, operator, issue, change_params) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id, change_params: change_params.symbolize_keys}) | |||
| when 'IssueCreatorExpire' | |||
| issue_id = args[0] | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless issue.present? | |||
| receivers = User.where(id: issue&.author_id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueCreatorExpire.get_message_content(receivers, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id}) | |||
| when 'IssueDeleted' | |||
| operator_id, issue_title, issue_assigned_to_id, issue_author_id = args[0], args[1], args[2], args[3] | |||
| operator = User.find_by_id(operator_id) | |||
| return unless operator.present? | |||
| receivers = User.where(id: [issue_assigned_to_id, issue_author_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueDeleted.get_message_content(receivers, operator, issue_title) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_title: issue_title}) | |||
| when 'OrganizationJoined' | |||
| user_id, organization_id = args[0], args[1] | |||
| user = User.find_by_id(user_id) | |||
| organization = Organization.find_by_id(organization_id) | |||
| return unless user.present? && organization.present? | |||
| receivers = User.where(id: user.id) | |||
| receivers_string, content, notification_url = MessageTemplate::OrganizationJoined.get_message_content(receivers, organization) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::OrganizationJoined.get_email_message_content(receiver, organization) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'OrganizationLeft' | |||
| user_id, organization_id = args[0], args[1] | |||
| user = User.find_by_id(user_id) | |||
| organization = Organization.find_by_id(organization_id) | |||
| return unless user.present? && organization.present? | |||
| receivers = User.where(id: user.id) | |||
| receivers_string, content, notification_url = MessageTemplate::OrganizationLeft.get_message_content(receivers, organization) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::OrganizationLeft.get_email_message_content(receiver, organization) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'OrganizationRole' | |||
| user_id, organization_id, role = args[0], args[1], args[2] | |||
| user = User.find_by_id(user_id) | |||
| organization = Organization.find_by_id(organization_id) | |||
| return unless user.present? && organization.present? | |||
| receivers = User.where(id: user.id) | |||
| receivers_string, content, notification_url = MessageTemplate::OrganizationRole.get_message_content(receivers, organization, role) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, role: role}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::OrganizationRole.get_email_message_content(receiver, organization, role) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectIssue' | |||
| operator_id, issue_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless operator.present? && issue.present? && issue&.project.present? | |||
| managers = issue&.project&.all_managers.where.not(id: operator&.id) | |||
| followers = User.none # TODO | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectIssue.get_message_content(managers, followers, operator, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}) | |||
| managers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectIssue.get_email_message_content(receiver, true, operator, issue) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| followers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectIssue.get_email_message_content(receiver, false, operator, issue) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectJoined' | |||
| operator_id, user_id, project_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = User.where(id: user.id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectJoined.get_message_content(receivers, project) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectJoined.get_email_message_content(receiver, project) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectLeft' | |||
| operator_id, user_id, project_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = User.where(id: user.id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectLeft.get_message_content(receivers, project) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectLeft.get_email_message_content(receiver, project) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectMemberJoined' | |||
| operator_id, user_id, project_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = project&.all_managers.where.not(id: [operator&.id, user&.id]) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectMemberJoined.get_message_content(receivers, user, project) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberJoined.get_email_message_content(receiver, user, project) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectMemberLeft' | |||
| operator_id, user_id, project_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = project&.all_managers.where.not(id: [operator&.id, user&.id]) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectMemberLeft.get_message_content(receivers, user, project) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberLeft.get_email_message_content(receiver, user, project) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectPullRequest' | |||
| operator_id, pull_request_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| return unless operator.present? && pull_request.present? && pull_request&.project.present? | |||
| managers = pull_request&.project&.all_managers.where.not(id: operator&.id) | |||
| followers = User.none # TODO | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectPullRequest.get_message_content(managers, followers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}) | |||
| managers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectPullRequest.get_email_message_content(receiver, true, operator, pull_request) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| followers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectPullRequest.get_email_message_content(receiver, false, operator, pull_request) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectRole' | |||
| operator_id, user_id, project_id, role = args[0], args[1], args[2], args[3] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = User.where(id: user.id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectRole.get_message_content(receivers, project, role) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id, role: role}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectRole.get_email_message_content(receivers, project, role) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectSettingChanged' | |||
| operator_id, project_id, change_params = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && project.present? | |||
| receivers = project.all_managers.where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectSettingChanged.get_message_content(receivers, operator, project, change_params.symbolize_keys) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id, change_params: change_params}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectSettingChanged.get_email_message_content(receiver, operator, project, change_params.symbolize_keys) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'PullRequestAssigned' | |||
| operator_id, pull_request_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| issue = Issue.find_by_id(pull_request&.issue_id) | |||
| return unless operator.present? && pull_request.present? && issue.present? | |||
| receivers = User.where(id: issue&.assigned_to_id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestAssigned.get_message_content(receivers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::PullRequestAssigned.get_email_message_content(receiver, operator, pull_request) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'PullRequestAtme' | |||
| receivers, operator_id, pull_request_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| return unless operator.present? && pull_request.present? | |||
| receivers = receivers.where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestAtme.get_message_content(receivers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}, 2) | |||
| when 'PullRequestChanged' | |||
| operator_id, pull_request_id, change_params = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| issue = Issue.find_by_id(pull_request&.issue_id) | |||
| return unless operator.present? && pull_request.present? && issue.present? | |||
| receivers = User.where(id: [issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestChanged.get_message_content(receivers, operator, pull_request, change_params.symbolize_keys) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id, change_params: change_params}) | |||
| when 'PullRequestClosed' | |||
| operator_id, pull_request_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| return unless operator.present? && pull_request.present? | |||
| receivers = User.where(id: [pull_request&.issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestClosed.get_message_content(receivers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}) | |||
| when 'PullRequestMerged' | |||
| operator_id, pull_request_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| return unless operator.present? && pull_request.present? | |||
| receivers = User.where(id: [pull_request&.issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestMerged.get_message_content(receivers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}) | |||
| end | |||
| end | |||
| end | |||
| @@ -26,6 +26,7 @@ class SyncMirroredRepositoryJob < ApplicationJob | |||
| result = Gitea::Repository::SyncMirroredService.call(repo.owner.login, | |||
| repo.identifier, token: user.gitea_token) | |||
| repo&.mirror.set_status! if result[:status] === 200 | |||
| BroadcastMirrorRepoMsgJob.perform_later(repo.id) unless repo&.mirror.waiting? | |||
| end | |||
| end | |||
| @@ -0,0 +1,21 @@ | |||
| module Notice | |||
| class << self | |||
| def notice_config | |||
| notice_config = {} | |||
| begin | |||
| config = Rails.application.config_for(:configuration).symbolize_keys! | |||
| notice_config = config[:notice].symbolize_keys! | |||
| raise 'notice config missing' if notice_config.blank? | |||
| rescue => exception | |||
| raise ex if Rails.env.production? | |||
| puts %Q{\033[33m [warning] gitea config or configuration.yml missing, | |||
| please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m} | |||
| notice_config = {} | |||
| end | |||
| notice_config | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,99 @@ | |||
| # == 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 < ApplicationRecord | |||
| def self.build_init_data | |||
| self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}') | |||
| email_html = File.read("#{email_template_html_dir}/issue_assigned.html") | |||
| self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 指派给你一个易修') | |||
| self.create(type: 'MessageTemplate::IssueAssignerExpire', sys_notice: '您负责的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::IssueAtme', sys_notice: '<b>{nickname}</b> 在易修 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的易修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::IssueCreatorExpire', sys_notice: '您发布的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将易修 <b>{title}</b> 删除', notification_url: '') | |||
| self.create(type: 'MessageTemplate::IssueJournal', sys_notice: '{nickname}评论易修{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::LoginIpTip', sys_notice: '您的账号{nickname}于{login_time)在非常用的IP地址{ip}登录,如非本人操作,请立即修改密码', notification_url: '') | |||
| email_html = File.read("#{email_template_html_dir}/organization_joined.html") | |||
| self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: '你已加入 {organization} 组织') | |||
| email_html = File.read("#{email_template_html_dir}/organization_left.html") | |||
| self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: '你已被移出 {organization} 组织') | |||
| self.create(type: 'MessageTemplate::OrganizationRole', sys_notice: '组织 <b>{organization}</b> 已把你的角色改为 <b>{role}</b>', notification_url: '{baseurl}/{login}') | |||
| self.create(type: 'MessageTemplate::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '') | |||
| self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '<b>{nickname}</b> 关注了你管理的仓库', notification_url: '{baseurl}/{login}') | |||
| self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库{nickname1}/{repository1}到{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}') | |||
| email_html = File.read("#{email_template_html_dir}/project_issue.html") | |||
| self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 新建了一个易修') | |||
| email_html = File.read("#{email_template_html_dir}/project_joined.html") | |||
| self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '你已加入 {repository} 项目') | |||
| email_html = File.read("#{email_template_html_dir}/project_left.html") | |||
| self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: '你已被移出 {repository} 项目') | |||
| email_html = File.read("#{email_template_html_dir}/project_member_joined.html") | |||
| self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '{nickname1} 已加入项目 {nickname2}/{repository}') | |||
| email_html = File.read("#{email_template_html_dir}/project_member_left.html") | |||
| self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '{nickname1} 已被移出项目 {nickname2}/{repository}') | |||
| self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}') | |||
| self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname}</b> 点赞了你管理的仓库', notification_url: '{baseurl}/{login}') | |||
| email_html = File.read("#{email_template_html_dir}/project_pull_request.html") | |||
| self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 提交了一个合并请求') | |||
| self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{repository}</b> 已把你的角色改为 <b>{role}</b>', notification_url: '{baseurl}/{owner}/{identifier}') | |||
| email_html = File.read("#{email_template_html_dir}/project_setting_changed.html") | |||
| self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: '您管理的仓库 {nickname2}/{repository} 仓库设置已被更改') | |||
| self.create(type: 'MessageTemplate::ProjectTransfer', sys_notice: '你关注的仓库{nickname1}/{repository1}已被转移至{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}') | |||
| self.create(type: 'MessageTemplate::ProjectVersion', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了发行版:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/releases') | |||
| email_html = File.read("#{email_template_html_dir}/pull_request_assigned.html") | |||
| self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求') | |||
| self.create(type: 'MessageTemplate::PullRequestAtme', sys_notice: '<b>{nickname}</b> 在合并请求 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount') | |||
| self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount') | |||
| self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', notification_url: '') | |||
| self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount') | |||
| self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount') | |||
| end | |||
| def self.sys_notice | |||
| self.last&.sys_notice | |||
| end | |||
| def self.email | |||
| self.last&.email | |||
| end | |||
| def self.email_title | |||
| self.last&.email_title | |||
| end | |||
| def self.notification_url | |||
| self.last&.notification_url.gsub('{baseurl}', base_url) | |||
| end | |||
| def self.base_url | |||
| Rails.application.config_for(:configuration)['platform_url'] | |||
| end | |||
| def self.receivers_string(receivers) | |||
| receivers.pluck(:id).join(",") | |||
| end | |||
| def self.receivers_email_string(receivers) | |||
| receivers.pluck(:mail).join(",") | |||
| end | |||
| def self.email_template_html_dir | |||
| "#{Rails.root}/public/message_template" | |||
| end | |||
| def simple_type | |||
| self.type.split("::")[-1] | |||
| end | |||
| end | |||
| @@ -0,0 +1,24 @@ | |||
| # == 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::FollowedTip < MessageTemplate | |||
| # MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last) | |||
| def self.get_message_content(receivers, followeder) | |||
| return receivers_string(receivers), sys_notice.gsub('{nickname}', followeder&.real_name), notification_url.gsub('{login}', followeder.login) | |||
| rescue | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,54 @@ | |||
| # == 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::IssueAssigned < MessageTemplate | |||
| # MessageTemplate::IssueAssigned.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last) | |||
| def self.get_message_content(receivers, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssigned.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname1}', operator&.real_name) | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{title}', issue&.subject) | |||
| content.gsub!('{id}', issue&.id.to_s) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssigned.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == 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::IssueAssignerExpire < MessageTemplate | |||
| # MessageTemplate::IssueAssignerExpire.get_message_content(User.where(login: 'yystopf'), Issue.last) | |||
| def self.get_message_content(receivers, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == 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::IssueAtme < MessageTemplate | |||
| # MessageTemplate::IssueAtme.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last) | |||
| def self.get_message_content(receivers, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAtme.get_message_content [ERROR] #{e}") | |||
| return 0, '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,183 @@ | |||
| # == 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::IssueChanged < MessageTemplate | |||
| # MessageTemplate::IssueChanged.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last, {status_id: [1, 2], assigned_to_id: [nil, 203], tracker_id: [4, 3], priority_id: [2, 4], fixed_version_id: [nil, 5], due_date: ['', '2021-09-11'], done_ratio: [0, 40], issue_tags_value: ["", "7"], branch_name: ["", "master"]}) | |||
| def self.get_message_content(receivers, operator, issue, change_params) | |||
| return '', '', '' if change_params.blank? | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = MessageTemplate::IssueChanged.sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| change_count = change_params.keys.size | |||
| # 易修负责人修改 | |||
| if change_params[:assigned_to_id].present? | |||
| assigner1 = User.find_by_id(change_params[:assigned_to_id][0]) | |||
| assigner2 = User.find_by_id(change_params[:assigned_to_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifassigner}', '<br/>') | |||
| else | |||
| content.sub!('{ifassigner}', '') | |||
| end | |||
| content.sub!('{endassigner}', '') | |||
| content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员') | |||
| content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员') | |||
| else | |||
| content.gsub!(/({ifassigner})(.*)({endassigner})/, '') | |||
| end | |||
| # 易修状态修改 | |||
| if change_params[:status_id].present? | |||
| status1 = IssueStatus.find_by_id(change_params[:status_id][0]) | |||
| status2 = IssueStatus.find_by_id(change_params[:status_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifstatus}', '<br/>') | |||
| else | |||
| content.sub!('{ifstatus}', '') | |||
| end | |||
| content.sub!('{endstatus}', '') | |||
| content.gsub!('{status1}', status1&.name) | |||
| content.gsub!('{status2}', status2&.name) | |||
| else | |||
| content.gsub!(/({ifstatus})(.*)({endstatus})/, '') | |||
| end | |||
| # 易修类型修改 | |||
| if change_params[:tracker_id].present? | |||
| tracker1 = Tracker.find_by_id(change_params[:tracker_id][0]) | |||
| tracker2 = Tracker.find_by_id(change_params[:tracker_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{iftracker}', '<br/>') | |||
| else | |||
| content.sub!('{iftracker}', '') | |||
| end | |||
| content.sub!('{endtracker}', '') | |||
| content.gsub!('{tracker1}', tracker1&.name) | |||
| content.gsub!('{tracker2}', tracker2&.name) | |||
| else | |||
| content.gsub!(/({iftracker})(.*)({endtracker})/, '') | |||
| end | |||
| # 易修里程碑修改 | |||
| if change_params[:fixed_version_id].present? | |||
| fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0]) | |||
| fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifmilestone}', '<br/>') | |||
| else | |||
| content.sub!('{ifmilestone}', '') | |||
| end | |||
| content.sub!('{endmilestone}', '') | |||
| content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑') | |||
| content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑') | |||
| else | |||
| content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '') | |||
| end | |||
| # 易修标记修改 | |||
| if change_params[:issue_tags_value].present? | |||
| issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct | |||
| issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct | |||
| tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",") | |||
| tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",") | |||
| if change_count > 1 | |||
| content.sub!('{iftag}', '<br/>') | |||
| else | |||
| content.sub!('{iftag}', '') | |||
| end | |||
| content.sub!('{endtag}', '') | |||
| content.gsub!('{tag1}', tag1) | |||
| content.gsub!('{tag2}', tag2) | |||
| else | |||
| content.gsub!(/({iftag})(.*)({endtag})()/, '') | |||
| end | |||
| # 易修优先级修改 | |||
| if change_params[:priority_id].present? | |||
| priority1 = IssuePriority.find_by_id(change_params[:priority_id][0]) | |||
| priority2 = IssuePriority.find_by_id(change_params[:priority_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifpriority}', '<br/>') | |||
| else | |||
| content.sub!('{ifpriority}', '') | |||
| end | |||
| content.sub!('{endpriority}', '') | |||
| content.gsub!('{priority1}', priority1&.name) | |||
| content.gsub!('{priority2}', priority2&.name) | |||
| else | |||
| content.gsub!(/({ifpriority})(.*)({endpriority})/, '') | |||
| end | |||
| # 易修完成度修改 | |||
| if change_params[:done_ratio].present? | |||
| doneratio1 = change_params[:done_ratio][0] | |||
| doneratio2 = change_params[:done_ratio][1] | |||
| if change_count > 1 | |||
| content.sub!('{ifdoneratio}', '<br/>') | |||
| else | |||
| content.sub!('{ifdoneratio}', '') | |||
| end | |||
| content.sub!('{enddoneratio}', '') | |||
| content.gsub!('{doneratio1}', "#{doneratio1}%") | |||
| content.gsub!('{doneratio2}', "#{doneratio2}%") | |||
| else | |||
| content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '') | |||
| end | |||
| # 易修指定分支修改 | |||
| if change_params[:branch_name].present? | |||
| branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0] | |||
| branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1] | |||
| if change_count > 1 | |||
| content.sub!('{ifbranch}', '<br/>') | |||
| else | |||
| content.sub!('{ifbranch}', '') | |||
| end | |||
| content.sub!('{endbranch}', '') | |||
| content.gsub!('{branch1}', branch1) | |||
| content.gsub!('{branch2}', branch2) | |||
| else | |||
| content.gsub!(/({ifbranch})(.*)({endbranch})/, '') | |||
| end | |||
| # 易修开始日期修改 | |||
| if change_params[:start_date].present? | |||
| startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0] | |||
| startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1] | |||
| if change_count > 1 | |||
| content.sub!('{ifstartdate}', '<br/>') | |||
| else | |||
| content.sub!('{ifstartdate}', '') | |||
| end | |||
| content.sub!('{endstartdate}', '') | |||
| content.gsub!('{startdate1}', startdate1 ) | |||
| content.gsub!('{startdate2}', startdate2) | |||
| else | |||
| content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '') | |||
| end | |||
| # 易修结束日期修改 | |||
| if change_params[:due_date].present? | |||
| duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0] | |||
| duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1] | |||
| if change_count > 1 | |||
| content.sub!('{ifduedate}', '<br/>') | |||
| else | |||
| content.sub!('{ifduedate}', '') | |||
| end | |||
| content.sub!('{endduedate}', '') | |||
| content.gsub!('{duedate1}', duedate1) | |||
| content.gsub!('{duedate2}', duedate2) | |||
| else | |||
| content.gsub!(/({ifduedate})(.*)({endduedate})/, '') | |||
| end | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssigned.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == 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::IssueCreatorExpire < MessageTemplate | |||
| # MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last) | |||
| def self.get_message_content(receivers, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,26 @@ | |||
| # == 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::IssueDeleted < MessageTemplate | |||
| # MessageTemplate::IssueDeleted.get_message_content(User.where(login: 'yystopf'), User.last, "hahah") | |||
| def self.get_message_content(receivers, operator, issue_title) | |||
| content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', issue_title) | |||
| return receivers_string(receivers), content, notification_url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAtme.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我创建或负责的易修有新的评论 | |||
| class MessageTemplate::IssueJournal < MessageTemplate | |||
| # MessageTemplate::IssueJournal.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueJournal.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 登录异常提示 | |||
| class MessageTemplate::LoginIpTip < MessageTemplate | |||
| # MessageTemplate::LoginIpTip.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::LoginIpTip.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,42 @@ | |||
| # == 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::OrganizationJoined < MessageTemplate | |||
| # MessageTemplate::OrganizationJoined.get_message_content(User.where(login: 'yystopf'), Organization.last) | |||
| def self.get_message_content(receivers, organization) | |||
| content = sys_notice.gsub('{organization}', organization&.real_name) | |||
| url = notification_url.gsub('{login}', organization&.name) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationJoined.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, organization) | |||
| title = email_title | |||
| title.gsub!('{organization}', organization&.real_name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', organization&.login) | |||
| content.gsub!('{organization}', organization&.real_name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationJoined.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,42 @@ | |||
| # == 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::OrganizationLeft < MessageTemplate | |||
| # MessageTemplate::OrganizationLeft.get_message_content(User.where(login: 'yystopf'), Organization.last) | |||
| def self.get_message_content(receivers, organization) | |||
| content = sys_notice.gsub('{organization}', organization&.real_name) | |||
| url = notification_url.gsub('{login}', organization&.name) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationLeft.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, organization) | |||
| title = email_title | |||
| title.gsub!('{organization}', organization&.real_name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', organization&.login) | |||
| content.gsub!('{organization}', organization&.real_name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationLeft.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,44 @@ | |||
| # == 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::OrganizationRole < MessageTemplate | |||
| # MessageTemplate::OrganizationRole.get_message_content(User.where(login: 'yystopf'), Organization.last, '管理员') | |||
| def self.get_message_content(receivers, organization, role) | |||
| content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{role}', role) | |||
| url = notification_url.gsub('{login}', organization&.login) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationRole.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, organization, role) | |||
| title = email_title | |||
| title.gsub!('{organization}', organization&.real_name) | |||
| title.gsub!('{role}', role) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', organization&.login) | |||
| content.gsub!('{organization}', organization&.real_name) | |||
| content.gsub!('{role}', role) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationRole.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我关注的仓库被删除 | |||
| class MessageTemplate::ProjectDeleted < MessageTemplate | |||
| # MessageTemplate::ProjectDeleted.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectDeleted.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我管理的仓库被关注 | |||
| class MessageTemplate::ProjectFollowed < MessageTemplate | |||
| # MessageTemplate::ProjectFollowed.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectFollowed.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我管理的仓库被复刻 | |||
| class MessageTemplate::ProjectForked < MessageTemplate | |||
| # MessageTemplate::ProjectForked.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectForked.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,57 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我管理/关注的仓库有新的易修 | |||
| class MessageTemplate::ProjectIssue < MessageTemplate | |||
| # MessageTemplate::ProjectIssue.get_message_content(User.where(login: 'yystopf'), User.where(login: 'forgetest1'), User.last, Issue.last) | |||
| def self.get_message_content(managers, followers, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| receivers = managers + followers | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectIssue.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, is_manager, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname1}', operator&.real_name) | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{id}', issue&.id.to_s) | |||
| content.gsub!('{title}', issue&.subject) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectIssue.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,45 @@ | |||
| # == 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::ProjectJoined < MessageTemplate | |||
| # MessageTemplate::ProjectJoined.get_message_content(User.where(login: 'yystopf'), Project.last) | |||
| def self.get_message_content(receivers, project) | |||
| content = sys_notice.gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectJoined.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, project) | |||
| title = email_title | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{nickname}', project&.owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectJoined.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,45 @@ | |||
| # == 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::ProjectLeft < MessageTemplate | |||
| # MessageTemplate::ProjectLeft.get_message_content(User.where(login: 'yystopf'), Project.last) | |||
| def self.get_message_content(receivers, project) | |||
| content = sys_notice.gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectLeft.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, project) | |||
| title = email_title | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{nickname}', project&.owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectLeft.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,49 @@ | |||
| # == 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::ProjectMemberJoined < MessageTemplate | |||
| # MessageTemplate::ProjectMemberJoined.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers, user, project) | |||
| content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMemberJoined.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, user, project) | |||
| title = email_title | |||
| title.gsub!('{nickname1}', user&.real_name) | |||
| title.gsub!('{nickname2}', project&.owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', user&.login) | |||
| content.gsub!('{login2}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{nickname1}', user&.real_name) | |||
| content.gsub!('{nickname2}', project&.owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMemberJoined.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,49 @@ | |||
| # == 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::ProjectMemberLeft < MessageTemplate | |||
| # MessageTemplate::ProjectMemberLeft.get_message_content(User.where(login: 'yystopf'), User.last, Project.last) | |||
| def self.get_message_content(receivers, user, project) | |||
| content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMemberLeft.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, user, project) | |||
| title = email_title | |||
| title.gsub!('{nickname1}', user&.real_name) | |||
| title.gsub!('{nickname2}', project&.owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', user&.login) | |||
| content.gsub!('{login2}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{nickname1}', user&.real_name) | |||
| content.gsub!('{nickname2}', project&.owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMemberLeft.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我管理的仓库有新的里程碑 | |||
| class MessageTemplate::ProjectMilestone < MessageTemplate | |||
| # MessageTemplate::ProjectMilestone.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMilestone.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我管理的仓库被点赞 | |||
| class MessageTemplate::ProjectPraised < MessageTemplate | |||
| # MessageTemplate::ProjectPraised.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectPraised.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,57 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我管理/关注的仓库有新的合并请求 | |||
| class MessageTemplate::ProjectPullRequest < MessageTemplate | |||
| # MessageTemplate::ProjectPullRequest.get_message_content(User.where(login: 'yystopf'), User.where(login: 'testforge2'), User.last, PullRequest.last) | |||
| def self.get_message_content(managers, followers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| receivers = managers + followers | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectPullRequest.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, is_manager, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname1}', operator&.real_name) | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{id}', pull_request&.id.to_s) | |||
| content.gsub!('{title}', pull_request&.title) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectPullRequest.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,45 @@ | |||
| # == 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::ProjectRole < MessageTemplate | |||
| # MessageTemplate::ProjectRole.get_message_content(User.where(login: 'yystopf'), Project.last, '管理员') | |||
| def self.get_message_content(receivers, project, role) | |||
| content = sys_notice.gsub('{repository}', project&.name).gsub('{role}', role) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectRole.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receivers, project, role) | |||
| title = email_title | |||
| title.gsub!('{repository}', project&.name) | |||
| title.gsub!('{role}', role) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{role}', role) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectRole.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,277 @@ | |||
| # == 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::ProjectSettingChanged < MessageTemplate | |||
| # MessageTemplate::ProjectSettingChanged.get_message_content(User.where(login: 'yystopf'), User.last, Project.last, {description: '测试修改项目简介', category: '大数据', language: 'Ruby', permission: '公有', navbar: '易修, 合并请求'}) | |||
| def self.get_message_content(receivers, operator, project, change_params) | |||
| return '', '', '' if change_params.blank? | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier) | |||
| change_count = change_params.keys.size | |||
| # 项目名称更改 | |||
| if change_params[:name].present? | |||
| if change_count > 1 | |||
| content.sub!('{ifname}', '<br/>') | |||
| else | |||
| content.sub!('{ifname}', '') | |||
| end | |||
| content.sub!('{endname}', '') | |||
| content.gsub!('{name}', change_params[:name][1]) | |||
| else | |||
| content.gsub!(/({ifname})(.*)({endname})/, '') | |||
| end | |||
| # 项目简介更改 | |||
| if change_params[:description].present? | |||
| if change_params[:description][1].blank? | |||
| if change_count > 1 | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '<br/>删除了项目简介') | |||
| else | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '删除了项目简介') | |||
| end | |||
| else | |||
| if change_count > 1 | |||
| content.sub!('{ifdescription}', '<br/>') | |||
| else | |||
| content.sub!('{ifdescription}', '') | |||
| end | |||
| content.sub!('{enddescription}', '') | |||
| content.gsub!('{description}', change_params[:description][1]) | |||
| end | |||
| else | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '') | |||
| end | |||
| # 项目类别更改 | |||
| if change_params[:project_category_id].present? | |||
| category = ProjectCategory.find_by_id(change_params[:project_category_id][1]) | |||
| if category.present? | |||
| if change_count > 1 | |||
| content.sub!('{ifcategory}', '<br/>') | |||
| else | |||
| content.sub!('{ifcategory}', '') | |||
| end | |||
| content.sub!('{endcategory}', '') | |||
| content.gsub!('{category}', category&.name) | |||
| else | |||
| if change_count > 1 | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '<br/>删除了项目类别') | |||
| else | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '删除了项目类别') | |||
| end | |||
| end | |||
| else | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '') | |||
| end | |||
| # 项目语言更改 | |||
| if change_params[:project_language_id].present? | |||
| language = ProjectLanguage.find_by_id(change_params[:project_language_id][1]) | |||
| if language.present? | |||
| if change_count > 1 | |||
| content.sub!('{iflanguage}', '<br/>') | |||
| else | |||
| content.sub!('{iflanguage}', '') | |||
| end | |||
| content.sub!('{endlanguage}', '') | |||
| content.gsub!('{language}', language&.name) | |||
| else | |||
| if change_count > 1 | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '<br/>删除了项目语言') | |||
| else | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '删除了项目语言') | |||
| end | |||
| end | |||
| else | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '') | |||
| end | |||
| # 项目公私有更改 | |||
| if change_params[:is_public].present? | |||
| permission = change_params[:is_public][1] ? '公有' : '私有' | |||
| if change_count > 1 | |||
| content.sub!('{ifpermission}', '<br/>') | |||
| else | |||
| content.sub!('{ifpermission}', '') | |||
| end | |||
| content.sub!('{endpermission}', '') | |||
| content.gsub!('{permission}', permission) | |||
| else | |||
| content.gsub!(/({ifpermission})(.*)({endpermission})/, '') | |||
| end | |||
| # 项目导航更改 | |||
| if change_params[:navbar].present? | |||
| unit_types = project.project_units.order(unit_type: :asc).pluck(:unit_type) | |||
| unit_types.delete('code') | |||
| unit_types.unshift('代码库') | |||
| unit_types.unshift('主页') | |||
| unit_types.append('动态') | |||
| navbar = unit_types.join(',') | |||
| navbar.gsub!('issues', '易修') | |||
| navbar.gsub!('pulls', '合并请求') | |||
| navbar.gsub!('wiki', 'Wiki') | |||
| navbar.gsub!('devops', '工作流') | |||
| navbar.gsub!('versions', '里程碑') | |||
| navbar.gsub!('resources', '资源库') | |||
| if change_count > 1 | |||
| content.sub!('{ifnavbar}', '<br/>') | |||
| else | |||
| content.sub!('{ifnavbar}', '') | |||
| end | |||
| content.sub!('{endnavbar}', '') | |||
| content.gsub!('{navbar}', navbar) | |||
| else | |||
| content.gsub!(/({ifnavbar})(.*)({endnavbar})/, '') | |||
| end | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectSettingChanged.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, operator, project, change_params) | |||
| return '', '', '' if change_params.blank? | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{repository}', project&.name) | |||
| change_count = change_params.keys.size | |||
| # 项目名称更改 | |||
| if change_params[:name].present? | |||
| if change_count > 1 | |||
| content.sub!('{ifname}', '<br/>') | |||
| else | |||
| content.sub!('{ifname}', '') | |||
| end | |||
| content.sub!('{endname}', '') | |||
| content.gsub!('{name}', change_params[:name][1]) | |||
| else | |||
| content.gsub!(/({ifname})(.*)({endname})/, '') | |||
| end | |||
| # 项目简介更改 | |||
| if change_params[:description].present? | |||
| if change_params[:description][1].blank? | |||
| if change_count > 1 | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '<br/>删除了项目简介') | |||
| else | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '删除了项目简介') | |||
| end | |||
| else | |||
| if change_count > 1 | |||
| content.sub!('{ifdescription}', '<br/>') | |||
| else | |||
| content.sub!('{ifdescription}', '') | |||
| end | |||
| content.sub!('{enddescription}', '') | |||
| content.gsub!('{description}', change_params[:description][1]) | |||
| end | |||
| else | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '') | |||
| end | |||
| # 项目类别更改 | |||
| if change_params[:project_category_id].present? | |||
| category = ProjectCategory.find_by_id(change_params[:project_category_id][1]) | |||
| if category.present? | |||
| if change_count > 1 | |||
| content.sub!('{ifcategory}', '<br/>') | |||
| else | |||
| content.sub!('{ifcategory}', '') | |||
| end | |||
| content.sub!('{endcategory}', '') | |||
| content.gsub!('{category}', category&.name) | |||
| else | |||
| if change_count > 1 | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '<br/>删除了项目类别') | |||
| else | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '删除了项目类别') | |||
| end | |||
| end | |||
| else | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '') | |||
| end | |||
| # 项目语言更改 | |||
| if change_params[:project_language_id].present? | |||
| language = ProjectLanguage.find_by_id(change_params[:project_language_id][1]) | |||
| if language.present? | |||
| if change_count > 1 | |||
| content.sub!('{iflanguage}', '<br/>') | |||
| else | |||
| content.sub!('{iflanguage}', '') | |||
| end | |||
| content.sub!('{endlanguage}', '') | |||
| content.gsub!('{language}', language&.name) | |||
| else | |||
| if change_count > 1 | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '<br/>删除了项目语言') | |||
| else | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '删除了项目语言') | |||
| end | |||
| end | |||
| else | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '') | |||
| end | |||
| # 项目公私有更改 | |||
| if change_params[:is_public].present? | |||
| permission = change_params[:is_public][1] ? '公有' : '私有' | |||
| if change_count > 1 | |||
| content.sub!('{ifpermission}', '<br/>') | |||
| else | |||
| content.sub!('{ifpermission}', '') | |||
| end | |||
| content.sub!('{endpermission}', '') | |||
| content.gsub!('{permission}', permission) | |||
| else | |||
| content.gsub!(/({ifpermission})(.*)({endpermission})/, '') | |||
| end | |||
| # 项目导航更改 | |||
| if change_params[:navbar].present? | |||
| unit_types = project.project_units.order(unit_type: :asc).pluck(:unit_type) | |||
| unit_types.delete('code') | |||
| unit_types.unshift('代码库') | |||
| unit_types.unshift('主页') | |||
| unit_types.append('动态') | |||
| navbar = unit_types.join(',') | |||
| navbar.gsub!('issues', '易修') | |||
| navbar.gsub!('pulls', '合并请求') | |||
| navbar.gsub!('wiki', 'Wiki') | |||
| navbar.gsub!('devops', '工作流') | |||
| navbar.gsub!('versions', '里程碑') | |||
| navbar.gsub!('resources', '资源库') | |||
| if change_count > 1 | |||
| content.sub!('{ifnavbar}', '<br/>') | |||
| else | |||
| content.sub!('{ifnavbar}', '') | |||
| end | |||
| content.sub!('{endnavbar}', '') | |||
| content.gsub!('{navbar}', navbar) | |||
| else | |||
| content.gsub!(/({ifnavbar})(.*)({endnavbar})/, '') | |||
| end | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectSettingChanged.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我关注的仓库被转移 | |||
| class MessageTemplate::ProjectTransfer < MessageTemplate | |||
| # MessageTemplate::ProjectTransfer.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectTransfer.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我关注的仓库有新的发行版 | |||
| class MessageTemplate::ProjectVersion < MessageTemplate | |||
| # MessageTemplate::ProjectVersion.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectVersion.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,54 @@ | |||
| # == 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::PullRequestAssigned < MessageTemplate | |||
| # MessageTemplate::PullRequestAssigned.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last) | |||
| def self.get_message_content(receivers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestAssigned.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname1}', operator&.real_name) | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{title}', pull_request&.title) | |||
| content.gsub!('{id}', pull_request&.id.to_s) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestAssigned.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == 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::PullRequestAtme < MessageTemplate | |||
| # MessageTemplate::PullRequestAtme.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last) | |||
| def self.get_message_content(receivers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestAtme.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,95 @@ | |||
| # == 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::PullRequestChanged < MessageTemplate | |||
| # MessageTemplate::PullRequestChanged.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last, {assigned_to_id: [nil, 203], priority_id: [2, 4], fixed_version_id: [nil, 5], issue_tags_value: ["", "7"]}) | |||
| def self.get_message_content(receivers, operator, pull_request, change_params) | |||
| return '', '', '' if change_params.blank? | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| issue = pull_request&.issue | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub("{title}", pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| change_count = change_params.keys.size | |||
| # 合并请求审查成员修改 | |||
| if change_params[:assigned_to_id].present? | |||
| assigner1 = User.find_by_id(change_params[:assigned_to_id][0]) | |||
| assigner2 = User.find_by_id(change_params[:assigned_to_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifassigner}', '<br/>') | |||
| else | |||
| content.sub!('{ifassigner}', '') | |||
| end | |||
| content.sub!('{endassigner}', '') | |||
| content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员') | |||
| content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员') | |||
| else | |||
| content.gsub!(/({ifassigner})(.*)({endassigner})/, '') | |||
| end | |||
| # 合并请求里程碑修改 | |||
| if change_params[:fixed_version_id].present? | |||
| fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0]) | |||
| fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifmilestone}', '<br/>') | |||
| else | |||
| content.sub!('{ifmilestone}', '') | |||
| end | |||
| content.sub!('{endmilestone}', '') | |||
| content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑') | |||
| content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑') | |||
| else | |||
| content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '') | |||
| end | |||
| # 合并请求标记修改 | |||
| if change_params[:issue_tags_value].present? | |||
| issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct | |||
| issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct | |||
| tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",") | |||
| tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",") | |||
| if change_count > 1 | |||
| content.sub!('{iftag}', '<br/>') | |||
| else | |||
| content.sub!('{iftag}', '') | |||
| end | |||
| content.sub!('{endtag}', '') | |||
| content.gsub!('{tag1}', tag1) | |||
| content.gsub!('{tag2}', tag2) | |||
| else | |||
| content.gsub!(/({iftag})(.*)({endtag})()/, '') | |||
| end | |||
| # 合并请求优先级修改 | |||
| if change_params[:priority_id].present? | |||
| priority1 = IssuePriority.find_by_id(change_params[:priority_id][0]) | |||
| priority2 = IssuePriority.find_by_id(change_params[:priority_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifpriority}', '<br/>') | |||
| else | |||
| content.sub!('{ifpriority}', '') | |||
| end | |||
| content.sub!('{ifpriority}', '') | |||
| content.sub!('{endpriority}', '') | |||
| content.gsub!('{priority1}', priority1&.name) | |||
| content.gsub!('{priority2}', priority2&.name) | |||
| else | |||
| content.gsub!(/({ifpriority})(.*)({endpriority})/, '') | |||
| end | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestChanged.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == 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::PullRequestClosed < MessageTemplate | |||
| # MessageTemplate::PullRequestClosed.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last) | |||
| def self.get_message_content(receivers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{title}', pull_request&.title) | |||
| url = notification_url | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestClosed.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == 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) | |||
| # | |||
| # TODO 我创建或负责的合并请求有新的评论 | |||
| class MessageTemplate::PullRequestJournal < MessageTemplate | |||
| # MessageTemplate::PullRequestJournal.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestJournal.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == 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::PullRequestMerged < MessageTemplate | |||
| # MessageTemplate::PullRequestMerged.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last) | |||
| def self.get_message_content(receivers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{title}', pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestMerged.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -18,7 +18,7 @@ class Mirror < ApplicationRecord | |||
| # 0: 同步镜像成功;1: 正在同步镜像;2: 同步失败; 默认值为0 | |||
| enum status: { succeeded: 0, waiting: 1, failed: 2 } | |||
| after_update :websocket_boardcast, if: :saved_change_to_status? | |||
| # after_update :websocket_boardcast, if: :saved_change_to_status? | |||
| belongs_to :repository, foreign_key: :repo_id | |||
| @@ -22,6 +22,9 @@ class OrganizationUser < ApplicationRecord | |||
| validates :user_id, uniqueness: {scope: :organization_id} | |||
| after_create :send_create_message_to_notice_system | |||
| after_destroy :send_destroy_message_to_notice_system | |||
| def self.build(organization_id, user_id) | |||
| org_user = self.find_by(organization_id: organization_id, user_id: user_id) | |||
| return org_user unless org_user.nil? | |||
| @@ -31,4 +34,12 @@ class OrganizationUser < ApplicationRecord | |||
| def teams | |||
| organization.teams.joins(:team_users).where(team_users: {user_id: user_id}) | |||
| end | |||
| def send_create_message_to_notice_system | |||
| SendTemplateMessageJob.perform_later('OrganizationJoined', self.user_id, self.organization_id) | |||
| end | |||
| def send_destroy_message_to_notice_system | |||
| SendTemplateMessageJob.perform_later('OrganizationLeft', self.user_id, self.organization_id) | |||
| end | |||
| end | |||
| @@ -32,9 +32,13 @@ class ProjectUnit < ApplicationRecord | |||
| types.delete("pulls") if project.sync_mirror? | |||
| # 默认code类型自动创建 | |||
| types << "code" | |||
| before_units = project.project_units.pluck(:unit_type).sort | |||
| project.project_units.where.not(unit_type: types).each(&:destroy!) | |||
| types.each do |type| | |||
| project.project_units.find_or_create_by!(unit_type: type) | |||
| end | |||
| after_units = project.project_units.pluck(:unit_type).sort | |||
| return before_units, after_units | |||
| end | |||
| end | |||
| @@ -54,4 +54,15 @@ class Team < ApplicationRecord | |||
| team_users.where(user_id: user_id).present? | |||
| end | |||
| def authorize_name | |||
| case self.authorize | |||
| when 'read' then '报告者' | |||
| when 'write' then '开发者' | |||
| when 'admin' then '管理员' | |||
| when 'owner' then '拥有者' | |||
| else | |||
| '' | |||
| end | |||
| end | |||
| end | |||
| @@ -187,7 +187,7 @@ class User < Owner | |||
| :show_email, :show_location, :show_department, | |||
| :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true | |||
| before_save :update_hashed_password, :set_lastname, :set_profile_completed | |||
| before_save :update_hashed_password, :set_lastname | |||
| after_create do | |||
| SyncTrustieJob.perform_later("user", 1) if allow_sync_to_trustie? | |||
| end | |||
| @@ -770,6 +770,10 @@ class User < Owner | |||
| laboratory_id.present? && laboratory_id != 1 | |||
| end | |||
| def profile_is_completed? | |||
| self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present? | |||
| end | |||
| protected | |||
| def validate_password_length | |||
| # 管理员的初始密码是5位 | |||
| @@ -796,10 +800,6 @@ class User < Owner | |||
| def set_lastname | |||
| self.lastname = self.nickname if changes[:nickname].present? | |||
| end | |||
| def set_profile_completed | |||
| self.profile_completed = self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present? | |||
| end | |||
| end | |||
| @@ -17,6 +17,7 @@ | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # repository_id :integer | |||
| # sha :string(255) | |||
| # | |||
| # Indexes | |||
| # | |||
| @@ -29,4 +30,9 @@ class VersionRelease < ApplicationRecord | |||
| has_many :project_trends, as: :trend, dependent: :destroy | |||
| scope :releases_size, ->{where(draft: false, prerelease: false).size} | |||
| has_many :attachments, as: :container, dependent: :destroy | |||
| def update_sha | |||
| git_release = Gitea::Versions::GetService.call(user.gitea_token, repository&.owner&.login, repository&.identifier, version_gid) | |||
| self.update(sha: git_release["sha"]) | |||
| end | |||
| end | |||
| @@ -24,6 +24,7 @@ class Watcher < ApplicationRecord | |||
| after_save :reset_cache_data | |||
| after_destroy :reset_cache_data | |||
| after_create :send_create_message_to_notice_system | |||
| def reset_cache_data | |||
| if self.watchable.is_a?(User) | |||
| @@ -35,4 +36,8 @@ class Watcher < ApplicationRecord | |||
| self.reset_platform_cache_async_job | |||
| end | |||
| def send_create_message_to_notice_system | |||
| SendTemplateMessageJob.perform_later('FollowTip', self.id) if self.watchable.is_a?(User) | |||
| end | |||
| end | |||
| @@ -11,7 +11,7 @@ class Projects::ListQuery < ApplicationQuery | |||
| end | |||
| def call | |||
| q = Project.all_visible(current_user_id).by_name_or_identifier(params[:search]) | |||
| q = Project.visible.by_name_or_identifier(params[:search]) | |||
| scope = q | |||
| .with_project_type(params[:project_type]) | |||
| @@ -18,7 +18,7 @@ class Admins::DeleteUnitApplyService < ApplicationService | |||
| use_extensions = UserExtension&.where(school_id: @unit_apply.school_id) | |||
| user_ids = UserExtension&.where(school_id: @unit_apply.school_id)&.pluck(:user_id) | |||
| User.where(id: user_ids).update_all(profile_completed: false) | |||
| User.where(id: user_ids) | |||
| use_extensions.update_all(school_id: nil,department_id: nil) | |||
| @unit_apply&.user&.user_extension&.update_attribute("department_id", nil) | |||
| @@ -57,7 +57,7 @@ class Admins::ImportUserService < ApplicationService | |||
| password: '12345678', | |||
| phone: data.phone, | |||
| mail: "#{prefix}#{data.student_id}@qq.com", | |||
| profile_completed: true | |||
| # profile_completed: true | |||
| } | |||
| ActiveRecord::Base.transaction do | |||
| user = User.create!(attr) | |||
| @@ -24,7 +24,7 @@ class Gitea::PullRequest::FilesService < Gitea::ClientService | |||
| def params | |||
| Hash.new.merge(token: token) | |||
| end | |||
| def url | |||
| "/repos/#{owner}/#{repo}/pulls/#{pull_number}/files".freeze | |||
| end | |||
| @@ -0,0 +1,22 @@ | |||
| class Gitea::Repository::Branches::ListSliceService < Gitea::ClientService | |||
| attr_reader :user, :repo | |||
| def initialize(user, repo) | |||
| @user = user | |||
| @repo = repo | |||
| end | |||
| def call | |||
| response = get(url, params) | |||
| render_200_response(response) | |||
| end | |||
| private | |||
| def params | |||
| Hash.new.merge(token: user.gitea_token) | |||
| end | |||
| def url | |||
| "/repos/#{user.login}/#{repo}/branches/branches_slice".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,43 @@ | |||
| # Get a list of all commits from a repository | |||
| class Gitea::Repository::Commits::FileListService < Gitea::ClientService | |||
| attr_reader :owner, :repo_name, :filepath, :args | |||
| # sha: SHA or branch to start listing commits from (usually 'master') | |||
| # ex: | |||
| # Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier, | |||
| # sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call | |||
| def initialize(owner, repo_name, filepath, **args) | |||
| @owner = owner | |||
| @repo_name = repo_name | |||
| @filepath = filepath | |||
| @args = args | |||
| end | |||
| def call | |||
| response = get(url, params) | |||
| render_result(response) | |||
| end | |||
| private | |||
| def params | |||
| {sha: args[:sha] || 'master', page: args[:page] || PAGINATE_DEFAULT_PAGE, limit: args[:limit] || PAGINATE_DEFAULT_LIMIT, token: args[:token] || "" } | |||
| end | |||
| def url | |||
| "/repos/#{owner}/#{repo_name}/file_commits/#{filepath}".freeze | |||
| end | |||
| def render_result(response) | |||
| case response.status | |||
| when 200 | |||
| result = {} | |||
| headers = response.headers.to_hash | |||
| body = JSON.parse(response.body) | |||
| total_count = headers["x-total"] | |||
| result.merge(total_count: total_count.to_i, body: body) | |||
| else | |||
| nil | |||
| # {status: -1, message: "#{body['message']}"} | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,42 @@ | |||
| # Get a list of all commits from a repository | |||
| class Gitea::Repository::Commits::ListSliceService < Gitea::ClientService | |||
| attr_reader :owner, :repo_name, :args | |||
| # sha: SHA or branch to start listing commits from (usually 'master') | |||
| # ex: | |||
| # Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier, | |||
| # sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call | |||
| def initialize(owner, repo_name, **args) | |||
| @owner = owner | |||
| @repo_name = repo_name | |||
| @args = args | |||
| end | |||
| def call | |||
| response = get(url, params) | |||
| render_result(response) | |||
| end | |||
| private | |||
| def params | |||
| { sha: args[:sha] || 'master', page: args[:page] || PAGINATE_DEFAULT_PAGE, limit: args[:limit] || PAGINATE_DEFAULT_LIMIT, token: args[:token] || "" } | |||
| end | |||
| def url | |||
| "/repos/#{owner}/#{repo_name}/commits_slice".freeze | |||
| end | |||
| def render_result(response) | |||
| case response.status | |||
| when 200 | |||
| result = {} | |||
| headers = response.headers.to_hash | |||
| body = JSON.parse(response.body) | |||
| total_count = headers["x-total"] | |||
| result.merge(total_count: total_count.to_i, body: body) | |||
| else | |||
| nil | |||
| # {status: -1, message: "#{body['message']}"} | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,34 @@ | |||
| class Gitea::Repository::Readme::DirService < Gitea::ClientService | |||
| attr_reader :owner, :repo, :ref, :dir, :token | |||
| def initialize(owner, repo, dir, ref='', token=nil) | |||
| @owner = owner | |||
| @repo = repo | |||
| @dir = dir | |||
| @ref = ref | |||
| @token = token | |||
| end | |||
| def call | |||
| response = get(url, params) | |||
| status, message, body = render_response(response) | |||
| json_format(status, message, body) | |||
| end | |||
| private | |||
| def params | |||
| Hash.new.merge(token: token, ref: ref) | |||
| end | |||
| def url | |||
| "/repos/#{owner}/#{repo}/readme/#{dir}".freeze | |||
| end | |||
| def json_format(status, message, body) | |||
| case status | |||
| when 200 then success(body) | |||
| when 404 then error(message, 404) | |||
| else error(message, status) | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,37 @@ | |||
| # Get a list of all commits from a repository | |||
| class Gitea::Versions::GetService < Gitea::ClientService | |||
| attr_reader :token, :user_name, :repo, :gid, :args | |||
| # sha: SHA or branch to start listing commits from (usually 'master') | |||
| def initialize(token, user_name, repo, gid, args={}) | |||
| @token = token | |||
| @user_name = user_name | |||
| @repo = repo | |||
| @gid = gid | |||
| @args = args | |||
| end | |||
| def call | |||
| response = get(url, params) | |||
| render_result(response) | |||
| end | |||
| private | |||
| def params | |||
| args.merge(token: token) | |||
| end | |||
| def url | |||
| "/repos/#{@user_name}/#{@repo}/releases/#{@gid}".freeze | |||
| end | |||
| def render_result(response) | |||
| body = JSON.parse(response.body) | |||
| case response.status | |||
| when 200 | |||
| body | |||
| else | |||
| {status: -1, message: "#{body['message']}"} | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,108 @@ | |||
| class Notice::Read::ClientService < ApplicationService | |||
| attr_reader :url, :params | |||
| def initialize(options={}) | |||
| @url = options[:url] | |||
| @params = options[:params] | |||
| end | |||
| def post(url, params={}) | |||
| puts "[notice][read][POST] request params: #{params}" | |||
| conn.post do |req| | |||
| req.url = full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def get(url, params={}) | |||
| puts "[notice][read][GET] request params: #{params}" | |||
| conn.get do |req| | |||
| req.url full_url(url, 'get') | |||
| params.each_pair do |key, value| | |||
| req.params["#{key}"] = value | |||
| end | |||
| end | |||
| end | |||
| def delete(url, params={}) | |||
| puts "[notice][read][DELETE] request params: #{params}" | |||
| conn.delete do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def patch(url, params={}) | |||
| puts "[notice][read][PATCH] request params: #{params}" | |||
| conn.patch do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def put(url, params={}) | |||
| puts "[notice][read][PUT] request params: #{params}" | |||
| conn.put do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def platform | |||
| Notice.notice_config[:platform] | |||
| end | |||
| private | |||
| def conn | |||
| @client ||= begin | |||
| Faraday.new(url: domain) do |req| | |||
| req.request :url_encoded | |||
| req.headers['Content-Type'] = 'application/json' | |||
| req.adapter Faraday.default_adapter | |||
| end | |||
| end | |||
| @client | |||
| end | |||
| def base_url | |||
| Notice.notice_config[:base_url] | |||
| end | |||
| def domain | |||
| Notice.notice_config[:read_domain] | |||
| end | |||
| def api_url | |||
| [domain, base_url].join('') | |||
| end | |||
| def full_url(api_rest, action='post') | |||
| url = [api_url, api_rest].join('').freeze | |||
| url = action === 'get' ? url : URI.escape(url) | |||
| url = URI.escape(url) unless url.ascii_only? | |||
| puts "[notice][read] request url: #{url}" | |||
| return url | |||
| end | |||
| def log_error(status, body) | |||
| puts "[notice][read] status: #{status}" | |||
| puts "[notice][read] body: #{body}" | |||
| end | |||
| def render_response(response) | |||
| status = response.status | |||
| body = JSON.parse(response&.body) | |||
| log_error(status, body) | |||
| if status == 200 | |||
| if body["code"] == 1 | |||
| return [body["code"], body["message"], body["data"]] | |||
| else | |||
| puts "[notice][read][ERROR] code: #{body["code"]}" | |||
| puts "[notice][read][ERROR] message: #{body["message"]}" | |||
| end | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| class Notice::Read::CountService < Notice::Read::ClientService | |||
| attr_accessor :receiver, :type | |||
| def initialize(receiver, type=-1) | |||
| @receiver = receiver | |||
| @type = type | |||
| end | |||
| def call | |||
| result = get(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_params | |||
| { | |||
| receiver: receiver, | |||
| type: type | |||
| }.stringify_keys | |||
| end | |||
| def url | |||
| "/notification/#{platform}/count".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,32 @@ | |||
| class Notice::Read::ListService < Notice::Read::ClientService | |||
| attr_accessor :receiver, :type, :status, :page, :size | |||
| def initialize(receiver, type=-1, status=2, page=1, size=15) | |||
| @receiver = receiver | |||
| @type = type | |||
| @status = status | |||
| @page = page | |||
| @size = size | |||
| end | |||
| def call | |||
| result = get(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_params | |||
| { | |||
| receiver: receiver, | |||
| page: page, | |||
| status: status, | |||
| size: size, | |||
| type: type | |||
| }.stringify_keys | |||
| end | |||
| def url | |||
| "/notification/#{platform}/list".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,35 @@ | |||
| class Notice::Write::ChangeStatusService < Notice::Write::ClientService | |||
| attr_accessor :notification_ids, :receiver, :type, :status | |||
| def initialize(notification_ids, receiver, type=-1, status=2) | |||
| @notification_ids = notification_ids | |||
| @receiver = receiver | |||
| @type = type | |||
| @status = status | |||
| end | |||
| def call | |||
| result = put(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_notification_ids | |||
| notification_ids.join(",") | |||
| end | |||
| def request_params | |||
| Hash.new.merge(data: { | |||
| notificationIds: request_notification_ids, | |||
| receiver: receiver, | |||
| type: type, | |||
| status: status | |||
| }.stringify_keys) | |||
| end | |||
| def url | |||
| "/notification/#{platform}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,108 @@ | |||
| class Notice::Write::ClientService < ApplicationService | |||
| attr_reader :url, :params | |||
| def initialize(options={}) | |||
| @url = options[:url] | |||
| @params = options[:params] | |||
| end | |||
| def post(url, params={}) | |||
| puts "[notice][write][POST] request params: #{params}" | |||
| conn.post do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def get(url, params={}) | |||
| puts "[notice][write][GET] request params: #{params}" | |||
| conn.get do |req| | |||
| req.url full_url(url, 'get') | |||
| params.each_pair do |key, value| | |||
| req.params["#{key}"] = value | |||
| end | |||
| end | |||
| end | |||
| def delete(url, params={}) | |||
| puts "[notice][write][DELETE] request params: #{params}" | |||
| conn.delete do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def patch(url, params={}) | |||
| puts "[notice][write][PATCH] request params: #{params}" | |||
| conn.patch do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def put(url, params={}) | |||
| puts "[notice][write][PUT] request params: #{params}" | |||
| conn.put do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def platform | |||
| Notice.notice_config[:platform] | |||
| end | |||
| private | |||
| def conn | |||
| @client ||= begin | |||
| Faraday.new(url: domain) do |req| | |||
| req.request :url_encoded | |||
| req.headers['Content-Type'] = 'application/json' | |||
| req.adapter Faraday.default_adapter | |||
| end | |||
| end | |||
| @client | |||
| end | |||
| def base_url | |||
| Notice.notice_config[:base_url] | |||
| end | |||
| def domain | |||
| Notice.notice_config[:write_domain] | |||
| end | |||
| def api_url | |||
| [domain, base_url].join('') | |||
| end | |||
| def full_url(api_rest, action='post') | |||
| url = [api_url, api_rest].join('').freeze | |||
| url = action === 'get' ? url : URI.escape(url) | |||
| url = URI.escape(url) unless url.ascii_only? | |||
| puts "[notice][write] request url: #{url}" | |||
| return url | |||
| end | |||
| def log_error(status, body) | |||
| puts "[notice][write] status: #{status}" | |||
| puts "[notice][write] body: #{body}" | |||
| end | |||
| def render_response(response) | |||
| status = response.status | |||
| body = JSON.parse(response&.body) | |||
| log_error(status, body) | |||
| if status == 200 | |||
| if body["code"] == 1 | |||
| return [body["code"], body["message"], body["data"]] | |||
| else | |||
| puts "[notice][write][ERROR] code: #{body["code"]}" | |||
| puts "[notice][write][ERROR] message: #{body["message"]}" | |||
| end | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,42 @@ | |||
| class Notice::Write::CreateService < Notice::Write::ClientService | |||
| attr_accessor :receivers, :sender, :content, :notification_url, :source, :extra, :type | |||
| def initialize(receivers, content, notification_url, source, extra={}, type=1, sender=-1) | |||
| @receivers = receivers | |||
| @sender = sender | |||
| @content = content | |||
| @notification_url = notification_url | |||
| @source = source | |||
| @extra = extra | |||
| @type = type | |||
| end | |||
| def call | |||
| return nil if request_receivers.blank? | |||
| result = post(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_receivers | |||
| receivers.is_a?(Array) ? receivers.join(",") : receivers | |||
| end | |||
| def request_params | |||
| Hash.new.merge(data: { | |||
| receivers: request_receivers, | |||
| sender: sender, | |||
| content: content, | |||
| notification_url: notification_url, | |||
| source: source, | |||
| extra: extra.to_json.to_s, | |||
| type: type | |||
| }.stringify_keys) | |||
| end | |||
| def url | |||
| "/notification/#{platform}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,33 @@ | |||
| class Notice::Write::DeleteService < Notice::Write::ClientService | |||
| attr_accessor :notification_ids, :receiver, :type | |||
| def initialize(notification_ids, receiver, type=-1) | |||
| @notification_ids = notification_ids | |||
| @receiver = receiver | |||
| @type = type | |||
| end | |||
| def call | |||
| result = delete(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_notification_ids | |||
| notification_ids.join(",") | |||
| end | |||
| def request_params | |||
| Hash.new.merge(data: { | |||
| notificationIds: request_notification_ids, | |||
| receiver: receiver, | |||
| type: type | |||
| }.stringify_keys) | |||
| end | |||
| def url | |||
| "/notification/#{platform}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,40 @@ | |||
| class Notice::Write::EmailCreateService < Notice::Write::ClientService | |||
| attr_accessor :receivers, :sender, :content, :subject | |||
| def initialize(receivers, subject, content, sender=-1) | |||
| @receivers = receivers | |||
| @sender = sender | |||
| @content = content | |||
| @subject = subject | |||
| end | |||
| def call | |||
| return nil if request_receivers.blank? | |||
| result = post(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_receivers | |||
| receivers.is_a?(Array) ? receivers.join(",") : receivers | |||
| end | |||
| def request_subject | |||
| "Trustie: #{subject}" | |||
| end | |||
| def request_params | |||
| Hash.new.merge(data: { | |||
| emails: request_receivers, | |||
| sender: sender, | |||
| content: content, | |||
| subject: request_subject | |||
| }.stringify_keys) | |||
| end | |||
| def url | |||
| "/email/#{platform}".freeze | |||
| end | |||
| end | |||
| @@ -53,6 +53,8 @@ class Projects::AcceptJoinService < ApplicationService | |||
| def operate_project_member | |||
| Projects::AddMemberInteractor.call(@project.owner, @project, @applied_project.user, permission) | |||
| SendTemplateMessageJob.perform_later('ProjectJoined', @user.id, @applied_project.user_id, @project.id) | |||
| SendTemplateMessageJob.perform_later('ProjectMemberJoined', @user.id, @applied_project.user_id, @project.id) | |||
| end | |||
| def send_apply_message | |||
| @@ -24,7 +24,7 @@ class Projects::ApplyTransferService < ApplicationService | |||
| raise Error, '仓库标识不正确' if @project.identifier != params[:identifier] | |||
| raise Error, '该仓库正在迁移' if @project.is_transfering | |||
| raise Error, '新拥有者不存在' unless @owner.present? | |||
| raise Error, '新拥有者资料不完善' if @owner.is_a?(User) && !@owner.profile_completed | |||
| raise Error, '新拥有者资料不完善' if @owner.is_a?(User) && !@owner.profile_is_completed? | |||
| raise Error, '新拥有者已经存在同名仓库!' if Project.where(user_id: @owner.id, identifier: params[:identifier]).present? | |||
| raise Error, '未拥有转移权限' unless is_permit_owner | |||
| end | |||
| @@ -8,27 +8,25 @@ class Repositories::DetailService < ApplicationService | |||
| end | |||
| def call | |||
| if @repo.project.educoder? | |||
| return { | |||
| repo: {}, | |||
| release: [], | |||
| branch: [], | |||
| tag: [], | |||
| contributor: [], | |||
| language: {}, | |||
| readme: {} | |||
| } | |||
| else | |||
| return { | |||
| repo: repo_suitable, | |||
| release: release_suitable, | |||
| branch: branch_suitable, | |||
| tag: tag_suitable, | |||
| contributor: contributor_suitable, | |||
| language: language_suitable, | |||
| readme: readme_suitable | |||
| } | |||
| end | |||
| return { | |||
| repo: repo_suitable, | |||
| release: release_suitable, | |||
| branch: branch_suitable, | |||
| tag: tag_suitable, | |||
| contributor: contributor_suitable, | |||
| language: language_suitable | |||
| } | |||
| rescue | |||
| return { | |||
| repo: {}, | |||
| release: [], | |||
| branch: [], | |||
| branch_type: [], | |||
| tag: [], | |||
| contributor: [], | |||
| language: {}, | |||
| readme: {} | |||
| } | |||
| end | |||
| private | |||
| @@ -43,7 +41,7 @@ class Repositories::DetailService < ApplicationService | |||
| def branch_suitable | |||
| branches = Gitea::Repository::Branches::ListService.call(@owner, @repo.identifier) | |||
| branches.is_a?(Hash) && branches[:status] == :error ? [] : branches | |||
| branches.is_a?(Hash) && branches.key?(:status) ? [] : branches | |||
| end | |||
| def tag_suitable | |||
| @@ -60,9 +58,4 @@ class Repositories::DetailService < ApplicationService | |||
| result = Gitea::Repository::Languages::ListService.call(@owner.login, @repo.identifier, @user&.gitea_token) | |||
| result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil | |||
| end | |||
| def readme_suitable | |||
| result = Gitea::Repository::Readme::GetService.call(@owner.login, @repo.identifier, @repo.default_branch, @owner.gitea_token) | |||
| result[:status] === :success ? result[:body] : nil | |||
| end | |||
| end | |||
| @@ -7,7 +7,7 @@ class Users::ApplyAuthenticationService < ApplicationService | |||
| end | |||
| def call | |||
| raise Error, '请先完善基本信息' unless user.profile_completed? | |||
| raise Error, '请先完善基本信息' unless user.profile_is_completed? | |||
| Users::ApplyAuthenticationForm.new(params).validate! | |||
| # raise Error, '您已经申请过实名认证了' if ApplyUserAuthentication.real_name_auth.processing.exists?(user_id: user.id) | |||
| @@ -9,7 +9,7 @@ class Users::ApplyProfessionalAuthService < ApplicationService | |||
| end | |||
| def call | |||
| raise Error, '请先完善基本信息' unless user.profile_completed? | |||
| raise Error, '请先完善基本信息' unless user.profile_is_completed? | |||
| Users::ApplyProfessionalAuthForm.new(params).validate! | |||
| # raise Error, '您已经申请过职业认证了' if ApplyUserAuthentication.professional_auth.processing.exists?(user_id: user.id) | |||
| @@ -43,7 +43,7 @@ class Users::UpdateAccountService < ApplicationService | |||
| end | |||
| # 表示资料完整 | |||
| user.profile_completed = true | |||
| # user.profile_completed = true | |||
| extension.save! | |||
| user.save! | |||
| @@ -0,0 +1,65 @@ | |||
| <div class="box search-form-container project-list-form"> | |||
| <div style="line-height: 38px;" class="flex-1"><%= type == "create" ? "新建" : "编辑" %><%= @message_template.simple_type %>消息模版</div> | |||
| <%= link_to "返回", admins_message_templates_path, class: "btn btn-default pull-right" %> | |||
| </div> | |||
| <div class="box"> | |||
| <%= form_for @message_template, url: {controller: "message_templates", action: "#{type}"} do |f| %> | |||
| <div class="form-group"> | |||
| <label> | |||
| <span class="color-grey-6 pt10"> | |||
| 站内信 | |||
| <span class="ml10 color-orange mr20">*</span> | |||
| </span> | |||
| </label> | |||
| <div class="mt-10"> | |||
| <%= f.text_area :sys_notice, class:"form-control", rows: "10", cols: "20",placeholer: "请输入站内信" %> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label> | |||
| <span class="color-grey-6 pt10"> | |||
| 站内信跳转地址 | |||
| <span class="ml10 color-orange mr20">*</span> | |||
| </span> | |||
| </label> | |||
| <div class="mt-10"> | |||
| <%= f.text_field :notification_url, class: "form-control input-lg", maxlength: "60", placeholder: "请输入站内信跳转地址" %> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label> | |||
| <span class="color-grey-6 pt10"> | |||
| 邮件标题 | |||
| <span class="ml10 color-orange mr20">*</span> | |||
| </span> | |||
| </label> | |||
| <div class="mt-10"> | |||
| <%= f.text_field :email_title, class: "form-control input-lg", maxlength: "60", placeholder: "请输入邮件标题" %> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label> | |||
| <span class="color-grey-6 pt10"> | |||
| 邮件正文 | |||
| <span class="ml10 color-orange mr20">*</span> | |||
| </span> | |||
| </label> | |||
| <div class="mt-10"> | |||
| <div class="pl-0 my-3 setting-item-body" id="message-template-email-editor"> | |||
| <%= f.text_area :email, class:"form-control", style: 'display: none;', rows: "10", cols: "20", placeholer: "请输入邮件正文" %> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <%= f.submit "确认", class: "btn btn-primary submit-btn" %> | |||
| </div> | |||
| <% end %> | |||
| </div> | |||
| @@ -0,0 +1,39 @@ | |||
| <table class="table table-hover text-center subject-list-table"> | |||
| <thead class="thead-light"> | |||
| <tr> | |||
| <th width="5%">序号</th> | |||
| <th width="10%">类型</th> | |||
| <th width="35%">系统消息模版</th> | |||
| <th width="30%">邮件模版</th> | |||
| <th width="25%">通知地址</th> | |||
| <th width="10%">操作</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <% if message_templates.present? %> | |||
| <% message_templates.each_with_index do |message_template_type, index| %> | |||
| <% message_template = message_template_type.constantize.last%> | |||
| <tr class="project-language-item-<%= message_template.id %>"> | |||
| <td><%= list_index_no((params[:page] || 1).to_i, index) %></td> | |||
| <td><%= message_template.simple_type %></td> | |||
| <td> | |||
| <%= message_template.sys_notice.to_s.truncate(200) %> | |||
| </td> | |||
| <td> | |||
| <%= message_template.email.to_s.truncate(100) %> | |||
| </td> | |||
| <td> | |||
| <%= message_template.notification_url.to_s.truncate(200) %> | |||
| </td> | |||
| <td class="action-container"> | |||
| <%= link_to "编辑", edit_admins_message_template_path(message_template),remote: true, class: "action" %> | |||
| </td> | |||
| </tr> | |||
| <% end %> | |||
| <% else %> | |||
| <%= render 'admins/shared/no_data_for_table' %> | |||
| <% end %> | |||
| </tbody> | |||
| </table> | |||
| <%= render partial: 'admins/shared/paginate', locals: { objects: message_templates } %> | |||
| @@ -0,0 +1,2 @@ | |||
| $("#admins-message-templates-content").html("<%= j render partial: 'admins/message_templates/form', locals:{type: 'update'} %>") | |||
| createMDEditor('message-template-email-editor', { height: 500, placeholder: '请输入邮件模版' }); | |||
| @@ -0,0 +1,12 @@ | |||
| <% define_admin_breadcrumbs do %> | |||
| <% add_admin_breadcrumb('消息模版') %> | |||
| <% end %> | |||
| <div id="admins-message-templates-content"> | |||
| <div class="box search-form-container project-list-form"> | |||
| <%= link_to "初始化数据", init_data_admins_message_templates_path, class: "btn btn-primary pull-right", "data-disabled-with":"...初始化数据" %> | |||
| </div> | |||
| <div class="box admin-list-container message-templates-list-container"> | |||
| <%= render partial: 'admins/message_templates/list', locals: { message_templates: @message_templates } %> | |||
| </div> | |||
| </div> | |||
| @@ -0,0 +1 @@ | |||
| $('.message-templates-list-container').html("<%= j( render partial: 'admins/message_templates/list', locals: { message_templates: @message_templates } ) %>"); | |||
| @@ -30,6 +30,7 @@ | |||
| </li> | |||
| <li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li> | |||
| <li><%= sidebar_item(admins_message_templates_path, '消息模版', icon: 'folder', controller: 'admins-message_templates') %></li> | |||
| <li><%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %></li> | |||
| @@ -1,5 +1,9 @@ | |||
| json.id organization.id | |||
| json.name organization.login | |||
| json.nickname organization.nickname.blank? ? organization.name : organization.nickname | |||
| json.description organization.description | |||
| json.avatar_url url_to_avatar(organization) | |||
| if organization.present? | |||
| json.id organization.id | |||
| json.name organization.login | |||
| json.nickname organization.nickname.blank? ? organization.name : organization.nickname | |||
| json.description organization.description | |||
| json.avatar_url url_to_avatar(organization) | |||
| else | |||
| nil | |||
| end | |||