| @@ -0,0 +1,35 @@ | |||||
| class Oauth::MulanossController < Oauth::BaseController | |||||
| include RegisterHelper | |||||
| # 需要educoder那边设置回调地址 | |||||
| def create | |||||
| # user, new_user = Oauth::CreateOrFindWechatAccountService.call(current_user ,params) | |||||
| begin | |||||
| code = params['code'].to_s.strip | |||||
| tip_exception("code不能为空") if code.blank? | |||||
| new_user = false | |||||
| result = MulanossOauth::Service.access_token(code) | |||||
| result = MulanossOauth::Service.user_info(result[:access_token]) | |||||
| # 存在该用户 | |||||
| open_user = OpenUsers::Mulan.find_by(uid: result['id']) | |||||
| if open_user.present? && open_user.user.present? | |||||
| successful_authentication(open_user.user) | |||||
| else | |||||
| if current_user.blank? || !current_user.logged? | |||||
| new_user = true | |||||
| login = User.generate_login('ML') | |||||
| reg_result = autologin_register(login, "#{login}@forge.com" , "M#{login}2021#", 'mulan', true) | |||||
| open_user = OpenUsers::Mulan.create!(user_id: reg_result[:user][:id], uid: result['id'], extra: result) | |||||
| successful_authentication(open_user.user) | |||||
| else | |||||
| OpenUsers::Mulan.create!(user: current_user, uid: result["id"]) | |||||
| end | |||||
| end | |||||
| redirect_to "/explore" | |||||
| rescue Exception => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -46,6 +46,10 @@ class SettingsController < ApplicationController | |||||
| name: 'educoder', | name: 'educoder', | ||||
| url: EducoderOauth.oauth_url | url: EducoderOauth.oauth_url | ||||
| } | } | ||||
| @third_party << { | |||||
| name: 'mulan', | |||||
| url: MulanossOauth.oauth_url | |||||
| } | |||||
| end | end | ||||
| def get_site_url(key, value) | def get_site_url(key, value) | ||||
| @@ -0,0 +1,18 @@ | |||||
| module MulanossOauth | |||||
| class << self | |||||
| attr_accessor :client_id, :client_secret, :base_url, :redirect_uri | |||||
| def logger | |||||
| @_logger ||= STDOUT | |||||
| end | |||||
| def logger=(l) | |||||
| @_logger = l | |||||
| end | |||||
| def oauth_url | |||||
| "#{base_url}/action/oauth2/authorize?client_id=#{client_id}&redirect_uri=#{URI.encode_www_form_component(redirect_uri)}&response_type=code" | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,38 @@ | |||||
| require 'oauth2' | |||||
| module MulanossOauth::Service | |||||
| module_function | |||||
| def request(method, url, params) | |||||
| begin | |||||
| Rails.logger.info("[MulanossOauth] [#{method.to_s.upcase}] #{url} || #{params}") | |||||
| client = Faraday.new(url: MulanossOauth.base_url) | |||||
| response = client.public_send(method, url, params) | |||||
| result = JSON.parse(response.body) | |||||
| Rails.logger.info("[MulanossOauth] [#{response.status}] #{result}") | |||||
| result | |||||
| rescue Exception => e | |||||
| raise Educoder::TipException.new(e.message) | |||||
| end | |||||
| end | |||||
| def access_token(code) | |||||
| begin | |||||
| Rails.logger.info("[MulanossOauth] [code] #{code} ") | |||||
| Rails.logger.info("[MulanossOauth] [redirect_uri] #{MulanossOauth.redirect_uri} ") | |||||
| client = OAuth2::Client.new(MulanossOauth.client_id, MulanossOauth.client_secret, site: MulanossOauth.base_url, token_url:"/action/openapi/token") | |||||
| result = client.auth_code.get_token(code, redirect_uri: MulanossOauth.redirect_uri).to_hash | |||||
| Rails.logger.info("[MulanossOauth] [GetToken] #{result[:access_token]}") | |||||
| return result | |||||
| rescue Exception => e | |||||
| raise Educoder::TipException.new(e.message) | |||||
| end | |||||
| end | |||||
| def user_info(access_token) | |||||
| request(:get, '/action/openapi/user', {access_token: access_token}) | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,27 @@ | |||||
| # == Schema Information | |||||
| # | |||||
| # Table name: open_users | |||||
| # | |||||
| # id :integer not null, primary key | |||||
| # user_id :integer | |||||
| # type :string(255) | |||||
| # uid :string(255) | |||||
| # created_at :datetime not null | |||||
| # updated_at :datetime not null | |||||
| # extra :text(65535) | |||||
| # | |||||
| # Indexes | |||||
| # | |||||
| # index_open_users_on_type_and_uid (type,uid) UNIQUE | |||||
| # index_open_users_on_user_id (user_id) | |||||
| # | |||||
| class OpenUsers::Mulan < OpenUser | |||||
| def nickname | |||||
| extra&.[]('name') | |||||
| end | |||||
| def en_type | |||||
| 'mulan' | |||||
| end | |||||
| end | |||||
| @@ -114,7 +114,7 @@ class User < Owner | |||||
| # trustie: 来自Trustie平台 | # trustie: 来自Trustie平台 | ||||
| # forge: 平台本身注册的用户 | # forge: 平台本身注册的用户 | ||||
| # military: 军科的用户 | # military: 军科的用户 | ||||
| enumerize :platform, in: [:forge, :educoder, :trustie, :military], default: :forge, scope: :shallow | |||||
| enumerize :platform, in: [:forge, :educoder, :trustie, :military, :mulan], default: :forge, scope: :shallow | |||||
| belongs_to :laboratory, optional: true | belongs_to :laboratory, optional: true | ||||
| has_many :composes, dependent: :destroy | has_many :composes, dependent: :destroy | ||||
| @@ -154,7 +154,7 @@ class User < Owner | |||||
| # 项目 | # 项目 | ||||
| has_many :applied_projects, dependent: :destroy | has_many :applied_projects, dependent: :destroy | ||||
| has_many :operate_applied_transfer_projects, class_name: 'AppliedTransferProject', dependent: :destroy | has_many :operate_applied_transfer_projects, class_name: 'AppliedTransferProject', dependent: :destroy | ||||
| has_many :members, dependent: :destroy | |||||
| has_many :members, dependent: :destroy | |||||
| has_many :team_users, dependent: :destroy | has_many :team_users, dependent: :destroy | ||||
| has_many :teams, through: :team_users | has_many :teams, through: :team_users | ||||
| @@ -168,7 +168,7 @@ class User < Owner | |||||
| has_many :pinned_projects, dependent: :destroy | has_many :pinned_projects, dependent: :destroy | ||||
| has_many :is_pinned_projects, through: :pinned_projects, source: :project | has_many :is_pinned_projects, through: :pinned_projects, source: :project | ||||
| accepts_nested_attributes_for :is_pinned_projects | accepts_nested_attributes_for :is_pinned_projects | ||||
| has_many :issues, dependent: :destroy, foreign_key: :author_id | |||||
| has_many :issues, dependent: :destroy, foreign_key: :author_id | |||||
| has_many :pull_requests, dependent: :destroy | has_many :pull_requests, dependent: :destroy | ||||
| has_many :public_keys, class_name: "Gitea::PublicKey",primary_key: :gitea_uid, foreign_key: :owner_id, dependent: :destroy | has_many :public_keys, class_name: "Gitea::PublicKey",primary_key: :gitea_uid, foreign_key: :owner_id, dependent: :destroy | ||||
| @@ -205,14 +205,14 @@ class User < Owner | |||||
| validate :validate_password_length | validate :validate_password_length | ||||
| # 用户参与的所有项目 | # 用户参与的所有项目 | ||||
| def full_member_projects | |||||
| def full_member_projects | |||||
| normal_projects = Project.members_projects(self.id).to_sql | normal_projects = Project.members_projects(self.id).to_sql | ||||
| org_projects = Project.joins(teams: :team_users).where(team_users: {user_id: self.id}).to_sql | org_projects = Project.joins(teams: :team_users).where(team_users: {user_id: self.id}).to_sql | ||||
| return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct | return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct | ||||
| end | end | ||||
| # 用户管理的所有项目 | # 用户管理的所有项目 | ||||
| def full_admin_projects | |||||
| def full_admin_projects | |||||
| normal_projects = Project.joins(members: :roles).where(roles: {name: 'Manager'}, members: {user_id: self.id}).to_sql | normal_projects = Project.joins(members: :roles).where(roles: {name: 'Manager'}, members: {user_id: self.id}).to_sql | ||||
| org_projects = Project.joins(teams: :team_users).where(teams: {authorize: %w(admin owner)}, team_users: {user_id: self.id}).to_sql | org_projects = Project.joins(teams: :team_users).where(teams: {authorize: %w(admin owner)}, team_users: {user_id: self.id}).to_sql | ||||
| return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct | return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct | ||||
| @@ -221,7 +221,7 @@ class User < Owner | |||||
| def name | def name | ||||
| login | login | ||||
| end | end | ||||
| # 删除自动登录的token,一旦退出下次会提示需要登录 | # 删除自动登录的token,一旦退出下次会提示需要登录 | ||||
| def delete_autologin_token(value) | def delete_autologin_token(value) | ||||
| Token.where(:user_id => id, :action => 'autologin', :value => value).delete_all | Token.where(:user_id => id, :action => 'autologin', :value => value).delete_all | ||||
| @@ -427,7 +427,7 @@ class User < Owner | |||||
| self.status = STATUS_LOCKED | self.status = STATUS_LOCKED | ||||
| end | end | ||||
| def need_edit_info | |||||
| def need_edit_info | |||||
| self.status = STATUS_EDIT_INFO | self.status = STATUS_EDIT_INFO | ||||
| end | end | ||||
| @@ -14,7 +14,7 @@ json.issues do | |||||
| pr = issue.pull_request | pr = issue.pull_request | ||||
| json.pull_request_id pr.id | json.pull_request_id pr.id | ||||
| json.pull_request_status pr.status | json.pull_request_status pr.status | ||||
| json.pull_request_head pr.head | |||||
| json.pull_request_head pr.head | |||||
| json.pull_request_base pr.base | json.pull_request_base pr.base | ||||
| json.pull_request_staus pr.status == 1 ? "merged" : (pr.status == 2 ? "closed" : "open") | json.pull_request_staus pr.status == 1 ? "merged" : (pr.status == 2 ? "closed" : "open") | ||||
| json.is_original pr.is_original | json.is_original pr.is_original | ||||
| @@ -22,9 +22,10 @@ json.issues do | |||||
| json.fork_project_identifier pr&.fork_project&.identifier | json.fork_project_identifier pr&.fork_project&.identifier | ||||
| json.fork_project_user pr&.fork_project&.owner.try(:login) | json.fork_project_user pr&.fork_project&.owner.try(:login) | ||||
| json.id issue.id | json.id issue.id | ||||
| json.name issue.subject | json.name issue.subject | ||||
| json.description issue.description | |||||
| json.pr_time time_from_now(pr.status == 1 ? pr.updated_at : issue.updated_on) | json.pr_time time_from_now(pr.status == 1 ? pr.updated_at : issue.updated_on) | ||||
| json.assign_user_name issue.get_assign_user.try(:show_real_name) | json.assign_user_name issue.get_assign_user.try(:show_real_name) | ||||
| json.assign_user_login issue.get_assign_user.try(:login) | json.assign_user_login issue.get_assign_user.try(:login) | ||||
| @@ -37,4 +38,3 @@ json.issues do | |||||
| json.issue_tags issue.get_issue_tags | json.issue_tags issue.get_issue_tags | ||||
| end | end | ||||
| end | end | ||||
| @@ -0,0 +1,16 @@ | |||||
| oauth_config = {} | |||||
| begin | |||||
| config = Rails.application.config_for(:configuration) | |||||
| oauth_config = config.dig('oauth', 'mulan') | |||||
| raise 'oauth educoder config missing' if oauth_config.blank? | |||||
| rescue => ex | |||||
| raise ex if Rails.env.production? | |||||
| puts %Q{\033[33m [warning] wechat oauth config or configuration.yml missing, | |||||
| please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m} | |||||
| end | |||||
| MulanossOauth.client_id = oauth_config['client_id'] | |||||
| MulanossOauth.client_secret = oauth_config['client_secret'] | |||||
| MulanossOauth.base_url = oauth_config['base_url'] | |||||
| MulanossOauth.redirect_uri = oauth_config['redirect_uri'] | |||||