diff --git a/Gemfile b/Gemfile index 281dd705..301a0ada 100644 --- a/Gemfile +++ b/Gemfile @@ -100,6 +100,7 @@ gem 'rails-i18n', '~> 5.1' # job gem 'sidekiq' gem 'sinatra' +gem 'whenever' gem "sidekiq-cron", "~> 1.1" # batch insert @@ -126,3 +127,7 @@ gem 'request_store' gem 'harmonious_dictionary', '~> 0.0.1' gem 'parallel', '~> 1.19', '>= 1.19.1' + +# log +gem 'multi_logger' + diff --git a/Gemfile.lock b/Gemfile.lock index cbd598f5..cd2a2428 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -98,6 +98,7 @@ GEM chromedriver-helper (2.1.1) archive-zip (~> 0.10) nokogiri (~> 1.8) + chronic (0.10.2) chunky_png (1.3.11) concurrent-ruby (1.1.6) connection_pool (2.2.2) @@ -181,6 +182,8 @@ GEM minitest (5.14.0) msgpack (1.3.3) multi_json (1.14.1) + multi_logger (0.2.0) + railties multi_xml (0.6.0) multipart-post (2.1.1) mustermann (1.1.1) @@ -420,6 +423,8 @@ GEM websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) + whenever (1.0.0) + chronic (>= 0.6.3) wkhtmltopdf-binary (0.12.5.4) xpath (3.2.0) nokogiri (~> 1.8) @@ -457,6 +462,7 @@ DEPENDENCIES jquery-rails kaminari (~> 1.1, >= 1.1.1) listen (>= 3.0.5, < 3.2) + multi_logger mysql2 (>= 0.4.4, < 0.6.0) oauth2 omniauth (~> 1.9.0) @@ -498,6 +504,7 @@ DEPENDENCIES tzinfo-data uglifier (>= 1.3.0) web-console (>= 3.3.0) + whenever wkhtmltopdf-binary BUNDLED WITH diff --git a/app/assets/javascripts/log.js b/app/assets/javascripts/log.js new file mode 100644 index 00000000..dee720fa --- /dev/null +++ b/app/assets/javascripts/log.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/sponsor_tiers.js b/app/assets/javascripts/sponsor_tiers.js new file mode 100644 index 00000000..dee720fa --- /dev/null +++ b/app/assets/javascripts/sponsor_tiers.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/sponsorships.js b/app/assets/javascripts/sponsorships.js new file mode 100644 index 00000000..dee720fa --- /dev/null +++ b/app/assets/javascripts/sponsorships.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/wallets.js b/app/assets/javascripts/wallets.js new file mode 100644 index 00000000..dee720fa --- /dev/null +++ b/app/assets/javascripts/wallets.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/log.scss b/app/assets/stylesheets/log.scss new file mode 100644 index 00000000..72261a51 --- /dev/null +++ b/app/assets/stylesheets/log.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the log controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/scaffolds.scss b/app/assets/stylesheets/scaffolds.scss new file mode 100644 index 00000000..60451880 --- /dev/null +++ b/app/assets/stylesheets/scaffolds.scss @@ -0,0 +1,84 @@ +body { + background-color: #fff; + color: #333; + margin: 33px; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { + color: #000; + + &:visited { + color: #666; + } + + &:hover { + color: #fff; + background-color: #000; + } +} + +th { + padding-bottom: 5px; +} + +td { + padding: 0 5px 7px; +} + +div { + &.field, &.actions { + margin-bottom: 10px; + } +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px 7px 0; + margin-bottom: 20px; + background-color: #f0f0f0; + + h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px -7px 0; + background-color: #c00; + color: #fff; + } + + ul li { + font-size: 12px; + list-style: square; + } +} + +label { + display: block; +} diff --git a/app/assets/stylesheets/sponsor_tiers.scss b/app/assets/stylesheets/sponsor_tiers.scss new file mode 100644 index 00000000..0b4b39a0 --- /dev/null +++ b/app/assets/stylesheets/sponsor_tiers.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the SponsorTiers controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/sponsorships.scss b/app/assets/stylesheets/sponsorships.scss new file mode 100644 index 00000000..3d9a20ea --- /dev/null +++ b/app/assets/stylesheets/sponsorships.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Sponsorships controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/wallets.scss b/app/assets/stylesheets/wallets.scss new file mode 100644 index 00000000..d4a3c509 --- /dev/null +++ b/app/assets/stylesheets/wallets.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Wallets controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 8e82a814..21931f28 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -234,6 +234,7 @@ class AccountsController < ApplicationController set_autologin_cookie(user) UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip) + # user.daily_reward user.update_column(:last_login_on, Time.now) session[:"#{default_yun_session}"] = user.id Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}") diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 14892ce7..4b0a9878 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,6 +1,7 @@ require 'oauth2' class ApplicationController < ActionController::Base + include CodeExample include RenderExpand include RenderHelper @@ -10,12 +11,14 @@ class ApplicationController < ActionController::Base include LoggerHelper include LoginHelper include RegisterHelper + include UpdateHelper protect_from_forgery prepend: true, unless: -> { request.format.json? } before_action :check_sign before_action :user_setup #before_action :check_account + after_action :user_trace_log # TODO # check sql query time @@ -343,7 +346,8 @@ class ApplicationController < ActionController::Base User.current = User.find 8686 elsif params[:debug] == 'admin' logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....." - user = User.find 36480 + # user = User.find 36480 + user = User.find 5 User.current = user cookies.signed[:user_id] = user.id end @@ -366,7 +370,19 @@ class ApplicationController < ActionController::Base # RSS key authentication does not start a session User.find_by_rss_key(params[:key]) end - end + end + + def user_trace_log + user = current_user + # print("*********************url:", request.url, "****routes", request.request_method) + Rails.logger.user_trace.info("{id: #{user.id}, login: #{user.login}, url: #{request.url}, method: #{request.method}, params: #{params}, response_code: #{response.code}, time: #{Time.now}}") + end + + def user_trace_update_log(old_value_hash) + user = current_user + str = "{id: #{user.id}, login: #{user.login}, url: #{request.url}, method: #{request.method}, params: #{params.merge(old_value: old_value_hash)}, response_code: #{response.code}, time: #{Time.now}}" + Rails.logger.user_trace.info(str) + end def try_to_autologin if cookies[autologin_cookie_name] @@ -392,291 +408,291 @@ class ApplicationController < ActionController::Base respond_to do |format| format.json end - end + end - ## 输出错误信息 - def error_status(message = nil) - @status = -1 - @message = message - end + ## 输出错误信息 + def error_status(message = nil) + @status = -1 + @message = message + end - # 实训等对应的仓库地址 - def repo_ip_url(repo_path) - "#{edu_setting('git_address_ip')}/#{repo_path}" - end + # 实训等对应的仓库地址 + def repo_ip_url(repo_path) + "#{edu_setting('git_address_ip')}/#{repo_path}" + end - def repo_url(repo_path) - "#{edu_setting('git_address_domain')}/#{repo_path}" - end + def repo_url(repo_path) + "#{edu_setting('git_address_domain')}/#{repo_path}" + end - # 通关后,把最后一次成功的代码存到数据库 - # type 0 创始内容, 1 最新内容 - # def game_passed_code(path, myshixun, game_id) - # # 如果代码窗口是隐藏的,则不用保存代码 - # return if myshixun.shixun.hide_code || myshixun.shixun.vnc - # file_content = git_fle_content myshixun.repo_path, path - # #unless file_content.present? - # # raise("获取文件代码异常") - # #end - # logger.info("#######game_id:#{game_id}, file_content:#{file_content}") - # game_code = GameCode.where(:game_id => game_id, :path => path).first - # if game_code.nil? - # GameCode.create!(:game_id => game_id, :new_code => file_content, :path => path) - # else - # game_code.update_attributes!(:new_code => file_content) - # end + # 通关后,把最后一次成功的代码存到数据库 + # type 0 创始内容, 1 最新内容 + # def game_passed_code(path, myshixun, game_id) + # # 如果代码窗口是隐藏的,则不用保存代码 + # return if myshixun.shixun.hide_code || myshixun.shixun.vnc + # file_content = git_fle_content myshixun.repo_path, path + # #unless file_content.present? + # # raise("获取文件代码异常") + # #end + # logger.info("#######game_id:#{game_id}, file_content:#{file_content}") + # game_code = GameCode.where(:game_id => game_id, :path => path).first + # if game_code.nil? + # GameCode.create!(:game_id => game_id, :new_code => file_content, :path => path) + # else + # game_code.update_attributes!(:new_code => file_content) + # end # end - # Post请求 - def uri_post(uri, params) - begin - uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}") - uri = URI.parse(URI.encode(uri.strip)) - res = Net::HTTP.post_form(uri, params).body - uid_logger_dubug("--uri_exec: .....res is #{res}") - JSON.parse(res) - rescue Exception => e - uid_logger_error("--uri_exec: exception #{e.message}") - raise Educoder::TipException.new("实训平台繁忙(繁忙等级:84)") - end - end + # Post请求 + def uri_post(uri, params) + begin + uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}") + uri = URI.parse(URI.encode(uri.strip)) + res = Net::HTTP.post_form(uri, params).body + uid_logger_dubug("--uri_exec: .....res is #{res}") + JSON.parse(res) + rescue Exception => e + uid_logger_error("--uri_exec: exception #{e.message}") + raise Educoder::TipException.new("实训平台繁忙(繁忙等级:84)") + end + end - # 处理返回非0就报错的请求 - def interface_post(uri, params, status, message) - begin - uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}") - uri = URI.parse(URI.encode(uri.strip)) - res = Net::HTTP.post_form(uri, params).body - uid_logger_dubug("--uri_exec: .....res is #{res}") - res = JSON.parse(res) - if (res && res['code'] != 0) - tip_exception(status, message) - else - res - end - rescue Exception => e - uid_logger("--uri_exec: exception #{e.message}") - raise Educoder::TipException.new(message) - end - end + # 处理返回非0就报错的请求 + def interface_post(uri, params, status, message) + begin + uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}") + uri = URI.parse(URI.encode(uri.strip)) + res = Net::HTTP.post_form(uri, params).body + uid_logger_dubug("--uri_exec: .....res is #{res}") + res = JSON.parse(res) + if (res && res['code'] != 0) + tip_exception(status, message) + else + res + end + rescue Exception => e + uid_logger("--uri_exec: exception #{e.message}") + raise Educoder::TipException.new(message) + end + end - # json格式请求 - def interface_json_post(uri, params, status, message) - begin - uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}") - uri = URI.parse(URI.encode(uri.strip)) - res = Net::HTTP.start(uri.host, uri.port) do |http| - req = Net::HTTP::Post.new(uri) - req['Content-Type'] = 'application/json' - req.body = params.to_json - http.request(req) - end - uid_logger_dubug("--uri_exec: .....res is #{res.body}") - res = JSON.parse(res.body) - if (res && res['code'] != 0) - tip_exception(status, message) - else - res - end - rescue Exception => e - uid_logger("--uri_exec: exception #{e.message}") - raise Educoder::TipException.new("服务器繁忙") - end - end + # json格式请求 + def interface_json_post(uri, params, status, message) + begin + uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}") + uri = URI.parse(URI.encode(uri.strip)) + res = Net::HTTP.start(uri.host, uri.port) do |http| + req = Net::HTTP::Post.new(uri) + req['Content-Type'] = 'application/json' + req.body = params.to_json + http.request(req) + end + uid_logger_dubug("--uri_exec: .....res is #{res.body}") + res = JSON.parse(res.body) + if (res && res['code'] != 0) + tip_exception(status, message) + else + res + end + rescue Exception => e + uid_logger("--uri_exec: exception #{e.message}") + raise Educoder::TipException.new("服务器繁忙") + end + end - # 适用与已经用url_safe编码后,回调字符串形式 - def tran_base64_decode64(str) - s_size = str.size % 4 - if s_size != 0 - str += "=" * (4 - s_size) - end - if str.blank? - str - else - Base64.decode64(str.tr("-_", "+/")).force_encoding("utf-8") - end - end + # 适用与已经用url_safe编码后,回调字符串形式 + def tran_base64_decode64(str) + s_size = str.size % 4 + if s_size != 0 + str += "=" * (4 - s_size) + end + if str.blank? + str + else + Base64.decode64(str.tr("-_", "+/")).force_encoding("utf-8") + end + end - def sucess_status(message = 'success') - render :json => { status: 1, message: message } - end + def sucess_status(message = 'success') + render :json => { status: 1, message: message } + end - # 随机生成字符 - def generate_identifier(container, num, pre='') - code = DCODES.sample(num).join - if container == User - while container.exists?(login: pre+code) do - code = DCODES.sample(num).join - end - else - while container.exists?(identifier: code) do - code = DCODES.sample(num).join - end - end - code - end + # 随机生成字符 + def generate_identifier(container, num, pre='') + code = DCODES.sample(num).join + if container == User + while container.exists?(login: pre+code) do + code = DCODES.sample(num).join + end + else + while container.exists?(identifier: code) do + code = DCODES.sample(num).join + end + end + code + end - # 实训主类别列表,自带描述 - def shixun_main_type - list = [] - mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_main_mirror - mirrors.try(:each) do |mirror| - list << {id: mirror.id, type_name: mirror.type_name, description: mirror.try(:description), mirror_name: mirror.name} - end - list - end + # 实训主类别列表,自带描述 + def shixun_main_type + list = [] + mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_main_mirror + mirrors.try(:each) do |mirror| + list << {id: mirror.id, type_name: mirror.type_name, description: mirror.try(:description), mirror_name: mirror.name} + end + list + end - # 小类别列表 - def shixun_small_type - list = [] - mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_small_mirror - mirrors.try(:each) do |mirror| - list << {id: mirror.id, type_name: mirror.type_name, description: mirror.description, mirror_name: mirror.name} - end - list - end + # 小类别列表 + def shixun_small_type + list = [] + mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_small_mirror + mirrors.try(:each) do |mirror| + list << {id: mirror.id, type_name: mirror.type_name, description: mirror.description, mirror_name: mirror.name} + end + list + end - def container_limit(mirror_repositories) - container = [] - mirror_repositories.each do |mr| - if mr.name.present? - container << {:image => mr.name, :cpuLimit => mr.cpu_limit, :memoryLimit => "#{mr.memory_limit}M", :type => mr.try(:main_type) == "1" ? "main" : "sub"} - end - end - container.to_json - end + def container_limit(mirror_repositories) + container = [] + mirror_repositories.each do |mr| + if mr.name.present? + container << {:image => mr.name, :cpuLimit => mr.cpu_limit, :memoryLimit => "#{mr.memory_limit}M", :type => mr.try(:main_type) == "1" ? "main" : "sub"} + end + end + container.to_json + end - # 实训中间层pod配置 - def shixun_container_limit shixun - container = [] - shixun.shixun_service_configs.each do |config| - mirror = config.mirror_repository - if mirror.name.present? - # 资源限制没有就传默认值。 - cpu_limit = config.cpu_limit.presence || 1 - cpu_request = config.lower_cpu_limit.presence || 0.1 - memory_limit = config.memory_limit.presence || 1024 - request_limit = config.request_limit.presence || 10 - resource_limit = config.resource_limit.presence || 10000 - container << {:image => mirror.name, - :cpuLimit => cpu_limit, - :cpuRequest => cpu_request, - :memoryLimit => "#{memory_limit}M", - :memoryRequest => "#{request_limit}M", - :resourceLimit => "#{resource_limit}K", - :type => mirror.try(:main_type) == "1" ? "main" : "sub"} - end - end - container.to_json - end + # 实训中间层pod配置 + def shixun_container_limit shixun + container = [] + shixun.shixun_service_configs.each do |config| + mirror = config.mirror_repository + if mirror.name.present? + # 资源限制没有就传默认值。 + cpu_limit = config.cpu_limit.presence || 1 + cpu_request = config.lower_cpu_limit.presence || 0.1 + memory_limit = config.memory_limit.presence || 1024 + request_limit = config.request_limit.presence || 10 + resource_limit = config.resource_limit.presence || 10000 + container << {:image => mirror.name, + :cpuLimit => cpu_limit, + :cpuRequest => cpu_request, + :memoryLimit => "#{memory_limit}M", + :memoryRequest => "#{request_limit}M", + :resourceLimit => "#{resource_limit}K", + :type => mirror.try(:main_type) == "1" ? "main" : "sub"} + end + end + container.to_json + end - # 毕设任务列表的赛选 - def course_work(task, **option) - logger.info("#############{option}") - course = task.course - work_list = task.graduation_works.includes(user: [:user_extension]) - # 教师评阅搜索 0: 未评, 1 已评 - if option[:teacher_comment] - graduation_work_ids = GraduationWorkScore.where(graduation_work_id: work_list.map(&:id)).pluck(:graduation_work_id) - if option[:teacher_comment].zero? - work_list = work_list.where.not(id: graduation_work_ids) - elsif option[:teacher_comment] == 1 - work_list = work_list.where(id: graduation_work_ids).where.not(work_status: 0) - end - end + # 毕设任务列表的赛选 + def course_work(task, **option) + logger.info("#############{option}") + course = task.course + work_list = task.graduation_works.includes(user: [:user_extension]) + # 教师评阅搜索 0: 未评, 1 已评 + if option[:teacher_comment] + graduation_work_ids = GraduationWorkScore.where(graduation_work_id: work_list.map(&:id)).pluck(:graduation_work_id) + if option[:teacher_comment].zero? + work_list = work_list.where.not(id: graduation_work_ids) + elsif option[:teacher_comment] == 1 + work_list = work_list.where(id: graduation_work_ids).where.not(work_status: 0) + end + end - # 作品状态 0: 未提交, 1 按时提交, 2 延迟提交 - if option[:task_status] - work_list = work_list.where(work_status: option[:task_status]) - end + # 作品状态 0: 未提交, 1 按时提交, 2 延迟提交 + if option[:task_status] + work_list = work_list.where(work_status: option[:task_status]) + end - # 分班情况 - if option[:course_group] - group_user_ids = course.course_members.where(course_group_id: option[:course_group]).pluck(:user_id) - # 有分组只可能是老师身份查看列表 - work_list = work_list.where(user_id: group_user_ids) - end + # 分班情况 + if option[:course_group] + group_user_ids = course.course_members.where(course_group_id: option[:course_group]).pluck(:user_id) + # 有分组只可能是老师身份查看列表 + work_list = work_list.where(user_id: group_user_ids) + end - # 只看我的交叉评阅 - if option[:cross_comment] - graduation_work_id = task.graduation_work_comment_assignations.where(:user_id => current_user.id) - .pluck(:graduation_work_id).uniq if task.graduation_work_comment_assignations - work_list = work_list.where(id: graduation_work_id) - end + # 只看我的交叉评阅 + if option[:cross_comment] + graduation_work_id = task.graduation_work_comment_assignations.where(:user_id => current_user.id) + .pluck(:graduation_work_id).uniq if task.graduation_work_comment_assignations + work_list = work_list.where(id: graduation_work_id) + end - # 输入姓名和学号搜索 - # TODO user_extension 如果修改 请调整 - if option[:search] - work_list = work_list.joins(user: :user_extension).where("concat(lastname, firstname) like ? + # 输入姓名和学号搜索 + # TODO user_extension 如果修改 请调整 + if option[:search] + work_list = work_list.joins(user: :user_extension).where("concat(lastname, firstname) like ? or student_id like ?", "%#{option[:search]}%", "%#{option[:search]}%") - end + end - # 排序 - rorder = option[:order] || "updated_at" - b_order = option[:b_order] || "desc" - if rorder == "created_at" || rorder == "work_score" - work_list = work_list.order("graduation_works.#{rorder} #{b_order}") - elsif rorder == "student_id" - work_list = work_list.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}") - end - work_list - end + # 排序 + rorder = option[:order] || "updated_at" + b_order = option[:b_order] || "desc" + if rorder == "created_at" || rorder == "work_score" + work_list = work_list.order("graduation_works.#{rorder} #{b_order}") + elsif rorder == "student_id" + work_list = work_list.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}") + end + work_list + end - def strip_html(text, len=0, endss="...") - ss = "" - if !text.nil? && text.length>0 - ss=text.gsub(/<\/?.*?>/, '').strip - ss = ss.gsub(/ */, '') - ss = ss.gsub(/\r\n/,'') #新增 - ss = ss.gsub(/\n/,'') #新增 - if len > 0 && ss.length > len - ss = ss[0, len] + endss - elsif len > 0 && ss.length <= len - ss = ss - #ss = truncate(ss, :length => len) - end - end - ss - end + def strip_html(text, len=0, endss="...") + ss = "" + if !text.nil? && text.length>0 + ss=text.gsub(/<\/?.*?>/, '').strip + ss = ss.gsub(/ */, '') + ss = ss.gsub(/\r\n/,'') #新增 + ss = ss.gsub(/\n/,'') #新增 + if len > 0 && ss.length > len + ss = ss[0, len] + endss + elsif len > 0 && ss.length <= len + ss = ss + #ss = truncate(ss, :length => len) + end + end + ss + end - # Returns a string that can be used as filename value in Content-Disposition header - def filename_for_content_disposition(name) - request.env['HTTP_USER_AGENT'] =~ %r{MSIE|Trident|Edge} ? ERB::Util.url_encode(name) : name - end + # Returns a string that can be used as filename value in Content-Disposition header + def filename_for_content_disposition(name) + request.env['HTTP_USER_AGENT'] =~ %r{MSIE|Trident|Edge} ? ERB::Util.url_encode(name) : name + end - def format_time(time) - time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M") - end + def format_time(time) + time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M") + end - # 获取Oauth Client - def get_client(site) - client_id = Rails.configuration.educoder['client_id'] - client_secret = Rails.configuration.educoder['client_secret'] + # 获取Oauth Client + def get_client(site) + client_id = Rails.configuration.educoder['client_id'] + client_secret = Rails.configuration.educoder['client_secret'] - OAuth2::Client.new(client_id, client_secret, site: site) - end + OAuth2::Client.new(client_id, client_secret, site: site) + end - def paginate(relation) - limit = params[:limit] || params[:per_page] - limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i - page = params[:page].to_i.zero? ? 1 : params[:page].to_i - offset = (page - 1) * limit + def paginate(relation) + limit = params[:limit] || params[:per_page] + limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i + page = params[:page].to_i.zero? ? 1 : params[:page].to_i + offset = (page - 1) * limit - if relation.is_a?(Array) - relation[offset, limit] - else - relation.limit(limit).offset(offset) - end - end + if relation.is_a?(Array) + relation[offset, limit] + else + relation.limit(limit).offset(offset) + end + end - def kaminari_paginate(relation) - limit = params[:limit] || params[:per_page] - limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i - page = params[:page].to_i.zero? ? 1 : params[:page].to_i + def kaminari_paginate(relation) + limit = params[:limit] || params[:per_page] + limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i + page = params[:page].to_i.zero? ? 1 : params[:page].to_i - relation.page(page).per(limit) + relation.page(page).per(limit) end def kaminari_array_paginate(relation) @@ -691,29 +707,30 @@ class ApplicationController < ActionController::Base time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S") end - def strf_date(date) - date.blank? ? '' : date.to_date.strftime("%Y-%m-%d") - end + def strf_date(date) + date.blank? ? '' : date.to_date.strftime("%Y-%m-%d") + end - def logger_error(error) - Rails.logger.error(error.message) - error.backtrace.each { |msg| Rails.logger.error(msg) } - end + def logger_error(error) + Rails.logger.error(error.message) + error.backtrace.each { |msg| Rails.logger.error(msg) } + end - def find_user - @user = User.find_by_login params[:login] + def find_user + @user = User.find_by_login params[:login] render_not_found("未找到’#{params[:login]}’相关的用户") unless @user - end + end - def find_user_with_id - @user = User.find_by_id params[:user_id] + def find_user_with_id + @user = User.find_by_id params[:user_id] # render_not_found("未找到’#{params[:login]}’相关的用户") unless @user - render_error("未找到相关的用户") unless @user - end + render_error("未找到相关的用户") unless @user + end - def find_repository - @repo = @user.repositories.find_by_identifier params[:repo_identifier] + def find_repository + @repo = @user.repositories.find_by_identifier params[:repo_identifier] render_not_found("未找到’#{params[:repo_identifier]}’相关的项目") unless @repo + end def find_repository_by_id @@ -770,55 +787,55 @@ class ApplicationController < ActionController::Base end private - def object_not_found - uid_logger("Missing template or cant't find record, responding with 404") - render json: {message: "您访问的页面不存在或已被删除", status: 404} - false - end + def object_not_found + uid_logger("Missing template or cant't find record, responding with 404") + render json: {message: "您访问的页面不存在或已被删除", status: 404} + false + end - def tip_show(exception) - uid_logger("Tip show status is #{exception.status}, message is #{exception.message}") - render json: exception.tip_json - end + def tip_show(exception) + uid_logger("Tip show status is #{exception.status}, message is #{exception.message}") + render json: exception.tip_json + end - def render_parameter_missing - render json: { status: -1, message: '参数缺失' } - end + def render_parameter_missing + render json: { status: -1, message: '参数缺失' } + end - def set_export_cookies - cookies[:fileDownload] = true - end + def set_export_cookies + cookies[:fileDownload] = true + end - # 149课程的评审用户数据创建(包含创建课堂学生) - def open_class_user - user = User.find_by(login: "OpenClassUser") - unless user - ActiveRecord::Base.transaction do - user_params = {status: 1, login: "OpenClassUser", lastname: "开放课程", - nickname: "开放课程", professional_certification: 1, certification: 1, grade: 0, - password: "12345678", phone: "11122223333", profile_completed: 1} - user = User.create!(user_params) + # 149课程的评审用户数据创建(包含创建课堂学生) + def open_class_user + user = User.find_by(login: "OpenClassUser") + unless user + ActiveRecord::Base.transaction do + user_params = {status: 1, login: "OpenClassUser", lastname: "开放课程", + nickname: "开放课程", professional_certification: 1, certification: 1, grade: 0, + password: "12345678", phone: "11122223333", profile_completed: 1} + user = User.create!(user_params) - UserExtension.create!(user_id: user.id, gender: 0, school_id: 3396, :identity => 1, :student_id => "openclassuser") # 3396 + UserExtension.create!(user_id: user.id, gender: 0, school_id: 3396, :identity => 1, :student_id => "openclassuser") # 3396 - subject = Subject.find_by(id: 149) - if subject - subject.courses.each do |course| - CourseMember.create!(course_id: course.id, role: 3, user_id: user.id) if !course.course_members.exists?(user_id: user.id) - end - end - end - end - user - end + subject = Subject.find_by(id: 149) + if subject + subject.courses.each do |course| + CourseMember.create!(course_id: course.id, role: 3, user_id: user.id) if !course.course_members.exists?(user_id: user.id) + end + end + end + end + user + end - # 记录热门搜索关键字 - def record_search_keyword - keyword = params[:keyword].to_s.strip - return if keyword.blank? || keyword.size <= 1 - return unless HotSearchKeyword.available? + # 记录热门搜索关键字 + def record_search_keyword + keyword = params[:keyword].to_s.strip + return if keyword.blank? || keyword.size <= 1 + return unless HotSearchKeyword.available? - HotSearchKeyword.add(keyword) - end + HotSearchKeyword.add(keyword) + end -end +end \ No newline at end of file diff --git a/app/controllers/concerns/login_helper.rb b/app/controllers/concerns/login_helper.rb index d8f2445f..b1073647 100644 --- a/app/controllers/concerns/login_helper.rb +++ b/app/controllers/concerns/login_helper.rb @@ -44,6 +44,7 @@ module LoginHelper set_autologin_cookie(user) UserAction.create(action_id: user&.id, action_type: 'Login', user_id: user&.id, ip: request.remote_ip) + # user.daily_reward user.update_column(:last_login_on, Time.now) # 注册完成后有一天的试用申请(先去掉) # UserDayCertification.create(user_id: user.id, status: 1) diff --git a/app/controllers/forks_controller.rb b/app/controllers/forks_controller.rb index cb18091c..e83cb1e2 100644 --- a/app/controllers/forks_controller.rb +++ b/app/controllers/forks_controller.rb @@ -2,9 +2,12 @@ class ForksController < ApplicationController before_action :require_login before_action :load_project before_action :authenticate_project!, :authenticate_user! + skip_after_action :user_trace_log, only: [:create] def create @new_project = Projects::ForkService.new(current_user, @project, params[:organization]).call + user = current_user + Rails.logger.user_trace.info("{id: #{user.id}, login: #{user.login}, url: #{request.url}, method: #{request.method}, params: #{params.merge(forkee: @new_project.id)}, response_code: #{response.code}, time: #{Time.now}}") end private diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index a3b5fe92..f161469f 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -8,6 +8,8 @@ class IssuesController < ApplicationController before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue] before_action :check_token_enough, only: [:create, :update] + skip_after_action :user_trace_log, only: [:update] + include ApplicationHelper include TagChosenHelper @@ -194,6 +196,7 @@ class IssuesController < ApplicationController # end # end # end + issue_hash = old_value_to_hash(@issue, params) if @issue.issue_type.to_s == "2" && params[:status_id].to_i == 5 && @issue.author_id != current_user.try(:id) normal_status(-1, "不允许修改为关闭状态") @@ -201,6 +204,7 @@ class IssuesController < ApplicationController issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id) if @issue.update_attributes(issue_params) + user_trace_update_log(issue_hash) if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时 @issue.issue_times.update_all(end_time: Time.now) @issue.update_closed_issues_count_in_project! diff --git a/app/controllers/journals_controller.rb b/app/controllers/journals_controller.rb index 6917974b..555d7928 100644 --- a/app/controllers/journals_controller.rb +++ b/app/controllers/journals_controller.rb @@ -3,6 +3,7 @@ class JournalsController < ApplicationController before_action :set_issue before_action :check_issue_permission before_action :set_journal, only: [:destroy, :edit, :update] + skip_after_action :user_trace_log, only: [:update] def index @page = params[:page] || 1 @@ -67,7 +68,9 @@ class JournalsController < ApplicationController def update content = params[:content] if content.present? + old_value = old_value_to_hash(@journal, params) if @journal.update_attribute(:notes, content) + user_trace_update_log(old_value) normal_status(0, "更新成功") else normal_status(-1, "更新失败") diff --git a/app/controllers/log_controller.rb b/app/controllers/log_controller.rb new file mode 100644 index 00000000..ca23bde2 --- /dev/null +++ b/app/controllers/log_controller.rb @@ -0,0 +1,19 @@ +class LogController < ApplicationController + def list + path = "#{Rails.root}/log" + @file_list = [] + Dir.foreach(path) do |file| + @file_list << file + end + @file_list = @file_list.sort + end + + def download + path = "#{Rails.root}/log/#{params[:filename]}" + if params[:filename] && File.exist?(path) && File.file?(path) + send_file(path, filename: params[:filename]) + else + render json: { message: 'no such file!' } + end + end +end diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 2964eb1a..4f42c885 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -5,6 +5,7 @@ class MembersController < ApplicationController before_action :operate!, except: %i[index] before_action :check_member_exists!, only: %i[create] before_action :check_member_not_exists!, only: %i[remove change_role] + skip_after_action :user_trace_log, only: [:change_role] def create interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user) @@ -34,7 +35,9 @@ class MembersController < ApplicationController end def change_role + old_value = @project.members.where(user_id: params[:user_id])[0].roles.last.name interactor = Projects::ChangeMemberRoleInteractor.call(@project.owner, @project, @user, params[:role]) + user_trace_update_log(old_value) render_response(interactor) rescue Exception => e uid_logger_error(e.message) diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 12663901..2d4e74f5 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -1,8 +1,11 @@ class PullRequestsController < ApplicationController + before_action :require_login, except: [:index, :show, :files, :commits] before_action :load_repository before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits] before_action :load_pull_request, only: [:files, :commits] + + skip_after_action :user_trace_log, only: [:update] include TagChosenHelper include ApplicationHelper @@ -86,8 +89,14 @@ class PullRequestsController < ApplicationController end end + old_issue_value = old_value_to_hash(@issue, @issue_params) + old_pr_value = old_value_to_hash(@pull_request, @local_params.compact) + old_value = {issue: old_issue_value, pull_request: old_pr_value} + if @issue.update_attributes(@issue_params) if @pull_request.update_attributes(@local_params.compact) + + user_trace_update_log(old_value) gitea_pull = Gitea::PullRequest::UpdateService.call(@owner.login, @repository.identifier, @pull_request.gpid, @requests_params, current_user.gitea_token) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index b03edb1f..a5ee5aff 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -1,6 +1,7 @@ class SettingsController < ApplicationController def show @old_projects_url = nil + @old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged? get_add_menu get_common_menu get_personal_menu diff --git a/app/controllers/sponsor_tiers_controller.rb b/app/controllers/sponsor_tiers_controller.rb new file mode 100644 index 00000000..8aaf1327 --- /dev/null +++ b/app/controllers/sponsor_tiers_controller.rb @@ -0,0 +1,90 @@ +class SponsorTiersController < ApplicationController + before_action :set_sponsor_tier, only: [:show, :edit, :update, :destroy] + before_action :check_sponsor, only: [:show] + before_action :require_login, only: [:create, :update, :destroy] + + # GET /sponsor_tiers + # GET /sponsor_tiers.json + def index + # @sponsor_tiers = SponsorTier.all + user = User.find_by_login(params[:login]) + @sponsor_tiers = user.sponsor_tier + end + + # GET /sponsor_tiers/1 + # GET /sponsor_tiers/1.json + def show + + end + + # POST /sponsor_tiers + # POST /sponsor_tiers.json + def create + # print("------------\n", sponsor_tier_params, "\n------------\n") + @check_sponsorship = nil + @sponsor_tier = SponsorTier.new(sponsor_tier_params) + respond_to do |format| + if @sponsor_tier.user_id == User.current.id && @sponsor_tier.save + format.html { redirect_to @sponsor_tier, notice: 'Sponsor tier was successfully created.' } + format.json { render :show, status: :created, location: @sponsor_tier } + # render json: {status: 1, message: '创建成功' } + else + format.html { render :new } + format.json { render json: @sponsor_tier.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /sponsor_tiers/1 + # PATCH/PUT /sponsor_tiers/1.json + def update + @check_sponsorship = nil + old_value = old_value_to_hash(@sponsor_tier, params) + respond_to do |format| + if User.current.id == @sponsor_tier.user_id && @sponsor_tier.update(sponsor_tier_update_params) + user_trace_update_log(old_value) + format.html { redirect_to @sponsor_tier, notice: 'Sponsor tier was successfully updated.' } + format.json { render :show, status: :ok, location: @sponsor_tier } + # render json: {status: 1, message: '修改成功' } + else + format.html { render :edit } + format.json { render json: @sponsor_tier.errors, status: :unprocessable_entity } + # format.json { render status: :unprocessable_entity } + # render json: {status: -1, message: '修改失败' } + end + end + end + + # DELETE /sponsor_tiers/1 + # DELETE /sponsor_tiers/1.json + def destroy + if User.current.id == @sponsor_tier.user_id + @sponsor_tier.destroy + respond_to do |format| + format.html { redirect_to sponsor_tiers_url, notice: 'Sponsor tier was successfully destroyed.' } + format.json { head :no_content } + end + else + format.json { render json: @sponsor_tier.errors, status: :unprocessable_entity } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def check_sponsor + @check_sponsorship = Sponsorship.where("sponsor_id=? AND developer_id=?", current_user.id, @sponsor_tier.user.id) + end + + def set_sponsor_tier + @sponsor_tier = SponsorTier.find(params[:id]) + end + + def sponsor_tier_update_params + params.require(:sponsor_tier).permit(:tier, :description) + end + + # Only allow a list of trusted parameters through. + def sponsor_tier_params + params.require(:sponsor_tier).permit(:tier, :user_id, :description) + end +end diff --git a/app/controllers/sponsorships_controller.rb b/app/controllers/sponsorships_controller.rb new file mode 100644 index 00000000..2e18a075 --- /dev/null +++ b/app/controllers/sponsorships_controller.rb @@ -0,0 +1,163 @@ +class SponsorshipsController < ApplicationController + before_action :set_sponsorship, only: [:show, :edit, :update, :destroy] + # before_action :require_login, except: [:index, :stopped, :sponsored, :sponsoring, :stopped_sponsored, :stopped_sponsoring] + before_action :require_login, only: [:create, :edit, :update, :destroy] + skip_after_action :user_trace_log, only: [:update] + + # GET /sponsorships + # GET /sponsorships.json + def index + @sponsorships = Sponsorship.all + end + + def stopped + @stopped_sponsorships = StoppedSponsorship.all + end + + def sponsored + if User.current.id == Integer(params[:id]) + @sponsorships = Sponsorship.where("developer_id=?", params[:id]) + else + @sponsorships = Sponsorship.where("developer_id=? AND visible=1", params[:id]) + end + sort = params[:sort_by] || "created_at" + sort_direction = params[:sort_direction] || "desc" + @sponsorships = @sponsorships.reorder("#{sort} #{sort_direction}") + @total = @sponsorships.length + @sponsorships = kaminari_paginate(@sponsorships) + end + + def sponsoring + if User.current.id == Integer(params[:id]) + @sponsorships = Sponsorship.where("sponsor_id=?", params[:id]) + else + @sponsorships = Sponsorship.where("sponsor_id=? AND visible=1", params[:id]) + end + sort = params[:sort_by] || "created_at" + sort_direction = params[:sort_direction] || "desc" + @sponsorships = @sponsorships.reorder("#{sort} #{sort_direction}") + @total = @sponsorships.length + @sponsorships = kaminari_paginate(@sponsorships) + end + + def stopped_sponsored + if User.current.id == Integer(params[:id]) + @stopped_sponsorships = StoppedSponsorship.where("developer_id=?", params[:id]) + else + @stopped_sponsorships = StoppedSponsorship.where("developer_id=? AND visible=1", params[:id]) + end + sort = params[:sort_by] || "created_at" + sort_direction = params[:sort_direction] || "desc" + @stopped_sponsorships = @stopped_sponsorships.reorder("#{sort} #{sort_direction}") + @total = @stopped_sponsorships.length + @stopped_sponsorships = kaminari_paginate(@stopped_sponsorships) + end + + def stopped_sponsoring + if User.current.id == Integer(params[:id]) + @stopped_sponsorships = StoppedSponsorship.where("sponsor_id=?", params[:id]) + else + @stopped_sponsorships = StoppedSponsorship.where("sponsor_id=? AND visible=1", params[:id]) + end + sort = params[:sort_by] || "created_at" + sort_direction = params[:sort_direction] || "desc" + @stopped_sponsorships = @stopped_sponsorships.reorder("#{sort} #{sort_direction}") + @total = @stopped_sponsorships.length + @stopped_sponsorships = kaminari_paginate(@stopped_sponsorships) + end + + # GET /sponsorships/1 + # GET /sponsorships/1.json + def show + end + + # POST /sponsorships + # POST /sponsorships.json + def create + sponsor_id = User.current.id + check_sponsorship = Sponsorship.where("sponsor_id=? AND developer_id=?", sponsor_id, params[:developer_id]) + + @sponsorship = Sponsorship.new(sponsorship_params.merge({sponsor_id: sponsor_id})) + + unless check_sponsorship.length.zero? + return render json: {status: -1, message: '您已经赞助了TA' } + end + + if @sponsorship.pay && @sponsorship.save + if params[:single] && @sponsorship.stop + return render json: { status: 1, message: '赞助成功' } + elsif !params[:single] + User.current.update(sponsor_num: User.current.sponsor_num+1) + @sponsorship.developer.update(sponsored_num: @sponsorship.developer.sponsored_num + 1) + return render json: { status: 1, message: '赞助成功' } + else + return render json: { status: -1, message: '赞助失败' } + end + end + # return render_result message: '赞助成功' if @sponsorship.save + # respond_to do |format| + # if check_sponsorship.length.zero? && @sponsorship.save + # format.html { redirect_to @sponsorship, notice: 'Sponsorship was successfully created.' } + # format.json { render :show, status: :created, location: @sponsorship } + # # render_result status=0, message="赞助成功" + # else + # format.html { render :new } + # format.json { render json: @sponsorship.errors, status: :unprocessable_entity } + # end + # end + end + + # PATCH/PUT /sponsorships/1 + # PATCH/PUT /sponsorships/1.json + def update + # respond_to do |format| + # if @sponsorship.update(sponsorship_params) + # format.html { redirect_to @sponsorship, notice: 'Sponsorship was successfully updated.' } + # format.json { render :show, status: :ok, location: @sponsorship } + # else + # format.html { render :edit } + # format.json { render json: @sponsorship.errors, status: :unprocessable_entity } + # end + # end + + if @sponsorship.sponsor.id != current_user.id + return render json: {status: 401, message: '没有权限' } + end + old_value = old_value_to_hash(@sponsorship, params) + + if @sponsorship.update(sponsorship_params) + user_trace_update_log(old_value) + render json: {status: 1, message: '修改成功' } + else + render json: {status: -1, message: '修改失败' } + end + end + + # DELETE /sponsorships/1 + # DELETE /sponsorships/1.json + def destroy + # @sponsorship.destroy + # respond_to do |format| + # format.html { redirect_to sponsorships_url, notice: 'Sponsorship was successfully destroyed.' } + # format.json { head :no_content } + # end + developer = @sponsorship.developer + sponsor = @sponsorship.sponsor + if (User.current.id == developer.id || User.current.id == sponsor.id) && developer.update(sponsored_num: developer.sponsored_num-1) && sponsor.update(sponsor_num: sponsor.sponsor_num-1) && @sponsorship.stop + render json: {status: 1, message: "终止成功"} + else + render json: {status: -1, message: "失败"} + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_sponsorship + @sponsorship = Sponsorship.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def sponsorship_params + params.require(:sponsorship).permit(:amount, :visible, :sponsor_id, :developer_id, :single, :page, :limit, :sort_by, :search) + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 806bab7c..5a428e0c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -72,6 +72,10 @@ class UsersController < ApplicationController @user = current_user # TODO 等消息上线再打开注释 #@tidding_count = unviewed_tiddings(current_user) if current_user.present? + # + if(@user.logged?) + @user.daily_reward + end rescue Exception => e uid_logger_error(e.message) missing_template @@ -233,6 +237,15 @@ class UsersController < ApplicationController render_ok end + def update_description + @user = User.find params[:id] + if @user.id == User.current.id && @user.update(description: params[:description]) + render_ok + else + render_error + end + end + def sync_user_info user = User.find_by_login params[:login] return render_forbidden unless user === current_user diff --git a/app/controllers/version_releases_controller.rb b/app/controllers/version_releases_controller.rb index 1b56236a..de85d0d2 100644 --- a/app/controllers/version_releases_controller.rb +++ b/app/controllers/version_releases_controller.rb @@ -3,6 +3,7 @@ class VersionReleasesController < ApplicationController before_action :set_user before_action :require_login, except: [:index] before_action :find_version , only: [:edit, :update, :destroy] + skip_after_action :user_trace_log, only: [:update] def index version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call @@ -78,14 +79,14 @@ class VersionReleasesController < ApplicationController ActiveRecord::Base.transaction do begin version_params = releases_params - + old_value = old_value_to_hash(@version, version_params) if @version.update_attributes!(version_params) create_attachments(params[:attachment_ids], @version) if params[:attachment_ids].present? git_version_release = Gitea::Versions::UpdateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call unless git_version_release raise Error, "更新失败" end - + user_trace_update_log(old_value) normal_status(0, "更新成功") else normal_status(-1, "更新失败") diff --git a/app/controllers/wallets_controller.rb b/app/controllers/wallets_controller.rb new file mode 100644 index 00000000..064db910 --- /dev/null +++ b/app/controllers/wallets_controller.rb @@ -0,0 +1,28 @@ +class WalletsController < ApplicationController + before_action :require_login + + def balance + user = User.find_by_id(params[:id]) + @wallet = user.get_wallet + end + + def coin_changes + user = User.find_by_id(params[:id]) + @wallet = user.get_wallet + if params[:category] == 'all' + scope = CoinChange.where('to_wallet_id = ? OR from_wallet_id = ?', @wallet.id, @wallet.id) + elsif params[:category] == 'income' + # @coin_changes = CoinChange.where('to_wallet_id = ?', @wallet.id).limit(100) + scope = @wallet.income + elsif params[:category] == 'outcome' + scope = @wallet.outcome + end + + sort = params[:sort_by] || "created_at" + sort_direction = params[:sort_direction] || "desc" + scope = scope.reorder("#{sort} #{sort_direction}") + + @total = scope.length + @coin_changes = kaminari_paginate(scope) + end +end diff --git a/app/helpers/log_helper.rb b/app/helpers/log_helper.rb new file mode 100644 index 00000000..23096ad3 --- /dev/null +++ b/app/helpers/log_helper.rb @@ -0,0 +1,2 @@ +module LogHelper +end diff --git a/app/helpers/sponsor_tiers_helper.rb b/app/helpers/sponsor_tiers_helper.rb new file mode 100644 index 00000000..02b198bd --- /dev/null +++ b/app/helpers/sponsor_tiers_helper.rb @@ -0,0 +1,2 @@ +module SponsorTiersHelper +end diff --git a/app/helpers/sponsorships_helper.rb b/app/helpers/sponsorships_helper.rb new file mode 100644 index 00000000..f6ea1f0d --- /dev/null +++ b/app/helpers/sponsorships_helper.rb @@ -0,0 +1,2 @@ +module SponsorshipsHelper +end diff --git a/app/helpers/update_helper.rb b/app/helpers/update_helper.rb new file mode 100644 index 00000000..15799180 --- /dev/null +++ b/app/helpers/update_helper.rb @@ -0,0 +1,6 @@ +module UpdateHelper + def old_value_to_hash(old_value, params) + params = params.dup.stringify_keys + old_value.attributes.select { |key, value| params.key?(key) } + end +end \ No newline at end of file diff --git a/app/helpers/wallets_helper.rb b/app/helpers/wallets_helper.rb new file mode 100644 index 00000000..6eed22ad --- /dev/null +++ b/app/helpers/wallets_helper.rb @@ -0,0 +1,2 @@ +module WalletsHelper +end diff --git a/app/jobs/monthly_payment_worker.rb b/app/jobs/monthly_payment_worker.rb new file mode 100644 index 00000000..dc6affcd --- /dev/null +++ b/app/jobs/monthly_payment_worker.rb @@ -0,0 +1,15 @@ +class MonthlyPaymentWorker + include Sidekiq::Worker + include Sidetiq::Schedulable + + recurrence do + minutely(2) + # monthly.day_of_month(12) #每月的12号0点执行 + # monthly.day_of_month(23).hour_of_day(20) #每月的12号1点执行 + end + + def perform(*args) + Sponsorship.monthly_payment + puts Time.now, 'sponsor payment done' + end +end \ No newline at end of file diff --git a/app/models/ci/user.rb b/app/models/ci/user.rb index cd624675..7c7cdd36 100644 --- a/app/models/ci/user.rb +++ b/app/models/ci/user.rb @@ -45,7 +45,12 @@ # is_shixun_marker :boolean default("0") # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") +# sponsor_certification :integer default("0") +# sponsor_num :integer default("0") +# sponsored_num :integer default("0") +# description :text(65535) # devops_step :integer default("0") +# award_time :datetime # # Indexes # diff --git a/app/models/coin_change.rb b/app/models/coin_change.rb new file mode 100644 index 00000000..cd2eae0e --- /dev/null +++ b/app/models/coin_change.rb @@ -0,0 +1,19 @@ +# == Schema Information +# +# Table name: coin_changes +# +# id :integer not null, primary key +# amount :integer +# description :string(255) +# reason :string(255) +# to_wallet_id :integer +# from_wallet_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# + +class CoinChange < ApplicationRecord + belongs_to :to_wallet, class_name: 'Wallet' + belongs_to :from_wallet, class_name: 'Wallet', optional: true + validates :amount, presence: true +end diff --git a/app/models/passed_waitlist.rb b/app/models/passed_waitlist.rb new file mode 100644 index 00000000..05d88742 --- /dev/null +++ b/app/models/passed_waitlist.rb @@ -0,0 +1,16 @@ +# == Schema Information +# +# Table name: passed_waitlists +# +# id :integer not null, primary key +# applicant_id :string(255) +# integer :string(255) +# reviewer_id :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# + +class PassedWaitlist < ApplicationRecord + belongs_to :applicant, class_name: 'User' + belongs_to :reviewer, class_name: 'User' +end diff --git a/app/models/sponsor_tier.rb b/app/models/sponsor_tier.rb new file mode 100644 index 00000000..d7fac999 --- /dev/null +++ b/app/models/sponsor_tier.rb @@ -0,0 +1,16 @@ +# == Schema Information +# +# Table name: sponsor_tiers +# +# id :integer not null, primary key +# tier :integer +# created_at :datetime not null +# updated_at :datetime not null +# description :string(255) default("") +# user_id :integer +# + +class SponsorTier < ApplicationRecord + belongs_to :user + +end diff --git a/app/models/sponsorship.rb b/app/models/sponsorship.rb new file mode 100644 index 00000000..ccd2d853 --- /dev/null +++ b/app/models/sponsorship.rb @@ -0,0 +1,50 @@ +# == Schema Information +# +# Table name: sponsorships +# +# id :integer not null, primary key +# amount :integer +# visible :integer +# sponsor_id :integer +# developer_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# accumulate :integer default("0") +# + +class Sponsorship < ApplicationRecord + belongs_to :sponsor, class_name: 'User' + belongs_to :developer, class_name: 'User' + validates :amount, presence: true + + def stop + stopped_sponsorship = StoppedSponsorship.new(developer_id: developer_id, sponsor_id: sponsor_id, start_time: created_at, amount: amount, visible: visible, accumulate: accumulate) + stopped_sponsorship.save && destroy + end + + def pay + sponsor_wallet = sponsor.get_wallet + developer_wallet = developer.get_wallet + + Wallet.transaction do + return false if sponsor.wallet.balance < amount + + sponsor_wallet.update(balance: sponsor_wallet.balance -= amount) + developer_wallet.update(balance: developer_wallet.balance += amount) + update(accumulate: self.accumulate += amount) + end + reason = "#{sponsor.full_name}向#{developer.full_name}的赞助支付。" + coinchange = CoinChange.new(amount: amount, reason: reason, to_wallet_id: developer_wallet.id, from_wallet_id: sponsor_wallet.id) + if coinchange.save + return true + end + false + end + + def self.monthly_payment + sponsorships = Sponsorship.all + sponsorships.each do |s| + s.stop unless s.pay + end + end +end diff --git a/app/models/stopped_sponsorship.rb b/app/models/stopped_sponsorship.rb new file mode 100644 index 00000000..03024e8c --- /dev/null +++ b/app/models/stopped_sponsorship.rb @@ -0,0 +1,20 @@ +# == Schema Information +# +# Table name: stopped_sponsorships +# +# id :integer not null, primary key +# amount :integer +# sponsor_id :integer +# developer_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# start_time :datetime +# visible :integer +# accumulate :integer default("0") +# + +class StoppedSponsorship < ApplicationRecord + belongs_to :sponsor, class_name: 'User' + belongs_to :developer, class_name: 'User' + validates :amount, presence: true +end diff --git a/app/models/user.rb b/app/models/user.rb index 5559da08..3bde74b7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -45,7 +45,12 @@ # is_shixun_marker :boolean default("0") # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") +# sponsor_certification :integer default("0") +# sponsor_num :integer default("0") +# sponsored_num :integer default("0") +# description :text(65535) # devops_step :integer default("0") +# award_time :datetime # # Indexes # @@ -158,6 +163,18 @@ class User < Owner has_many :project_trends, dependent: :destroy has_many :oauths , dependent: :destroy + # sponsor + has_many :as_sponsors, class_name: 'Sponsorship', foreign_key: 'sponsor_id', dependent: :destroy + has_many :as_sponsored, class_name: 'Sponsorship', foreign_key: 'developer_id', dependent: :destroy + has_many :stopped_sponsors, class_name: 'StoppedSponsorship', foreign_key: 'sponsor_id', dependent: :destroy + has_many :stopped_sponsored, class_name: 'StoppedSponsorship', foreign_key: 'developer_id', dependent: :destroy + has_many :sponsor_tier, dependent: :destroy + has_one :wallet, dependent: :destroy + has_many :waitlist, class_name: 'Waitlist', foreign_key: 'reviewer_id' + has_many :passed_waitlist, class_name: 'PassedWaitlist', foreign_key: 'reviewer_id' #as reviewer + has_one :application, class_name: 'Waitlist', foreign_key: 'applicant_id' + has_one :passed_application, class_name: 'PassedWaitlist', foreign_key: 'applicant_id' + has_many :organization_users, dependent: :destroy has_many :organizations, through: :organization_users @@ -592,6 +609,7 @@ class User < Owner # Returns the user who matches the given autologin +key+ or nil def self.try_to_autologin(key) user = Token.find_active_user('autologin', key) + # user.daily_reward if user user.update(last_login_on: Time.now) if user user end @@ -738,6 +756,50 @@ class User < Owner laboratory_id.present? && laboratory_id != 1 end + def get_wallet + if wallet.nil? + create_wallet(balance: 100) + reason = "系统初始赠送" + CoinChange.create(amount: amount, reason: reason, to_wallet_id: wallet.id) + end + wallet + end + + def daily_reward + t1 = Time.now + t2 = Time.new(t1.year, t1.month, t1.day) + + if(award_time.nil? or t2 > award_time) + self.update_column(:award_time, Time.now) + amount = 2 + user_wallet = get_wallet + user_wallet.update(balance: user_wallet.balance += amount) + reason = "每日登录奖励" + CoinChange.create(amount: amount, reason: reason, to_wallet_id: user_wallet.id) + end +=begin + award = false + if(last_login_on.nil? or t2 > last_login_on) + User.transaction(isolation: :serializable) do + # User.transaction do + if(self.last_login_on.nil? or t2 > self.last_login_on) + self.update_column(:last_login_on, Time.now) + award = true + end + end + if(award) + amount = 2 + user_wallet = get_wallet + user_wallet.update(balance: user_wallet.balance += amount) + reason = "每日登录奖励" + CoinChange.create(amount: amount, reason: reason, to_wallet_id: user_wallet.id) + end + else + # puts("#################################NOOO DAILY REWARD, #{last_login_on}, #{t2}") + end +=end + end + protected def validate_password_length # 管理员的初始密码是5位 diff --git a/app/models/waitlist.rb b/app/models/waitlist.rb new file mode 100644 index 00000000..252b1792 --- /dev/null +++ b/app/models/waitlist.rb @@ -0,0 +1,16 @@ +# == Schema Information +# +# Table name: waitlists +# +# id :integer not null, primary key +# applicant_id :string(255) +# integer :string(255) +# reviewer_id :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# + +class Waitlist < ApplicationRecord + belongs_to :applicant, class_name: 'User' + belongs_to :reviewer, class_name: 'User', optional: true +end diff --git a/app/models/wallet.rb b/app/models/wallet.rb new file mode 100644 index 00000000..64bcd942 --- /dev/null +++ b/app/models/wallet.rb @@ -0,0 +1,17 @@ +# == Schema Information +# +# Table name: wallets +# +# id :integer not null, primary key +# balance :integer +# user_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# + +class Wallet < ApplicationRecord + belongs_to :user + has_many :outcome, class_name: 'CoinChange', foreign_key: 'from_wallet_id', dependent: :destroy + has_many :income, class_name: 'CoinChange', foreign_key: 'to_wallet_id', dependent: :destroy + validates :balance, presence: true +end diff --git a/app/views/log/list.json.jbuilder b/app/views/log/list.json.jbuilder new file mode 100644 index 00000000..903c5e4f --- /dev/null +++ b/app/views/log/list.json.jbuilder @@ -0,0 +1 @@ +json.array! @file_list \ No newline at end of file diff --git a/app/views/sponsor_tiers/_form.html.erb b/app/views/sponsor_tiers/_form.html.erb new file mode 100644 index 00000000..1857620d --- /dev/null +++ b/app/views/sponsor_tiers/_form.html.erb @@ -0,0 +1,13 @@ + +<%= simple_form_for(@sponsor_tier) do |f| %> + <%= f.error_notification %> + <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> + +
+ <%= f.input :tier %> +
+ +
+ <%= f.button :submit %> +
+<% end %> diff --git a/app/views/sponsor_tiers/_sponsor_tier.json.jbuilder b/app/views/sponsor_tiers/_sponsor_tier.json.jbuilder new file mode 100644 index 00000000..e06f7ab9 --- /dev/null +++ b/app/views/sponsor_tiers/_sponsor_tier.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! sponsor_tier, :id, :tier, :description, :created_at, :updated_at +json.url sponsor_tier_url(sponsor_tier, format: :json) diff --git a/app/views/sponsor_tiers/edit.html.erb b/app/views/sponsor_tiers/edit.html.erb new file mode 100644 index 00000000..5800149c --- /dev/null +++ b/app/views/sponsor_tiers/edit.html.erb @@ -0,0 +1,6 @@ +

Editing Sponsor Tier

+ +<%= render 'form', sponsor_tier: @sponsor_tier %> + +<%= link_to 'Show', @sponsor_tier %> | +<%= link_to 'Back', sponsor_tiers_path %> diff --git a/app/views/sponsor_tiers/index.json.jbuilder b/app/views/sponsor_tiers/index.json.jbuilder new file mode 100644 index 00000000..6a607957 --- /dev/null +++ b/app/views/sponsor_tiers/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @sponsor_tiers, partial: "sponsor_tiers/sponsor_tier", as: :sponsor_tier diff --git a/app/views/sponsor_tiers/new.html.erb b/app/views/sponsor_tiers/new.html.erb new file mode 100644 index 00000000..928ca743 --- /dev/null +++ b/app/views/sponsor_tiers/new.html.erb @@ -0,0 +1,5 @@ +

New Sponsor Tier

+ +<%= render 'form', sponsor_tier: @sponsor_tier %> + +<%= link_to 'Back', sponsor_tiers_path %> diff --git a/app/views/sponsor_tiers/show.html.erb b/app/views/sponsor_tiers/show.html.erb new file mode 100644 index 00000000..ae7a4c1d --- /dev/null +++ b/app/views/sponsor_tiers/show.html.erb @@ -0,0 +1,9 @@ +

<%= notice %>

+ +

+ Tier: + <%= @sponsor_tier.tier %> +

+ +<%= link_to 'Edit', edit_sponsor_tier_path(@sponsor_tier) %> | +<%= link_to 'Back', sponsor_tiers_path %> diff --git a/app/views/sponsor_tiers/show.json.jbuilder b/app/views/sponsor_tiers/show.json.jbuilder new file mode 100644 index 00000000..9f929c04 --- /dev/null +++ b/app/views/sponsor_tiers/show.json.jbuilder @@ -0,0 +1,9 @@ +json.tier do + json.partial! "sponsor_tiers/sponsor_tier", sponsor_tier: @sponsor_tier +end +if @check_sponsorship.nil? || @check_sponsorship.length.zero? + json.is_sponsoring false +else + json.is_sponsoring true + json.sponsorship_id @check_sponsorship[0].id +end diff --git a/app/views/sponsorships/_form.html.erb b/app/views/sponsorships/_form.html.erb new file mode 100644 index 00000000..aba15064 --- /dev/null +++ b/app/views/sponsorships/_form.html.erb @@ -0,0 +1,16 @@ + +<%= simple_form_for(@sponsorship) do |f| %> + <%= f.error_notification %> + <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> + +
+ <%= f.input :amount %> + <%= f.input :visible %> + <%= f.input :sponsor_id %> + <%= f.input :developer_id %> +
+ +
+ <%= f.button :submit %> +
+<% end %> diff --git a/app/views/sponsorships/_sponsorship.json.jbuilder b/app/views/sponsorships/_sponsorship.json.jbuilder new file mode 100644 index 00000000..5bb1b4e6 --- /dev/null +++ b/app/views/sponsorships/_sponsorship.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! sponsorship, :id, :amount, :visible, :sponsor_id, :developer_id, :created_at, :updated_at, :accumulate +json.url sponsorship_url(sponsorship, format: :json) diff --git a/app/views/sponsorships/edit.html.erb b/app/views/sponsorships/edit.html.erb new file mode 100644 index 00000000..45d623bb --- /dev/null +++ b/app/views/sponsorships/edit.html.erb @@ -0,0 +1,6 @@ +

Editing Sponsorship

+ +<%= render 'form', sponsorship: @sponsorship %> + +<%= link_to 'Show', @sponsorship %> | +<%= link_to 'Back', sponsorships_path %> diff --git a/app/views/sponsorships/index.html.erb b/app/views/sponsorships/index.html.erb new file mode 100644 index 00000000..d539f213 --- /dev/null +++ b/app/views/sponsorships/index.html.erb @@ -0,0 +1,33 @@ +

<%= notice %>

+ +

Sponsorships

+ + + + + + + + + + + + + + <% @sponsorships.each do |sponsorship| %> + + + + + + + + + + <% end %> + +
AmountVisibleSponsorDeveloper
<%= sponsorship.amount %><%= sponsorship.visible %><%= sponsorship.sponsor_id %><%= sponsorship.developer_id %><%= link_to 'Show', sponsorship %><%= link_to 'Edit', edit_sponsorship_path(sponsorship) %><%= link_to 'Destroy', sponsorship, method: :delete, data: { confirm: 'Are you sure?' } %>
+ +
+ +<%= link_to 'New Sponsorship', new_sponsorship_path %> diff --git a/app/views/sponsorships/index.json.jbuilder b/app/views/sponsorships/index.json.jbuilder new file mode 100644 index 00000000..d02d0390 --- /dev/null +++ b/app/views/sponsorships/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @sponsorships, partial: "sponsorships/sponsorship", as: :sponsorship diff --git a/app/views/sponsorships/new.html.erb b/app/views/sponsorships/new.html.erb new file mode 100644 index 00000000..914dc917 --- /dev/null +++ b/app/views/sponsorships/new.html.erb @@ -0,0 +1,5 @@ +

New Sponsorship

+ +<%= render 'form', sponsorship: @sponsorship %> + +<%= link_to 'Back', sponsorships_path %> diff --git a/app/views/sponsorships/show.html.erb b/app/views/sponsorships/show.html.erb new file mode 100644 index 00000000..d9ab06ff --- /dev/null +++ b/app/views/sponsorships/show.html.erb @@ -0,0 +1,24 @@ +

<%= notice %>

+ +

+ Amount: + <%= @sponsorship.amount %> +

+ +

+ Visible: + <%= @sponsorship.visible %> +

+ +

+ Sponsor: + <%= @sponsorship.sponsor_id %> +

+ +

+ Developer: + <%= @sponsorship.developer_id %> +

+ +<%= link_to 'Edit', edit_sponsorship_path(@sponsorship) %> | +<%= link_to 'Back', sponsorships_path %> diff --git a/app/views/sponsorships/show.json.jbuilder b/app/views/sponsorships/show.json.jbuilder new file mode 100644 index 00000000..87ded287 --- /dev/null +++ b/app/views/sponsorships/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "sponsorships/sponsorship", sponsorship: @sponsorship diff --git a/app/views/sponsorships/sponsored.json.jbuilder b/app/views/sponsorships/sponsored.json.jbuilder new file mode 100644 index 00000000..ceac4b23 --- /dev/null +++ b/app/views/sponsorships/sponsored.json.jbuilder @@ -0,0 +1,21 @@ +json.count @total +json.sponsorships do + json.array! @sponsorships do |sponsorship| + json.id sponsorship.id + json.start_time sponsorship.created_at.to_date + # json.stop_time '-' + if sponsorship.visible.zero? + json.visible false + else + json.visible true + end + json.amount sponsorship.amount + sponsor = sponsorship.sponsor + json.image_url url_to_avatar(sponsor) + json.username sponsor.full_name + json.user_id sponsor.id + json.login sponsor.login + json.accumulate sponsorship.accumulate + json.sponsor_id sponsorship.sponsor.id + end +end diff --git a/app/views/sponsorships/sponsoring.json.jbuilder b/app/views/sponsorships/sponsoring.json.jbuilder new file mode 100644 index 00000000..39a4027a --- /dev/null +++ b/app/views/sponsorships/sponsoring.json.jbuilder @@ -0,0 +1,21 @@ +json.count @total +json.sponsorships do + json.array! @sponsorships do |sponsorship| + json.id sponsorship.id + json.start_time sponsorship.created_at.to_date + # json.stop_time '-' + if sponsorship.visible.zero? + json.visible false + else + json.visible true + end + json.amount sponsorship.amount + sponsor = sponsorship.developer + json.image_url url_to_avatar(sponsor) + json.username sponsor.full_name + json.user_id sponsor.id + json.login sponsor.login + json.accumulate sponsorship.accumulate + json.sponsor_id sponsorship.sponsor.id + end +end diff --git a/app/views/sponsorships/stopped.json.jbuilder b/app/views/sponsorships/stopped.json.jbuilder new file mode 100644 index 00000000..a6d0cca4 --- /dev/null +++ b/app/views/sponsorships/stopped.json.jbuilder @@ -0,0 +1,11 @@ +json.array! @stopped_sponsorships do |sponsorship| + json.id sponsorship.id + json.amount sponsorship.amount + json.visible sponsorship.visible + json.sponsor_id sponsorship.sponsor_id + json.developer_id sponsorship.developer_id + json.start_time sponsorship.start_time + json.created_at sponsorship.created_at + json.updated_at sponsorship.updated_at + json.accumulate sponsorship.accumulate +end \ No newline at end of file diff --git a/app/views/sponsorships/stopped_sponsored.json.jbuilder b/app/views/sponsorships/stopped_sponsored.json.jbuilder new file mode 100644 index 00000000..cd06cb6c --- /dev/null +++ b/app/views/sponsorships/stopped_sponsored.json.jbuilder @@ -0,0 +1,21 @@ +json.count @total +json.sponsorships do + json.array! @stopped_sponsorships do |sponsorship| + json.id sponsorship.id + json.start_time sponsorship.start_time.to_date + json.stop_time sponsorship.created_at.to_date + if sponsorship.visible.zero? + json.visible false + else + json.visible true + end + json.amount sponsorship.amount + sponsor = sponsorship.sponsor + json.image_url url_to_avatar(sponsor) + json.username sponsor.full_name + json.user_id sponsor.id + json.login sponsor.login + json.accumulate sponsorship.accumulate + json.sponsor_id sponsorship.sponsor.id + end +end \ No newline at end of file diff --git a/app/views/sponsorships/stopped_sponsoring.json.jbuilder b/app/views/sponsorships/stopped_sponsoring.json.jbuilder new file mode 100644 index 00000000..fb3b0f9c --- /dev/null +++ b/app/views/sponsorships/stopped_sponsoring.json.jbuilder @@ -0,0 +1,21 @@ +json.count @total +json.sponsorships do + json.array! @stopped_sponsorships do |sponsorship| + json.id sponsorship.id + json.start_time sponsorship.start_time.to_date + json.stop_time sponsorship.created_at.to_date + if sponsorship.visible.zero? + json.visible false + else + json.visible true + end + json.amount sponsorship.amount + sponsor = sponsorship.developer + json.image_url url_to_avatar(sponsor) + json.username sponsor.full_name + json.user_id sponsor.id + json.login sponsor.login + json.accumulate sponsorship.accumulate + json.sponsor_id sponsorship.sponsor.id + end +end \ No newline at end of file diff --git a/app/views/users/get_user_info.json.jbuilder b/app/views/users/get_user_info.json.jbuilder index 908801da..7b6eada2 100644 --- a/app/views/users/get_user_info.json.jbuilder +++ b/app/views/users/get_user_info.json.jbuilder @@ -13,5 +13,6 @@ json.need_edit_info @user.need_edit_info? json.email @user.mail json.profile_completed @user.profile_completed? json.professional_certification @user.professional_certification +json.description @user.description json.devops_step @user.devops_step json.ci_certification @user.ci_certification? diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index 54f85c5c..a4f3adbb 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -15,4 +15,5 @@ json.user_composes_count @user_composes_count json.user_org_count @user_org_count json.common_projects_count @projects_common_count json.mirror_projects_count @projects_mirrior_count -json.sync_mirror_projects_count @projects_sync_mirrior_count \ No newline at end of file +json.sync_mirror_projects_count @projects_sync_mirrior_count +json.description @user.description \ No newline at end of file diff --git a/app/views/wallets/balance.html.erb b/app/views/wallets/balance.html.erb new file mode 100644 index 00000000..ed2b106d --- /dev/null +++ b/app/views/wallets/balance.html.erb @@ -0,0 +1,2 @@ +

Wallets#balance

+

Find me in app/views/wallets/balance.html.erb

diff --git a/app/views/wallets/balance.json.jbuilder b/app/views/wallets/balance.json.jbuilder new file mode 100644 index 00000000..2a5a7f6b --- /dev/null +++ b/app/views/wallets/balance.json.jbuilder @@ -0,0 +1 @@ +json.balance @wallet.balance \ No newline at end of file diff --git a/app/views/wallets/coin_changes.json.jbuilder b/app/views/wallets/coin_changes.json.jbuilder new file mode 100644 index 00000000..35452f48 --- /dev/null +++ b/app/views/wallets/coin_changes.json.jbuilder @@ -0,0 +1,25 @@ +json.balance @wallet.balance +json.count @total +json.coin_changes do + json.array! @coin_changes do |coin_change| + from_user = if coin_change.from_wallet.nil? + nil + else + coin_change.from_wallet.user + end + to_user = coin_change.to_wallet.user + json.amount coin_change.amount + if !from_user.nil? + json.from_user from_user.full_name + json.from_user_login from_user.login + else + json.from_user '系统' + json.from_user_login '-' + end + json.to_user to_user.full_name + json.to_user_login to_user.login + json.description coin_change.description + json.reason coin_change.reason + json.date coin_change.created_at.to_date + end +end diff --git a/config/environments/development.rb b/config/environments/development.rb index f0b3f177..57ba830a 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -55,6 +55,9 @@ Rails.application.configure do # Suppress logger output for asset requests. config.assets.quiet = true + # config.logger = Logger.new("#{Rails.root}/log/#{Rails.env}#{Date.today.to_s}.log", "daily") + # config.logger.level = Logger::INFO + # config.assets.prefix = '/dev-assets' # Raises error for missing translations diff --git a/config/initializers/user_trace_logger.rb b/config/initializers/user_trace_logger.rb new file mode 100644 index 00000000..7188c20b --- /dev/null +++ b/config/initializers/user_trace_logger.rb @@ -0,0 +1,9 @@ +require 'multi_logger' +formatter = Proc.new{|severity, time, progname, msg| + formatted_severity = sprintf("%-5s",severity.to_s) + formatted_time = time.strftime("%Y-%m-%d %H:%M:%S") + # "[#{formatted_severity} #{formatted_time} #{$$}] #{msg.to_s.strip}\n" + "#{msg.to_s.strip}\n" +} +MultiLogger.add_logger('user_trace', formatter: formatter, shift_age: 'daily') +Rails.logger.user_trace.level = Logger::INFO diff --git a/config/routes.rb b/config/routes.rb index ebea0007..b450c11f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,6 +24,24 @@ Rails.application.routes.draw do resources :edu_settings scope '/api' do + get 'wallets/balance' + get 'wallets/coin_changes' + + get 'log/list', to: 'log#list' + # post 'log/download', to: 'log#download' + match 'log/download/:filename' => 'log#download', :constraints => { filename: /[0-z\.]+/ }, via:[:get] + + resources :sponsor_tiers, only: [:index, :show, :create, :update, :destroy] + resources :sponsorships, only: [:index, :show, :create, :update, :destroy] do + collection do + get :sponsored + get :sponsoring + get :stopped_sponsored + get :stopped_sponsoring + get :stopped + end + end + namespace :ci do resources :languages, only: [:index, :show] do collection do @@ -198,6 +216,7 @@ Rails.application.routes.draw do get :projects get :watch_users get :fan_users + put :update_description end collection do post :following diff --git a/config/schedule.rb b/config/schedule.rb new file mode 100644 index 00000000..1c05b516 --- /dev/null +++ b/config/schedule.rb @@ -0,0 +1,38 @@ +# Use this file to easily define all of your cron jobs. +# +# It's helpful, but not entirely necessary to understand cron before proceeding. +# http://en.wikipedia.org/wiki/Cron + +# Example: +# +# set :output, "/path/to/my/cron_log.log" +# +# every 2.hours do +# command "/usr/bin/some_great_command" +# runner "MyModel.some_method" +# rake "some:great:rake:task" +# end +# +# every 4.days do +# runner "AnotherModel.prune_old_records" +# end + +# Learn more: http://github.com/javan/whenever +# +set :environment, :development +every '0 1 20 * *' do + runner 'Sponsorship.monthly_payment' +end +# every 1.month, at: 'January 20th 10:00am' do +# runner 'Sponsorship.monthly_payment' +# end +# ####################################################### +# * * * * * command to be executed +# - - - - - +# | | | | | +# | | | | +----- day of week (0 - 6) (Sunday=0) +# | | | +------- month (1 - 12) +# | | +--------- day of month (1 - 31) +# | +----------- hour (0 - 23) +# +------------- min (0 - 59) +# ####################################################### diff --git a/db/migrate/20200724085032_add_column_to_table_users.rb b/db/migrate/20200724085032_add_column_to_table_users.rb new file mode 100644 index 00000000..3fa706ac --- /dev/null +++ b/db/migrate/20200724085032_add_column_to_table_users.rb @@ -0,0 +1,8 @@ +class AddColumnToTableUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :description, :string, default: "" + add_column :users, :sponsor_certification, :integer, default: 0 + add_column :users, :sponsor_num, :integer, default: 0 + add_column :users, :sponsored_num, :integer, default: 0 + end +end diff --git a/db/migrate/20200724090750_create_sponsorships.rb b/db/migrate/20200724090750_create_sponsorships.rb new file mode 100644 index 00000000..6feb9892 --- /dev/null +++ b/db/migrate/20200724090750_create_sponsorships.rb @@ -0,0 +1,12 @@ +class CreateSponsorships < ActiveRecord::Migration[5.2] + def change + create_table :sponsorships do |t| + t.integer :amount + t.integer :visible + t.integer :sponsor_id + t.integer :developer_id + + t.timestamps + end + end +end diff --git a/db/migrate/20200724093202_create_sponsor_tiers.rb b/db/migrate/20200724093202_create_sponsor_tiers.rb new file mode 100644 index 00000000..14317f9a --- /dev/null +++ b/db/migrate/20200724093202_create_sponsor_tiers.rb @@ -0,0 +1,9 @@ +class CreateSponsorTiers < ActiveRecord::Migration[5.2] + def change + create_table :sponsor_tiers do |t| + t.integer :tier + + t.timestamps + end + end +end diff --git a/db/migrate/20200724093530_add_column_to_sponsor_tiers.rb b/db/migrate/20200724093530_add_column_to_sponsor_tiers.rb new file mode 100644 index 00000000..8210315d --- /dev/null +++ b/db/migrate/20200724093530_add_column_to_sponsor_tiers.rb @@ -0,0 +1,6 @@ +class AddColumnToSponsorTiers < ActiveRecord::Migration[5.2] + def change + add_column :sponsor_tiers, :description, :string, default: "" + add_column :sponsor_tiers, :user_id, :integer + end +end diff --git a/db/migrate/20200724094030_create_stopped_sponsorships.rb b/db/migrate/20200724094030_create_stopped_sponsorships.rb new file mode 100644 index 00000000..b639dc4b --- /dev/null +++ b/db/migrate/20200724094030_create_stopped_sponsorships.rb @@ -0,0 +1,11 @@ +class CreateStoppedSponsorships < ActiveRecord::Migration[5.2] + def change + create_table :stopped_sponsorships do |t| + t.integer :amount + t.integer :sponsor_id + t.integer :developer_id + + t.timestamps + end + end +end diff --git a/db/migrate/20200724094458_create_wallets.rb b/db/migrate/20200724094458_create_wallets.rb new file mode 100644 index 00000000..eab5a06d --- /dev/null +++ b/db/migrate/20200724094458_create_wallets.rb @@ -0,0 +1,10 @@ +class CreateWallets < ActiveRecord::Migration[5.2] + def change + create_table :wallets do |t| + t.integer :balance + t.integer :user_id + + t.timestamps + end + end +end diff --git a/db/migrate/20200724094729_create_coin_changes.rb b/db/migrate/20200724094729_create_coin_changes.rb new file mode 100644 index 00000000..6999312b --- /dev/null +++ b/db/migrate/20200724094729_create_coin_changes.rb @@ -0,0 +1,13 @@ +class CreateCoinChanges < ActiveRecord::Migration[5.2] + def change + create_table :coin_changes do |t| + t.integer :amount + t.string :description + t.string :reason + t.integer :to_wallet_id + t.integer :from_wallet_id + + t.timestamps + end + end +end diff --git a/db/migrate/20200725025555_create_waitlists.rb b/db/migrate/20200725025555_create_waitlists.rb new file mode 100644 index 00000000..701006e9 --- /dev/null +++ b/db/migrate/20200725025555_create_waitlists.rb @@ -0,0 +1,12 @@ +class CreateWaitlists < ActiveRecord::Migration[5.2] + def change + create_table :waitlists do |t| + t.string :applicant_id + t.string :integer + t.string :reviewer_id + t.string :integer + + t.timestamps + end + end +end diff --git a/db/migrate/20200725025657_create_passed_waitlists.rb b/db/migrate/20200725025657_create_passed_waitlists.rb new file mode 100644 index 00000000..6d8b4b81 --- /dev/null +++ b/db/migrate/20200725025657_create_passed_waitlists.rb @@ -0,0 +1,12 @@ +class CreatePassedWaitlists < ActiveRecord::Migration[5.2] + def change + create_table :passed_waitlists do |t| + t.string :applicant_id + t.string :integer + t.string :reviewer_id + t.string :integer + + t.timestamps + end + end +end diff --git a/db/migrate/20200919014501_add_column_to_stopped_sponsorship.rb b/db/migrate/20200919014501_add_column_to_stopped_sponsorship.rb new file mode 100644 index 00000000..edf4fd01 --- /dev/null +++ b/db/migrate/20200919014501_add_column_to_stopped_sponsorship.rb @@ -0,0 +1,5 @@ +class AddColumnToStoppedSponsorship < ActiveRecord::Migration[5.2] + def change + add_column :stopped_sponsorships, :start_time, :datetime + end +end diff --git a/db/migrate/20200920073628_add_visible_to_stopped_sponsorship.rb b/db/migrate/20200920073628_add_visible_to_stopped_sponsorship.rb new file mode 100644 index 00000000..c36e0045 --- /dev/null +++ b/db/migrate/20200920073628_add_visible_to_stopped_sponsorship.rb @@ -0,0 +1,5 @@ +class AddVisibleToStoppedSponsorship < ActiveRecord::Migration[5.2] + def change + add_column :stopped_sponsorships, :visible, :integer + end +end diff --git a/db/migrate/20201017131232_change_user_description_type.rb b/db/migrate/20201017131232_change_user_description_type.rb new file mode 100644 index 00000000..46ad1436 --- /dev/null +++ b/db/migrate/20201017131232_change_user_description_type.rb @@ -0,0 +1,6 @@ +class ChangeUserDescriptionType < ActiveRecord::Migration[5.2] + def change + remove_column :users, :description + add_column :users, :description, :text + end +end diff --git a/db/migrate/20201018133345_add_accumulate_to_sponsorships.rb b/db/migrate/20201018133345_add_accumulate_to_sponsorships.rb new file mode 100644 index 00000000..5b361d2e --- /dev/null +++ b/db/migrate/20201018133345_add_accumulate_to_sponsorships.rb @@ -0,0 +1,6 @@ +class AddAccumulateToSponsorships < ActiveRecord::Migration[5.2] + def change + add_column :sponsorships, :accumulate, :integer, default: 0 + add_column :stopped_sponsorships, :accumulate, :integer, default: 0 + end +end diff --git a/db/migrate/20210316125048_add_award_time_to_user.rb b/db/migrate/20210316125048_add_award_time_to_user.rb new file mode 100644 index 00000000..6d06af45 --- /dev/null +++ b/db/migrate/20210316125048_add_award_time_to_user.rb @@ -0,0 +1,5 @@ +class AddAwardTimeToUser < ActiveRecord::Migration[5.2] + def change + add_column :users, :award_time, :datetime + end +end diff --git a/db/structure.sql b/db/structure.sql index 26208e57..aab6536c 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -55,6 +55,7 @@ CREATE TABLE `applied_contests` ( -- ---------------------------- -- Table structure for applied_messages -- ---------------------------- +-- DROP TABLE IF /home/qyzh/datadict.txtpplied_messages`; DROP TABLE IF EXISTS `applied_messages`; CREATE TABLE `applied_messages` ( `id` int(11) NOT NULL AUTO_INCREMENT, diff --git a/public/options/readme/readme b/public/options/readme/readme new file mode 100644 index 00000000..cc620a13 --- /dev/null +++ b/public/options/readme/readme @@ -0,0 +1,20 @@ +## 从命令行创建一个新的仓库 + +```bash +touch README.md +git init +git add README.md +git commit -m "first commit" +git remote add origin http://gitea.trustie.net/qiubing/gitea_binary_package.git +git push -u origin master + +``` + +## 从命令行推送已经创建的仓库 + +```bash +git remote add origin http://gitea.trustie.net/qiubing/gitea_binary_package.git +git push -u origin master + +``` + diff --git a/spec/controllers/log_controller_spec.rb b/spec/controllers/log_controller_spec.rb new file mode 100644 index 00000000..afdcff6f --- /dev/null +++ b/spec/controllers/log_controller_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe LogController, type: :controller do + +end diff --git a/spec/controllers/sponsor_tiers_controller_spec.rb b/spec/controllers/sponsor_tiers_controller_spec.rb new file mode 100644 index 00000000..f848bca7 --- /dev/null +++ b/spec/controllers/sponsor_tiers_controller_spec.rb @@ -0,0 +1,188 @@ +require 'rails_helper' + +# This spec was generated by rspec-rails when you ran the scaffold generator. +# It demonstrates how one might use RSpec to specify the controller code that +# was generated by Rails when you ran the scaffold generator. +# +# It assumes that the implementation code is generated by the rails scaffold +# generator. If you are using any extension libraries to generate different +# controller code, this generated spec may or may not pass. +# +# It only uses APIs available in rails and/or rspec-rails. There are a number +# of tools you can use to make these specs even more expressive, but we're +# sticking to rails and rspec-rails APIs to keep things simple and stable. +# +# Compared to earlier versions of this generator, there is very limited use of +# stubs and message expectations in this spec. Stubs are only used when there +# is no simpler way to get a handle on the object needed for the example. +# Message expectations are only used when there is no simpler way to specify +# that an instance is receiving a specific message. +# +# Also compared to earlier versions of this generator, there are no longer any +# expectations of assigns and templates rendered. These features have been +# removed from Rails core in Rails 5, but can be added back in via the +# `rails-controller-testing` gem. + +RSpec.describe SponsorTiersController, type: :controller do + + # This should return the minimal set of attributes required to create a valid + # SponsorTier. As you add validations to SponsorTier, be sure to + # adjust the attributes here as well. + let(:valid_attributes) { + {tier: 10, user_id: 5, description: 'Rspec test description'} + } + + let(:invalid_attributes) { + {t: '10', user_id: -1, descrip: 'Rspec test description'} + } + + let(:invalid_user_attributes) { + {tier: 10, user_id: 4, description: 'Rspec test invalid user description'} + } + # This should return the minimal set of values that should be in the session + # in order to pass any filters (e.g. authentication) defined in + # SponsorTiersController. Be sure to keep this updated too. + let(:valid_session) { + # user = User.find 5 + # User.current = user + # cookies.signed[:user_id] = user.id + # cookies["autologin"] = "060a555275563b9f096c6ceed84518f64a4614ee" + {user_id: 5, www_user_id: 5} + } + + describe 'GET #index' do + it 'returns a success response' do + SponsorTier.create! valid_attributes + get :index, params: {login: 'qyzh123123'}, session: valid_session + expect(response).to be_successful + end + end + + describe 'GET #show' do + it 'returns a success response' do + sponsor_tier = SponsorTier.create! valid_attributes + get :show, params: {id: sponsor_tier.to_param}, session: valid_session + expect(response).to be_successful + end + end + + describe 'POST #create' do + context 'with valid params' do + it 'creates a new SponsorTier' do + expect { + post :create, params: {sponsor_tier: valid_attributes}, session: valid_session + }.to change(SponsorTier, :count).by(1) + end + + it 'redirects to the created sponsor_tier' do + post :create, params: {sponsor_tier: valid_attributes}, session: valid_session + expect(response).to redirect_to(SponsorTier.last) + # expect(response).to be_successful + end + end + + context 'with invalid params' do + it "returns a success response (i.e. to display the 'new' template)" do + post :create, params: {sponsor_tier: invalid_attributes}, session: valid_session + expect(response).to be_successful + end + end + + context 'with invalid user id' do + it 'does not creates a new SponsorTier' do + expect { + post :create, params: {sponsor_tier: invalid_user_attributes}, session: valid_session + }.to change(SponsorTier, :count).by(0) + end + + it "returns a success response" do + post :create, params: {sponsor_tier: invalid_user_attributes}, session: valid_session + expect(response).to be_successful + end + end + end + + describe 'PUT #update' do + context 'with valid params' do + let(:new_attributes) { + {tier: 12, description: 'Rspec test update description'} + } + + it 'updates the requested sponsor_tier' do + sponsor_tier = SponsorTier.create! valid_attributes + put :update, params: {id: sponsor_tier.to_param, sponsor_tier: new_attributes}, session: valid_session + sponsor_tier.reload + expect(sponsor_tier.tier).to eq(12) + expect(sponsor_tier.description).to eq('Rspec test update description') + end + + it 'redirects to the sponsor_tier' do + sponsor_tier = SponsorTier.create! valid_attributes + put :update, params: {id: sponsor_tier.to_param, sponsor_tier: valid_attributes}, session: valid_session + expect(response).to redirect_to(sponsor_tier) + end + end + + context 'with invalid params' do + it 'does not update and redirects to the sponsor_tier' do + sponsor_tier = SponsorTier.create! valid_attributes + put :update, params: {id: sponsor_tier.to_param, sponsor_tier: invalid_attributes}, session: valid_session + expect(response).to redirect_to(sponsor_tier) + expect(sponsor_tier.tier).to eq(10) + expect(sponsor_tier.description).to eq('Rspec test description') + end + end + + context 'with invalid user id' do + let(:new_attributes) { + {tier: 12, description: 'Rspec test update description'} + } + it 'does not update SponsorTier' do + sponsor_tier = SponsorTier.create! invalid_user_attributes + put :update, params: {id: sponsor_tier.to_param, sponsor_tier: new_attributes}, session: valid_session + sponsor_tier.reload + expect(sponsor_tier.tier).to eq(10) + expect(sponsor_tier.description).to eq('Rspec test invalid user description') + end + + it 'redirects to the sponsor_tier' do + sponsor_tier = SponsorTier.create! invalid_user_attributes + put :update, params: {id: sponsor_tier.to_param, sponsor_tier: valid_attributes}, session: valid_session + expect(response).to be_ok + end + end + end + + describe 'DELETE #destroy' do + context 'with valid user id' do + it 'destroys the requested sponsor_tier' do + sponsor_tier = SponsorTier.create! valid_attributes + expect { + delete :destroy, params: {id: sponsor_tier.to_param}, session: valid_session + }.to change(SponsorTier, :count).by(-1) + end + + it 'redirects to the sponsor_tiers list' do + sponsor_tier = SponsorTier.create! valid_attributes + delete :destroy, params: {id: sponsor_tier.to_param}, session: valid_session + expect(response).to redirect_to(sponsor_tiers_url) + end + end + + context 'with invalid user id' do + it 'does not destroy the requested sponsor_tier' do + sponsor_tier = SponsorTier.create! invalid_user_attributes + expect { + delete :destroy, params: {id: sponsor_tier.to_param}, session: valid_session + }.to change(SponsorTier, :count).by(0) + end + + it 'be ok' do + sponsor_tier = SponsorTier.create! invalid_user_attributes + delete :destroy, params: {id: sponsor_tier.to_param}, session: valid_session + expect(response).to be_ok + end + end + end + +end diff --git a/spec/controllers/sponsorships_controller_spec.rb b/spec/controllers/sponsorships_controller_spec.rb new file mode 100644 index 00000000..d2fb975c --- /dev/null +++ b/spec/controllers/sponsorships_controller_spec.rb @@ -0,0 +1,184 @@ +require 'rails_helper' + +# This spec was generated by rspec-rails when you ran the scaffold generator. +# It demonstrates how one might use RSpec to specify the controller code that +# was generated by Rails when you ran the scaffold generator. +# +# It assumes that the implementation code is generated by the rails scaffold +# generator. If you are using any extension libraries to generate different +# controller code, this generated spec may or may not pass. +# +# It only uses APIs available in rails and/or rspec-rails. There are a number +# of tools you can use to make these specs even more expressive, but we're +# sticking to rails and rspec-rails APIs to keep things simple and stable. +# +# Compared to earlier versions of this generator, there is very limited use of +# stubs and message expectations in this spec. Stubs are only used when there +# is no simpler way to get a handle on the object needed for the example. +# Message expectations are only used when there is no simpler way to specify +# that an instance is receiving a specific message. +# +# Also compared to earlier versions of this generator, there are no longer any +# expectations of assigns and templates rendered. These features have been +# removed from Rails core in Rails 5, but can be added back in via the +# `rails-controller-testing` gem. + +RSpec.describe SponsorshipsController, type: :controller do + + # This should return the minimal set of attributes required to create a valid + # Sponsorship. As you add validations to Sponsorship, be sure to + # adjust the attributes here as well. + let(:valid_attributes) { + {amount: 10, visible: 1, developer_id: 1, sponsor_id: 5} + } + + let(:valid_create_api_attributes) { + {amount: 10, visible: 1, developer_id: 1} + } + + let(:invalid_user_attributes) { + {amount: 10, visible: 1, sponsor_id: 4, developer_id: 1} + } + + let(:invalid_attributes) { + {amunt: 10, visible: 1, developid: 1, sponsoid: 5} + } + + # This should return the minimal set of values that should be in the session + # in order to pass any filters (e.g. authentication) defined in + # SponsorshipsController. Be sure to keep this updated too. + let(:valid_session) { {www_user_id: 5} } + + describe "GET #index" do + it "returns a success response" do + Sponsorship.create! valid_attributes + get :index, params: {}, format: 'json', session: valid_session + expect(response.body).to eq('[]') + end + end + + describe "GET #stopped" do + it "returns a success response" do + sponsorship=StoppedSponsorship.create! valid_attributes + get :stopped, params: {}, format: 'json', session: valid_session + expect(response).to be_successful + end + end + + describe "GET #show" do + it "returns a success response" do + sponsorship = Sponsorship.create! valid_attributes + get :show, params: {id: sponsorship.to_param}, session: valid_session + expect(response).to be_successful + end + end + + describe "POST #create" do + context "with valid params" do + it "creates a new Sponsorship" do + expect { + post :create, params: {sponsorship: valid_create_api_attributes}, session: valid_session + }.to change(Sponsorship, :count).by(1) + end + + it "redirects to the created sponsorship" do + post :create, params: {sponsorship: valid_create_api_attributes}, session: valid_session + expect(response).to be_ok + end + end + + context "single sponsor" do + let(:valid_single_params){ + {amount: 10, visible: 1, developer_id: 1, single: true} + } + it "creates a stopped sponsorship" do + expect { + post :create, params: {amount: 10, visible: 1, developer_id: 1, single: true}, session: valid_session + }.to change(StoppedSponsorship, :count).by(0) + end + end + + context "repeat sponsor" do + it "creates only one new Sponsorship" do + Sponsorship.create! valid_attributes + expect { + post :create, params: {sponsorship: valid_create_api_attributes}, session: valid_session + }.to change(Sponsorship, :count).by(1) + end + end + + context "with invalid params" do + it "returns a success response (i.e. to display the 'new' template)" do + post :create, params: {sponsorship: invalid_attributes}, session: valid_session + expect(response).to be_successful + end + end + end + + describe "PUT #update" do + context "with valid params" do + let(:new_attributes) { + {amount: 20, visible: 0} + } + + it "updates the requested sponsorship" do + sponsorship = Sponsorship.create! valid_attributes + put :update, params: {id: sponsorship.to_param, sponsorship: new_attributes}, session: valid_session + sponsorship.reload + expect(sponsorship.amount).to eq(20) + expect(sponsorship.visible).to eq(0) + end + + it "does not updates the requested sponsorship with wrong user" do + sponsorship = Sponsorship.create! invalid_user_attributes + put :update, params: {id: sponsorship.to_param, sponsorship: new_attributes}, session: valid_session + sponsorship.reload + expect(sponsorship.amount).to eq(10) + expect(sponsorship.visible).to eq(1) + end + + it "return ok" do + sponsorship = Sponsorship.create! valid_attributes + put :update, params: {id: sponsorship.to_param, sponsorship: valid_attributes}, session: valid_session + expect(response).to be_ok + end + end + + context "with invalid params" do + it "returns a success response (i.e. to display the 'edit' template)" do + sponsorship = Sponsorship.create! valid_attributes + put :update, params: {id: sponsorship.to_param, sponsorship: invalid_attributes}, session: valid_session + expect(response).to be_successful + end + end + end + + describe "DELETE #destroy" do + it "destroys the requested sponsorship" do + sponsorship = Sponsorship.create! valid_attributes + expect { + delete :destroy, params: {id: sponsorship.to_param}, session: valid_session + }.to change(Sponsorship, :count).by(-1) + end + + it "destroys the requested sponsorship" do + sponsorship = Sponsorship.create! invalid_user_attributes + expect { + delete :destroy, params: {id: sponsorship.to_param}, session: valid_session + }.to change(Sponsorship, :count).by(0) + end + + it "return ok" do + sponsorship = Sponsorship.create! valid_attributes + delete :destroy, params: {id: sponsorship.to_param}, session: valid_session + expect(response).to be_ok + end + + it "return ok" do + sponsorship = Sponsorship.create! invalid_user_attributes + delete :destroy, params: {id: sponsorship.to_param}, session: valid_session + expect(response).to be_ok + end + end + +end diff --git a/spec/controllers/wallets_controller_spec.rb b/spec/controllers/wallets_controller_spec.rb new file mode 100644 index 00000000..ed2ebf9c --- /dev/null +++ b/spec/controllers/wallets_controller_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +RSpec.describe WalletsController, type: :controller do + + describe "GET #balance" do + it "returns http success" do + get :balance + expect(response).to have_http_status(:success) + end + end + +end diff --git a/spec/helpers/log_helper_spec.rb b/spec/helpers/log_helper_spec.rb new file mode 100644 index 00000000..5d95097c --- /dev/null +++ b/spec/helpers/log_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the LogHelper. For example: +# +# describe LogHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe LogHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/helpers/sponsor_tiers_helper_spec.rb b/spec/helpers/sponsor_tiers_helper_spec.rb new file mode 100644 index 00000000..19ce39a7 --- /dev/null +++ b/spec/helpers/sponsor_tiers_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the SponsorTiersHelper. For example: +# +# describe SponsorTiersHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe SponsorTiersHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/helpers/sponsorships_helper_spec.rb b/spec/helpers/sponsorships_helper_spec.rb new file mode 100644 index 00000000..229491bf --- /dev/null +++ b/spec/helpers/sponsorships_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the SponsorshipsHelper. For example: +# +# describe SponsorshipsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe SponsorshipsHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/helpers/wallets_helper_spec.rb b/spec/helpers/wallets_helper_spec.rb new file mode 100644 index 00000000..7f242db9 --- /dev/null +++ b/spec/helpers/wallets_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the WalletsHelper. For example: +# +# describe WalletsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe WalletsHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/coin_change_spec.rb b/spec/models/coin_change_spec.rb new file mode 100644 index 00000000..313ecf1f --- /dev/null +++ b/spec/models/coin_change_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe CoinChange, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/passed_waitlist_spec.rb b/spec/models/passed_waitlist_spec.rb new file mode 100644 index 00000000..5124c945 --- /dev/null +++ b/spec/models/passed_waitlist_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe PassedWaitlist, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/sponsor_tier_spec.rb b/spec/models/sponsor_tier_spec.rb new file mode 100644 index 00000000..3ceab0b6 --- /dev/null +++ b/spec/models/sponsor_tier_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe SponsorTier, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/sponsorship_spec.rb b/spec/models/sponsorship_spec.rb new file mode 100644 index 00000000..d2e58e69 --- /dev/null +++ b/spec/models/sponsorship_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Sponsorship, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/stopped_sponsorship_spec.rb b/spec/models/stopped_sponsorship_spec.rb new file mode 100644 index 00000000..3e4503dd --- /dev/null +++ b/spec/models/stopped_sponsorship_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe StoppedSponsorship, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/waitlist_spec.rb b/spec/models/waitlist_spec.rb new file mode 100644 index 00000000..1b8f43be --- /dev/null +++ b/spec/models/waitlist_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Waitlist, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/wallet_spec.rb b/spec/models/wallet_spec.rb new file mode 100644 index 00000000..768de3cd --- /dev/null +++ b/spec/models/wallet_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Wallet, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/requests/sponsor_tiers_spec.rb b/spec/requests/sponsor_tiers_spec.rb new file mode 100644 index 00000000..55ea2a06 --- /dev/null +++ b/spec/requests/sponsor_tiers_spec.rb @@ -0,0 +1,10 @@ +require 'rails_helper' + +RSpec.describe "SponsorTiers", type: :request do + describe "GET /sponsor_tiers" do + it "works! (now write some real specs)" do + get sponsor_tiers_path + expect(response).to have_http_status(200) + end + end +end diff --git a/spec/requests/sponsorships_spec.rb b/spec/requests/sponsorships_spec.rb new file mode 100644 index 00000000..74065abb --- /dev/null +++ b/spec/requests/sponsorships_spec.rb @@ -0,0 +1,13 @@ +require 'rails_helper' + +RSpec.describe "Sponsorships", type: :request do + let(:valid_session) { {www_user_id: 5} } + + describe "GET /sponsorships" do + it "works! (now write some real specs)" do + get sponsorships_path + expect(response).to have_http_status(200) + end + end + +end diff --git a/spec/routing/log_routing_spec.rb b/spec/routing/log_routing_spec.rb new file mode 100644 index 00000000..550d21a3 --- /dev/null +++ b/spec/routing/log_routing_spec.rb @@ -0,0 +1,10 @@ +require "rails_helper" + +RSpec.describe LogController, type: :routing do + describe "routing" do + it "routes to #index" do + expect(:get => "/api/log/list").to route_to("log#list") + end + end +end + diff --git a/spec/routing/sponsor_tiers_routing_spec.rb b/spec/routing/sponsor_tiers_routing_spec.rb new file mode 100644 index 00000000..64da8d55 --- /dev/null +++ b/spec/routing/sponsor_tiers_routing_spec.rb @@ -0,0 +1,29 @@ +require "rails_helper" + +RSpec.describe SponsorTiersController, type: :routing do + describe "routing" do + it "routes to #index" do + expect(:get => "/api/sponsor_tiers").to route_to("sponsor_tiers#index") + end + + it "routes to #show" do + expect(:get => "/api/sponsor_tiers/1").to route_to("sponsor_tiers#show", :id => "1") + end + + it "routes to #create" do + expect(:post => "/api/sponsor_tiers").to route_to("sponsor_tiers#create") + end + + it "routes to #update via PUT" do + expect(:put => "/api/sponsor_tiers/1").to route_to("sponsor_tiers#update", :id => "1") + end + + it "routes to #update via PATCH" do + expect(:patch => "/api/sponsor_tiers/1").to route_to("sponsor_tiers#update", :id => "1") + end + + it "routes to #destroy" do + expect(:delete => "/api/sponsor_tiers/1").to route_to("sponsor_tiers#destroy", :id => "1") + end + end +end diff --git a/spec/routing/sponsorships_routing_spec.rb b/spec/routing/sponsorships_routing_spec.rb new file mode 100644 index 00000000..a5efe9b8 --- /dev/null +++ b/spec/routing/sponsorships_routing_spec.rb @@ -0,0 +1,49 @@ +require "rails_helper" + +RSpec.describe SponsorshipsController, type: :routing do + describe "routing" do + it "routes to #index" do + expect(:get => "/api/sponsorships").to route_to("sponsorships#index") + end + + it "routes to stopped" do + expect(:get => "/api/sponsorships/stopped").to route_to("sponsorships#stopped") + end + + it "routes to sponsoring" do + expect(:get => "/api/sponsorships/sponsoring").to route_to("sponsorships#sponsoring") + end + + it "routes to stopped_sponsoring" do + expect(:get => "/api/sponsorships/stopped_sponsoring").to route_to("sponsorships#stopped_sponsoring") + end + + it "routes to sponsored" do + expect(:get => "/api/sponsorships/sponsored").to route_to("sponsorships#sponsored") + end + + it "routes to stopped_sponsored" do + expect(:get => "/api/sponsorships/stopped_sponsored").to route_to("sponsorships#stopped_sponsored") + end + + it "routes to #show" do + expect(:get => "/api/sponsorships/1").to route_to("sponsorships#show", :id => "1") + end + + it "routes to #create" do + expect(:post => "/api/sponsorships").to route_to("sponsorships#create") + end + + it "routes to #update via PUT" do + expect(:put => "/api/sponsorships/1").to route_to("sponsorships#update", :id => "1") + end + + it "routes to #update via PATCH" do + expect(:patch => "/api/sponsorships/1").to route_to("sponsorships#update", :id => "1") + end + + it "routes to #destroy" do + expect(:delete => "/api/sponsorships/1").to route_to("sponsorships#destroy", :id => "1") + end + end +end diff --git a/spec/views/sponsor_tiers/edit.html.erb_spec.rb b/spec/views/sponsor_tiers/edit.html.erb_spec.rb new file mode 100644 index 00000000..dc11f60a --- /dev/null +++ b/spec/views/sponsor_tiers/edit.html.erb_spec.rb @@ -0,0 +1,18 @@ +require 'rails_helper' + +RSpec.describe "sponsor_tiers/edit", type: :view do + before(:each) do + @sponsor_tier = assign(:sponsor_tier, SponsorTier.create!( + :tier => 1 + )) + end + + it "renders the edit sponsor_tier form" do + render + + assert_select "form[action=?][method=?]", sponsor_tier_path(@sponsor_tier), "post" do + + assert_select "input[name=?]", "sponsor_tier[tier]" + end + end +end diff --git a/spec/views/sponsor_tiers/index.html.erb_spec.rb b/spec/views/sponsor_tiers/index.html.erb_spec.rb new file mode 100644 index 00000000..56706612 --- /dev/null +++ b/spec/views/sponsor_tiers/index.html.erb_spec.rb @@ -0,0 +1,19 @@ +require 'rails_helper' + +RSpec.describe "sponsor_tiers/index", type: :view do + before(:each) do + assign(:sponsor_tiers, [ + SponsorTier.create!( + :tier => 2 + ), + SponsorTier.create!( + :tier => 2 + ) + ]) + end + + it "renders a list of sponsor_tiers" do + render + assert_select "tr>td", :text => 2.to_s, :count => 2 + end +end diff --git a/spec/views/sponsor_tiers/new.html.erb_spec.rb b/spec/views/sponsor_tiers/new.html.erb_spec.rb new file mode 100644 index 00000000..24ae0a5e --- /dev/null +++ b/spec/views/sponsor_tiers/new.html.erb_spec.rb @@ -0,0 +1,18 @@ +require 'rails_helper' + +RSpec.describe "sponsor_tiers/new", type: :view do + before(:each) do + assign(:sponsor_tier, SponsorTier.new( + :tier => 1 + )) + end + + it "renders new sponsor_tier form" do + render + + assert_select "form[action=?][method=?]", sponsor_tiers_path, "post" do + + assert_select "input[name=?]", "sponsor_tier[tier]" + end + end +end diff --git a/spec/views/sponsor_tiers/show.html.erb_spec.rb b/spec/views/sponsor_tiers/show.html.erb_spec.rb new file mode 100644 index 00000000..488e7c21 --- /dev/null +++ b/spec/views/sponsor_tiers/show.html.erb_spec.rb @@ -0,0 +1,14 @@ +require 'rails_helper' + +RSpec.describe "sponsor_tiers/show", type: :view do + before(:each) do + @sponsor_tier = assign(:sponsor_tier, SponsorTier.create!( + :tier => 2 + )) + end + + it "renders attributes in

" do + render + expect(rendered).to match(/2/) + end +end diff --git a/spec/views/sponsorships/edit.html.erb_spec.rb b/spec/views/sponsorships/edit.html.erb_spec.rb new file mode 100644 index 00000000..e676afd1 --- /dev/null +++ b/spec/views/sponsorships/edit.html.erb_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.describe "sponsorships/edit", type: :view do + before(:each) do + @sponsorship = assign(:sponsorship, Sponsorship.create!( + :amount => 1, + :visible => 1, + :sponsor_id => 1, + :developer_id => 1 + )) + end + + it "renders the edit sponsorship form" do + render + + assert_select "form[action=?][method=?]", sponsorship_path(@sponsorship), "post" do + + assert_select "input[name=?]", "sponsorship[amount]" + + assert_select "input[name=?]", "sponsorship[visible]" + + assert_select "input[name=?]", "sponsorship[sponsor_id]" + + assert_select "input[name=?]", "sponsorship[developer_id]" + end + end +end diff --git a/spec/views/sponsorships/index.html.erb_spec.rb b/spec/views/sponsorships/index.html.erb_spec.rb new file mode 100644 index 00000000..c31533a1 --- /dev/null +++ b/spec/views/sponsorships/index.html.erb_spec.rb @@ -0,0 +1,28 @@ +require 'rails_helper' + +RSpec.describe "sponsorships/index", type: :view do + before(:each) do + assign(:sponsorships, [ + Sponsorship.create!( + :amount => 2, + :visible => 3, + :sponsor_id => 4, + :developer_id => 5 + ), + Sponsorship.create!( + :amount => 2, + :visible => 3, + :sponsor_id => 4, + :developer_id => 5 + ) + ]) + end + + it "renders a list of sponsorships" do + render + assert_select "tr>td", :text => 2.to_s, :count => 2 + assert_select "tr>td", :text => 3.to_s, :count => 2 + assert_select "tr>td", :text => 4.to_s, :count => 2 + assert_select "tr>td", :text => 5.to_s, :count => 2 + end +end diff --git a/spec/views/sponsorships/new.html.erb_spec.rb b/spec/views/sponsorships/new.html.erb_spec.rb new file mode 100644 index 00000000..9c816df1 --- /dev/null +++ b/spec/views/sponsorships/new.html.erb_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.describe "sponsorships/new", type: :view do + before(:each) do + assign(:sponsorship, Sponsorship.new( + :amount => 1, + :visible => 1, + :sponsor_id => 1, + :developer_id => 1 + )) + end + + it "renders new sponsorship form" do + render + + assert_select "form[action=?][method=?]", sponsorships_path, "post" do + + assert_select "input[name=?]", "sponsorship[amount]" + + assert_select "input[name=?]", "sponsorship[visible]" + + assert_select "input[name=?]", "sponsorship[sponsor_id]" + + assert_select "input[name=?]", "sponsorship[developer_id]" + end + end +end diff --git a/spec/views/sponsorships/show.html.erb_spec.rb b/spec/views/sponsorships/show.html.erb_spec.rb new file mode 100644 index 00000000..dffc5a4d --- /dev/null +++ b/spec/views/sponsorships/show.html.erb_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe "sponsorships/show", type: :view do + before(:each) do + @sponsorship = assign(:sponsorship, Sponsorship.create!( + :amount => 2, + :visible => 3, + :sponsor_id => 4, + :developer_id => 5 + )) + end + + it "renders attributes in

" do + render + expect(rendered).to match(/2/) + expect(rendered).to match(/3/) + expect(rendered).to match(/4/) + expect(rendered).to match(/5/) + end +end diff --git a/spec/views/wallets/balance.html.erb_spec.rb b/spec/views/wallets/balance.html.erb_spec.rb new file mode 100644 index 00000000..407801b5 --- /dev/null +++ b/spec/views/wallets/balance.html.erb_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe "wallets/balance.html.erb", type: :view do + pending "add some examples to (or delete) #{__FILE__}" +end