diff --git a/app/controllers/concerns/register_helper.rb b/app/controllers/concerns/register_helper.rb index 2a920b6f..587108b7 100644 --- a/app/controllers/concerns/register_helper.rb +++ b/app/controllers/concerns/register_helper.rb @@ -1,7 +1,7 @@ module RegisterHelper extend ActiveSupport::Concern - def autologin_register(username, email, password, platform = 'forge', phone = nil) + def autologin_register(username, email, password, platform = 'forge', phone = nil, nickname =nil) result = {message: nil, user: nil} email = email.blank? ? "#{username}@example.org" : email @@ -12,11 +12,14 @@ module RegisterHelper user.password = password user.platform = platform user.phone = phone if phone.present? + user.nickname = nickname if nickname.present? user.activate return unless user.valid? interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) + # Rails.logger.info "interactor===#{interactor.success?}" + # Rails.logger.info "interactor===#{interactor.result}" result ={} if interactor.success? gitea_user = interactor.result diff --git a/app/controllers/oauth/base_controller.rb b/app/controllers/oauth/base_controller.rb index 3fe349bb..113f7933 100644 --- a/app/controllers/oauth/base_controller.rb +++ b/app/controllers/oauth/base_controller.rb @@ -2,6 +2,8 @@ class Oauth::BaseController < ActionController::Base include RenderHelper include LoginHelper include ControllerRescueHandler + include LoggerHelper + include RegisterHelper # include LaboratoryHelper skip_before_action :verify_authenticity_token @@ -11,6 +13,18 @@ class Oauth::BaseController < ActionController::Base end private + def tip_exception(status = -1, message) + raise Gitlink::TipException.new(status, message) + end + + def tip_show_exception(status = -2, message) + raise Gitlink::TipException.new(status, message) + end + + def tip_show(exception) + uid_logger("Tip show status is #{exception.status}, message is #{exception.message}") + render json: exception.tip_json + end def session_user_id # session[:user_id] diff --git a/app/controllers/oauth/openkylin_controller.rb b/app/controllers/oauth/openkylin_controller.rb new file mode 100644 index 00000000..8d532aae --- /dev/null +++ b/app/controllers/oauth/openkylin_controller.rb @@ -0,0 +1,84 @@ +class Oauth::OpenkylinController < Oauth::BaseController + def bind + begin + login = params[:login] + mail = params[:mail] || nil + callback_url = params[:callback_url] + token = params[:token] + + ::OauthEducoderForm.new({ login: login, token: token, callback_url: callback_url }).validate! + + open_user = OpenUsers::Openkylin.find_by(uid: login) || OpenUsers::Openkylin.find_by(uid: mail) + + if open_user.present? && open_user.user.present? && open_user.user.email_binded? + Rails.logger.info "######## open_user exist and open_user.user exsit and email is binded ok" + successful_authentication(open_user.user) + + redirect_to callback_url + else + Rails.logger.info "######## open user not exits" + user = User.find_by(login: login) || User.find_by(mail: mail) + + if user.is_a?(User) && !user.is_a?(AnonymousUser) + OpenUsers::Openkylin.create!(user: user, uid: login) + successful_authentication(user) + + redirect_to callback_url + else + redirect_to oauth_register_path(login: login, mail: mail, callback_url: callback_url) + end + end + rescue WechatOauth::Error => ex + render_error(ex.message) + end + end + + # 需要gitlink那边设置回调地址 + def create + begin + code = params['code'].to_s.strip + tip_exception("code不能为空") if code.blank? + + new_user = false + result = OpenkylinOauth::Service.access_token(code) + tip_exception("获取授权Token失败") if result['info'].blank? || result['info']['access_token'].blank? + result = OpenkylinOauth::Service.user_info(result['info']['access_token']) + + # 存在该用户 + login = result['data']['entity']['username'] + mail = result['data']['entity']['email'] + mail = "#{login}@gitlink.org.cn" if mail.blank? + nickName = result['data']['entity']['nickName'] + has_user = User.find_by(mail: mail) + new_user = false + if has_user.present? + successful_authentication(has_user) + else + open_user = OpenUsers::Openkylin.find_by(uid: login) + 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_user_login('P') + reg_result = autologin_register(login, mail, "Ec#{login}2021#", 'openkylin', nil, nickName) + Rails.logger.info("[KylinOauth] [reg_result] #{reg_result} ") + if reg_result.present? && reg_result[:message].blank? + open_user = OpenUsers::Openkylin.create!(user_id: reg_result[:user][:id], uid: login, extra: result) + successful_authentication(open_user.user) + else + tip_exception(reg_result.present? ? reg_result[:message] : "授权失败") + end + else + OpenUsers::Openkylin.create!(user: current_user, uid: login, extra: result) + end + end + end + redirect_to root_path(new_user: new_user) + rescue Exception => ex + render_error(ex.message) + end + end + + +end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index d2752cff..2a28e64c 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -59,7 +59,7 @@ class SettingsController < ApplicationController } @third_party << { name: 'Openkyin', - url: GitlinkOauth.oauth_url + url: OpenkylinOauth.oauth_url } end diff --git a/app/libs/openkylin_oauth.rb b/app/libs/openkylin_oauth.rb new file mode 100644 index 00000000..c57147f9 --- /dev/null +++ b/app/libs/openkylin_oauth.rb @@ -0,0 +1,18 @@ +module OpenkylinOauth + 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}/auth/authorize?client_id=#{client_id}&redirect_uri=#{URI.encode_www_form_component(redirect_uri)}" + end + + end +end \ No newline at end of file diff --git a/app/libs/openkylin_oauth/service.rb b/app/libs/openkylin_oauth/service.rb new file mode 100644 index 00000000..d6738b6f --- /dev/null +++ b/app/libs/openkylin_oauth/service.rb @@ -0,0 +1,36 @@ +require 'oauth2' + +module OpenkylinOauth::Service + module_function + + def request(method, url, params) + begin + Rails.logger.info("[KylinOauth] [#{method.to_s.upcase}] #{url} || #{params}") + + client = Faraday.new(url: OpenkylinOauth.base_url) + response = client.public_send(method, url, params) + result = JSON.parse(response.body) + + Rails.logger.info("[KylinOauth] [#{response.status}] #{result}") + + result + rescue Exception => e + raise Gitlink::TipException.new(e.message) + end + end + + def access_token(code) + Rails.logger.info("[KylinOauth] [code] #{code} ") + url = "/prod-api/oauth/token?code=#{code}&client_id=#{OpenkylinOauth.client_id}&client_secret=#{OpenkylinOauth.client_secret}&redirect_uri=#{URI.encode_www_form_component(OpenkylinOauth.redirect_uri)}" + Rails.logger.info("[KylinOauth] [url] #{url} ") + client = Faraday.new(url: OpenkylinOauth.base_url) + response = client.public_send(:get, url) + Rails.logger.info("[KylinOauth] [response.body] #{response.body} ") + result = JSON.parse(response.body) + result + end + + def user_info(access_token) + request(:get, '/prod-api/getOAuthInfo', { access_token: access_token }) + end +end \ No newline at end of file diff --git a/app/models/open_users/openkylin.rb b/app/models/open_users/openkylin.rb new file mode 100644 index 00000000..32ee64f2 --- /dev/null +++ b/app/models/open_users/openkylin.rb @@ -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::Openkylin < OpenUser + def nickname + extra&.[]('nickname') + end + + def en_type + 'openkylin' + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 5e16dbe1..0b409403 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -113,7 +113,7 @@ class User < Owner # trustie: 来自Trustie平台 # forge: 平台本身注册的用户 # military: 军科的用户 - enumerize :platform, in: [:forge, :educoder, :trustie, :military], default: :forge, scope: :shallow + enumerize :platform, in: [:forge, :educoder, :trustie, :military, :gitlink, :openkylin], default: :forge, scope: :shallow belongs_to :laboratory, optional: true has_one :user_extension, dependent: :destroy @@ -801,6 +801,15 @@ class User < Owner login end + # 生成数字账号 + CODES = %W(0 1 2 3 4 5 6 7 8 9) + def self.generate_user_login type + code = CODES.sample(8).join + code = type + code.to_s + return User.generate_user_login(type) if User.where(login: code).present? + code + end + def bind_open_user?(type) case type when 'wechat' then wechat_open_user.present? diff --git a/app/services/gitea/client_service.rb b/app/services/gitea/client_service.rb index e2bd9d49..8440c62a 100644 --- a/app/services/gitea/client_service.rb +++ b/app/services/gitea/client_service.rb @@ -233,7 +233,7 @@ class Gitea::ClientService < ApplicationService end def fix_body(body) - return [body, nil] if body.is_a?(Array) || body.is_a?(Hash) + return [body, nil] if body.is_a?(Array) body['message'].blank? ? [body, nil] : [nil, body['message']] end diff --git a/app/views/settings/show.json.jbuilder b/app/views/settings/show.json.jbuilder index 53fc8caa..192d354e 100644 --- a/app/views/settings/show.json.jbuilder +++ b/app/views/settings/show.json.jbuilder @@ -35,6 +35,7 @@ json.setting do json.common @common # json.third_party @third_party + json.third_party_test @third_party json.professional_field do json.array! @professional_fields diff --git a/config/initializers/openkylin_oauth_init.rb b/config/initializers/openkylin_oauth_init.rb new file mode 100644 index 00000000..27c3d6c2 --- /dev/null +++ b/config/initializers/openkylin_oauth_init.rb @@ -0,0 +1,16 @@ +oauth_config = {} +begin + config = Rails.application.config_for(:configuration) + oauth_config = config.dig('oauth', 'openkylin') + raise 'oauth openkylin config missing' if oauth_config.blank? +rescue => ex + raise ex if Rails.env.production? + + puts %Q{\033[33m [warning] openkylin oauth config or configuration.yml missing, + please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m} +end + +OpenkylinOauth.client_id = oauth_config['client_id'] +OpenkylinOauth.client_secret = oauth_config['client_secret'] +OpenkylinOauth.base_url = oauth_config['base_url'] +OpenkylinOauth.redirect_uri = oauth_config['redirect_uri'] diff --git a/config/routes.rb b/config/routes.rb index 2e9dc044..643a22cc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -416,6 +416,7 @@ Rails.application.routes.draw do get '/auth/wechat/callback', to: 'oauth/wechat#create' get '/auth/educoder/callback', to: 'oauth/educoder#create' get '/auth/gitlink/callback', to: 'oauth/gitlink#create' + get '/auth/openkylin/callback', to: 'oauth/openkylin#create' resource :bind_user, only: [:create] resources :hot_keywords, only: [:index]