| @@ -0,0 +1,78 @@ | |||||
| html{margin:0px;padding: 0px;font-size: 14px;font-family: "微软雅黑","宋体";} | |||||
| body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td { | |||||
| margin: 0; | |||||
| padding: 0; | |||||
| } | |||||
| .IndexContent{ | |||||
| height: 100vh; | |||||
| width: 100%; | |||||
| position: relative; | |||||
| background-image: url('/images/oauth/backImg.png'); | |||||
| background-repeat: no-repeat; | |||||
| background-size: cover; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| flex-direction: column; | |||||
| } | |||||
| .indexLogo{ | |||||
| width:80px; | |||||
| margin-bottom: 35px; | |||||
| } | |||||
| .indexPanel{ | |||||
| width: 580px; | |||||
| min-height: 400px; | |||||
| background-color: #fff; | |||||
| box-shadow: 0px 2px 10px 5px rgba(0,0,0,0.05); | |||||
| border-radius: 5px; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .indexTitle{ | |||||
| height: 75px; | |||||
| line-height: 75px; | |||||
| font-size: 18px; | |||||
| color:#333; | |||||
| text-align: center; | |||||
| border-bottom: 1px solid #eee; | |||||
| } | |||||
| .indexInfo{ | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: flex-start; | |||||
| } | |||||
| .indexInfos{ | |||||
| padding:40px 60px; | |||||
| } | |||||
| .indexInfo > span{ | |||||
| color: #333; | |||||
| font-size: 16px; | |||||
| margin-top: 5px; | |||||
| } | |||||
| .indexInfo input{ | |||||
| width: 100%; | |||||
| height:40px; | |||||
| border-radius: 2px; | |||||
| border:1px solid #eee; | |||||
| margin-top: 5px; | |||||
| padding:0px 0px 0px 8px; | |||||
| outline: none; | |||||
| } | |||||
| .indexInfo .checkInfo{ | |||||
| height: 15px; | |||||
| color: red; | |||||
| } | |||||
| .indexBtn{ | |||||
| text-align: center; | |||||
| margin-top: 20px; | |||||
| } | |||||
| .indexSubmit{ | |||||
| width: 50%; | |||||
| height: 32px; | |||||
| line-height: 32px; | |||||
| background-color: #1890FF; | |||||
| border:none; | |||||
| color: #fff; | |||||
| border-radius: 2px; | |||||
| cursor: pointer; | |||||
| outline: none; | |||||
| } | |||||
| @@ -13,24 +13,12 @@ class AccountsController < ApplicationController | |||||
| password = params[:password] | password = params[:password] | ||||
| platform = (params[:platform] || 'forge')&.gsub(/\s+/, "") | platform = (params[:platform] || 'forge')&.gsub(/\s+/, "") | ||||
| @user = User.new(admin: false, login: username, mail: email, type: "User") | |||||
| @user.password = password | |||||
| @user.platform = platform | |||||
| @user.activate | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) | |||||
| if interactor.success? | |||||
| gitea_user = interactor.result | |||||
| result = Gitea::User::GenerateTokenService.new(username, password).call | |||||
| @user.gitea_token = result['sha1'] | |||||
| @user.gitea_uid = gitea_user['id'] | |||||
| if @user.save! | |||||
| UserExtension.create!(user_id: @user.id) | |||||
| render_ok({user: {id: @user.id, token: @user.gitea_token}}) | |||||
| end | |||||
| result = autologin_register(username, email, password, platform) | |||||
| if result[:message].blank? | |||||
| render_ok({user: result[:user]}) | |||||
| else | else | ||||
| render_error(interactor.error) | |||||
| render_error(result[:message]) | |||||
| end | end | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -9,7 +9,8 @@ class ApplicationController < ActionController::Base | |||||
| include GitHelper | include GitHelper | ||||
| include LoggerHelper | include LoggerHelper | ||||
| include LoginHelper | include LoginHelper | ||||
| include RegisterHelper | |||||
| protect_from_forgery prepend: true, unless: -> { request.format.json? } | protect_from_forgery prepend: true, unless: -> { request.format.json? } | ||||
| before_action :check_sign | before_action :check_sign | ||||
| @@ -0,0 +1,28 @@ | |||||
| module RegisterHelper | |||||
| extend ActiveSupport::Concern | |||||
| def autologin_register(username, email, password, platform= '') | |||||
| result = {message: nil, user: nil} | |||||
| user = User.new(admin: false, login: username, mail: email, type: "User") | |||||
| user.password = password | |||||
| user.platform = platform | |||||
| user.activate | |||||
| interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) | |||||
| if interactor.success? | |||||
| gitea_user = interactor.result | |||||
| result = Gitea::User::GenerateTokenService.new(username, password).call | |||||
| user.gitea_token = result['sha1'] | |||||
| user.gitea_uid = gitea_user['id'] | |||||
| if user.save! | |||||
| UserExtension.create!(user_id: user.id) | |||||
| result[:user] = {id: user.id, token: user.gitea_token} | |||||
| end | |||||
| else | |||||
| result[:message] = interactor.error | |||||
| end | |||||
| result | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,36 @@ | |||||
| class Oauth::EducoderController < Oauth::BaseController | |||||
| def bind | |||||
| begin | |||||
| login = params[:login] | |||||
| callback_url = params[:callback_url] | |||||
| oauth_token = params[:key] | |||||
| raw_pay_load = params[:raw_pay_load] | |||||
| ::OauthEducoderForm.new({login: login, oauth_token: oauth_token, callback_url: callback_url, raw_pay_load: raw_pay_load}).validate! | |||||
| open_user= OpenUser::Educoder.find_by(uid: login) | |||||
| if open_user.present? && open_user.user.present? && open_user.user.email_bind? | |||||
| # 存在说明绑定了,验证信息是否齐全, | |||||
| if current_user != open_user.user | |||||
| logout_user | |||||
| successful_authentication(open_user.user) | |||||
| end | |||||
| redirect_to callback_url | |||||
| else | |||||
| # 未存在需要进行绑定 | |||||
| if current_user.blank? || !current_user.logged? | |||||
| # forge平台未登录 | |||||
| redirect_to oauth_register_path(user_id: login, callback_url: callback_url) | |||||
| else | |||||
| # forge平台已登录 | |||||
| OpenUsers::Educoder.create!(user: current_user, uid: login) | |||||
| redirect_to callback_url | |||||
| end | |||||
| end | |||||
| rescue WechatOauth::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,4 +1,6 @@ | |||||
| class OauthController < ApplicationController | class OauthController < ApplicationController | ||||
| layout "oauth_register", only: [:register] | |||||
| DEFAULT_PASSWORD = "a12345678" | DEFAULT_PASSWORD = "a12345678" | ||||
| TOKEN_CALL_BACK = "/oauth/get_token_callback" | TOKEN_CALL_BACK = "/oauth/get_token_callback" | ||||
| USER_INFO = "/oauth/userinfo" | USER_INFO = "/oauth/userinfo" | ||||
| @@ -51,4 +53,24 @@ class OauthController < ApplicationController | |||||
| def get_token_callback | def get_token_callback | ||||
| end | end | ||||
| def register | |||||
| # redirect_to params[:callback_url] | |||||
| end | |||||
| def auto_register | |||||
| login = params[:login] | |||||
| email = params[:email] | |||||
| password = params[:login] | |||||
| platform = params[:plathform] || 'forge' | |||||
| result = autologin_register(login, email, password, platform) | |||||
| if result[:message].blank? | |||||
| redirect_to params[:callback_url] | |||||
| else | |||||
| render :action => "auto_register" | |||||
| end | |||||
| end | |||||
| end | end | ||||
| @@ -0,0 +1,37 @@ | |||||
| class OauthEducoderForm | |||||
| include ActiveModel::Model | |||||
| attr_accessor :login, :oauth_token, :callback_url, :raw_pay_load | |||||
| validates :login, presence: true | |||||
| validates :oauth_token, presence: true | |||||
| validates :callback_url, presence: true | |||||
| validates :raw_pay_load, presence: true | |||||
| validate :check_oauth_token! | |||||
| validate :check_callback_url! | |||||
| def checke_raw_pay_load! | |||||
| secret = OauthEducoder.config[:access_key_secret] | |||||
| before_raw_pay_load = "#{login}#{secret}#{Time.now.to_i/60-1}" | |||||
| now_raw_pay_load = "#{login}#{secret}#{Time.now.to_i/60-1}" | |||||
| if raw_pay_load != Digest::SHA1.hexdigest(now_raw_pay_load) || raw_pay_load != Digest::SHA1.hexdigest(before_raw_pay_load) | |||||
| raise '你的请求无效值无效.' | |||||
| end | |||||
| end | |||||
| def checke_raw_pay_load! | |||||
| secret = OauthEducoder.config[:access_key_secret] | |||||
| raise 'oauth_token值无效.' if oauth_token != secret | |||||
| end | |||||
| def check_callback_url! | |||||
| request_host = URI.parse(callback_url).host | |||||
| callback_url = OauthEducoder.config[:callback_url_host] | |||||
| raise 'callback_url参数无效.' if request_host != callback_url | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,20 @@ | |||||
| module OauthEducoder | |||||
| class << self | |||||
| def config | |||||
| educoder_config = {} | |||||
| begin | |||||
| config = Rails.application.config_for(:configuration).symbolize_keys! | |||||
| educoder_config = config[:oauth][:educoder].symbolize_keys! | |||||
| raise 'oauth educoder config missing' if educoder_config.blank? | |||||
| rescue => ex | |||||
| raise ex if Rails.env.production? | |||||
| puts %Q{\033[33m [warning] educoder config or configuration.yml missing, | |||||
| please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m} | |||||
| educoder_config = {} | |||||
| end | |||||
| educoder_config | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,9 @@ | |||||
| class OpenUsers::EduCoder < OpenUser | |||||
| def nickname | |||||
| extra&.[]('nickname') | |||||
| end | |||||
| def en_type | |||||
| 'educoder' | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,13 @@ | |||||
| <html> | |||||
| <head> | |||||
| <%= csrf_meta_tags %> | |||||
| <%= csp_meta_tag %> | |||||
| <%= stylesheet_link_tag 'oauth', media: 'all','data-turbolinks-track': 'reload' %> | |||||
| </head> | |||||
| <body> | |||||
| <div class="IndexContent"> | |||||
| <%= image_tag('/images/oauth/logo.png') %> | |||||
| <%= yield %> | |||||
| </div> | |||||
| </body> | |||||
| </html> | |||||
| @@ -0,0 +1,54 @@ | |||||
| <div class="indexPanel"> | |||||
| <p class="indexTitle">完善信息,进入比赛</p> | |||||
| <div class="indexInfos"> | |||||
| <%= form_tag(oauth_auto_register_path, method: :post, class: 'form-inline search-form flex-1') do %> | |||||
| <%= hidden_field_tag 'callback_url', params[:callback_url] %> | |||||
| <div class="indexInfo"> | |||||
| <span>用户名:</span> | |||||
| <%= text_field_tag :mail, params[:login], placeholder: '请输入用户名', disabled: true, id: 'login' %> | |||||
| <p class="checkInfo loginCheck"><span></span></p> | |||||
| </div> | |||||
| <div class="indexInfo"> | |||||
| <span>邮箱:</span> | |||||
| <%= text_field_tag :mail, '', placeholder: '请输入绑定邮箱', maxlength: 40, id: 'email' %> | |||||
| <p class="checkInfo emailCheck"><span></span></p> | |||||
| </div> | |||||
| <div class="indexInfo"> | |||||
| <span>密码:</span> | |||||
| <%= password_field_tag :password, '', placeholder: '请输入账号密码', id: 'password' %> | |||||
| <p class="checkInfo passwordCheck"><span></span></p> | |||||
| </div> | |||||
| <div class="indexBtn"> | |||||
| <button class="indexSubmit" onclick="sureSubmit();">确定</button> | |||||
| </div> | |||||
| <% end %> | |||||
| </div> | |||||
| </div> | |||||
| <script type="text/javascript"> | |||||
| function sureSubmit(){ | |||||
| var login = $("#login").val(); | |||||
| var email = $("#email").val(); | |||||
| var password = $("#password").val(); | |||||
| alert(email) | |||||
| if(!login){ | |||||
| $(".loginCheck span").html("请输入账号"); | |||||
| return; | |||||
| }else{ | |||||
| $(".loginCheck span").html(""); | |||||
| } | |||||
| if(!login){ | |||||
| $(".loginCheck span").html("请输入账号"); | |||||
| return; | |||||
| }else{ | |||||
| $(".emailCheck span").html(""); | |||||
| } | |||||
| if(!password){ | |||||
| $(".passwordCheck span").html("请输入账号密码"); | |||||
| return; | |||||
| }else{ | |||||
| $(".passwordCheck span").html(""); | |||||
| } | |||||
| } | |||||
| </script> | |||||
| @@ -12,5 +12,4 @@ Rails.application.config.assets.paths << Rails.root.join('vendor/assets') | |||||
| # Precompile additional assets. | # Precompile additional assets. | ||||
| # application.js, application.css, and all non-JS/CSS in the app/assets | # application.js, application.css, and all non-JS/CSS in the app/assets | ||||
| # folder are already added. | # folder are already added. | ||||
| Rails.application.config.assets.precompile += %w( admin.js admin.css college.js college.css cooperative.js cooperative.css ) | |||||
| Rails.application.config.assets.precompile += %w( admin.js admin.css college.js college.css cooperative.js cooperative.css oauth.css ) | |||||
| @@ -13,6 +13,11 @@ Rails.application.routes.draw do | |||||
| get 'auth/qq/callback', to: 'oauth/qq#create' | get 'auth/qq/callback', to: 'oauth/qq#create' | ||||
| get 'auth/failure', to: 'oauth/base#auth_failure' | get 'auth/failure', to: 'oauth/base#auth_failure' | ||||
| get 'auth/cas/callback', to: 'oauth/cas#create' | get 'auth/cas/callback', to: 'oauth/cas#create' | ||||
| get 'oauth/bind', to: 'oauth/educoder#bind' | |||||
| get 'oauth/register', to: 'oauth#register' | |||||
| post 'oauth/auto_register', to: 'oauth#auto_register' | |||||
| resources :edu_settings | resources :edu_settings | ||||
| scope '/api' do | scope '/api' do | ||||