Merge branch 'educoder' into develop

dev_SaaS
cxt 6 years ago
commit d3fee9b877

@ -159,6 +159,7 @@ module Mobile
mount Apis::Sources
mount Apis::Careers
mount Apis::Assets
mount Apis::Ecloud

@ -0,0 +1,19 @@
# encoding=utf-8
module Mobile
module Apis
class Ecloud < Grape::API
# before {authenticate!}
content_type :json, 'application/json;charset=UTF-8'
resources :ecloud do
desc "ecloud接口测试"
post 'list' do
EcloudService.new.list
end
end
end
end
end

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

@ -0,0 +1,3 @@
// Place all the styles related to the oauth controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

@ -2,6 +2,7 @@
class EcCourseAchievementMethodsController < ApplicationController
before_filter :find_target, :only => [:edit_course_target, :create_evaluation_methods]
skip_before_filter :verify_authenticity_token, :only => [:create_evaluation_methods, :sync_course_data]
before_filter :find_ec_course, :only => [:index]
include ApplicationHelper
@ -59,11 +60,9 @@ class EcCourseAchievementMethodsController < ApplicationController
###############################################################
def index
achievement_list = []
# 具体工程课程
ec_course = EcCourse.find params[:ec_course_id]
# 课程的所有目标
targets = ec_course.ec_course_targets
targets = @ec_course.ec_course_targets
targets.each do |target|
evaluate_data = []
# 评价环节
@ -95,7 +94,7 @@ class EcCourseAchievementMethodsController < ApplicationController
end
achievement_list << {target_id: target.id, target_evaluate_data: evaluate_data}
end
render :json => {achievement_list: achievement_list}
render :json => {achievement_list: achievement_list, is_manager: @is_manager}
end
@ -306,4 +305,13 @@ class EcCourseAchievementMethodsController < ApplicationController
@target = EcCourseTarget.find params[:ec_course_target_id]
end
def find_ec_course
@ec_course = EcCourse.find(params[:ec_course_id])
@year = @ec_course.ec_year
@ec_major_school = @year.ec_major_school
@template_major = User.current.admin? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) ||
@ec_major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id)
@is_manager = @template_major || @ec_course.ec_course_users.pluck(:user_id).include?(User.current.id)
end
end

@ -47,6 +47,8 @@ class EcCourseSupportsController < ApplicationController
course_support_data = []
max_support_count = 0
subitems_count = 0
major_school = @year.ec_major_school
is_manager = User.current.admin? || major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id)
ec_graduation_requirements.each_with_index do |gr, i|
logger.info("#############index:#{i}#####_ec_gradiation_reqiorements: #{gr.id}")
subitems_count += gr.ec_graduation_subitems.count
@ -60,7 +62,12 @@ class EcCourseSupportsController < ApplicationController
course_data << { name: name, top_relation: cs.top_relation, weigths: cs.weigths}
end
gs.ec_course_supports.count > max_support_count && max_support_count = gs.ec_course_supports.count
course_support_data << {sequence_num: sequence_num, ec_graduation_subitem_id: gs.id, course_data: course_data, num_total: gs.ec_course_supports.count, weights_total: weigths_sum}
course_support_data << {sequence_num: sequence_num,
sequence_title: gs.content,
ec_graduation_subitem_id: gs.id,
course_data: course_data,
num_total: gs.ec_course_supports.count,
weights_total: weigths_sum}
end
end
render :json => {ec_year_id: @year.id,
@ -69,7 +76,8 @@ class EcCourseSupportsController < ApplicationController
subitems_url: "#{graduation_requirement_ec_major_school_ec_year_path(@year, :ec_major_school_id => @year.ec_major_school_id)}",
course_count: @year.ec_courses.count,
course_url: "#{ec_course_setting_ec_major_school_ec_year_path(@year, :ec_major_school_id => @year.ec_major_school_id)}",
max_support_count: max_support_count}
max_support_count: max_support_count,
is_manager: is_manager}
end
# 毕业要求vs课程体系 详情页面

@ -429,7 +429,7 @@ class EcCoursesController < ApplicationController
{score: 70, level: ""},
{score: 60, level: ""}]
end
render :json => {levels: ls}
render :json => {levels: ls, is_manager: @is_manager}
}
end
end
@ -630,7 +630,7 @@ class EcCoursesController < ApplicationController
# 遍历学生成绩统计数据
student_scores.each do |sc|
sub_ecss = EcCourseStudentScore.where(:ec_course_id => @ec_course.id, :ec_year_student_id => sc.ec_year_student_id).first
sub_score = base_score == 0 ? 0 : ((sc.try(:score).to_f/base_score) * percentage).round(3)
sub_score = base_score == 0 || sc.try(:score).nil? ? 0 : ((sc.try(:score).to_f/base_score) * percentage).round(3)
if sub_ecss
ess_target = sub_ecss.ec_student_score_targets.where(:ec_course_target_id => target.id,

@ -219,10 +219,10 @@ class GamesController < ApplicationController
@had_passed_testsests_public_count = had_test.blank? ? 0 : had_test.select{|had_test| had_test.result == true && had_test.is_public == true}.count
@mirror_name = @myshixun.mirror_name
@final_score = ((@shixun.status <= 1) ? 0 : @game.final_score.to_i)
if @myshixun.shixun.status <= 1 || (@game.final_score != 0 && @game.answer_open?)
if @myshixun.shixun.status <= 1 || (@game.final_score != 0 && @game.answer_open > 0)
@gold = 0
else
if @game.answer_open? && @game.final_score ==0
if @game.answer_open > 0 && @game.final_score ==0
@gold = -@game_challenge.score.to_i
else
@gold = @game.final_score.to_i

@ -510,7 +510,7 @@ class MyshixunsController < ApplicationController
challenge.path.split("").each do |path|
game_passed_code(game.id, path, myshixun.try(:gpid), 1)
end
if !game.answer_open && (challenge.shixun.try(:status) > 1) # 如果没有查看答案,则获得该关卡得分
if game.answer_open == 0 && (challenge.shixun.try(:status) > 1) # 如果没有查看答案,则获得该关卡得分
reward_grade(game.user, game.id, 'Game', challenge.score)
reward_experience(game.user, game.id, 'Game', challenge.score)
game.update_attributes!(:final_score => challenge.score)

@ -0,0 +1,167 @@
#encoding: utf-8
class OauthController < ApplicationController
include ApplicationHelper
before_filter :user_setup
before_filter :require_login, only: [:authorize]
skip_before_filter :verify_authenticity_token, only: [:token]
def index
render 'oauth/index', layout: false
end
# 客户端申请认证的URI包含以下参数
#
# response_type表示授权类型必选项此处的值固定为”code”
# client_id表示客户端的ID必选项
# redirect_uri表示重定向URI可选项
# scope表示申请的权限范围可选项
# state表示客户端的当前状态可以指定任意值最好是随机字符串认证服务器会原封不动地返回这个值可防止CSRF攻击
#
# 这个页显示授权页如果授权成功返回redirect_uri+code
#
#
# 服务器回应客户端的URI包含以下参数
#
# code表示授权码必选项。该码的有效期应该很短通常设为10分钟客户端只能使用该码一次 否则会被授权服务器拒绝。该码与客户端ID和重定向URI是一一对应关系。
# state如果客户端的请求中包含这个参数认证服务器的回应也必须一模一样包含这个参数。
def authorize
begin
#参数检查
raise "response_type只能为code" unless params["response_type"] == "code"
raise "client_id为必传项" unless params["client_id"].present?
raise "redirect_uri为必传项" unless params["redirect_uri"].present?
config = OauthConfig.where(client_id: params["client_id"], redirect_uri: params["redirect_uri"]).first
raise "client_id或redirect_uri不正确" unless config
@data = params
if params[:gen_code]
## 检查通过生成code
oauth = Oauth.create!(client_id: config.client_id,
client_secret: config.client_secret,
redirect_uri: config.redirect_uri,
user_id: User.current.id
)
code = oauth.gen_code
redirect_to params["redirect_uri"] + "?code=#{code}&state=#{params[:state]}"
else
render 'oauth/authorize', :layout => 'forge'
end
rescue => e
logger.error e
render :text => e.message
end
end
def test_callback
# 申请 token
#
client_id = "88d893c5a345313e7b8c6fcf23d3d024ee08d5e41ce120c3448b6eea77d8de30"
client_secret = "e9240cc5fc913741db5aea93f2986a8ea0631bb67f7c00e41e491b95d9619e64"
redirect_uri = "http://localhost:3000/oauth/cb"
url = "http://127.0.0.1:3000/oauth/token?grant_type=authorization_code&code=#{params['code']}&redirect_uri=#{redirect_uri}&client_id=#{client_id}&client_secret=#{client_secret}"
render text: url
end
# 客户端向认证服务器申请令牌的HTTP请求包含以下参数
#
# grant_type表示使用的授权模式必选项此处的值固定为”authorization_code”。
# code表示上一步获得的授权码必选项。
# redirect_uri表示重定向URI必选项且必须与A步骤中的该参数值保持一致。
# client_id表示客户端ID必选项。
# client_secret: 表示客户端密钥,必选项。
#
#
# 认证服务器核对了授权码和”重定向URI”确认无误后向客户端发送访问令牌access token和更新令牌refresh token
#
# 认证服务器发送的HTTP回复包含以下内容
#
# access_token表示访问令牌必选项。
# token_type表示令牌类型该值大小写不敏感必选项可以是bearer类型或mac类型。
# expires_in表示过期时间单位为秒。如果省略该参数必须其他方式设置过期时间。
# refresh_token表示更新令牌用来获取下一次的访问令牌可选项。
# scope表示权限范围如果与客户端申请的范围一致此项可省略。
def token
begin
res = {}
if params[:grant_type] == 'authorization_code'
raise "code必传" unless params["code"]
raise "client_id必传" unless params["client_id"]
raise "client_secret必传" unless params["client_secret"]
raise "code错误或已超时" unless Oauth.code_valid?(params["code"])
oauth = Oauth.auth_code(params["code"], params["client_id"], params["client_secret"])
raise "认证不通过" unless oauth
## 生成 token
#
oauth.gen_token
oauth.reload
res = {
access_token: oauth.access_token,
token_type: 'bearer',
expires_in: oauth.token_expires_in,
refresh_token: oauth.refresh_token
}
end
render json: res.to_json
rescue => e
logger.error e
render text: e.message
end
end
def get_userinfo
user = Oauth.auth(params["access_token"])
user_info = {}
if user
user_info = {
token: user.id,
login: user.login,
avatar_url: "https://openi.org.cn/images/" + url_to_avatar(user),
name: user.show_name,
email: user.mail,
allow: (user.login == "guange"||user.phone=='15607313899') ? 1 : 0
}
end
render json: user_info.to_json
end
private
def require_login
require "base64"
if !User.current.logged?
redirect_to '/login?back_url64=' + Base64.urlsafe_encode64(request.original_url)
end
end
include Trustie::Http
end

@ -0,0 +1,2 @@
module OauthHelper
end

@ -0,0 +1,53 @@
require 'base64'
class Oauth < ActiveRecord::Base
attr_accessible :client_id, :client_secret, :redirect_uri, :access_token,
:refresh_token, :token_created_at,:token_expires_in, :user_id
belongs_to :user
def gen_code
code = Base64.urlsafe_encode64 Digest::MD5.hexdigest "#{Time.now}-#{Random.new_seed}"
update_column(:code, code)
code
end
def gen_token
access_token = Digest::MD5.hexdigest "#{Time.now}-#{Random.new_seed}"
refresh_token = Digest::MD5.hexdigest "#{Random.new_seed}-#{Time.now}-#{Random.new_seed}"
self.update_attributes(access_token: access_token,
refresh_token: refresh_token,
token_created_at: Time.now.to_i,
token_expires_in: Time.now.to_i + 24*60*60,
)
end
def self.code_valid?(code)
# 1. 是否存在
oauth = Oauth.where(code: code).order("ID desc").first
return false unless oauth
# 2. 是否超过10分钟
return false if Time.now.to_i - oauth.created_at.to_i > 10*60
# 3. 是否有使用过
return false if oauth.access_token.present?
return true
end
def self.auth_code(code, client_id, client_secret)
Oauth.where(code: code, client_id: client_id, client_secret: client_secret).order('id desc').first
end
def self.auth(access_token)
oauth = self.find_by_access_token(access_token)
return nil unless oauth
oauth.user
end
end

@ -0,0 +1,3 @@
class OauthConfig < ActiveRecord::Base
attr_accessible :client_id, :client_secret, :redirect_uri, :scope
end

@ -0,0 +1,6 @@
class EcloudService
def list
return {status: 0, message: "test"}
end
end

@ -43,7 +43,7 @@ class GamesService
# 高性能取上一关、下一关
prev_game = Game.prev_identifier(shixun.id, game.myshixun_id, game_challenge.position)
next_game = if current_user.is_certification_teacher || shixun_manager(shixun, current_user) || game.status == 2
next_game = if current_user.is_certification_teacher || shixun_manager(shixun, current_user) || game.status || shixun.task_pass
Game.next_game(shixun.id, game.myshixun_id, game_challenge.position).try(:identifier)
end
@ -233,7 +233,7 @@ class GamesService
is_teacher = (current_user.user_extensions.identity == 0)
is_certification_teacher = current_user.is_certification_teacher
# 这几种情况可以直接查看答案的:实训未发布;当前用户为实训管理员;已经查看过答案;平台认证的老师;
if (@shixun.status < 2 || shixun_manager(@shixun, current_user) || @game.answer_open || is_certification_teacher)
if (@shixun.status < 2 || shixun_manager(@shixun, current_user) || @game.answer_open == 1 || is_certification_teacher)
Rails.logger.info("answer#{params[:identifier]}#### user is #{current_user.id}, status is #{@shixun.status}, manager is #{shixun_manager(@shixun, current_user)}, open #{@game.answer_open}, cer #{is_certification_teacher}")
if challenge.st == 0
result = challenge.try(:answer)
@ -258,7 +258,7 @@ class GamesService
challenge_score = challenge.try(:score)
final_score = @game.final_score
if current_user.grade.to_i - challenge_score > 0
unless @game.answer_open # 如果这是第一次查看答案
if @game.answer_open == 0 # 如果这是第一次查看答案
if challenge.st == 0
final_score = final_score - challenge_score
# 积分消耗情况记录
@ -697,7 +697,7 @@ class GamesService
if had_passed && !game.had_passed?
game.update_attributes(:status => 2, :end_time => Time.now)
# TPM实训已发布并且没有查看答案
if shixun.is_published? && !game.answer_open
if shixun.is_published? && game.answer_open == 0
# 查看答案的时候处理final_scor和扣分记录
experience = score
reward_grade(myshixun.owner, game.id, 'Game', score)
@ -796,7 +796,7 @@ class GamesService
if game_status == 2 # 通关
if shixun.status > 1
score = game.final_score # 查看答案的时候有对最终获得金币进行处理
experience = game.answer_open ? 0 : game_challenge.score.to_i
experience = game.answer_open > 0 ? 0 : game_challenge.score.to_i
else
score = 0
experience = 0
@ -930,7 +930,8 @@ class GamesService
end
#end
myshixun_job = Base64.urlsafe_encode64("myshixun_#{myshixun.id}")
StudentWork.where(:myshixun_id => myshixun.id).update_all(:myshixun_id => nil, :work_status => 0)
StudentWork.where(:myshixun_id => myshixun.id).update_all(:myshixun_id => 0, :work_status => 0, :work_score => nil, :final_score => nil,
:cost_time => 0, :update_time => nil, :compelete_status => 0, :commit_time => nil)
# myshixun.destroy
myshixun.delete
# 主从复制出现脏读的情况

@ -26,7 +26,7 @@
<% end %>
</li>
<% end %>
<% else %>
<% elsif @template_major %>
<form id="form_data_for_requirements">
<div class="clearfix ml30 mr30 pt20 pb20 bor-top-greyE" id="requirementNew">
<p class="df mb20"><input type="hidden" name="year_id" value="<%= @year.id %>">

@ -49,7 +49,7 @@
<!--</span>-->
</span>
<span class="column-2 fr edu-txt-center">
<% if @major_manager && !@major_school.template_major %>
<% if @major_manager && !@major_school.template_major || User.current.admin? %>
<a href="javascript:void(0);" onclick="delete_confirm_box_3('<%= ec_major_school_ec_year_path(year, :ec_major_school_id => @major_school) %>','您确定要删除吗?')" class="mr15 color-grey-c">删除</a>
<% end %>
<%#= link_to '删除', ec_major_school_ec_year_path(year, :ec_major_school_id => @major_school), method: :delete, :class => "mr15 color-grey-c", data: { confirm: '您确定要删除吗' } %>

@ -13,7 +13,7 @@
</li>
<% end %>
</ul>
<% elsif @ec_training_objective.present? %>
<% elsif @ec_training_objective.present? && @template_major && @ec_training_objective && @sub_training_objectives.count > 0 %>
<form id="edit_training_subitems">
<ul class="edu-back-white padding10-30" id="SubentryNewPanel">
<li class="df mb10">

@ -12,7 +12,7 @@
<a href="javascript:void(0)" class="defalutCancelbtn mr20 fr" onclick="CancelEditBtn();">取消</a>
</p>
</div>
<% else %>
<% elsif @template_major && @ec_training_objective && @sub_training_objectives.count > 0 %>
<div class="clearfix" id="targetEdit">
<textarea class="winput-100-130 mb10" id="training_obejctive"></textarea>
<p class="clearfix">

@ -1,9 +0,0 @@
Gitlab.configure do |config|
# config.endpoint = 'http://192.168.41.130:3000/trustie/api/v3' # API endpoint URL, default: ENV['GITLAB_API_ENDPOINT']
# config.private_token = 'cK15gUDwvt8EEkzwQ_63' # user's private token, default: ENV['GITLAB_API_PRIVATE_TOKEN']
config.endpoint = 'http://gitfast.trustie.net/api/v3' # API endpoint URL, default: ENV['GITLAB_API_ENDPOINT']
config.private_token = 'fPc_gBmEiSANve8TCfxW' # user's private token, default: ENV['GITLAB_API_PRIVATE_TOKEN']
# Optional
# config.user_agent = 'Custom User Agent' # user agent, default: 'Gitlab Ruby Gem [version]'
# config.sudo = 'user' # username for sudo mode, default: nil
end

@ -25,7 +25,14 @@
# 所有的 act: :act 变成 :act => :act
# Example: :via => :get ====> :via => :get
RedmineApp::Application.routes.draw do
RedmineApp::Application.routes.draw do ## oauth相关
match 'oauth', to: 'oauth#index'
match 'oauth/authorize', to: 'oauth#authorize', :via => [:get, :post]
match 'oauth/token', to: 'oauth#token', :via => :post
match 'oauth/cb', to: 'oauth#test_callback', :via => :get
match 'oauth/userinfo', to: 'oauth#get_userinfo', :via => :get
resources :ec_course_evaluations do
member do
match 'import_score', :via => [:post]

@ -1,5 +1,5 @@
class AddForbidCopyToShixun < ActiveRecord::Migration
def change
add_column :shixuns, :forbid_copy, :boolean, :default => 0
# add_column :shixuns, :forbid_copy, :boolean, :default => 0
end
end

@ -0,0 +1,44 @@
class CreateOauths < ActiveRecord::Migration
def change
create_table :oauths do |t|
t.string :client_id
t.string :client_secret
t.string :code
t.string :redirect_uri
t.string :scope
t.string :access_token
t.string :refresh_token
t.integer :token_created_at
t.integer :token_expires_in #过期时间
t.timestamps
end
add_column :oauths, :user_id, :integer, default: 0
add_index :oauths, :user_id
create_table :oauth_configs do |t|
t.string :client_id
t.string :client_secret
t.string :redirect_uri
t.string :scope
t.timestamps
end
OauthConfig.create(
client_id: '88d893c5a345313e7b8c6fcf23d3d024ee08d5e41ce120c3448b6eea77d8de30',
client_secret: 'e9240cc5fc913741db5aea93f2986a8ea0631bb67f7c00e41e491b95d9619e64',
redirect_uri: 'http://localhost:3000/oschina/login_cb',
scope: ''
)
end
end

@ -0,0 +1,40 @@
class AddPassedScoreForUsers < ActiveRecord::Migration
def up
games = Game.where("final_score = 0 and status = 2 and answer_open = 0 and created_at > '2019-03-09 00:00:00'").includes(:challenge)
puts "game_count: #{games.count}"
games.find_each do |game|
puts "#{game.id}"
challenge = game.challenge
# 选择题和实践题的分数
score = challenge.choose_score
user = game.user
game.update_column(:final_score, score)
# 奖励金币和提供记录
grade = Grade.where(:user_id => user.id, :container_id => game.id, :container_type => "Game").first
if grade.nil?
Grade.create!(:user_id => user.id,
:container_id => game.id,
:container_type => "Game",
:score => score,
:created_at => game.end_time || Time.now,
:updated_at => game.end_time || Time.now)
user.update_column(:grade, (score + user.grade.to_i))
end
# 经验奖励
experience = Experience.where(:user_id => user.id, :container_id => game.id, :container_type => "Game").first
if experience.nil?
Experience.create!(:user_id => user.id,
:container_id => game.id,
:container_type => "Game",
:score => score,
:created_at => game.end_time || Time.now,
:updated_at => game.end_time || Time.now)
user.update_column(:experience, (score + user.experience.to_i))
end
end
end
def down
end
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe OauthController, :type => :controller do
end

@ -0,0 +1,5 @@
FactoryGirl.define do
factory :oauth_config do
end
end

@ -0,0 +1,5 @@
FactoryGirl.define do
factory :oauth, class: 'Oauths' do
end
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe OauthConfig, :type => :model do
pending "add some examples to (or delete) #{__FILE__}"
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Oauths, :type => :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading…
Cancel
Save