| @@ -153,6 +153,10 @@ class AccountsController < ApplicationController | |||||
| user.gitea_uid = gitea_user[:body]['id'] | user.gitea_uid = gitea_user[:body]['id'] | ||||
| if user.save! | if user.save! | ||||
| UserExtension.create!(user_id: user.id) | UserExtension.create!(user_id: user.id) | ||||
| # 绑定授权账号 | |||||
| if ["qq", "wechat", "gitee", "github", "educoder"].include?(params[:type].to_s) && session[:unionid].present? | |||||
| "OpenUsers::#{params[:type].to_s.capitalize}".constantize.create!(user: user, uid: session[:unionid]) | |||||
| end | |||||
| successful_authentication(user) | successful_authentication(user) | ||||
| render_ok | render_ok | ||||
| end | end | ||||
| @@ -394,7 +398,7 @@ class AccountsController < ApplicationController | |||||
| end | end | ||||
| def register_params | def register_params | ||||
| params.permit(:login, :namespace, :password, :password_confirmation, :code) | |||||
| params.permit(:login, :namespace, :password, :password_confirmation, :code, :type) | |||||
| end | end | ||||
| def reset_password_params | def reset_password_params | ||||
| @@ -1,35 +1,18 @@ | |||||
| class BindUsersController < ApplicationController | class BindUsersController < ApplicationController | ||||
| # before_action :require_login | |||||
| def create | def create | ||||
| # user = CreateBindUserService.call(create_params) | |||||
| # | |||||
| if params[:type] == "qq" | |||||
| begin | |||||
| user = CreateBindUserService.call(current_user, create_params) | |||||
| successful_authentication(user) if user.id != current_user.id | |||||
| render_ok | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| else | |||||
| begin | |||||
| tip_exception '系统错误' if session[:unionid].blank? | |||||
| bind_user = User.try_to_login(params[:username], params[:password]) | |||||
| tip_exception '用户名或者密码错误' if bind_user.blank? | |||||
| tip_exception '用户名或者密码错误' unless bind_user.check_password?(params[:password].to_s) | |||||
| tip_exception '该账号已被绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s) | |||||
| OpenUsers::Wechat.create!(user: bind_user, uid: session[:unionid]) | |||||
| successful_authentication(bind_user) | |||||
| render_ok | |||||
| rescue Exception => e | |||||
| render_error(e.message) | |||||
| end | |||||
| end | |||||
| Rails.logger.debug "--------------开始绑定用户------------" | |||||
| Rails.logger.debug "--------------params: #{params.to_unsafe_h}" | |||||
| tip_exception '系统错误' if session[:unionid].blank? | |||||
| bind_user = User.try_to_login(params[:username], params[:password]) | |||||
| tip_exception '用户名或者密码错误' if bind_user.blank? | |||||
| tip_exception '用户名或者密码错误' unless bind_user.check_password?(params[:password].to_s) | |||||
| tip_exception '参数错误' unless ["qq", "wechat", "gitee", "github", "educoder"].include?(params[:type].to_s) | |||||
| tip_exception '该账号已被绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s) | |||||
| "OpenUsers::#{params[:type].to_s.capitalize}".constantize.create!(user: bind_user, uid: session[:unionid]) | |||||
| @user = bind_user | |||||
| end | end | ||||
| def new_user | def new_user | ||||
| @@ -1,6 +1,6 @@ | |||||
| class Oauth::CallbacksController < Oauth::BaseController | class Oauth::CallbacksController < Oauth::BaseController | ||||
| def create | def create | ||||
| process_callback | |||||
| process_callback_new | |||||
| rescue Exception => e | rescue Exception => e | ||||
| Rails.logger.info "授权失败:#{e}" | Rails.logger.info "授权失败:#{e}" | ||||
| tip_exception("授权失败") | tip_exception("授权失败") | ||||
| @@ -57,6 +57,28 @@ class Oauth::CallbacksController < Oauth::BaseController | |||||
| redirect_to root_path(new_user: new_user) | redirect_to root_path(new_user: new_user) | ||||
| end | end | ||||
| def process_callback_new | |||||
| Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}") | |||||
| if auth_hash.blank? | |||||
| redirect_to("/login") && return | |||||
| end | |||||
| platform = auth_hash[:provider] | |||||
| uid = auth_hash[:uid] | |||||
| uid = auth_hash.info.unionid if platform == "wechat" | |||||
| open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.find_by(uid: uid) | |||||
| if open_user.present? && open_user.user.present? | |||||
| successful_authentication(open_user.user) | |||||
| else | |||||
| if current_user.blank? || !current_user.logged? | |||||
| session[:unionid] = uid | |||||
| else | |||||
| "OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user: current_user, uid: uid) | |||||
| end | |||||
| end | |||||
| redirect_to "/bindlogin/#{platform}" | |||||
| end | |||||
| # gitee,github nickname=login,如果系统未占用保留原用户名 | # gitee,github nickname=login,如果系统未占用保留原用户名 | ||||
| def build_login_name(provider, nickname) | def build_login_name(provider, nickname) | ||||
| if ["gitee", "github"].include?(provider) && User.find_by(login: nickname).blank? | if ["gitee", "github"].include?(provider) && User.find_by(login: nickname).blank? | ||||
| @@ -46,6 +46,12 @@ class Organizations::OrganizationsController < Organizations::BaseController | |||||
| @organization.nickname = organization_params[:nickname] if organization_params[:nickname].present? | @organization.nickname = organization_params[:nickname] if organization_params[:nickname].present? | ||||
| @organization.save! | @organization.save! | ||||
| sync_organization_extension! | sync_organization_extension! | ||||
| # 更改组织可见性为私有,则需将该组织下的所有仓库同步更改为私有仓库 | |||||
| if organization_extension_params[:visibility] == "privacy" | |||||
| Project.where(user_id: @organization.id).where(is_public: true).each do |project| | |||||
| update_project_private(project) | |||||
| end | |||||
| end | |||||
| Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload) | Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload) | ||||
| Util.write_file(@image, avatar_path(@organization)) if params[:image].present? | Util.write_file(@image, avatar_path(@organization)) if params[:image].present? | ||||
| @@ -123,5 +129,20 @@ class Organizations::OrganizationsController < Organizations::BaseController | |||||
| def sync_organization_extension! | def sync_organization_extension! | ||||
| @organization.organization_extension.update_attributes!(organization_extension_params) | @organization.organization_extension.update_attributes!(organization_extension_params) | ||||
| end | end | ||||
| def update_project_private(project) | |||||
| project.update_attributes!(is_public: false) | |||||
| project.forked_projects.update_all(is_public: project.is_public) | |||||
| gitea_params = { | |||||
| private: true, | |||||
| default_branch: project.default_branch, | |||||
| website: project.website, | |||||
| name: project.identifier | |||||
| } | |||||
| gitea_repo = Gitea::Repository::UpdateService.call(@organization, project&.repository&.identifier, gitea_params) | |||||
| project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]}) | |||||
| # 更新对应所属分类下的项目数量(私有) | |||||
| project.project_category.decrement!(:private_projects_count, 1) if project.project_category.present? | |||||
| end | |||||
| end | end | ||||
| @@ -53,7 +53,7 @@ class ProjectsController < ApplicationController | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| Projects::CreateForm.new(project_params).validate! | Projects::CreateForm.new(project_params).validate! | ||||
| @project = Projects::CreateService.new(current_user, project_params).call | @project = Projects::CreateService.new(current_user, project_params).call | ||||
| OpenProjectDevOpsJob.perform_later(@project&.id, current_user.id) | |||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -6,7 +6,7 @@ module Admins::ProjectsHelper | |||||
| if owner.is_a?(User) | if owner.is_a?(User) | ||||
| link_to(project.owner&.real_name, "/#{project&.owner&.login}", target: '_blank') | link_to(project.owner&.real_name, "/#{project&.owner&.login}", target: '_blank') | ||||
| elsif owner.is_a?(Organization) | elsif owner.is_a?(Organization) | ||||
| link_to(project.owner&.real_name, "/organize/#{project&.owner&.login}", target: '_blank') | |||||
| link_to(project.owner&.real_name, "/#{project&.owner&.login}", target: '_blank') | |||||
| else | else | ||||
| "" | "" | ||||
| end | end | ||||
| @@ -1,7 +1,7 @@ | |||||
| class MigrateRemoteRepositoryJob < ApplicationJob | class MigrateRemoteRepositoryJob < ApplicationJob | ||||
| queue_as :default | queue_as :default | ||||
| def perform(repo_id, token, params) | |||||
| def perform(repo_id, token, user_id, params) | |||||
| repo = Repository.find_by(id: repo_id) | repo = Repository.find_by(id: repo_id) | ||||
| return if repo.blank? | return if repo.blank? | ||||
| @@ -12,6 +12,10 @@ class MigrateRemoteRepositoryJob < ApplicationJob | |||||
| if gitea_repository[0]==201 | if gitea_repository[0]==201 | ||||
| repo&.project&.update_columns(gpid: gitea_repository[2]["id"]) | repo&.project&.update_columns(gpid: gitea_repository[2]["id"]) | ||||
| repo&.mirror&.succeeded! | repo&.mirror&.succeeded! | ||||
| ## open jianmu devops | |||||
| project_id = repo&.project&.id | |||||
| puts "############ mirror project_id,user_id: #{project_id},#{user_id} ############" | |||||
| OpenProjectDevOpsJob.perform_later(project_id, user_id) if project_id.present? && user_id.present? | |||||
| puts "############ mirror status: #{repo.mirror.status} ############" | puts "############ mirror status: #{repo.mirror.status} ############" | ||||
| else | else | ||||
| repo&.mirror&.failed! | repo&.mirror&.failed! | ||||
| @@ -0,0 +1,16 @@ | |||||
| class OpenProjectDevOpsJob < ApplicationJob | |||||
| include ProjectsHelper | |||||
| queue_as :message | |||||
| def perform(project_id, user_id) | |||||
| project = Project.find_by(id: project_id) | |||||
| user = User.find_by(id: user_id) | |||||
| code = jianmu_devops_code(project, user) | |||||
| uri = URI.parse("#{jianmu_devops_url}/oauth2/authorize?code=#{URI.encode_www_form_component(code)}") | |||||
| response = Net::HTTP.get_response(uri) | |||||
| puts "jianmu_devops_url response.code ===== #{response.code}" | |||||
| SendTemplateMessageJob.perform_later('ProjectOpenDevOps', user_id, project_id) | |||||
| end | |||||
| end | |||||
| @@ -217,6 +217,14 @@ class SendTemplateMessageJob < ApplicationJob | |||||
| receivers = project&.all_managers.where.not(id: operator&.id) | receivers = project&.all_managers.where.not(id: operator&.id) | ||||
| receivers_string, content, notification_url = MessageTemplate::ProjectPraised.get_message_content(receivers, operator, project) | receivers_string, content, notification_url = MessageTemplate::ProjectPraised.get_message_content(receivers, operator, project) | ||||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id}) | Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id}) | ||||
| when 'ProjectOpenDevOps' | |||||
| operator_id, project_id = args[0], args[1] | |||||
| operator = User.find_by_id(operator_id) | |||||
| project = Project.find_by_id(project_id) | |||||
| return unless operator.present? && project.present? | |||||
| receivers = User.where(id: operator.id) | |||||
| receivers_string, content, notification_url = MessageTemplate::ProjectOpenDevOps.get_message_content(receivers, operator, project) | |||||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id}) | |||||
| when 'ProjectPullRequest' | when 'ProjectPullRequest' | ||||
| operator_id, pull_request_id = args[0], args[1] | operator_id, pull_request_id = args[0], args[1] | ||||
| operator = User.find_by_id(operator_id) | operator = User.find_by_id(operator_id) | ||||
| @@ -52,6 +52,7 @@ class MessageTemplate < ApplicationRecord | |||||
| email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html") | email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html") | ||||
| self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 <b>{nickname}/{repository}</b> 仓库,里程碑 <b>{name}</b> 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成") | self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 <b>{nickname}/{repository}</b> 仓库,里程碑 <b>{name}</b> 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成") | ||||
| self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname1}</b> 点赞了你管理的仓库 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{login}') | self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname1}</b> 点赞了你管理的仓库 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{login}') | ||||
| self.create(type: 'MessageTemplate::ProjectOpenDevOps', sys_notice: '您的仓库 <b>{repository}</b> 已成功开通引擎服务,可通过简单的节点编排完成自动化集成与部署。欢迎体验!', notification_url: '{baseurl}/{owner}/{identifier}/devops') | |||||
| email_html = File.read("#{email_template_html_dir}/project_pull_request.html") | 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}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求") | self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求") | ||||
| email_html = File.read("#{email_template_html_dir}/project_role.html") | email_html = File.read("#{email_template_html_dir}/project_role.html") | ||||
| @@ -0,0 +1,28 @@ | |||||
| # == 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::ProjectOpenDevOps < MessageTemplate | |||||
| # MessageTemplate::ProjectOpenDevOps.get_message_content(User.where(login: 'yystopf')) | |||||
| def self.get_message_content(receivers, user, project) | |||||
| return '', '', '' if receivers.blank? | |||||
| 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::ProjectOpenDevOps.get_message_content [ERROR] #{e}") | |||||
| return '', '', '' | |||||
| end | |||||
| end | |||||
| @@ -12,6 +12,10 @@ class Projects::ListQuery < ApplicationQuery | |||||
| def call | def call | ||||
| collection = Project.visible | collection = Project.visible | ||||
| # 增加私有组织中项目过滤 | |||||
| collection = collection.joins("left join organization_extensions on organization_extensions.organization_id = projects.user_id") | |||||
| .where("organization_extensions.visibility is null or organization_extensions.visibility in (0,1)") | |||||
| .where("projects.user_id > 0") | |||||
| collection = filter_projects(collection) | collection = filter_projects(collection) | ||||
| sort = params[:sort_by] || "updated_on" | sort = params[:sort_by] || "updated_on" | ||||
| @@ -15,13 +15,14 @@ class Admins::UpdateUserService < ApplicationService | |||||
| user.firstname = '' | user.firstname = '' | ||||
| user.password = params[:password] if params[:password].present? | user.password = params[:password] if params[:password].present? | ||||
| user.user_extension.assign_attributes(user_extension_attributes) | |||||
| user.user_extension.assign_attributes(user_extension_attributes) if user.user_extension.present? | |||||
| old_login = user.login | old_login = user.login | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| user.save! | user.save! | ||||
| user.user_extension.save! | |||||
| user.user_extension.save! if user.user_extension.present? | |||||
| update_gitea_user(old_login) | update_gitea_user(old_login) | ||||
| update_gitea_user_email(user.previous_changes[:mail]) | |||||
| end | end | ||||
| user | user | ||||
| @@ -65,4 +66,14 @@ class Admins::UpdateUserService < ApplicationService | |||||
| Util.logger_error(ex) | Util.logger_error(ex) | ||||
| raise Error, '保存失败' | raise Error, '保存失败' | ||||
| end | end | ||||
| def update_gitea_user_email(change_options) | |||||
| return if change_options.blank? | |||||
| return if user.gitea_uid.blank? || user.gitea_token.blank? | |||||
| $gitea_client.delete_user_emails({body: {emails: [change_options[0]]}.to_json, query: {access_token: user.gitea_token}}) | |||||
| $gitea_client.post_user_emails({body: {emails: [change_options[1]]}.to_json, query: {access_token: user.gitea_token}}) | |||||
| rescue Exception => ex | |||||
| Util.logger_error(ex) | |||||
| raise Error, '保存失败' | |||||
| end | |||||
| end | end | ||||
| @@ -11,7 +11,7 @@ class Repositories::MigrateService < ApplicationService | |||||
| @repository = Repository.new(repository_params) | @repository = Repository.new(repository_params) | ||||
| if @repository.save! | if @repository.save! | ||||
| @repository.set_mirror! | @repository.set_mirror! | ||||
| MigrateRemoteRepositoryJob.perform_later(@repository.id, user.gitea_token, gitea_repository_params) | |||||
| MigrateRemoteRepositoryJob.perform_later(@repository.id, user.gitea_token, user.id, gitea_repository_params) | |||||
| end | end | ||||
| @repository | @repository | ||||
| rescue => e | rescue => e | ||||
| @@ -68,12 +68,12 @@ | |||||
| <%= f.label :identity, label: '职业' %> | <%= f.label :identity, label: '职业' %> | ||||
| <%= select_tag('user[identity]', [], class: 'form-control identity-select optional', 'data-value': @user.user_extension&.identity, 'data-first-title': '请选择') %> | <%= select_tag('user[identity]', [], class: 'form-control identity-select optional', 'data-value': @user.user_extension&.identity, 'data-first-title': '请选择') %> | ||||
| </div> | </div> | ||||
| <div class="form-group technical-title-select-wrapper optional col-md-1" style="<%= @user.user_extension.student? ? 'display:none;' : '' %>"> | |||||
| <div class="form-group technical-title-select-wrapper optional col-md-1" style="<%= @user&.user_extension&.student? ? 'display:none;' : '' %>"> | |||||
| <%= f.label :technical_title, label: '职称' %> | <%= f.label :technical_title, label: '职称' %> | ||||
| <%= select_tag('user[technical_title]', [], class: 'form-control technical-title-select optional', 'data-value': @user.technical_title) %> | <%= select_tag('user[technical_title]', [], class: 'form-control technical-title-select optional', 'data-value': @user.technical_title) %> | ||||
| </div> | </div> | ||||
| <%= f.input :student_id, as: :tel, label: '学号', wrapper_html: { class: 'col-md-2', style: @user.user_extension.student? ? '' : 'display:none;' }, input_html: { class: 'student-id-input' } %> | |||||
| <%= f.input :student_id, as: :tel, label: '学号', wrapper_html: { class: 'col-md-2', style: @user&.user_extension&.student? ? '' : 'display:none;' }, input_html: { class: 'student-id-input' } %> | |||||
| </div> | </div> | ||||
| <div class="form-row"> | <div class="form-row"> | ||||
| @@ -27,7 +27,7 @@ | |||||
| <td><%= user.identity %></td> | <td><%= user.identity %></td> | ||||
| <td><%= display_text(user.created_on&.strftime('%Y-%m-%d %H:%M')) %></td> | <td><%= display_text(user.created_on&.strftime('%Y-%m-%d %H:%M')) %></td> | ||||
| <td><%= display_text(user.last_login_on&.strftime('%Y-%m-%d %H:%M')) %></td> | <td><%= display_text(user.last_login_on&.strftime('%Y-%m-%d %H:%M')) %></td> | ||||
| <td><%= link_to user.projects_count, "/users/#{user.login}/projects", target: "_blank" %></td> | |||||
| <td><%= link_to user.projects_count, "/#{user.login}/projects", target: "_blank" %></td> | |||||
| <td class="action-container"> | <td class="action-container"> | ||||
| <%= link_to '编辑', edit_admins_user_path(user), class: 'action' %> | <%= link_to '编辑', edit_admins_user_path(user), class: 'action' %> | ||||
| @@ -0,0 +1,8 @@ | |||||
| json.username @user.full_name | |||||
| json.real_name @user.real_name | |||||
| json.login @user.login | |||||
| json.user_id @user.id | |||||
| json.image_url url_to_avatar(@user) | |||||
| json.admin @user.admin? | |||||
| json.user_identity @user.identity | |||||
| json.is_watch current_user&.watched?(@user) | |||||