| @@ -14,7 +14,6 @@ | |||||
| # mac | # mac | ||||
| *.DS_Store | *.DS_Store | ||||
| .bashrc | .bashrc | ||||
| # Ignore all logfiles and tempfiles. | # Ignore all logfiles and tempfiles. | ||||
| /log/* | /log/* | ||||
| /tmp/* | /tmp/* | ||||
| @@ -42,6 +41,7 @@ public/react/yarn.lock | |||||
| /public/react/config/stats.json | /public/react/config/stats.json | ||||
| /public/react/stats.json | /public/react/stats.json | ||||
| /public/react/.idea/* | /public/react/.idea/* | ||||
| /public/react/build/* | |||||
| /public/h5build | /public/h5build | ||||
| /public/npm-debug.log | /public/npm-debug.log | ||||
| @@ -66,6 +66,7 @@ vendor/bundle/ | |||||
| /Users | /Users | ||||
| /files | /files | ||||
| /public/images/avatars | /public/images/avatars | ||||
| /public/cache_repository | |||||
| /public/files | /public/files | ||||
| /workspace | /workspace | ||||
| /log | /log | ||||
| @@ -80,3 +81,4 @@ docker/ | |||||
| educoder.sql | educoder.sql | ||||
| redis_data/ | redis_data/ | ||||
| Dockerfile | Dockerfile | ||||
| dump.rdb | |||||
| @@ -0,0 +1 @@ | |||||
| --require spec_helper | |||||
| @@ -11,4 +11,4 @@ steps: | |||||
| image: ruby | image: ruby | ||||
| commands: | commands: | ||||
| - bundle install --jobs=3 --retry=3 | - bundle install --jobs=3 --retry=3 | ||||
| - rake | |||||
| - rake | |||||
| @@ -19,8 +19,6 @@ gem 'kaminari', '~> 1.1', '>= 1.1.1' | |||||
| gem 'bootsnap', '>= 1.1.0', require: false | gem 'bootsnap', '>= 1.1.0', require: false | ||||
| gem 'gitlab', path: 'lib/gitlab-cli' | |||||
| gem 'chinese_pinyin' | gem 'chinese_pinyin' | ||||
| gem 'rack-cors' | gem 'rack-cors' | ||||
| @@ -40,7 +38,7 @@ gem 'oauth2' | |||||
| #导出为pdf | #导出为pdf | ||||
| gem 'pdfkit' | gem 'pdfkit' | ||||
| gem 'wkhtmltopdf-binary' | gem 'wkhtmltopdf-binary' | ||||
| gem 'request_store' | |||||
| # gem 'request_store' | |||||
| #gem 'iconv' | #gem 'iconv' | ||||
| # markdown 转html | # markdown 转html | ||||
| gem 'redcarpet', '~> 3.4' | gem 'redcarpet', '~> 3.4' | ||||
| @@ -55,16 +53,26 @@ gem 'ancestry' | |||||
| gem 'acts_as_list' | gem 'acts_as_list' | ||||
| gem 'omniauth-cas' | gem 'omniauth-cas' | ||||
| # profiler Middleware | |||||
| gem 'rack-mini-profiler' | |||||
| # object-based searching | |||||
| gem 'ransack' | |||||
| group :development, :test do | group :development, :test do | ||||
| gem 'rspec-rails', '~> 3.8' | gem 'rspec-rails', '~> 3.8' | ||||
| end | end | ||||
| group :development do | group :development do | ||||
| gem 'prettier' | |||||
| gem 'rubocop', '~> 0.52.0' | |||||
| gem 'solargraph', '~> 0.38.0' | |||||
| gem 'awesome_print' | gem 'awesome_print' | ||||
| gem 'web-console', '>= 3.3.0' | gem 'web-console', '>= 3.3.0' | ||||
| gem 'listen', '>= 3.0.5', '< 3.2' | gem 'listen', '>= 3.0.5', '< 3.2' | ||||
| gem 'spring' | gem 'spring' | ||||
| gem 'spring-watcher-listen', '~> 2.0.0' | gem 'spring-watcher-listen', '~> 2.0.0' | ||||
| gem "annotate", "~> 2.6.0" | |||||
| end | end | ||||
| group :test do | group :test do | ||||
| @@ -1,10 +1,3 @@ | |||||
| PATH | |||||
| remote: lib/gitlab-cli | |||||
| specs: | |||||
| gitlab (3.2.0) | |||||
| httparty | |||||
| terminal-table | |||||
| GEM | GEM | ||||
| remote: https://gems.ruby-china.com/ | remote: https://gems.ruby-china.com/ | ||||
| specs: | specs: | ||||
| @@ -61,9 +54,13 @@ GEM | |||||
| public_suffix (>= 2.0.2, < 5.0) | public_suffix (>= 2.0.2, < 5.0) | ||||
| ancestry (3.0.7) | ancestry (3.0.7) | ||||
| activerecord (>= 3.2.0) | activerecord (>= 3.2.0) | ||||
| annotate (2.6.5) | |||||
| activerecord (>= 2.3.0) | |||||
| rake (>= 0.8.7) | |||||
| archive-zip (0.12.0) | archive-zip (0.12.0) | ||||
| io-like (~> 0.3.0) | io-like (~> 0.3.0) | ||||
| arel (9.0.0) | arel (9.0.0) | ||||
| ast (2.4.0) | |||||
| autoprefixer-rails (9.7.4) | autoprefixer-rails (9.7.4) | ||||
| execjs | execjs | ||||
| awesome_print (1.8.0) | awesome_print (1.8.0) | ||||
| @@ -75,6 +72,8 @@ GEM | |||||
| axlsx_rails (0.5.2) | axlsx_rails (0.5.2) | ||||
| actionpack (>= 3.1) | actionpack (>= 3.1) | ||||
| axlsx (>= 2.0.1) | axlsx (>= 2.0.1) | ||||
| backport (1.1.2) | |||||
| benchmark (0.1.0) | |||||
| bindex (0.8.1) | bindex (0.8.1) | ||||
| bootsnap (1.4.6) | bootsnap (1.4.6) | ||||
| msgpack (~> 1.0) | msgpack (~> 1.0) | ||||
| @@ -107,6 +106,7 @@ GEM | |||||
| activerecord (>= 3.1.0, < 7) | activerecord (>= 3.1.0, < 7) | ||||
| diff-lcs (1.3) | diff-lcs (1.3) | ||||
| diffy (3.3.0) | diffy (3.3.0) | ||||
| e2mmap (0.1.0) | |||||
| elasticsearch (7.5.0) | elasticsearch (7.5.0) | ||||
| elasticsearch-api (= 7.5.0) | elasticsearch-api (= 7.5.0) | ||||
| elasticsearch-transport (= 7.5.0) | elasticsearch-transport (= 7.5.0) | ||||
| @@ -134,12 +134,10 @@ GEM | |||||
| harmonious_dictionary (0.0.1) | harmonious_dictionary (0.0.1) | ||||
| hashie (3.6.0) | hashie (3.6.0) | ||||
| htmlentities (4.3.4) | htmlentities (4.3.4) | ||||
| httparty (0.18.0) | |||||
| mime-types (~> 3.0) | |||||
| multi_xml (>= 0.5.2) | |||||
| i18n (1.8.2) | i18n (1.8.2) | ||||
| concurrent-ruby (~> 1.0) | concurrent-ruby (~> 1.0) | ||||
| io-like (0.3.1) | io-like (0.3.1) | ||||
| jaro_winkler (1.5.4) | |||||
| jbuilder (2.10.0) | jbuilder (2.10.0) | ||||
| activesupport (>= 5.0.0) | activesupport (>= 5.0.0) | ||||
| jquery-rails (4.3.5) | jquery-rails (4.3.5) | ||||
| @@ -170,10 +168,8 @@ GEM | |||||
| mini_mime (>= 0.1.1) | mini_mime (>= 0.1.1) | ||||
| marcel (0.3.3) | marcel (0.3.3) | ||||
| mimemagic (~> 0.3.2) | mimemagic (~> 0.3.2) | ||||
| maruku (0.7.3) | |||||
| method_source (0.9.2) | method_source (0.9.2) | ||||
| mime-types (3.3.1) | |||||
| mime-types-data (~> 3.2015) | |||||
| mime-types-data (3.2019.1009) | |||||
| mimemagic (0.3.4) | mimemagic (0.3.4) | ||||
| mini_mime (1.0.2) | mini_mime (1.0.2) | ||||
| mini_portile2 (2.4.0) | mini_portile2 (2.4.0) | ||||
| @@ -205,13 +201,21 @@ GEM | |||||
| oauth2 (~> 1.1) | oauth2 (~> 1.1) | ||||
| omniauth (~> 1.9) | omniauth (~> 1.9) | ||||
| parallel (1.19.1) | parallel (1.19.1) | ||||
| parser (2.7.1.1) | |||||
| ast (~> 2.4.0) | |||||
| pdfkit (0.8.4.1) | pdfkit (0.8.4.1) | ||||
| polyamorous (2.3.2) | |||||
| activerecord (>= 5.2.1) | |||||
| popper_js (1.16.0) | popper_js (1.16.0) | ||||
| powerpack (0.1.2) | |||||
| prettier (0.18.2) | |||||
| public_suffix (4.0.3) | public_suffix (4.0.3) | ||||
| puma (3.12.2) | puma (3.12.2) | ||||
| rack (2.0.9) | rack (2.0.9) | ||||
| rack-cors (1.1.1) | rack-cors (1.1.1) | ||||
| rack (>= 2.0.0) | rack (>= 2.0.0) | ||||
| rack-mini-profiler (2.0.1) | |||||
| rack (>= 1.2.0) | |||||
| rack-protection (2.0.8.1) | rack-protection (2.0.8.1) | ||||
| rack | rack | ||||
| rack-test (1.1.0) | rack-test (1.1.0) | ||||
| @@ -243,7 +247,13 @@ GEM | |||||
| method_source | method_source | ||||
| rake (>= 0.8.7) | rake (>= 0.8.7) | ||||
| thor (>= 0.19.0, < 2.0) | thor (>= 0.19.0, < 2.0) | ||||
| rainbow (3.0.0) | |||||
| rake (13.0.1) | rake (13.0.1) | ||||
| ransack (2.3.2) | |||||
| activerecord (>= 5.2.1) | |||||
| activesupport (>= 5.2.1) | |||||
| i18n | |||||
| polyamorous (= 2.3.2) | |||||
| rb-fsevent (0.10.3) | rb-fsevent (0.10.3) | ||||
| rb-inotify (0.10.1) | rb-inotify (0.10.1) | ||||
| ffi (~> 1.0) | ffi (~> 1.0) | ||||
| @@ -269,6 +279,8 @@ GEM | |||||
| regexp_parser (1.7.0) | regexp_parser (1.7.0) | ||||
| request_store (1.5.0) | request_store (1.5.0) | ||||
| rack (>= 1.4) | rack (>= 1.4) | ||||
| reverse_markdown (1.4.0) | |||||
| nokogiri | |||||
| roo (2.8.3) | roo (2.8.3) | ||||
| nokogiri (~> 1) | nokogiri (~> 1) | ||||
| rubyzip (>= 1.3.0, < 3.0.0) | rubyzip (>= 1.3.0, < 3.0.0) | ||||
| @@ -298,7 +310,15 @@ GEM | |||||
| rspec-mocks (~> 3.9.0) | rspec-mocks (~> 3.9.0) | ||||
| rspec-support (~> 3.9.0) | rspec-support (~> 3.9.0) | ||||
| rspec-support (3.9.2) | rspec-support (3.9.2) | ||||
| rubocop (0.52.1) | |||||
| parallel (~> 1.10) | |||||
| parser (>= 2.4.0.2, < 3.0) | |||||
| powerpack (~> 0.1) | |||||
| rainbow (>= 2.2.2, < 4.0) | |||||
| ruby-progressbar (~> 1.7) | |||||
| unicode-display_width (~> 1.0, >= 1.0.1) | |||||
| ruby-ole (1.2.12.2) | ruby-ole (1.2.12.2) | ||||
| ruby-progressbar (1.10.1) | |||||
| ruby2_keywords (0.0.2) | ruby2_keywords (0.0.2) | ||||
| ruby_dep (1.5.0) | ruby_dep (1.5.0) | ||||
| rubyzip (1.3.0) | rubyzip (1.3.0) | ||||
| @@ -344,6 +364,20 @@ GEM | |||||
| rack (~> 2.0) | rack (~> 2.0) | ||||
| rack-protection (= 2.0.8.1) | rack-protection (= 2.0.8.1) | ||||
| tilt (~> 2.0) | tilt (~> 2.0) | ||||
| solargraph (0.38.6) | |||||
| backport (~> 1.1) | |||||
| benchmark | |||||
| bundler (>= 1.17.2) | |||||
| e2mmap | |||||
| jaro_winkler (~> 1.5) | |||||
| maruku (~> 0.7, >= 0.7.3) | |||||
| nokogiri (~> 1.9, >= 1.9.1) | |||||
| parser (~> 2.3) | |||||
| reverse_markdown (~> 1.0, >= 1.0.5) | |||||
| rubocop (~> 0.52) | |||||
| thor (~> 1.0) | |||||
| tilt (~> 2.0) | |||||
| yard (~> 0.9) | |||||
| spreadsheet (1.2.6) | spreadsheet (1.2.6) | ||||
| ruby-ole (>= 1.0) | ruby-ole (>= 1.0) | ||||
| spring (2.0.2) | spring (2.0.2) | ||||
| @@ -358,8 +392,6 @@ GEM | |||||
| actionpack (>= 4.0) | actionpack (>= 4.0) | ||||
| activesupport (>= 4.0) | activesupport (>= 4.0) | ||||
| sprockets (>= 3.0.0) | sprockets (>= 3.0.0) | ||||
| terminal-table (1.8.0) | |||||
| unicode-display_width (~> 1.1, >= 1.1.1) | |||||
| thor (1.0.1) | thor (1.0.1) | ||||
| thread_safe (0.3.6) | thread_safe (0.3.6) | ||||
| tilt (2.0.10) | tilt (2.0.10) | ||||
| @@ -382,6 +414,7 @@ GEM | |||||
| wkhtmltopdf-binary (0.12.5.4) | wkhtmltopdf-binary (0.12.5.4) | ||||
| xpath (3.2.0) | xpath (3.2.0) | ||||
| nokogiri (~> 1.8) | nokogiri (~> 1.8) | ||||
| yard (0.9.24) | |||||
| PLATFORMS | PLATFORMS | ||||
| ruby | ruby | ||||
| @@ -392,6 +425,7 @@ DEPENDENCIES | |||||
| acts-as-taggable-on (~> 6.0) | acts-as-taggable-on (~> 6.0) | ||||
| acts_as_list | acts_as_list | ||||
| ancestry | ancestry | ||||
| annotate (~> 2.6.0) | |||||
| awesome_print | awesome_print | ||||
| axlsx (~> 3.0.0.pre) | axlsx (~> 3.0.0.pre) | ||||
| axlsx_rails (~> 0.5.2) | axlsx_rails (~> 0.5.2) | ||||
| @@ -407,7 +441,6 @@ DEPENDENCIES | |||||
| enumerize | enumerize | ||||
| faraday (~> 0.15.4) | faraday (~> 0.15.4) | ||||
| font-awesome-sass (= 4.7.0) | font-awesome-sass (= 4.7.0) | ||||
| gitlab! | |||||
| grape-entity (~> 0.7.1) | grape-entity (~> 0.7.1) | ||||
| groupdate (~> 4.1.0) | groupdate (~> 4.1.0) | ||||
| harmonious_dictionary (~> 0.0.1) | harmonious_dictionary (~> 0.0.1) | ||||
| @@ -422,10 +455,13 @@ DEPENDENCIES | |||||
| omniauth-oauth2 (~> 1.6.0) | omniauth-oauth2 (~> 1.6.0) | ||||
| parallel (~> 1.19, >= 1.19.1) | parallel (~> 1.19, >= 1.19.1) | ||||
| pdfkit | pdfkit | ||||
| prettier | |||||
| puma (~> 3.11) | puma (~> 3.11) | ||||
| rack-cors | rack-cors | ||||
| rack-mini-profiler | |||||
| rails (~> 5.2.0) | rails (~> 5.2.0) | ||||
| rails-i18n (~> 5.1) | rails-i18n (~> 5.1) | ||||
| ransack | |||||
| rchardet (~> 1.8) | rchardet (~> 1.8) | ||||
| redcarpet (~> 3.4) | redcarpet (~> 3.4) | ||||
| redis-rails | redis-rails | ||||
| @@ -434,6 +470,7 @@ DEPENDENCIES | |||||
| rqrcode (~> 0.10.1) | rqrcode (~> 0.10.1) | ||||
| rqrcode_png | rqrcode_png | ||||
| rspec-rails (~> 3.8) | rspec-rails (~> 3.8) | ||||
| rubocop (~> 0.52.0) | |||||
| ruby-ole | ruby-ole | ||||
| rubyzip | rubyzip | ||||
| sass-rails (~> 5.0) | sass-rails (~> 5.0) | ||||
| @@ -443,6 +480,7 @@ DEPENDENCIES | |||||
| simple_form | simple_form | ||||
| simple_xlsx_reader | simple_xlsx_reader | ||||
| sinatra | sinatra | ||||
| solargraph (~> 0.38.0) | |||||
| spreadsheet | spreadsheet | ||||
| spring | spring | ||||
| spring-watcher-listen (~> 2.0.0) | spring-watcher-listen (~> 2.0.0) | ||||
| @@ -456,4 +494,4 @@ RUBY VERSION | |||||
| ruby 2.3.7p456 | ruby 2.3.7p456 | ||||
| BUNDLED WITH | BUNDLED WITH | ||||
| 2.0.2 | |||||
| 2.1.4 | |||||
| @@ -1,4 +1,4 @@ | |||||
| Trustie (确实)是一个以大众化协同开发、开放式资源共享、持续性可信评估为核心机理,面向高校创新实践的在线协作平台 | |||||
| Trustie (确实)是一个以大众化协同开发、开放式资源共享、持续性可信评估为核心机理,面向高校创新实践的在线协作平台 | |||||
| ## 特性 | ## 特性 | ||||
| @@ -11,13 +11,13 @@ Trustie (确实)是一个以大众化协同开发、开放式资源共享、 | |||||
| ## 部署 | ## 部署 | ||||
| #### 1. 安装依赖包 | |||||
| ### 1. 安装依赖包 | |||||
| ```bash | ```bash | ||||
| bundle install | bundle install | ||||
| ``` | ``` | ||||
| #### 2. 配置初始化文件 | |||||
| ### 2. 配置初始化文件 | |||||
| 进入项目根目录执行一下命令: | 进入项目根目录执行一下命令: | ||||
| ```bash | ```bash | ||||
| @@ -27,38 +27,71 @@ touch config/redis.yml | |||||
| touch config/elasticsearch.yml | touch config/elasticsearch.yml | ||||
| ``` | ``` | ||||
| #### 3. 创建数据库 | |||||
| ### 3. 配置gitea服务(可选) | |||||
| **如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/** | |||||
| **因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/6070/coders** | |||||
| #### 配置gitea服务步骤 | |||||
| 1. 部署gitea服务,并注册root账户 | |||||
| 2. 修改forge平台的 config/configuration.yml中的gitea服务指向地址,如: | |||||
| ```ruby | |||||
| gitea: | |||||
| access_key_id: 'root' | |||||
| access_key_secret: 'password' | |||||
| domain: 'http://www.gitea.example.com' | |||||
| base_url: '/api/v1' | |||||
| ``` | |||||
| ### 4. 安装redis环境 | |||||
| **请自行搜索各平台如何安装部署redis环境** | |||||
| ### 5. 创建数据库 | |||||
| ```bash | ```bash | ||||
| rails db:create | rails db:create | ||||
| ``` | ``` | ||||
| #### 4. 导入数据表结构 | |||||
| ### 6. 导入数据表结构 | |||||
| ```bash | ```bash | ||||
| bundle exec rake sync_table_structure:import_csv | bundle exec rake sync_table_structure:import_csv | ||||
| ``` | ``` | ||||
| #### 5. 执行migrate迁移文件 | |||||
| ### 7. 执行migrate迁移文件 | |||||
| **开发环境为development, 生成环境为production** | |||||
| ```bash | ```bash | ||||
| rails db:migrate RAILS_ENV=development | rails db:migrate RAILS_ENV=development | ||||
| ``` | ``` | ||||
| #### 6. 启动rails服务 | |||||
| ### 8. 启动redis(此处已mac系统为例) | |||||
| ```bash | |||||
| redis-server& | |||||
| ``` | |||||
| ### 9. 启动sidekiq | |||||
| **开发环境为development, 生成环境为production** | |||||
| ```bash | |||||
| bundle exec sidekiq -C config/sidekiq.yml -e production -d | |||||
| ``` | |||||
| ### 10. 启动rails服务 | |||||
| ```bash | ```bash | ||||
| rails s | rails s | ||||
| ``` | ``` | ||||
| #### 7. 浏览器访问 | |||||
| ### 11. 浏览器访问 | |||||
| 在浏览器中输入如下地址访问: | 在浏览器中输入如下地址访问: | ||||
| ```bash | ```bash | ||||
| http://localhost:3000/projects | |||||
| http://localhost:3000/ | |||||
| ``` | ``` | ||||
| ## 页面展示 | ## 页面展示 | ||||
| - 代码库 | |||||
| - 代码库 | |||||
|  |  | ||||
| @@ -70,13 +103,10 @@ http://localhost:3000/projects | |||||
|  |  | ||||
| - 任务指派 | |||||
| - 任务指派 | |||||
|  |  | ||||
| - 里程碑 | - 里程碑 | ||||
|  |  | ||||
| @@ -0,0 +1,13 @@ | |||||
| // Action Cable provides the framework to deal with WebSockets in Rails. | |||||
| // You can generate new channels where WebSocket features live using the `rails generate channel` command. | |||||
| // | |||||
| //= require action_cable | |||||
| //= require_self | |||||
| //= require_tree ./channels | |||||
| (function() { | |||||
| this.App || (this.App = {}); | |||||
| App.cable = ActionCable.createConsumer(); | |||||
| }).call(this); | |||||
| @@ -0,0 +1,13 @@ | |||||
| App.mirror_project = App.cable.subscriptions.create("MirrorProjectChannel", { | |||||
| connected: function() { | |||||
| // Called when the subscription is ready for use on the server | |||||
| }, | |||||
| disconnected: function() { | |||||
| // Called when the subscription has been terminated by the server | |||||
| }, | |||||
| received: function(data) { | |||||
| // Called when there's incoming data on the websocket for this channel | |||||
| } | |||||
| }); | |||||
| @@ -135,5 +135,6 @@ | |||||
| padding: 10px 20px 0; | padding: 10px 20px 0; | ||||
| background: #fff; | background: #fff; | ||||
| } | } | ||||
| .mt-10{margin-top: 10px;} | |||||
| } | } | ||||
| @@ -0,0 +1,78 @@ | |||||
| html{margin:0px;padding: 0px;font-size: 14px;font-family: "微软雅黑","宋体";} | |||||
| body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td { | |||||
| margin: 0; | |||||
| padding: 0; | |||||
| } | |||||
| .IndexContent{ | |||||
| height: 100vh; | |||||
| width: 100%; | |||||
| position: relative; | |||||
| background-image: url('/images/oauth/backImg.png'); | |||||
| background-repeat: no-repeat; | |||||
| background-size: cover; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| flex-direction: column; | |||||
| } | |||||
| .indexLogo{ | |||||
| width:80px; | |||||
| margin-bottom: 35px; | |||||
| } | |||||
| .indexPanel{ | |||||
| width: 580px; | |||||
| min-height: 400px; | |||||
| background-color: #fff; | |||||
| box-shadow: 0px 2px 10px 5px rgba(0,0,0,0.05); | |||||
| border-radius: 5px; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .indexTitle{ | |||||
| height: 75px; | |||||
| line-height: 75px; | |||||
| font-size: 18px; | |||||
| color:#333; | |||||
| text-align: center; | |||||
| border-bottom: 1px solid #eee; | |||||
| } | |||||
| .indexInfo{ | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: flex-start; | |||||
| } | |||||
| .indexInfos{ | |||||
| padding:40px 60px; | |||||
| } | |||||
| .indexInfo > span{ | |||||
| color: #333; | |||||
| font-size: 16px; | |||||
| margin-top: 5px; | |||||
| } | |||||
| .indexInfo input{ | |||||
| width: 100%; | |||||
| height:40px; | |||||
| border-radius: 2px; | |||||
| border:1px solid #eee; | |||||
| margin-top: 5px; | |||||
| padding:0px 0px 0px 8px; | |||||
| outline: none; | |||||
| } | |||||
| .indexInfo .checkInfo{ | |||||
| height: 15px; | |||||
| color: red; | |||||
| } | |||||
| .indexBtn{ | |||||
| text-align: center; | |||||
| margin-top: 20px; | |||||
| } | |||||
| .indexSubmit{ | |||||
| width: 50%; | |||||
| height: 32px; | |||||
| line-height: 32px; | |||||
| background-color: #1890FF; | |||||
| border:none; | |||||
| color: #fff; | |||||
| border-radius: 2px; | |||||
| cursor: pointer; | |||||
| outline: none; | |||||
| } | |||||
| @@ -1,4 +1,21 @@ | |||||
| module ApplicationCable | module ApplicationCable | ||||
| class Connection < ActionCable::Connection::Base | class Connection < ActionCable::Connection::Base | ||||
| identified_by :current_user | |||||
| def connect | |||||
| self.current_user = find_verified_user | |||||
| logger.add_tags 'ActionCable', current_user.id | |||||
| end | |||||
| private | |||||
| def find_verified_user | |||||
| puts "############### cookies.signed[:user_id]: #{cookies.signed[:user_id]}" | |||||
| if current_user = User.find_by(id: cookies.signed[:user_id]) | |||||
| puts "############### find_verified_user success! ###############" | |||||
| current_user | |||||
| else | |||||
| reject_unauthorized_connection | |||||
| end | |||||
| end | |||||
| end | end | ||||
| end | end | ||||
| @@ -0,0 +1,11 @@ | |||||
| class MirrorProjectChannel < ApplicationCable::Channel | |||||
| def subscribed | |||||
| Rails.logger.info "################### channel params: #{params}" | |||||
| stream_from "channel_room_#{params[:id]}" | |||||
| end | |||||
| def unsubscribed | |||||
| # Any cleanup needed when channel is unsubscribed | |||||
| Rails.logger.info "################### unsubscribed ################### " | |||||
| end | |||||
| end | |||||
| @@ -1,8 +1,13 @@ | |||||
| class AdminConstraint | class AdminConstraint | ||||
| def matches?(request) | def matches?(request) | ||||
| laboratory = Laboratory.first | |||||
| return false unless request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"] | |||||
| user = User.find request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"] | |||||
| user && user.admin? | |||||
| if Rails.env.development? | |||||
| true | |||||
| else | |||||
| laboratory = Laboratory.first | |||||
| return false unless request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"] | |||||
| user = User.find request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"] | |||||
| user && user.admin? | |||||
| end | |||||
| end | end | ||||
| end | end | ||||
| @@ -13,23 +13,59 @@ class AccountsController < ApplicationController | |||||
| password = params[:password] | password = params[:password] | ||||
| platform = (params[:platform] || 'forge')&.gsub(/\s+/, "") | platform = (params[:platform] || 'forge')&.gsub(/\s+/, "") | ||||
| @user = User.new(admin: false, login: username, mail: email, type: "User") | |||||
| @user.password = password | |||||
| @user.platform = platform | |||||
| @user.activate | |||||
| ActiveRecord::Base.transaction do | |||||
| result = autologin_register(username, email, password, platform) | |||||
| if result[:message].blank? | |||||
| render_ok({user: result[:user]}) | |||||
| else | |||||
| render_error(result[:message]) | |||||
| end | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(-1, e.message) | |||||
| end | |||||
| # 其他平台修改用户的信息,这边同步修改 | |||||
| def remote_update | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) | |||||
| if interactor.success? | |||||
| gitea_user = interactor.result | |||||
| result = Gitea::User::GenerateTokenService.new(username, password).call | |||||
| @user.gitea_token = result['sha1'] | |||||
| @user.gitea_uid = gitea_user['id'] | |||||
| if @user.save! | |||||
| render_ok({user: {id: @user.id, token: @user.gitea_token}}) | |||||
| user_params = params[:user_params] | |||||
| user_extension_params = params[:user_extension_params] | |||||
| u = User.find_by(login: params[:old_user_login]) | |||||
| user_mail = u.try(:mail) | |||||
| if u.present? | |||||
| ue = u.user_extension | |||||
| u.login = user_params["login"] if user_params["login"] | |||||
| u.mail = user_params["mail"] if user_params["mail"] | |||||
| u.lastname = user_params["lastname"] if user_params["lastname"] | |||||
| ue.gender = user_extension_params["gender"] | |||||
| ue.school_id = user_extension_params["school_id"] | |||||
| ue.location = user_extension_params["location"] | |||||
| ue.location_city = user_extension_params["location_city"] | |||||
| ue.identity = user_extension_params["identity"] | |||||
| ue.technical_title = user_extension_params["technical_title"] | |||||
| ue.student_id = user_extension_params["student_id"] | |||||
| ue.description = user_extension_params["description"] | |||||
| ue.save! | |||||
| u.save! | |||||
| sync_params = {} | |||||
| if (user_params["mail"] && user_params["mail"] != user_mail) | |||||
| sync_params = sync_params.merge(email: user_params["mail"]) | |||||
| end | |||||
| if sync_params.present? | |||||
| interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params) | |||||
| if interactor.success? | |||||
| render_ok | |||||
| else | |||||
| render_error(interactor.error) | |||||
| end | |||||
| end | end | ||||
| else | |||||
| render_error(interactor.error) | |||||
| end | end | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -37,38 +73,70 @@ class AccountsController < ApplicationController | |||||
| tip_exception(-1, e.message) | tip_exception(-1, e.message) | ||||
| end | end | ||||
| # 其他平台同步登录 | |||||
| def remote_login | |||||
| @user = User.try_to_login(params[:login], params[:password]) | |||||
| if @user | |||||
| successful_authentication(@user) | |||||
| render_ok({user: {id: @user.id, token: @user.gitea_token}}) | |||||
| else | |||||
| render_error("用户不存在") | |||||
| end | |||||
| end | |||||
| #修改密码 | |||||
| def remote_password | |||||
| @user = User.find_by(login: params[:login]) | |||||
| return render_error("未找到相关用户!") if @user.blank? | |||||
| sync_params = { | |||||
| password: params[:password].to_s, | |||||
| email: @user.mail | |||||
| } | |||||
| interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params) | |||||
| if interactor.success? | |||||
| @user.update_attribute(:password, params[:password]) | |||||
| render_ok | |||||
| else | |||||
| render_error(interactor.error) | |||||
| end | |||||
| end | |||||
| # 用户注册 | # 用户注册 | ||||
| # 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用 | # 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用 | ||||
| # params[:login] 邮箱或者手机号 | # params[:login] 邮箱或者手机号 | ||||
| # params[:code] 验证码 | # params[:code] 验证码 | ||||
| # code_type 1:注册手机验证码 8:邮箱注册验证码 | # code_type 1:注册手机验证码 8:邮箱注册验证码 | ||||
| # 本地forge注册入口 | |||||
| def register | def register | ||||
| begin | begin | ||||
| # 查询验证码是否正确;type只可能是1或者8 | # 查询验证码是否正确;type只可能是1或者8 | ||||
| type = phone_mail_type(params[:login].strip) | type = phone_mail_type(params[:login].strip) | ||||
| code = params[:code].strip | |||||
| # code = params[:code].strip | |||||
| if type == 1 | if type == 1 | ||||
| uid_logger("start register by phone: type is #{type}") | uid_logger("start register by phone: type is #{type}") | ||||
| pre = 'p' | pre = 'p' | ||||
| email = nil | email = nil | ||||
| phone = params[:login] | phone = params[:login] | ||||
| verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last | |||||
| # verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last | |||||
| # TODO: 暂时限定邮箱注册 | |||||
| return normal_status(-1, '只支持邮箱注册') | |||||
| else | else | ||||
| uid_logger("start register by email: type is #{type}") | uid_logger("start register by email: type is #{type}") | ||||
| pre = 'm' | pre = 'm' | ||||
| email = params[:login] | email = params[:login] | ||||
| phone = nil | phone = nil | ||||
| verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last | |||||
| return normal_status(-1, "该邮箱已注册") if User.exists?(mail: params[:login]) | |||||
| return normal_status(-1, "邮箱格式错误") unless params[:login] =~ CustomRegexp::EMAIL | |||||
| # verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last | |||||
| end | end | ||||
| uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}") | |||||
| # uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}") | |||||
| # check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60) | # check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60) | ||||
| # todo 上线前请删除万能验证码"513231" | # todo 上线前请删除万能验证码"513231" | ||||
| unless code == "513231" && request.subdomain == "test-newweb" | |||||
| return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip | |||||
| return normal_status(-2, "验证码已失效") if !verifi_code&.effective? | |||||
| end | |||||
| return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD | return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD | ||||
| code = generate_identifier User, 8, pre | code = generate_identifier User, 8, pre | ||||
| @@ -78,23 +146,20 @@ class AccountsController < ApplicationController | |||||
| # 现在因为是验证码,所以在注册的时候就可以激活 | # 现在因为是验证码,所以在注册的时候就可以激活 | ||||
| @user.activate | @user.activate | ||||
| # 必须要用save操作,密码的保存是在users中 | # 必须要用save操作,密码的保存是在users中 | ||||
| if @user.save! | |||||
| # todo user_extension | |||||
| UserExtension.create!(user_id: @user.id) | |||||
| # 注册完成,手机号或邮箱想可以奖励500金币 | |||||
| # RewardGradeService.call( | |||||
| # @user, | |||||
| # container_id: @user.id, | |||||
| # container_type: pre == 'p' ? 'Phone' : 'Mail', | |||||
| # score: 500 | |||||
| # ) | |||||
| # 注册时,记录是否是引流用户 | |||||
| ip = request.remote_ip | |||||
| ua = UserAgent.find_by_ip(ip) | |||||
| ua.update_column(:agent_type, UserAgent::USER_REGISTER) if ua | |||||
| successful_authentication(@user) | |||||
| # session[:user_id] = @user.id | |||||
| normal_status("注册成功") | |||||
| interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: params[:password]}) | |||||
| if interactor.success? | |||||
| gitea_user = interactor.result | |||||
| result = Gitea::User::GenerateTokenService.new(login, params[:password]).call | |||||
| @user.gitea_token = result['sha1'] | |||||
| @user.gitea_uid = gitea_user['id'] | |||||
| if @user.save! | |||||
| UserExtension.create!(user_id: @user.id) | |||||
| successful_authentication(@user) | |||||
| normal_status("注册成功") | |||||
| end | |||||
| else | |||||
| tip_exception(-1, interactor.error) | |||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -125,7 +190,7 @@ class AccountsController < ApplicationController | |||||
| end | end | ||||
| successful_authentication(@user) | successful_authentication(@user) | ||||
| login_control.clear # 重置每日密码错误次数 | |||||
| sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步 | |||||
| # session[:user_id] = @user.id | # session[:user_id] = @user.id | ||||
| end | end | ||||
| @@ -171,27 +236,33 @@ class AccountsController < ApplicationController | |||||
| UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip) | UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip) | ||||
| user.update_column(:last_login_on, Time.now) | user.update_column(:last_login_on, Time.now) | ||||
| session[:"#{default_yun_session}"] = user.id | session[:"#{default_yun_session}"] = user.id | ||||
| Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}") | |||||
| # 注册完成后有一天的试用申请(先去掉) | # 注册完成后有一天的试用申请(先去掉) | ||||
| # UserDayCertification.create(user_id: user.id, status: 1) | # UserDayCertification.create(user_id: user.id, status: 1) | ||||
| end | end | ||||
| # def set_autologin_cookie(user) | |||||
| # token = Token.get_or_create_permanent_login_token(user, "autologin") | |||||
| # cookie_options = { | |||||
| # :value => token.value, | |||||
| # :expires => 1.month.from_now, | |||||
| # :path => '/', | |||||
| # :secure => false, | |||||
| # :httponly => true | |||||
| # } | |||||
| # if edu_setting('cookie_domain').present? | |||||
| # cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain')) | |||||
| # end | |||||
| # cookies[autologin_cookie_name] = cookie_options | |||||
| # logger.info("cookies is #{cookies}") | |||||
| # end | |||||
| def set_autologin_cookie(user) | |||||
| token = Token.get_or_create_permanent_login_token(user, "autologin") | |||||
| sync_user_token_to_trustie(user.login, token.value) | |||||
| cookie_options = { | |||||
| :value => token.value, | |||||
| :expires => 1.month.from_now, | |||||
| :path => '/', | |||||
| :secure => false, | |||||
| :httponly => true | |||||
| } | |||||
| if edu_setting('cookie_domain').present? | |||||
| cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain')) | |||||
| end | |||||
| cookies[autologin_cookie_name] = cookie_options | |||||
| cookies.signed[:user_id] ||= user.id | |||||
| logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}") | |||||
| end | |||||
| def logout | def logout | ||||
| Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}") | |||||
| UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip) | UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip) | ||||
| logout_user | logout_user | ||||
| render :json => {status: 1, message: "退出成功!"} | render :json => {status: 1, message: "退出成功!"} | ||||
| @@ -14,6 +14,7 @@ class Admins::BaseController < ApplicationController | |||||
| private | private | ||||
| def require_login | def require_login | ||||
| # User.current = User.find 1 | |||||
| return if User.current.logged? | return if User.current.logged? | ||||
| redirect_to "/login?back_url=#{CGI::escape(request.fullpath)}" | redirect_to "/login?back_url=#{CGI::escape(request.fullpath)}" | ||||
| @@ -42,4 +43,4 @@ class Admins::BaseController < ApplicationController | |||||
| def setup_laboratory | def setup_laboratory | ||||
| Laboratory.current = Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1) | Laboratory.current = Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1) | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -3,7 +3,13 @@ class Admins::LaboratoriesController < Admins::BaseController | |||||
| default_sort('id', 'desc') | default_sort('id', 'desc') | ||||
| laboratories = Admins::LaboratoryQuery.call(params) | laboratories = Admins::LaboratoryQuery.call(params) | ||||
| @laboratories = paginate laboratories.preload(:school, :laboratory_users) | |||||
| @laboratories = paginate laboratories.preload(:laboratory_users) | |||||
| end | |||||
| def new | |||||
| respond_to do |format| | |||||
| format.js | |||||
| end | |||||
| end | end | ||||
| def create | def create | ||||
| @@ -82,4 +88,4 @@ class Admins::LaboratoriesController < Admins::BaseController | |||||
| def setting_params | def setting_params | ||||
| params.permit(:sync_course, :sync_subject, :sync_shixun) | params.permit(:sync_course, :sync_subject, :sync_shixun) | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -1,4 +1,11 @@ | |||||
| class Admins::LaboratorySettingsController < Admins::BaseController | class Admins::LaboratorySettingsController < Admins::BaseController | ||||
| def new | |||||
| respond_to do |format| | |||||
| format.js | |||||
| end | |||||
| end | |||||
| def show | def show | ||||
| @laboratory = current_laboratory | @laboratory = current_laboratory | ||||
| end | end | ||||
| @@ -0,0 +1,83 @@ | |||||
| class Admins::ProjectCategoriesController < Admins::BaseController | |||||
| before_action :get_category, only: [:edit,:update, :destroy] | |||||
| before_action :validate_names, only: [:create, :update] | |||||
| def index | |||||
| sort_by = params[:sort_by] ||= 'created_at' | |||||
| sort_direction = params[:sort_direction] ||= 'desc' | |||||
| q = ProjectCategory.ransack(name_cont: params[:name]) | |||||
| project_categories = q.result(distinct: true).order("#{sort_by} #{sort_direction}") | |||||
| @project_categories = paginate(project_categories) | |||||
| end | |||||
| def new | |||||
| @project_category = ProjectCategory.new | |||||
| end | |||||
| def edit | |||||
| end | |||||
| def create | |||||
| max_position_items = ProjectCategory.select(:id, :position).pluck(:position).reject!(&:blank?) | |||||
| max_position = max_position_items.present? ? max_position_items.max.to_i : 0 | |||||
| @project_category = ProjectCategory.new(name: @name,position: max_position) | |||||
| if @project_category.save | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:success] = '创建成功' | |||||
| else | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:danger] = '创建失败' | |||||
| end | |||||
| end | |||||
| def update | |||||
| if @project_category.update_attribute(:name, @name) | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:success] = '更新成功' | |||||
| else | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:success] = '更新失败' | |||||
| end | |||||
| end | |||||
| def destroy | |||||
| if @project_language.destroy | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:success] = "删除成功" | |||||
| else | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:danger] = "删除失败" | |||||
| end | |||||
| end | |||||
| private | |||||
| def get_category | |||||
| @project_category = ProjectCategory.find_by(id: params[:id]) | |||||
| unless @project_category.present? | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:danger] = "分类不存在" | |||||
| end | |||||
| end | |||||
| def check_language_present?(name) | |||||
| return true if name.blank? | |||||
| name_downcase = name.downcase | |||||
| name_upcase = name.upcase | |||||
| name_first_big = name.capitalize | |||||
| ProjectCategory.exists?(name: name_downcase) || ProjectCategory.exists?(name: name_upcase) || ProjectCategory.exists?(name: name_first_big) | |||||
| end | |||||
| def validate_names | |||||
| @name = params[:project_category][:name].to_s.first(64) | |||||
| if @name.blank? | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:danger] = '名称不能为空' | |||||
| elsif check_language_present?(@name) && @project_category.blank? | |||||
| redirect_to admins_project_categories_path | |||||
| flash[:danger] = '分类已存在' | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,120 @@ | |||||
| class Admins::ProjectIgnoresController < Admins::BaseController | |||||
| before_action :set_ignore, only: [:edit,:update, :destroy,:show] | |||||
| before_action :validate_params, only: [:create, :update] | |||||
| def index | |||||
| sort_by = params[:sort_by] ||= 'created_at' | |||||
| sort_direction = params[:sort_direction] ||= 'desc' | |||||
| q = Ignore.ransack(name_cont: params[:search]) | |||||
| project_ignores = q.result(distinct: true).order("#{sort_by} #{sort_direction}") | |||||
| @project_ignores = paginate(project_ignores) | |||||
| end | |||||
| def new | |||||
| @project_ignore = Ignore.new | |||||
| end | |||||
| def show | |||||
| end | |||||
| def create | |||||
| # conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present? | |||||
| # permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present? | |||||
| # limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present? | |||||
| # max_position_items = License.select(:id, :position).pluck(:position).reject!(&:blank?) | |||||
| # max_position = max_position_items.present? ? max_position_items.max.to_i : 0 | |||||
| # other_params = { | |||||
| # conditions: conditions.to_s, | |||||
| # permissions: permissions.to_s, | |||||
| # limitations: limitations.to_s, | |||||
| # position: max_position | |||||
| # } | |||||
| @project_ignore = Ignore.new(ignore_params) | |||||
| if @project_ignore.save! | |||||
| redirect_to admins_project_ignores_path | |||||
| flash[:success] = "创建成功" | |||||
| else | |||||
| render :new | |||||
| flash[:danger] = "创建失败" | |||||
| end | |||||
| end | |||||
| def edit | |||||
| end | |||||
| def update | |||||
| # conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present? | |||||
| # permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present? | |||||
| # limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present? | |||||
| # other_params = { | |||||
| # conditions: conditions.to_s, | |||||
| # permissions: permissions.to_s, | |||||
| # limitations: limitations.to_s | |||||
| # } | |||||
| if @project_ignore.update_attributes(ignore_params) | |||||
| redirect_to admins_project_ignores_path | |||||
| flash[:success] = "更新成功" | |||||
| else | |||||
| render :edit | |||||
| flash[:danger] = "更新失败" | |||||
| end | |||||
| end | |||||
| def destroy | |||||
| if @project_ignore.present? | |||||
| if @project_ignore.destroy | |||||
| redirect_to admins_project_ignores_path | |||||
| flash[:success] = "删除成功" | |||||
| else | |||||
| redirect_to admins_project_ignores_path | |||||
| flash[:success] = "删除失败" | |||||
| end | |||||
| else | |||||
| redirect_to admins_project_ignores_path | |||||
| flash[:success] = "删除失败:许可证已被项目引用" | |||||
| end | |||||
| end | |||||
| # def move | |||||
| # cate_opt = params[:opr] | |||||
| # cate_position = @project_license.position.to_i | |||||
| # move_status = up_and_down(cate_opt,@project_license,cate_position,"license") | |||||
| # if move_status == 0 | |||||
| # @c_msg = "移动成功" | |||||
| # else | |||||
| # @c_msg = "移动失败" | |||||
| # end | |||||
| # end | |||||
| private | |||||
| def set_ignore | |||||
| @project_ignore = Ignore.find_by_id(params[:id]) | |||||
| end | |||||
| def ignore_params | |||||
| params.require(:ignore).permit(:name,:content) | |||||
| end | |||||
| def validate_params | |||||
| name = params[:ignore][:name] | |||||
| if name.blank? | |||||
| flash[:danger] = "名称不允许为空" | |||||
| redirect_to admins_project_ignores_path | |||||
| elsif check_ignore_present?(name) && @project_ignore.blank? | |||||
| flash[:danger] = "创建失败:名称已存在" | |||||
| redirect_to admins_project_ignores_path | |||||
| end | |||||
| end | |||||
| def check_ignore_present?(name) | |||||
| return true if name.blank? | |||||
| name_downcase = name.downcase | |||||
| name_upcase = name.upcase | |||||
| name_first_big = name.capitalize | |||||
| Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big) | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,82 @@ | |||||
| class Admins::ProjectLanguagesController < Admins::BaseController | |||||
| before_action :get_language, only: [:edit,:update, :destroy] | |||||
| before_action :validate_names, only: [:create, :update] | |||||
| def index | |||||
| sort_by = params[:sort_by] ||= 'created_at' | |||||
| sort_direction = params[:sort_direction] ||= 'desc' | |||||
| q = ProjectLanguage.ransack(name_cont: params[:search]) | |||||
| project_languages = q.result(distinct: true).order("#{sort_by} #{sort_direction}") | |||||
| @project_languages = paginate(project_languages) | |||||
| end | |||||
| def new | |||||
| @project_language = ProjectLanguage.new | |||||
| end | |||||
| def edit | |||||
| end | |||||
| def create | |||||
| max_position_items = ProjectLanguage.select(:id, :position).pluck(:position).reject!(&:blank?) | |||||
| max_position = max_position_items.present? ? max_position_items.max.to_i : 0 | |||||
| @project_language = ProjectLanguage.new(name: @name,position:max_position) | |||||
| if @project_language.save | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:success] = '创建成功' | |||||
| else | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:danger] = '创建失败' | |||||
| end | |||||
| end | |||||
| def update | |||||
| if @project_language.update_attribute(:name, @name) | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:success] = '更新成功' | |||||
| else | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:success] = '更新失败' | |||||
| end | |||||
| end | |||||
| def destroy | |||||
| if @project_language.destroy | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:success] = "项目语言删除成功" | |||||
| else | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:danger] = "项目语言删除失败" | |||||
| end | |||||
| end | |||||
| private | |||||
| def get_language | |||||
| @project_language = ProjectLanguage.find_by(id: params[:id]) | |||||
| unless @project_language.present? | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:danger] = "项目语言不存在" | |||||
| end | |||||
| end | |||||
| def check_language_present?(name) | |||||
| return true if name.blank? | |||||
| name_downcase = name.downcase | |||||
| name_upcase = name.upcase | |||||
| name_first_big = name.capitalize | |||||
| ProjectLanguage.exists?(name: name_downcase) || ProjectLanguage.exists?(name: name_upcase) || ProjectLanguage.exists?(name: name_first_big) | |||||
| end | |||||
| def validate_names | |||||
| @name = params[:project_language][:name].to_s.first(64) | |||||
| if @name.blank? | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:danger] = '名称不能为空' | |||||
| elsif check_language_present?(@name) && @project_language.blank? | |||||
| redirect_to admins_project_languages_path | |||||
| flash[:danger] = '项目语言已存在' | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,120 @@ | |||||
| class Admins::ProjectLicensesController < Admins::BaseController | |||||
| before_action :set_license, only: [:edit,:update, :destroy,:show] | |||||
| before_action :validate_params, only: [:create, :update] | |||||
| def index | |||||
| sort_by = params[:sort_by] ||= 'created_at' | |||||
| sort_direction = params[:sort_direction] ||= 'desc' | |||||
| q = License.ransack(name_cont: params[:search]) | |||||
| project_licenses = q.result(distinct: true).order("#{sort_by} #{sort_direction}") | |||||
| @project_licenses = paginate(project_licenses) | |||||
| end | |||||
| def new | |||||
| @project_license = License.new | |||||
| end | |||||
| def show | |||||
| end | |||||
| def create | |||||
| # conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present? | |||||
| # permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present? | |||||
| # limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present? | |||||
| # max_position_items = License.select(:id, :position).pluck(:position).reject!(&:blank?) | |||||
| # max_position = max_position_items.present? ? max_position_items.max.to_i : 0 | |||||
| # other_params = { | |||||
| # conditions: conditions.to_s, | |||||
| # permissions: permissions.to_s, | |||||
| # limitations: limitations.to_s, | |||||
| # position: max_position | |||||
| # } | |||||
| @project_license = License.new(license_params) | |||||
| if @project_license.save! | |||||
| redirect_to admins_project_licenses_path | |||||
| flash[:success] = "创建成功" | |||||
| else | |||||
| render :new | |||||
| flash[:danger] = "创建失败" | |||||
| end | |||||
| end | |||||
| def edit | |||||
| end | |||||
| def update | |||||
| # conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present? | |||||
| # permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present? | |||||
| # limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present? | |||||
| # other_params = { | |||||
| # conditions: conditions.to_s, | |||||
| # permissions: permissions.to_s, | |||||
| # limitations: limitations.to_s | |||||
| # } | |||||
| if @project_license.update_attributes(license_params) | |||||
| redirect_to admins_project_licenses_path | |||||
| flash[:success] = "更新成功" | |||||
| else | |||||
| render :edit | |||||
| flash[:danger] = "更新失败" | |||||
| end | |||||
| end | |||||
| def destroy | |||||
| if @project_license.present? | |||||
| if @project_license.destroy | |||||
| redirect_to admins_project_licenses_path | |||||
| flash[:success] = "删除成功" | |||||
| else | |||||
| redirect_to admins_project_licenses_path | |||||
| flash[:success] = "删除失败" | |||||
| end | |||||
| else | |||||
| redirect_to admins_project_licenses_path | |||||
| flash[:success] = "删除失败:许可证已被项目引用" | |||||
| end | |||||
| end | |||||
| # def move | |||||
| # cate_opt = params[:opr] | |||||
| # cate_position = @project_license.position.to_i | |||||
| # move_status = up_and_down(cate_opt,@project_license,cate_position,"license") | |||||
| # if move_status == 0 | |||||
| # @c_msg = "移动成功" | |||||
| # else | |||||
| # @c_msg = "移动失败" | |||||
| # end | |||||
| # end | |||||
| private | |||||
| def set_license | |||||
| @project_license = License.find_by_id(params[:id]) | |||||
| end | |||||
| def license_params | |||||
| params.require(:license).permit(:name,:content) | |||||
| end | |||||
| def validate_params | |||||
| name = params[:license][:name] | |||||
| if name.blank? | |||||
| flash[:danger] = "名称不允许为空" | |||||
| redirect_to admins_project_licenses_path | |||||
| elsif check_license_present?(name) && @project_license.blank? | |||||
| flash[:danger] = "创建失败:名称已存在" | |||||
| redirect_to admins_project_licenses_path | |||||
| end | |||||
| end | |||||
| def check_license_present?(name) | |||||
| return true if name.blank? | |||||
| name_downcase = name.downcase | |||||
| name_upcase = name.upcase | |||||
| name_first_big = name.capitalize | |||||
| License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big) | |||||
| end | |||||
| end | |||||
| @@ -1,25 +1,25 @@ | |||||
| class Admins::ProjectsController < Admins::BaseController | class Admins::ProjectsController < Admins::BaseController | ||||
| def index | def index | ||||
| default_sort('created_at', 'desc') | |||||
| sort_by = params[:sort_by] ||= 'created_on' | |||||
| sort_direction = params[:sort_direction] ||= 'desc' | |||||
| search = params[:search].to_s.strip | search = params[:search].to_s.strip | ||||
| projects = Project.where("name like ?", "%#{search}%") | |||||
| projects = Project.where("name like ?", "%#{search}%").order("#{sort_by} #{sort_direction}") | |||||
| @projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score) | @projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score) | ||||
| end | end | ||||
| def destroy | def destroy | ||||
| project = Project.find_by!(id: params[:id]) | project = Project.find_by!(id: params[:id]) | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| g = Gitlab.client | |||||
| g.delete_project(project.gpid) | |||||
| # 删除Trustie版本库记录 | |||||
| repoisitory = Repository.where(project_id: project.id, type: "Repository::Gitlab").first | |||||
| repoisitory.destroy! | |||||
| Tiding.where(container_id: project.id, container_type: ["JoinProject", "DealProject", "ReporterJoinProject", "ManagerJoinProject"]).destroy_all | |||||
| Gitea::Repository::DeleteService.new(project.owner, project.identifier).call | |||||
| project.destroy! | project.destroy! | ||||
| render_delete_success | |||||
| # render_delete_success | |||||
| redirect_to admins_projects_path | |||||
| flash[:success] = "删除成功" | |||||
| end | end | ||||
| rescue Exception => e | |||||
| redirect_to admins_projects_path | |||||
| flash[:danger] = "删除失败" | |||||
| end | end | ||||
| end | end | ||||
| @@ -4,7 +4,7 @@ class Admins::UsersController < Admins::BaseController | |||||
| params[:sort_direction] = params[:sort_direction].presence || 'desc' | params[:sort_direction] = params[:sort_direction].presence || 'desc' | ||||
| users = Admins::UserQuery.call(params) | users = Admins::UserQuery.call(params) | ||||
| @users = paginate users.includes(user_extension: :school) | |||||
| @users = paginate users.includes(:user_extension, projects: :members) | |||||
| end | end | ||||
| def edit | def edit | ||||
| @@ -65,4 +65,4 @@ class Admins::UsersController < Admins::BaseController | |||||
| mail phone location location_city school_id department_id admin business is_test | mail phone location location_city school_id department_id admin business is_test | ||||
| password professional_certification authentication]) | password professional_certification authentication]) | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -9,6 +9,7 @@ class ApplicationController < ActionController::Base | |||||
| include GitHelper | include GitHelper | ||||
| include LoggerHelper | include LoggerHelper | ||||
| include LoginHelper | include LoginHelper | ||||
| include RegisterHelper | |||||
| protect_from_forgery prepend: true, unless: -> { request.format.json? } | protect_from_forgery prepend: true, unless: -> { request.format.json? } | ||||
| @@ -16,6 +17,14 @@ class ApplicationController < ActionController::Base | |||||
| before_action :user_setup | before_action :user_setup | ||||
| #before_action :check_account | #before_action :check_account | ||||
| # TODO | |||||
| # check sql query time | |||||
| before_action do | |||||
| if request.subdomain === 'testforgeplus' || request.subdomain === "profiler" | |||||
| Rack::MiniProfiler.authorize_request | |||||
| end | |||||
| end | |||||
| DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z) | DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z) | ||||
| OPENKEY = "79e33abd4b6588941ab7622aed1e67e8" | OPENKEY = "79e33abd4b6588941ab7622aed1e67e8" | ||||
| @@ -23,23 +32,23 @@ class ApplicationController < ActionController::Base | |||||
| # 所有请求必须合法签名 | # 所有请求必须合法签名 | ||||
| def check_sign | def check_sign | ||||
| if !Rails.env.development? | |||||
| Rails.logger.info("66666 #{params}") | |||||
| # suffix = request.url.split(".").last.split("?").first | |||||
| # suffix_arr = ["xls", "xlsx", "pdf", "zip"] # excel文件先注释 | |||||
| # unless suffix_arr.include?(suffix) | |||||
| if params[:client_key].present? | |||||
| randomcode = params[:randomcode] | |||||
| # tip_exception(501, "请求不合理") unless (Time.now.to_i - randomcode.to_i).between?(0,5) | |||||
| sign = Digest::MD5.hexdigest("#{OPENKEY}#{randomcode}") | |||||
| Rails.logger.info("2222 #{sign}") | |||||
| tip_exception(501, "请求不合理") if sign != params[:client_key] | |||||
| else | |||||
| tip_exception(501, "请求不合理") | |||||
| end | |||||
| # end | |||||
| end | |||||
| # if !Rails.env.development? | |||||
| # Rails.logger.info("66666 #{params}") | |||||
| # # suffix = request.url.split(".").last.split("?").first | |||||
| # # suffix_arr = ["xls", "xlsx", "pdf", "zip"] # excel文件先注释 | |||||
| # # unless suffix_arr.include?(suffix) | |||||
| # if params[:client_key].present? | |||||
| # randomcode = params[:randomcode] | |||||
| # # tip_exception(501, "请求不合理") unless (Time.now.to_i - randomcode.to_i).between?(0,5) | |||||
| # | |||||
| # sign = Digest::MD5.hexdigest("#{OPENKEY}#{randomcode}") | |||||
| # Rails.logger.info("2222 #{sign}") | |||||
| # tip_exception(501, "请求不合理") if sign != params[:client_key] | |||||
| # else | |||||
| # tip_exception(501, "请求不合理") | |||||
| # end | |||||
| # # end | |||||
| # end | |||||
| end | end | ||||
| # 全局配置参数 | # 全局配置参数 | ||||
| @@ -233,6 +242,7 @@ class ApplicationController < ActionController::Base | |||||
| # 未授权的捕捉407,弹试用申请弹框 | # 未授权的捕捉407,弹试用申请弹框 | ||||
| def require_login | def require_login | ||||
| #6.13 -hs | #6.13 -hs | ||||
| tip_exception(401, "请登录后再操作") unless User.current.logged? | tip_exception(401, "请登录后再操作") unless User.current.logged? | ||||
| end | end | ||||
| @@ -333,7 +343,10 @@ class ApplicationController < ActionController::Base | |||||
| elsif params[:debug] == 'student' | elsif params[:debug] == 'student' | ||||
| User.current = User.find 8686 | User.current = User.find 8686 | ||||
| elsif params[:debug] == 'admin' | elsif params[:debug] == 'admin' | ||||
| User.current = User.find 1 | |||||
| logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....." | |||||
| user = User.find 36480 | |||||
| User.current = user | |||||
| cookies.signed[:user_id] = user.id | |||||
| end | end | ||||
| end | end | ||||
| # User.current = User.find 81403 | # User.current = User.find 81403 | ||||
| @@ -361,8 +374,8 @@ class ApplicationController < ActionController::Base | |||||
| # auto-login feature starts a new session | # auto-login feature starts a new session | ||||
| user = nil | user = nil | ||||
| Rails.logger.info("111111111111111111#{default_yun_session}, session is #{session[:"#{default_yun_session}"]} ") | Rails.logger.info("111111111111111111#{default_yun_session}, session is #{session[:"#{default_yun_session}"]} ") | ||||
| user = User.try_to_autologin(cookies[autologin_cookie_name]) if session[:"#{default_yun_session}"] | |||||
| start_user_session(user) if user | |||||
| user = User.try_to_autologin(cookies[autologin_cookie_name]) | |||||
| # start_user_session(user) if user # TODO 解决sso退出不同步的问题 | |||||
| user | user | ||||
| end | end | ||||
| end | end | ||||
| @@ -659,7 +672,13 @@ class ApplicationController < ActionController::Base | |||||
| end | end | ||||
| 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 | |||||
| relation.page(page).per(limit) | |||||
| end | |||||
| def strf_time(time) | def strf_time(time) | ||||
| time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S") | time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S") | ||||
| @@ -681,7 +700,8 @@ class ApplicationController < ActionController::Base | |||||
| def find_user_with_id | def find_user_with_id | ||||
| @user = User.find_by_id params[:user_id] | @user = User.find_by_id params[:user_id] | ||||
| render_not_found("未找到’#{params[:login]}’相关的用户") unless @user | |||||
| # render_not_found("未找到’#{params[:login]}’相关的用户") unless @user | |||||
| render_error("未找到相关的用户") unless @user | |||||
| end | end | ||||
| def find_repository | def find_repository | ||||
| @@ -689,6 +709,10 @@ class ApplicationController < ActionController::Base | |||||
| render_not_found("未找到’#{params[:repo_identifier]}’相关的项目") unless @repo | render_not_found("未找到’#{params[:repo_identifier]}’相关的项目") unless @repo | ||||
| end | end | ||||
| def find_repository_by_id | |||||
| @repo = Repository.find params[:id] | |||||
| end | |||||
| def find_project | def find_project | ||||
| project_id = params[:project_id] ? params[:project_id] : params[:id] | project_id = params[:project_id] ? params[:project_id] : params[:id] | ||||
| project = Project.where(identifier: project_id) | project = Project.where(identifier: project_id) | ||||
| @@ -701,11 +725,6 @@ class ApplicationController < ActionController::Base | |||||
| render_not_found("未找到’#{project}’相关的项目") unless @project | render_not_found("未找到’#{project}’相关的项目") unless @project | ||||
| end | end | ||||
| def find_project_with_identifier | |||||
| @project = Project.find_by_identifier! params[:id] | |||||
| render_not_found("未找到’#{params[:id]}’相关的项目") unless @project | |||||
| end | |||||
| def find_project_with_id | def find_project_with_id | ||||
| @project = Project.find(params[:project_id] || params[:id]) | @project = Project.find(params[:project_id] || params[:id]) | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -717,6 +736,32 @@ class ApplicationController < ActionController::Base | |||||
| interactor.success? ? render_ok : render_error(interactor.error) | interactor.success? ? render_ok : render_error(interactor.error) | ||||
| end | end | ||||
| # projects | |||||
| def load_project | |||||
| namespace = params[:owner] | |||||
| id = params[:repo] || params[:id] | |||||
| @project, @owner = Project.find_with_namespace(namespace, id) | |||||
| if @project and current_user.can_read_project?(@project) | |||||
| logger.info "###########: has project and can read project" | |||||
| @project | |||||
| elsif @project && current_user.is_a?(AnonymousUser) | |||||
| logger.info "###########:This is AnonymousUser" | |||||
| @project = nil if !@project.is_public? | |||||
| render_forbidden and return | |||||
| else | |||||
| logger.info "###########:project not found" | |||||
| @project = nil | |||||
| render_not_found and return | |||||
| end | |||||
| @project | |||||
| end | |||||
| def load_repository | |||||
| @repository ||= load_project&.repository | |||||
| end | |||||
| private | private | ||||
| def object_not_found | def object_not_found | ||||
| uid_logger("Missing template or cant't find record, responding with 404") | uid_logger("Missing template or cant't find record, responding with 404") | ||||
| @@ -2,7 +2,7 @@ | |||||
| # | # | ||||
| # 文件上传 | # 文件上传 | ||||
| class AttachmentsController < ApplicationController | class AttachmentsController < ApplicationController | ||||
| before_action :require_login, :check_auth, except: [:show] | |||||
| before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file] | |||||
| before_action :find_file, only: %i[show destroy] | before_action :find_file, only: %i[show destroy] | ||||
| before_action :attachment_candown, only: [:show] | before_action :attachment_candown, only: [:show] | ||||
| skip_before_action :check_sign, only: [:show, :create] | skip_before_action :check_sign, only: [:show, :create] | ||||
| @@ -28,11 +28,20 @@ class AttachmentsController < ApplicationController | |||||
| update_downloads(@file) | update_downloads(@file) | ||||
| end | end | ||||
| def get_file | |||||
| normal_status(-1, "参数缺失") if params[:download_url].blank? | |||||
| url = URI.encode(params[:download_url].to_s.gsub("http:", "https:")) | |||||
| response = Faraday.get(url) | |||||
| filename = params[:download_url].to_s.split("/").pop() | |||||
| send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment') | |||||
| end | |||||
| def create | def create | ||||
| # 1. 本地存储 | # 1. 本地存储 | ||||
| # 2. 上传到云 | # 2. 上传到云 | ||||
| begin | begin | ||||
| upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称 | |||||
| upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称 | |||||
| uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}") | uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}") | ||||
| raise "未上传文件" unless upload_file | raise "未上传文件" unless upload_file | ||||
| @@ -98,6 +107,26 @@ class AttachmentsController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| # 附件为视频时,点击播放 | |||||
| def preview_attachment | |||||
| attachment = Attachment.find_by(id: params[:id]) | |||||
| dir_path = "#{Rails.root}/public/preview" | |||||
| Dir.mkdir(dir_path) unless Dir.exist?(dir_path) | |||||
| if params[:status] == "preview" | |||||
| if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/") | |||||
| render json: {status: 1, url: "/preview/#{attachment.disk_filename}"} | |||||
| else | |||||
| normal_status(-1, "出现错误,请稍后重试") | |||||
| end | |||||
| else | |||||
| if system("rm -rf #{dir_path}/#{attachment.disk_filename}") | |||||
| normal_status(1, "操作成功") | |||||
| else | |||||
| normal_status(-1, "出现错误,请稍后重试") | |||||
| end | |||||
| end | |||||
| end | |||||
| private | private | ||||
| def find_file | def find_file | ||||
| @file = | @file = | ||||
| @@ -177,31 +206,14 @@ class AttachmentsController < ApplicationController | |||||
| candown = true | candown = true | ||||
| unless params[:type] == 'history' | unless params[:type] == 'history' | ||||
| if @file.container && current_user.logged? | if @file.container && current_user.logged? | ||||
| # 课堂资源、作业、毕设相关资源的权限判断 | |||||
| if @file.container.is_a?(Course) | |||||
| course = @file.container | |||||
| candown = current_user.member_of_course?(course) || (course.is_public? && @file.publiced?) | |||||
| elsif @file.container.is_a?(HomeworkCommon) || @file.container.is_a?(GraduationTask) || @file.container.is_a?(GraduationTopic) | |||||
| course = @file.container&.course | |||||
| candown = current_user.member_of_course?(course) | |||||
| elsif @file.container.is_a?(StudentWork) | |||||
| course = @file.container&.homework_common&.course | |||||
| candown = current_user.member_of_course?(course) | |||||
| elsif @file.container.is_a?(StudentWorksScore) | |||||
| course = @file.container&.student_work&.homework_common&.course | |||||
| candown = current_user.member_of_course?(course) | |||||
| elsif @file.container.is_a?(GraduationWork) | |||||
| course = @file.container&.graduation_task&.course | |||||
| candown = current_user.member_of_course?(course) | |||||
| elsif @file.container.is_a?(GraduationWorkScore) | |||||
| course = @file.container&.graduation_work&.graduation_task&.course | |||||
| candown = current_user.member_of_course?(course) | |||||
| elsif @file.container.is_a?(Issue) | |||||
| if @file.container.is_a?(Issue) | |||||
| course = @file.container.project | course = @file.container.project | ||||
| candown = course.member?(current_user) | candown = course.member?(current_user) | ||||
| elsif @file.container.is_a?(Journal) | elsif @file.container.is_a?(Journal) | ||||
| course = @file.container.issue.project | course = @file.container.issue.project | ||||
| candown = course.member?(current_user) | candown = course.member?(current_user) | ||||
| else | |||||
| course = nil | |||||
| end | end | ||||
| tip_exception(403, "您没有权限进入") if course.present? && !candown | tip_exception(403, "您没有权限进入") if course.present? && !candown | ||||
| tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication) | tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication) | ||||
| @@ -1,12 +0,0 @@ | |||||
| class BlobController < ApplicationController | |||||
| def new | |||||
| commit unless @repository.empty? | |||||
| end | |||||
| def create | |||||
| create_commit(Files::CreateService, success_path: after_create_path, | |||||
| failure_view: :new, | |||||
| failure_path: namespace_project_new_blob_path(@project.namespace, @project, @ref)) | |||||
| end | |||||
| end | |||||
| @@ -1,342 +0,0 @@ | |||||
| class ChallengesController < ApplicationController | |||||
| before_action :require_login, :check_auth, except: [:index] | |||||
| before_action :find_shixun, only: [:new, :create, :index] | |||||
| skip_before_action :verify_authenticity_token, only: [:create, :update, :create_choose_question, :crud_answer] | |||||
| before_action :find_challenge, only: [:edit, :show, :update, :create_choose_question, :index_down, :index_up, | |||||
| :edit_choose_question, :show_choose_question, :destroy_challenge_choose, | |||||
| :update_choose_question, :destroy, :crud_answer, :answer] | |||||
| # 关卡更新和操作的权限控制 | |||||
| before_action :update_allowed, except: [:index] | |||||
| # 关卡访问的权限控制 | |||||
| before_action :shixun_access_allowed, only: [:index] | |||||
| include ShixunsHelper | |||||
| include ChallengesHelper | |||||
| # 新建实践题 | |||||
| def new | |||||
| @position = @shixun.challenges.count + 1 | |||||
| @st = params[:st].to_i | |||||
| @task_pass_default = PlatformSample.find_by(samples_type: "taskPass").try(:contents) | |||||
| end | |||||
| # params | |||||
| # challenge:{"subject": "标题", "task_pass": "过关任务", | |||||
| # "diffculty": "关卡难度", "score": "关卡分数", "st": "关卡类型"} 关卡相关信息 | |||||
| # challenge_tag: 关卡标签 | |||||
| # | |||||
| def create | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @challenge = Challenge.new(challenge_params) | |||||
| @challenge.position = @shixun.challenges.count + 1 | |||||
| @challenge.shixun_id = @shixun.id | |||||
| @challenge.user_id = current_user.id | |||||
| @challenge.modify_time = Time.now | |||||
| @challenge.save! | |||||
| # 实训是否需要重置, 非实践任务创建第一个阶段调用, 避免不包含实践任务的实训进行模拟实战报错 todo: 新建实训需要重置TPI | |||||
| # shixun_modify_status_without_publish(@shixun, 1) if @challenge.position != 1 | |||||
| tags = params[:challenge_tag] | |||||
| if tags.present? | |||||
| tags.each do |tag| | |||||
| # TODO 创建tag的时候为什么一直报challenge choose必须存在?? | |||||
| ChallengeTag.create!(name: tag, challenge_id: @challenge.id) | |||||
| end | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error("create challenge failed #{e}") | |||||
| end | |||||
| end | |||||
| end | |||||
| # 创建选择题 | |||||
| def create_choose_question | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @challenge_choose = ChallengeChoose.new(chooce_params) | |||||
| @challenge_choose.position = @challenge.challenge_chooses.count + 1 | |||||
| @challenge_choose.category = @challenge_choose.standard_answer.length == 1 ? 1 : 2 | |||||
| @challenge_choose.challenge_id = @challenge.id | |||||
| if @challenge_choose.save! | |||||
| # 创建选项 | |||||
| params[:question][:cnt].each_with_index do |test, index| | |||||
| answer = params[:choice][:answer][index] | |||||
| ChallengeQuestion.create(:option_name => test, | |||||
| :challenge_choose_id => @challenge_choose.id, | |||||
| :position => index, :right_key => answer) | |||||
| end | |||||
| # 创建单选多选的技能标签 | |||||
| if params[:challenge_tag].present? | |||||
| params[:challenge_tag].each do |tag| | |||||
| ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id) | |||||
| end | |||||
| end | |||||
| @challenge.update_column(:score, @challenge.challenge_chooses.sum(:score)) | |||||
| end | |||||
| rescue Exception => e | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # 选择题详情页面 | |||||
| def show_choose_question | |||||
| @challenge_choose = ChallengeChoose.find params[:choose_id] | |||||
| end | |||||
| # 选择题更新页面 | |||||
| def update_choose_question | |||||
| @challenge_choose = ChallengeChoose.find(params[:choose_id]) | |||||
| ActiveRecord::Base.transaction do | |||||
| if params[:standard_answer] != @challenge_choose.standard_answer | |||||
| @challenge.update_column(:modify_time, Time.now) | |||||
| end | |||||
| @challenge_choose.update_attributes(chooce_params) | |||||
| @challenge.update_column(:score, @challenge.challenge_chooses.sum(:score)) | |||||
| # 单选多选题的更新 | |||||
| category = @challenge_choose.standard_answer.length > 1 ? 2 : 1 | |||||
| @challenge_choose.update_column(:category, category) | |||||
| begin | |||||
| @challenge_choose.challenge_questions.delete_all | |||||
| params[:question][:cnt].each_with_index do |test, index| | |||||
| answer = params[:choice][:answer][index] | |||||
| ChallengeQuestion.create(:option_name => test, :challenge_choose_id => @challenge_choose.id, :position => index, :right_key => answer) | |||||
| end | |||||
| @challenge_choose.challenge_tags.delete_all unless @challenge_choose.challenge_tags.blank? | |||||
| if params[:challenge_tag].present? | |||||
| params[:challenge_tag].each do |tag| | |||||
| ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id) | |||||
| end | |||||
| end | |||||
| @challenge_choose = ChallengeChoose.find params[:choose_id] | |||||
| rescue Exception => e | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # 选择题的编辑 | |||||
| def edit_choose_question | |||||
| @challenge_choose = ChallengeChoose.find params[:choose_id] | |||||
| end | |||||
| def destroy_challenge_choose | |||||
| ActiveRecord::Base.transaction do | |||||
| @challenge_choose = ChallengeChoose.where(:id => params[:choose_id]).first | |||||
| pos = @challenge_choose.position | |||||
| @challenge.challenge_chooses.where("position > ?", pos).update_all("position = position - 1") | |||||
| @challenge_choose.destroy | |||||
| @status = 1 | |||||
| # 发起重置请求 TODO: 重置实训需要后续做 | |||||
| # shixun_modify_status_without_publish(@shixun, 1) | |||||
| end | |||||
| end | |||||
| # 编辑模式 | |||||
| # tab 0,nil 过关任务, 1 评测设置, 2 参考答案 | |||||
| def edit | |||||
| @tab = params[:tab].to_i | |||||
| @power = @shixun.status == 0 | |||||
| challenge_num = Challenge.where(:shixun_id => @shixun).count | |||||
| @position = @challenge.position | |||||
| @chooses = @challenge.challenge_chooses | |||||
| if @position < challenge_num | |||||
| @next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first | |||||
| end | |||||
| @prev_challenge = Challenge.where(:shixun_id => @shixun, :position => @position - 1).first if @position - 1 > 0 | |||||
| end | |||||
| def index | |||||
| uid_logger("identifier: #{params}") | |||||
| @challenges = @shixun.challenges.fields_for_list | |||||
| @editable = @shixun.status == 0 # before_action:有判断权限,如果没发布,则肯定是管理人员 | |||||
| @user = current_user | |||||
| @shixun.increment!(:visits) | |||||
| end | |||||
| def show | |||||
| @tab = params[:tab].nil? ? 1 : params[:tab].to_i | |||||
| challenge_num = @shixun.challenges_count | |||||
| @power = @shixun.status == 0 # 之前验证走过了是不是管理员,因此这里只用判断是否发布 | |||||
| @position = @challenge.position | |||||
| if @position < challenge_num | |||||
| @next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first | |||||
| end | |||||
| @prev_challenge = Challenge.where(:shixun_id => @shixun, :position => @position - 1).first if @position - 1 > 0 | |||||
| end | |||||
| # tab 0:过关任务的更新; 1:评测设置的更新; 2:表示参考答案的更新; | |||||
| def update | |||||
| begin | |||||
| ActiveRecord::Base.transaction do | |||||
| tab = params[:tab].to_i | |||||
| @challenge.update_attributes!(challenge_params) | |||||
| if tab == 0 && @challenge.st == 0 | |||||
| @challenge.challenge_tags.delete_all | |||||
| if params[:challenge_tag].present? | |||||
| params[:challenge_tag].each do |input| | |||||
| ChallengeTag.create!(:name => input, :challenge_id => @challenge.id) | |||||
| end | |||||
| end | |||||
| elsif tab == 1 | |||||
| path = @challenge.path | |||||
| exec_path = @challenge.exec_path | |||||
| test_set = @challenge.test_sets | |||||
| sets_output = test_set.map(&:output) | |||||
| sets_input = test_set.map(&:input) | |||||
| sets_open = test_set.map(&:is_public) | |||||
| set_score = test_set.map(&:score) | |||||
| set_match_rule = test_set.map(&:match_rule) | |||||
| params_hidden = params[:test_set].map{|set| set[:hidden].to_i == 0} | |||||
| params_output = params[:test_set].map{|set| set[:output] } | |||||
| params_input = params[:test_set].map{|set| set[:input] } | |||||
| params_score = params[:test_set].map{|set| set[:score]} | |||||
| params_test_set = params[:test_set].map{|set| set[:match_rule]} | |||||
| # 测试集变化则需要更新(输入、 输出、 是否隐藏) | |||||
| if sets_output != params_output || sets_open != params_hidden || sets_input != params_input || | |||||
| set_score != params_score || params_test_set != set_match_rule | |||||
| test_set.delete_all unless test_set.blank? | |||||
| params[:test_set].each_with_index do |set, index| | |||||
| # last: 末尾匹配, full: 全完匹配 | |||||
| logger.info("set: #{set}; match_rule : #{set[:match_rule]}") | |||||
| match_rule = set[:match_rule] == 'last' ? 'last' : 'full' | |||||
| TestSet.create!(:challenge_id => @challenge.id, | |||||
| :input => "#{set[:input]}", | |||||
| :output => "#{set[:output]}", | |||||
| :is_public => params_hidden[index], | |||||
| :score => set[:score], | |||||
| :match_rule => "#{match_rule}", | |||||
| :position => (index + 1)) | |||||
| end | |||||
| @challenge.update_column(:modify_time, Time.now) | |||||
| # 测试集的 | |||||
| @shixun.myshixuns.update_all(:system_tip => 0) | |||||
| end | |||||
| if params[:challenge][:show_type].to_i == -1 | |||||
| @challenge.update_attributes(picture_path: nil, web_route: nil, expect_picture_path: nil, original_picture_path: nil) | |||||
| end | |||||
| # 关卡评测执行文件如果被修改,需要修改脚本内容 | |||||
| logger.info("############shixun_publiced:#{@shixun.public == 0}") | |||||
| if @shixun.public == 0 | |||||
| script = modify_shixun_script @shixun, @shixun.evaluate_script | |||||
| @shixun.shixun_info.update_column(:evaluate_script, script) | |||||
| end | |||||
| # TODO: | |||||
| # if path != params[:challenge][:path] | |||||
| # shixun_modify_status_without_publish(@shixun, 1) | |||||
| # end | |||||
| #Attachment.attach_files(@challenge, params[:attachments]) | |||||
| end | |||||
| end | |||||
| rescue Exception => e | |||||
| logger.error("##update_challenges: ##{e.message}") | |||||
| tip_exception("#{e.message}") | |||||
| end | |||||
| end | |||||
| # 参考答案的'增,删,改' | |||||
| # POST: /shixuns/:id/challenges/:id/crud_answer | |||||
| # {'challenge_answer': [ | |||||
| # {'name': 'name', contents: 'contents', score: 10}, | |||||
| # {...}, | |||||
| # {...}, ...] | |||||
| #} | |||||
| def crud_answer | |||||
| if @challenge.challenge_answers && params[:challenge_answer].blank? | |||||
| @challenge.challenge_answers.destroy_all | |||||
| else | |||||
| raise '参考答案不能为空' if params[:challenge_answer].empty? | |||||
| raise '占比之和必须为100%' if params[:challenge_answer].map{|a| a[:score]}.sum != 100 | |||||
| ActiveRecord::Base.transaction do | |||||
| @challenge.challenge_answers.destroy_all if @challenge.challenge_answers | |||||
| params[:challenge_answer].each_with_index do |answer, index| | |||||
| # 内容为空不保存 | |||||
| next if answer[:contents].blank? | |||||
| ChallengeAnswer.create!(name: answer[:name], contents: answer[:contents], | |||||
| level: index+1, score: answer[:score], challenge_id: @challenge.id) | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| # 查看参考答案接口 | |||||
| def answer | |||||
| @answers = @challenge.challenge_answers | |||||
| end | |||||
| def index_down | |||||
| next_challenge = @challenge.next_challenge | |||||
| position = @challenge.position | |||||
| @challenge.update_attribute(:position, (position + 1)) | |||||
| next_challenge.update_attribute(:position, next_challenge.position - 1) | |||||
| # 关卡位置被修改,需要修改脚本 | |||||
| script = modify_shixun_script @shixun, @shixun.evaluate_script | |||||
| @shixun.shixun_info.update_column(:evaluate_script, script) | |||||
| end | |||||
| def index_up | |||||
| position = @challenge.position | |||||
| last_challenge = @challenge.last_challenge | |||||
| @challenge.update_attribute(:position, (position - 1)) | |||||
| last_challenge.update_attribute(:position, last_challenge.position + 1) | |||||
| # 关卡位置被修改,需要修改脚本 | |||||
| script = modify_shixun_script @shixun, @shixun.evaluate_script | |||||
| @shixun.shixun_info.update_column(:evaluate_script, script) | |||||
| end | |||||
| def destroy | |||||
| next_challenges = @shixun.challenges.where("position > #{@challenge.position}") | |||||
| next_challenges.update_all("position = position - 1") | |||||
| # Todo: 实训修改后,关卡需要重置 | |||||
| # shixun_modify_status_without_publish(@shixun, 1) | |||||
| @challenge.destroy | |||||
| # 关卡位置被删除,需要修改脚本 | |||||
| script = modify_shixun_script @shixun, @shixun.evaluate_script | |||||
| @shixun.shixun_info.update_column(:evaluate_script, script) | |||||
| end | |||||
| private | |||||
| def find_shixun | |||||
| @shixun = Shixun.find_by_identifier(params[:shixun_identifier]) | |||||
| end | |||||
| # 通用接口 | |||||
| def find_challenge | |||||
| @challenge = Challenge.find params[:id] | |||||
| @shixun = Shixun.find_by!(identifier: params[:shixun_identifier]) | |||||
| end | |||||
| def challenge_params | |||||
| tip_exception("评测时间不能超过300秒") if params[:challenge][:exec_time].to_i > 300 | |||||
| params.require(:challenge).permit(:subject, :task_pass, :difficulty, :score, :st, :modify_time, :test_set_average, | |||||
| :path, :exec_path, :show_type, :original_picture_path, :test_set_score, | |||||
| :expect_picture_path, :picture_path, :web_route, :answer, :exec_time) | |||||
| end | |||||
| def chooce_params | |||||
| params.require(:challenge_choose).permit(:subject, :answer, | |||||
| :standard_answer, :score, :difficult) | |||||
| end | |||||
| def update_allowed | |||||
| unless current_user.manager_of_shixun?(@shixun) | |||||
| raise Educoder::TipException.new(403, "..") | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,47 @@ | |||||
| class Ci::BaseController < ApplicationController | |||||
| include Ci::DbConnectable | |||||
| before_action :require_login | |||||
| before_action :connect_to_ci_database, if: -> { current_user && !current_user.is_a?(AnonymousUser) && !current_user.devops_uninit? } | |||||
| def load_repo | |||||
| namespace = params[:owner] | |||||
| id = params[:repo] || params[:id] | |||||
| @ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id) | |||||
| end | |||||
| private | |||||
| def authorize_access_project! | |||||
| unless @project.manager?(current_user) | |||||
| return render_forbidden | |||||
| end | |||||
| end | |||||
| def authenticate_manager! | |||||
| unless @project.manager?(current_user) | |||||
| return render_forbidden | |||||
| end | |||||
| end | |||||
| def authenticate_admin! | |||||
| return render_forbidden unless current_user.admin? | |||||
| end | |||||
| def authorize_owner! | |||||
| unless @project.owner?(current_user) | |||||
| return render_forbidden | |||||
| end | |||||
| end | |||||
| def find_cloud_account | |||||
| @cloud_account ||= current_user.ci_cloud_account | |||||
| @cloud_account.blank? ? nil : @cloud_account | |||||
| end | |||||
| def load_ci_user | |||||
| @ci_user ||= Ci::User.find_by(user_login: params[:owner]) | |||||
| @ci_user.blank? ? raise("未找到相关的记录") : @ci_user | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,54 @@ | |||||
| class Ci::BuildsController < Ci::BaseController | |||||
| include RepositoriesHelper | |||||
| before_action :load_project | |||||
| before_action :authorize_owner!, only: [:restart, :stop] | |||||
| before_action :load_repo | |||||
| before_action :find_cloud_account, except: [:index, :show] | |||||
| def index | |||||
| @user = current_user | |||||
| scope = @repo.builds | |||||
| scope = Ci::Builds::ListQuery.call(@repo, params) | |||||
| @total_count = scope.map(&:build_id).size | |||||
| @builds = paginate scope | |||||
| end | |||||
| def show | |||||
| @build = @repo.builds.includes(stages: [:steps]).find_by(build_number: params[:build]) | |||||
| end | |||||
| def restart | |||||
| result = Ci::Drone::API.new(@ci_user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:build]).restart | |||||
| render json: result | |||||
| end | |||||
| def stop | |||||
| result = Ci::Drone::API.new(@ci_user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:build]).stop | |||||
| render json: result | |||||
| end | |||||
| def logs | |||||
| # TODO **待优化** | |||||
| # 因直接操作ci库,如下查询待优化,可直接根据log id查询即可 | |||||
| build = @repo.builds.find_by(build_number: params[:build]) | |||||
| return render_not_found("Couldn't found build with 'number'= #{params[:build]}") if build.blank? | |||||
| stage = build.stages.includes(steps: [:log]).find_by(stage_number: params[:stage]) | |||||
| return render_not_found("Couldn't found build with 'number'= #{params[:stage]}") if stage.blank? | |||||
| step = stage.steps.find_by(step_number: params[:step]) | |||||
| return render_not_found("Couldn't found build with 'number'= #{params[:step]}") if step.blank? | |||||
| log = step.log | |||||
| result = log.blank? ? nil : (log.log_data[0..5].include?('null') ? nil : JSON.parse(log.log_data)) | |||||
| # result = Ci::Drone::API.new(@user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, build: params[:build], stage: params[:stage], step: params[:step]).logs | |||||
| render json: result | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,101 @@ | |||||
| class Ci::CloudAccountsController < Ci::BaseController | |||||
| include Ci::CloudAccountManageable | |||||
| skip_before_action :connect_to_ci_database, only: %i[create bind] | |||||
| before_action :load_project, only: %i[create activate] | |||||
| before_action :authorize_owner!, only: %i[create activate] | |||||
| before_action :load_repo, only: %i[activate] | |||||
| before_action :find_cloud_account, only: %i[show oauth_grant] | |||||
| before_action :validate_params!, only: %i[create bind] | |||||
| before_action only: %i[create bind] do | |||||
| connect_to_ci_database(master_db: true) | |||||
| end | |||||
| def create | |||||
| flag, msg = check_bind_cloud_account! | |||||
| return render_error(msg) if flag === true | |||||
| ActiveRecord::Base.transaction do | |||||
| @cloud_account = bind_account! | |||||
| if @cloud_account.blank? | |||||
| render_error('激活失败, 请检查你的云服务器信息是否正确.') | |||||
| raise ActiveRecord::Rollback | |||||
| else | |||||
| current_user.set_drone_step!(User::DEVOPS_UNVERIFIED) | |||||
| render_ok(redirect_url: @cloud_account.authenticate_url) | |||||
| end | |||||
| end | |||||
| rescue Exception => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def activate | |||||
| return render_error('请先认证') unless current_user.ci_certification? | |||||
| begin | |||||
| @cloud_account = Ci::CloudAccount.find params[:id] | |||||
| ActiveRecord::Base.transaction do | |||||
| if @repo | |||||
| return render_error('该项目已经激活') if @repo.repo_active? | |||||
| @repo.activate!(@ci_user.user_id) | |||||
| else | |||||
| @repo = Ci::Repo.auto_create!(@ci_user, @project) | |||||
| @user.update_column(:user_syncing, false) | |||||
| end | |||||
| result = bind_hook!(current_user, @cloud_account, @repo) | |||||
| @project.update_columns(open_devops: true, gitea_webhook_id: result['id']) | |||||
| @cloud_account.update_column(:ci_user_id, @ci_user.user_id) | |||||
| end | |||||
| render_ok | |||||
| rescue Exception => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| end | |||||
| def show | |||||
| end | |||||
| def bind | |||||
| flag, msg = check_bind_cloud_account! | |||||
| return render_error(msg) if flag === true | |||||
| ActiveRecord::Base.transaction do | |||||
| @cloud_account = bind_account! | |||||
| if @cloud_account.blank? | |||||
| render_error('激活失败, 请检查你的云服务器信息是否正确.') | |||||
| raise ActiveRecord::Rollback | |||||
| else | |||||
| current_user.set_drone_step!(User::DEVOPS_UNVERIFIED) | |||||
| end | |||||
| end | |||||
| rescue Exception => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def unbind | |||||
| ActiveRecord::Base.transaction do | |||||
| unbind_account! | |||||
| render_ok | |||||
| end | |||||
| rescue Exception => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def oauth_grant | |||||
| password = params[:password].to_s | |||||
| return render_error('你输入的密码不正确.') unless current_user.check_password?(password) | |||||
| oauth = current_user.oauths.last | |||||
| return render_error("服务器出小差了.") if oauth.blank? | |||||
| result = gitea_oauth_grant!(password, oauth) | |||||
| return render_error('授权失败.') unless result === true | |||||
| current_user.set_drone_step!(User::DEVOPS_CERTIFICATION) | |||||
| end | |||||
| private | |||||
| def validate_params! | |||||
| Ci::CreateCloudAccountForm.new(devops_params).validate! | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,20 @@ | |||||
| class Ci::LanguagesController < Ci::BaseController | |||||
| # TODO 需要开启权限认证,只有该项目devops初始化成功后才能获取语言列表 | |||||
| before_action :find_langugae, only: :show | |||||
| def index | |||||
| @languages = Ci::Language.by_usage_amount_desc | |||||
| end | |||||
| def show | |||||
| end | |||||
| def common | |||||
| @languages = Ci::Language.six_common | |||||
| end | |||||
| private | |||||
| def find_langugae | |||||
| @language = Ci::Language.find params[:id] | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,73 @@ | |||||
| class Ci::ProjectsController < Ci::BaseController | |||||
| include RepositoriesHelper | |||||
| include Ci::CloudAccountManageable | |||||
| before_action :load_project | |||||
| before_action :load_repo, only: [:update_trustie_pipeline, :activate, :deactivate] | |||||
| before_action :authorize_owner!, only: [:authorize] | |||||
| before_action :find_cloud_account, only: [:authorize, :activate, :deactivate] | |||||
| def authorize | |||||
| @user = current_user | |||||
| end | |||||
| # get .trustie-pipeline.yml file | |||||
| def get_trustie_pipeline | |||||
| file_path_uri = URI.parse('.trustie-pipeline.yml') | |||||
| interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: params[:ref] || "master") | |||||
| if interactor.success? | |||||
| file = interactor.result | |||||
| return render json: {} if file[:status] | |||||
| json = {name: file['name'], path: file['path'], sha: file['sha'], content: render_decode64_content(file['content'])} | |||||
| render json: json | |||||
| end | |||||
| end | |||||
| def update_trustie_pipeline | |||||
| interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, params[:owner], params.merge(identifier: @project.identifier)) | |||||
| if interactor.success? | |||||
| @file = interactor.result | |||||
| render_result(1, "更新成功") | |||||
| else | |||||
| render_error(interactor.error) | |||||
| end | |||||
| end | |||||
| def activate | |||||
| return render_error('你还未认证') unless current_user.ci_certification? | |||||
| begin | |||||
| ActiveRecord::Base.transaction do | |||||
| if @repo | |||||
| return render_error('该项目已经激活') if @repo.repo_active? | |||||
| if @project.ci_reactivate? | |||||
| @project.ci_reactivate!(@repo) | |||||
| return render_ok | |||||
| end | |||||
| @repo.activate!(@ci_user.user_id) | |||||
| else | |||||
| @repo = Ci::Repo.auto_create!(@ci_user, @project) | |||||
| @ci_user.update_column(:user_syncing, false) | |||||
| end | |||||
| result = bind_hook!(current_user, @cloud_account, @repo) | |||||
| @project.update_columns(open_devops: true, gitea_webhook_id: result['id']) | |||||
| @project.increment!(:open_devops_count) | |||||
| @cloud_account.update_column(:ci_user_id, @ci_user.user_id) | |||||
| end | |||||
| render_ok | |||||
| rescue Exception => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| end | |||||
| def deactivate | |||||
| return render_error('该项目已经取消激活') if !@repo.repo_active? | |||||
| @project.update_column(:open_devops, false) | |||||
| @repo.deactivate! | |||||
| render_ok | |||||
| end | |||||
| end | |||||
| @@ -1,75 +0,0 @@ | |||||
| class CommentsController < ApplicationController | |||||
| before_action :find_hack | |||||
| before_action :require_login | |||||
| # 评论 | |||||
| def create | |||||
| begin | |||||
| @discuss = @hack.discusses.new(comment_params) # 管理员回复的能够显示 | |||||
| @discuss.hidden = false | |||||
| @discuss.user_id = current_user.id | |||||
| @discuss.save! | |||||
| rescue Exception => e | |||||
| uid_logger_error("create discuss failed : #{e.message}") | |||||
| render_error("评论异常") | |||||
| end | |||||
| end | |||||
| # 回复 | |||||
| def reply | |||||
| begin | |||||
| @discuss = @hack.discusses.new(reply_params) | |||||
| @discuss.hidden = false | |||||
| @discuss.user_id = current_user.id | |||||
| @discuss.root_id = params[:comments][:parent_id] | |||||
| @discuss.save! | |||||
| rescue Exception => e | |||||
| uid_logger_error("reply discuss failed : #{e.message}") | |||||
| render_error("回复评论异常") | |||||
| end | |||||
| end | |||||
| # 列表 | |||||
| def index | |||||
| discusses = | |||||
| if current_user.admin_or_business? | |||||
| @hack.discusses.where(root_id: nil) | |||||
| else | |||||
| @hack.discusses.where(root_id: nil, hidden: false) | |||||
| end | |||||
| @discusses_count = discusses.count | |||||
| @discusses= paginate discusses | |||||
| end | |||||
| # 删除 | |||||
| def destroy | |||||
| @hack.discusses.find_by(id: params[:id]).destroy | |||||
| render_ok | |||||
| end | |||||
| # 隐藏、取消隐藏 | |||||
| def hidden | |||||
| if current_user.admin_or_business? | |||||
| @discuss = @hack.discusses.where(id: params[:id]).first | |||||
| @discuss.update_attribute(:hidden, params[:hidden].to_i == 1) | |||||
| sucess_status | |||||
| else | |||||
| Educoder::TipException(403, "..") | |||||
| end | |||||
| end | |||||
| private | |||||
| def find_hack | |||||
| @hack = Hack.find_by_identifier(params[:hack_identifier]) | |||||
| end | |||||
| def comment_params | |||||
| params.require(:comments).permit(:content) | |||||
| end | |||||
| def reply_params | |||||
| params.require(:comments).permit(:content, :parent_id) | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,15 @@ | |||||
| class CompareController < ApplicationController | |||||
| # skip_before_action :require_login | |||||
| before_action :load_repository | |||||
| def index | |||||
| end | |||||
| def show | |||||
| base_ref = Addressable::URI.unescape(params[:base]) | |||||
| @ref = head_ref = Addressable::URI.unescape(params[:head]&.split('.json')[0]) | |||||
| @compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base_ref, head_ref) | |||||
| # render json: @compare_result | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,138 @@ | |||||
| module Ci::CloudAccountManageable | |||||
| extend ActiveSupport::Concern | |||||
| included do | |||||
| end | |||||
| def bind_account! | |||||
| # 1. 保存华为云服务器帐号 | |||||
| create_params = devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num].strip).to_i, secret: Ci::CloudAccount.encrypted_secret(devops_params[:secret])) | |||||
| cloud_account = Ci::CloudAccount.new(create_params) | |||||
| cloud_account.user = current_user | |||||
| cloud_account.save! | |||||
| # 2. 生成oauth2应用程序的client_id和client_secrete | |||||
| gitea_oauth = Gitea::Oauth2::CreateService.call(current_user.gitea_token, {name: "pipeline-#{SecureRandom.hex(8)}", redirect_uris: ["#{cloud_account.drone_url}/login"]}) | |||||
| logger.info "######### gitea_oauth: #{gitea_oauth}" | |||||
| oauth = Oauth.new(client_id: gitea_oauth['client_id'], | |||||
| client_secret: gitea_oauth['client_secret'], | |||||
| redirect_uri: gitea_oauth['redirect_uris'], | |||||
| gitea_oauth_id: gitea_oauth['id'], | |||||
| user_id: current_user.id) | |||||
| oauth.save! | |||||
| # 创建数据ci端数据库 | |||||
| database_result = auto_create_database!(@connection, "#{current_user.login}_drone") | |||||
| logger.info "[CI::DbConnectable] auto_create_database's result: #{database_result}" | |||||
| # 初始化表结构 | |||||
| sub_connection = connect_to_ci_database | |||||
| auto_create_table_structure!(sub_connection) | |||||
| rpc_secret = SecureRandom.hex 16 | |||||
| logger.info "######### rpc_secret: #{rpc_secret}" | |||||
| # 3. 创建drone server | |||||
| drone_server_cmd = Ci::Drone::Server.new(current_user.login, oauth.client_id, oauth.client_secret, cloud_account.drone_host, rpc_secret).generate_cmd | |||||
| logger.info "######### drone_server_cmd: #{drone_server_cmd}" | |||||
| # 4. 创建drone client | |||||
| drone_client_cmd = Ci::Drone::Client.new(oauth.client_id, cloud_account.drone_ip, rpc_secret).generate_cmd | |||||
| logger.info "######### drone_client_cmd: #{drone_client_cmd}" | |||||
| # 5. 登录远程服务器,启动drone服务 | |||||
| result = Ci::Drone::Start.new(cloud_account.account, cloud_account.visible_secret, cloud_account.drone_ip, drone_server_cmd, drone_client_cmd).run | |||||
| logger.info "######### result: #{result}" | |||||
| redirect_url = "#{cloud_account.drone_url}/login" | |||||
| logger.info "######### redirect_url: #{redirect_url}" | |||||
| return nil unless result.present? | |||||
| result && !result.blank? ? cloud_account : nil | |||||
| end | |||||
| def unbind_account! | |||||
| cloud_account = current_user.ci_cloud_account | |||||
| return render_error('你未绑定CI服务器') if current_user.devops_step == User::DEVOPS_UNINIT || cloud_account.blank? | |||||
| cloud_account.destroy! unless cloud_account.blank? | |||||
| @connection.execute("DROP DATABASE IF EXISTS #{current_user.login}_drone") # TOTO drop drone database | |||||
| current_user.unbind_account! | |||||
| end | |||||
| def bind_hook!(user, cloud_account, repo) | |||||
| hook_params = { | |||||
| active: true, | |||||
| config: { | |||||
| content_type: "json", | |||||
| url: cloud_account.drone_url + "/hook?secret=#{repo.repo_signer}" | |||||
| }, | |||||
| type: "gitea" | |||||
| } | |||||
| result = Gitea::Hooks::CreateService.call(user.gitea_token, user.login, repo.repo_name, hook_params) | |||||
| result[:status].present? ? nil : result | |||||
| end | |||||
| def check_bind_cloud_account! | |||||
| return [true, "你已经绑定了云帐号."] unless current_user.ci_cloud_account.blank? | |||||
| ip_num = IPAddr.new(devops_params[:ip_num]).to_i | |||||
| Ci::CloudAccount.exists?(ip_num: ip_num) ? [true, "#{devops_params[:ip_num]}服务器已被使用."] : [false, nil] | |||||
| end | |||||
| def gitea_auto_create_auth_grant!(gitea_oauth_id) | |||||
| connection = Gitea::Database.set_connection.connection | |||||
| unix_time = Time.now.to_i | |||||
| # 目前直接操作db,可以建立对应的model进行操作 | |||||
| sql = "INSERT INTO oauth2_grant ( user_id, application_id, counter, created_unix, updated_unix ) VALUES ( #{current_user.gitea_uid}, #{gitea_oauth_id}, 0, #{unix_time}, #{unix_time} );" | |||||
| connection.execute(sql) | |||||
| end | |||||
| def gitea_oauth_grant!(password, oauth) | |||||
| gitea_auto_create_auth_grant!(oauth&.gitea_oauth_id) | |||||
| state = SecureRandom.hex(8) | |||||
| # redirect_uri eg: | |||||
| # https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805 | |||||
| redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login") | |||||
| grant_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{oauth&.client_id}&redirect_uri=#{redirect_uri}&response_type=code&state=#{state}" | |||||
| logger.info "[gitea] grant_url: #{grant_url}" | |||||
| conn = Faraday.new(url: grant_url) do |req| | |||||
| req.request :url_encoded | |||||
| req.adapter Faraday.default_adapter | |||||
| req.basic_auth(current_user.login, password) | |||||
| end | |||||
| response = conn.get | |||||
| logger.info "[gitea] response headers: #{response.headers}" | |||||
| drone_oauth_user!(response.headers.to_h['location'], state) | |||||
| end | |||||
| def drone_oauth_user!(url, state) | |||||
| logger.info "[drone] drone_oauth_user url: #{url}" | |||||
| conn = Faraday.new(url: url) do |req| | |||||
| req.request :url_encoded | |||||
| req.adapter Faraday.default_adapter | |||||
| req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}" | |||||
| end | |||||
| response = conn.get | |||||
| logger.info "[drone] response headers: #{response.headers}" | |||||
| response.headers['location'].include?('error') ? false : true | |||||
| end | |||||
| private | |||||
| def devops_params | |||||
| params.permit(:account, :secret, :ip_num) | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,40 @@ | |||||
| module Ci::DbConnectable | |||||
| extend ActiveSupport::Concern | |||||
| include do | |||||
| end | |||||
| # Dynamically sets the database connection. | |||||
| def connect_to_ci_database(options={}) | |||||
| master_db = options[:master_db] || false | |||||
| config = Rails.application.config_for(:configuration).symbolize_keys! | |||||
| db_config = config[:ci_db_server].symbolize_keys! | |||||
| raise 'ci database config missing' if db_config.blank? | |||||
| req_params = { | |||||
| host: db_config[:host], | |||||
| username: db_config[:username], | |||||
| password: db_config[:password], | |||||
| port: db_config[:port] | |||||
| } | |||||
| req_params = req_params.merge(database: "#{current_user.login}_#{db_config[:database]}") unless master_db === true | |||||
| db_params = Ci::Database.get_connection_params(req_params) | |||||
| @connection = Ci::Database.set_connection(db_params).connection | |||||
| end | |||||
| def auto_create_database!(connection, database) | |||||
| Rails.logger.info "[CI::DbConnectable] auto_create_database's connection: #{connection}" | |||||
| connection.execute("CREATE DATABASE IF NOT EXISTS #{database}") | |||||
| end | |||||
| def auto_create_table_structure!(connection) | |||||
| Rails.logger.info "[CI::DbConnectable] auto_create_table_structure's connection: #{connection}" | |||||
| sqls = Ci::Schema.statement.split(';').map(&:strip).reject { |e| e.to_s.empty? } | |||||
| sqls.each do |sql| | |||||
| con_result = connection.execute(sql) | |||||
| Rails.logger.info "=============> ci create tabels result: #{con_result}" | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -7,6 +7,7 @@ module LaboratoryHelper | |||||
| helper_method :current_laboratory | helper_method :current_laboratory | ||||
| helper_method :default_setting | helper_method :default_setting | ||||
| helper_method :default_yun_session | helper_method :default_yun_session | ||||
| helper_method :default_course_links | |||||
| end | end | ||||
| def current_laboratory | def current_laboratory | ||||
| @@ -29,4 +30,20 @@ module LaboratoryHelper | |||||
| laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1)) | laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1)) | ||||
| @_default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id" | @_default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id" | ||||
| end | end | ||||
| end | |||||
| def default_course_links | |||||
| # my_projects: "/users/#{current_user.try(:login)}/projects", | |||||
| # my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist", | |||||
| { | |||||
| new_syllabuses: "https://www.trustie.net/syllabuses/new", | |||||
| new_course: "https://www.trustie.net/courses/new", | |||||
| edit_account: "https://www.trustie.net/my/account", | |||||
| my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist", | |||||
| my_projects: "/users/#{current_user.try(:login)}/projects", | |||||
| my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations", | |||||
| default_url: "https://www.trustie.net/", | |||||
| tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages", | |||||
| register_url: "https://www.trustie.net/login?login=false" | |||||
| } | |||||
| end | |||||
| end | |||||
| @@ -11,18 +11,28 @@ module LoginHelper | |||||
| def set_autologin_cookie(user) | def set_autologin_cookie(user) | ||||
| token = Token.get_or_create_permanent_login_token(user, "autologin") | token = Token.get_or_create_permanent_login_token(user, "autologin") | ||||
| sync_user_token_to_trustie(user.login, token.value) | |||||
| Rails.logger.info "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}" | |||||
| cookie_options = { | cookie_options = { | ||||
| :value => token.value, | :value => token.value, | ||||
| :expires => 1.month.from_now, | :expires => 1.month.from_now, | ||||
| :path => '/', | :path => '/', | ||||
| :secure => false, | :secure => false, | ||||
| :httponly => false | |||||
| :httponly => true | |||||
| } | } | ||||
| if edu_setting('cookie_domain').present? | if edu_setting('cookie_domain').present? | ||||
| cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain')) | cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain')) | ||||
| end | end | ||||
| # unless cookies[autologin_cookie_name].present? | |||||
| # cookies[autologin_cookie_name] = cookie_options | |||||
| # end | |||||
| cookies[autologin_cookie_name] = cookie_options | cookies[autologin_cookie_name] = cookie_options | ||||
| Rails.logger.info("cookies is #{cookies}") | |||||
| # for action cable | |||||
| cookies.signed[:user_id] ||= user.id | |||||
| Rails.logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]}") | |||||
| end | end | ||||
| def successful_authentication(user) | def successful_authentication(user) | ||||
| @@ -40,13 +50,22 @@ module LoginHelper | |||||
| end | end | ||||
| def logout_user | def logout_user | ||||
| Rails.logger.info("####################__User.current_id______######{current_user.try(:id)}###___#{current_user&.logged?}") | |||||
| if User.current.logged? | if User.current.logged? | ||||
| if autologin = cookies.delete(autologin_cookie_name) | |||||
| User.current.delete_autologin_token(autologin) | |||||
| end | |||||
| User.current.delete_session_token(session[:tk]) | |||||
| user = User.current | |||||
| autologin = | |||||
| if edu_setting('cookie_domain').present? | |||||
| cookies.delete(autologin_cookie_name, domain: edu_setting('cookie_domain')) | |||||
| else | |||||
| cookies.delete(autologin_cookie_name) | |||||
| end | |||||
| user.delete_autologin_token(autologin) | |||||
| user.delete_session_token(session[:tk]) | |||||
| self.logged_user = nil | self.logged_user = nil | ||||
| end | end | ||||
| # 云上实验室退出清理当前session | # 云上实验室退出清理当前session | ||||
| laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1)) | laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1)) | ||||
| default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id" | default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id" | ||||
| @@ -56,8 +75,10 @@ module LoginHelper | |||||
| # Sets the logged in user | # Sets the logged in user | ||||
| def logged_user=(user) | def logged_user=(user) | ||||
| # reset_session | |||||
| reset_session | |||||
| if user && user.is_a?(User) | if user && user.is_a?(User) | ||||
| Rails.logger.info("########________logged_user___________###########{user.id}") | |||||
| User.current = user | User.current = user | ||||
| start_user_session(user) | start_user_session(user) | ||||
| else | else | ||||
| @@ -78,8 +99,53 @@ module LoginHelper | |||||
| # # end | # # end | ||||
| # session[:user_id] = user.id | # session[:user_id] = user.id | ||||
| Rails.logger.info("########________start_user_session___________###########{user.id}") | |||||
| session[:"#{default_yun_session}"] = user.id | session[:"#{default_yun_session}"] = user.id | ||||
| session[:ctime] = Time.now.utc.to_i | session[:ctime] = Time.now.utc.to_i | ||||
| session[:atime] = Time.now.utc.to_i | session[:atime] = Time.now.utc.to_i | ||||
| end | end | ||||
| end | |||||
| def sync_pwd_to_gitea!(user, hash={}) | |||||
| return true if user.is_sync_pwd? | |||||
| sync_params = { email: user.mail } | |||||
| interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash)) | |||||
| if interactor.success? | |||||
| Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########" | |||||
| true | |||||
| else | |||||
| Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}" | |||||
| false | |||||
| end | |||||
| end | |||||
| # TODO 同步token到trustie平台,保持同步登录状态 | |||||
| def sync_user_token_to_trustie(login, token_value) | |||||
| config = Rails.application.config_for(:configuration).symbolize_keys! | |||||
| token = config[:sync_token] | |||||
| api_host = config[:sync_url] | |||||
| return if api_host.blank? | |||||
| url = "#{api_host}/api/v1/users/sync_user_token" | |||||
| sync_json = { | |||||
| "token": token, | |||||
| "login": login, | |||||
| "user_token": token_value | |||||
| } | |||||
| uri = URI.parse(url) | |||||
| if api_host | |||||
| http = Net::HTTP.new(uri.hostname, uri.port) | |||||
| if api_host.include?("https://") | |||||
| http.use_ssl = true | |||||
| end | |||||
| http.send_request('POST', uri.path, sync_json.to_json, {'Content-Type' => 'application/json'}) | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -5,7 +5,12 @@ module OperateProjectAbilityAble | |||||
| end | end | ||||
| def authorizate_user_can_edit_project! | def authorizate_user_can_edit_project! | ||||
| return if current_user.project_manager? @project || current_user.admin? | |||||
| return if @project.manager?(current_user) || current_user.admin? | |||||
| render_forbidden('你没有权限操作.') | |||||
| end | |||||
| def authorizate_user_can_edit_repo! | |||||
| return if @repository.project.manager?(current_user) || current_user.admin? | |||||
| render_forbidden('你没有权限操作.') | render_forbidden('你没有权限操作.') | ||||
| end | end | ||||
| @@ -0,0 +1,28 @@ | |||||
| module RegisterHelper | |||||
| extend ActiveSupport::Concern | |||||
| def autologin_register(username, email, password, platform= 'forge') | |||||
| result = {message: nil, user: nil} | |||||
| user = User.new(admin: false, login: username, mail: email, type: "User") | |||||
| user.password = password | |||||
| user.platform = platform | |||||
| user.activate | |||||
| interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) | |||||
| if interactor.success? | |||||
| gitea_user = interactor.result | |||||
| result = Gitea::User::GenerateTokenService.new(username, password).call | |||||
| user.gitea_token = result['sha1'] | |||||
| user.gitea_uid = gitea_user['id'] | |||||
| if user.save! | |||||
| UserExtension.create!(user_id: user.id) | |||||
| result[:user] = {id: user.id, token: user.gitea_token} | |||||
| end | |||||
| else | |||||
| result[:message] = interactor.error | |||||
| end | |||||
| result | |||||
| end | |||||
| end | |||||
| @@ -1,73 +0,0 @@ | |||||
| class CourseGroupsController < ApplicationController | |||||
| before_action :require_login, :check_auth | |||||
| before_action :set_group, except: [:create] | |||||
| before_action :find_course, only: [:create] | |||||
| before_action :teacher_allowed, except: [:set_invite_code_halt] | |||||
| def create | |||||
| tip_exception("分班名称不能为空") if params[:name].blank? | |||||
| if @course.course_groups.where(name: params[:name]).count > 0 | |||||
| normal_status(-1, "已存在同名分班") | |||||
| else | |||||
| course_group = @course.course_groups.create!(name: params[:name], position: @course.course_groups.count + 1) | |||||
| render :json => {group_id: course_group.id, status: 0, message: "创建成功"} | |||||
| end | |||||
| end | |||||
| def destroy | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @course.course_groups.where("position > #{@group.position}").update_all("position = position - 1") | |||||
| # 将该分班的学生转到未分班 | |||||
| @group.course_members.update_all(course_group_id: 0) | |||||
| @group.destroy | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception("删除分班失败") | |||||
| end | |||||
| end | |||||
| end | |||||
| # 分班重命名 | |||||
| def rename_group | |||||
| tip_exception("名称不能为空") if params[:name].blank? | |||||
| if @course.course_groups.where(name: params[:name]).count > 0 | |||||
| normal_status(-1, "已存在同名分班") | |||||
| else | |||||
| @group.update_attributes(name: params[:name].strip) | |||||
| normal_status(0, "更新成功") | |||||
| end | |||||
| end | |||||
| # 分班的拖动 | |||||
| def move_category | |||||
| tip_exception("移动失败") if params[:position].blank? | |||||
| unless params[:position].to_i == @group.position | |||||
| if params[:position].to_i < @group.position | |||||
| @course.course_groups.where("position < #{@group.position} and position >= ?", params[:position]).update_all("position = position + 1") | |||||
| else | |||||
| @course.course_groups.where("position > #{@group.position} and position <= ?", params[:position]).update_all("position = position - 1") | |||||
| end | |||||
| @group.update_attributes(position: params[:position]) | |||||
| normal_status(0, "移动成功") | |||||
| else | |||||
| normal_status(-1, "位置没有变化") | |||||
| end | |||||
| end | |||||
| # 邀请码停用/启用 | |||||
| def set_invite_code_halt | |||||
| teacher = @course.teachers.find_by(user_id: current_user.id) | |||||
| tip_exception(403, "无权限") unless current_user.admin_or_business? || | |||||
| (teacher.present? && (teacher.teacher_course_groups.pluck(:course_group_id).include?(@group.id) || teacher.teacher_course_groups.size == 0)) | |||||
| @group.update!(invite_code_halt: !@group.invite_code_halt) | |||||
| normal_status(0, "成功") | |||||
| end | |||||
| private | |||||
| def set_group | |||||
| @group = CourseGroup.find_by!(id: params[:id]) | |||||
| @course = @group.course | |||||
| end | |||||
| end | |||||
| @@ -1,68 +0,0 @@ | |||||
| class CourseModulesController < ApplicationController | |||||
| before_action :require_login, :check_auth | |||||
| before_action :set_module, except: [:unhidden_modules] | |||||
| before_action :find_course, only: [:unhidden_modules] | |||||
| before_action :teacher_or_admin_allowed, except: [:add_second_category] | |||||
| before_action :teacher_allowed, only: [:add_second_category] | |||||
| # 模块置顶 | |||||
| def sticky_module | |||||
| # position为1则不做处理,否则该模块的position置为1,position小于当前模块的position加1 | |||||
| unless @course_module.position == 1 | |||||
| @course.course_modules.where("position < #{@course_module.position}").update_all("position = position + 1") | |||||
| @course_module.update_attributes(position: 1) | |||||
| end | |||||
| normal_status(0, "置顶成功") | |||||
| end | |||||
| # 模块隐藏 | |||||
| def hidden_module | |||||
| tip_exception("请至少保留一个课堂模块") if @course.none_hidden_course_modules.where.not(id: @course_module.id).size == 0 | |||||
| @course_module.update_attributes(hidden: 1) | |||||
| normal_status(0, "更新成功") | |||||
| end | |||||
| # 模块重命名 | |||||
| def rename_module | |||||
| name = params[:name].strip | |||||
| tip_exception("名称不能为空") if name.blank? | |||||
| tip_exception("已存在同名模块") if @course.course_modules.exists?(module_name: name) | |||||
| @course_module.update_attributes(module_name: name) | |||||
| case @course_module.module_type | |||||
| when 'board' | |||||
| @course.course_board.update_columns(name: name) | |||||
| end | |||||
| normal_status(0, "更新成功") | |||||
| end | |||||
| # 模块的显示 | |||||
| def unhidden_modules | |||||
| tip_exception("请选择要显示的模块") if params[:module_ids].blank? | |||||
| @course.course_modules.where(id: params[:module_ids]).update_all(hidden: 0) | |||||
| normal_status(0, "更新成功") | |||||
| end | |||||
| # 添加二级目录 | |||||
| def add_second_category | |||||
| tip_exception("子目录名称不能为空") if params[:name].blank? | |||||
| tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip) | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| category = @course_module.course_second_categories.create!(name: params[:name].strip, category_type: @course_module.module_type, | |||||
| course_id: @course.id, position: @course_module.course_second_categories.count + 1) | |||||
| render :json => {category_id: category.id, status: 0, message: "添加成功"} | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception("添加子目录失败") | |||||
| end | |||||
| end | |||||
| end | |||||
| private | |||||
| def set_module | |||||
| @course_module = CourseModule.find_by!(id: params[:id]) | |||||
| @course = @course_module.course | |||||
| end | |||||
| end | |||||
| @@ -1,60 +0,0 @@ | |||||
| class CourseSecondCategoriesController < ApplicationController | |||||
| before_action :require_login, :check_auth | |||||
| before_action :set_category | |||||
| before_action :teacher_allowed | |||||
| # 目录重命名 | |||||
| def rename_category | |||||
| tip_exception("毕设子目录不能重命名") if @category.category_type == "graduation" | |||||
| tip_exception("名称不能为空") if params[:name].blank? | |||||
| tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip) | |||||
| @category.update_attributes!(name: params[:name].strip) | |||||
| normal_status(0, "更新成功") | |||||
| end | |||||
| # 子目录的拖动 | |||||
| def move_category | |||||
| tip_exception("移动失败") if params[:position].blank? | |||||
| unless params[:position].to_i == @category.position | |||||
| if params[:position].to_i < @category.position | |||||
| @course_module.course_second_categories.where("position < #{@category.position} and position >= ?", params[:position]).update_all("position = position + 1") | |||||
| else | |||||
| @course_module.course_second_categories.where("position > #{@category.position} and position <= ?", params[:position]).update_all("position = position - 1") | |||||
| end | |||||
| @category.update!(position: params[:position]) | |||||
| normal_status(0, "移动成功") | |||||
| else | |||||
| normal_status(-1, "位置没有变化") | |||||
| end | |||||
| end | |||||
| def destroy | |||||
| tip_exception("毕设子目录不能删除") if @category.category_type == "graduation" | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @course_module.course_second_categories.where("position > #{@category.position}").update_all("position = position - 1") | |||||
| # 更新相应对象的子目录id | |||||
| if @course_module.module_type == "shixun_homework" | |||||
| @category.homework_commons.update_all(course_second_category_id: 0) | |||||
| @right_url = "/courses/#{@course.id}/shixun_homeworks/#{@course_module.id}" | |||||
| elsif @course_module.module_type == "attachment" | |||||
| Attachment.where(course_second_category_id: @category.id).update_all(course_second_category_id: 0) | |||||
| @right_url = "/courses/#{@course.id}/files/#{@course_module.id}" | |||||
| end | |||||
| @category.destroy | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception("删除子目录失败") | |||||
| end | |||||
| end | |||||
| end | |||||
| private | |||||
| def set_category | |||||
| @category = CourseSecondCategory.find_by!(id: params[:id]) | |||||
| @course_module = @category.course_module | |||||
| @course = @course_module.try(:course) | |||||
| end | |||||
| end | |||||
| @@ -1,13 +0,0 @@ | |||||
| class DepartmentsController < ApplicationController | |||||
| skip_before_action :check_sign | |||||
| def for_option | |||||
| render_ok(departments: current_school.departments.without_deleted.select(:id, :name).as_json) | |||||
| end | |||||
| private | |||||
| def current_school | |||||
| @_current_school ||= School.find(params[:id]) | |||||
| end | |||||
| end | |||||
| @@ -1,6 +0,0 @@ | |||||
| class DisciplinesController < ApplicationController | |||||
| def index | |||||
| end | |||||
| end | |||||
| @@ -1,29 +0,0 @@ | |||||
| class EduDatasController < ApplicationController | |||||
| before_action :find_game | |||||
| skip_before_action :user_setup | |||||
| skip_before_action :setup_laboratory | |||||
| # layout :false | |||||
| include GitHelper | |||||
| # params[:game_id] | |||||
| def game | |||||
| @shixun = @challenge.shixun | |||||
| @shixun_env = @shixun.mirror_name | |||||
| @shixun_tags = @challenge.challenge_tags.map(&:name) | |||||
| end | |||||
| def code_lines | |||||
| path = @challenge.path | |||||
| myshixun = @game.myshixun | |||||
| # content = git_fle_content(myshixun.repo_path, path) || "" | |||||
| @content = {"content":"#coding=utf-8\n\n#请在此处添加代码完成输出“Hello Python”,注意要区分大小写!\n###### Begin ######\n\n\n\n###### End ######\n\n"} | |||||
| @content[:content].include?("Begin") | |||||
| end | |||||
| private | |||||
| def find_game | |||||
| game_id = params[:game_id] | |||||
| @game = Game.find(game_id) | |||||
| @challenge = @game.challenge | |||||
| end | |||||
| end | |||||
| @@ -1,92 +0,0 @@ | |||||
| class ExaminationBanksController < ApplicationController | |||||
| include PaginateHelper | |||||
| before_action :require_login | |||||
| before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public, :revoke_item] | |||||
| before_action :find_exam, except: [:index, :create] | |||||
| before_action :edit_auth, only: [:update, :destroy, :set_public, :revoke_item] | |||||
| before_action :identity_auth, only: [:index] | |||||
| def index | |||||
| exams = ExaminationBankQuery.call(params) | |||||
| @exams_count = exams.size | |||||
| @exams = paginate exams.includes(:user, :examination_items) | |||||
| end | |||||
| def show | |||||
| @items = @exam.examination_items | |||||
| @single_questions = @items.where(item_type: "SINGLE") | |||||
| @multiple_questions = @items.where(item_type: "MULTIPLE") | |||||
| @judgement_questions = @items.where(item_type: "JUDGMENT") | |||||
| @program_questions = @items.where(item_type: "PROGRAM") | |||||
| end | |||||
| def create | |||||
| ActiveRecord::Base.transaction do | |||||
| exam = ExaminationBank.new(user: current_user) | |||||
| # 保存试卷基础信息 | |||||
| exam = ExaminationBanks::SaveExaminationBankService.call(exam, form_params) | |||||
| # 将试题篮中的试题发送到试卷,试卷的题目与试题独立 | |||||
| current_user.item_baskets.includes(:item_bank).each do |basket| | |||||
| item = basket.item_bank | |||||
| if item.present? | |||||
| new_item = ExaminationItem.new | |||||
| new_item.new_item(item, exam, basket.score, basket.position) | |||||
| end | |||||
| end | |||||
| current_user.item_baskets.destroy_all | |||||
| end | |||||
| render_ok | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def edit; end | |||||
| def update | |||||
| ExaminationBanks::SaveExaminationBankService.call(@exam, form_params) | |||||
| render_ok | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def destroy | |||||
| ActiveRecord::Base.transaction do | |||||
| ApplyAction.where(container_type: "ExaminationBank", container_id: @exam.id).destroy_all | |||||
| @exam.destroy! | |||||
| render_ok | |||||
| end | |||||
| end | |||||
| def set_public | |||||
| tip_exception(-1, "该试卷已公开") if @exam.public? | |||||
| tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @exam.id, container_type: "ExaminationBank", status: 0).exists? | |||||
| ApplyAction.create!(container_id: @exam.id, container_type: "ExaminationBank", user_id: current_user.id) | |||||
| # @exam.update_attributes!(public: 1) | |||||
| render_ok | |||||
| end | |||||
| def revoke_item | |||||
| item = @exam.examination_items.find_by!(item_bank_id: params[:item_id]) | |||||
| ActiveRecord::Base.transaction do | |||||
| @exam.examination_items.where(item_type: item.item_type).where("position > #{item.position}").update_all("position = position -1") | |||||
| item.destroy! | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| private | |||||
| def form_params | |||||
| params.permit(:discipline_id, :sub_discipline_id, :difficulty, :name, :duration, tag_discipline_id: []) | |||||
| end | |||||
| def find_exam | |||||
| @exam = ExaminationBank.find_by!(id: params[:id]) | |||||
| end | |||||
| def edit_auth | |||||
| current_user.admin_or_business? || @exam.user == current_user | |||||
| end | |||||
| end | |||||
| @@ -1,108 +0,0 @@ | |||||
| class ExaminationIntelligentSettingsController < ApplicationController | |||||
| before_action :require_login | |||||
| before_action :certi_identity_auth, only: [:create, :optinal_items, :save_exam, :exchange_one_item, :exchange_items] | |||||
| before_action :find_exam, only: [:exchange_one_item, :exchange_items, :save_exam] | |||||
| def optinal_items | |||||
| sub_discipline_id = params[:sub_discipline_id] | |||||
| tag_discipline_id = params[:tag_discipline_id] | |||||
| difficulty = params[:difficulty] | |||||
| source = params[:source] | |||||
| items = OptionalItemQuery.call(sub_discipline_id, tag_discipline_id, difficulty, source) | |||||
| @single_question_count = items.select{ |item| item.item_type == "SINGLE" }.size | |||||
| @multiple_question_count = items.select{ |item| item.item_type == "MULTIPLE" }.size | |||||
| @judgement_question_count = items.select{ |item| item.item_type == "JUDGMENT" }.size | |||||
| @program_question_count = items.select{ |item| item.item_type == "PROGRAM" }.size | |||||
| end | |||||
| def create | |||||
| ActiveRecord::Base.transaction do | |||||
| exam = ExaminationIntelligentSetting.new(user: current_user) | |||||
| # 保存试卷基础信息 | |||||
| exam = ExaminationIntelligentSettings::SaveSettingService.call(exam, form_params) | |||||
| render_ok({exam_setting_id: exam.id}) | |||||
| end | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def save_exam | |||||
| new_exam = ExaminationBank.new(user: current_user) | |||||
| # 保存试卷基础信息 | |||||
| ExaminationIntelligentSettings::SaveExaminationService.call(new_exam, save_params, @exam) | |||||
| render_ok | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def exchange_one_item | |||||
| item = @exam.item_baskets.find_by!(item_bank_id: params[:item_id]) | |||||
| exam_type_setting = @exam.examination_type_settings.find_by!(item_type: item.item_type) | |||||
| # 获取可选的题 | |||||
| items = OptionalItemQuery.call(@exam.sub_discipline_id, @exam.tag_discipline_containers.pluck(:tag_discipline_id), @exam.difficulty, @exam.public) | |||||
| # 可选题中去掉已组卷的试题 | |||||
| type_items = items.select{ |t_item| t_item.item_type == item.item_type } | |||||
| optional_item_ids = (type_items.pluck(:id) - @exam.item_baskets.where(item_type: item.item_type).pluck(:item_bank_id)).uniq | |||||
| # 如果可选的题数等于0则提示无可换的题 | |||||
| tip_exception("无可换的题") if optional_item_ids.size == 0 | |||||
| new_item = ItemBank.find optional_item_ids.sample(1).first | |||||
| ActiveRecord::Base.transaction do | |||||
| @exam.item_baskets << ItemBasket.new(item_bank_id: new_item.id, position: item.position, score: item.score, item_type: new_item.item_type) | |||||
| item.destroy! | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| def exchange_items | |||||
| exam_type_setting = @exam.examination_type_settings.find_by!(item_type: params[:item_type]) | |||||
| choosed_items = @exam.item_baskets.where(item_type: params[:item_type]) | |||||
| # 获取可选的题 | |||||
| items = OptionalItemQuery.call(@exam.sub_discipline_id, @exam.tag_discipline_containers.pluck(:tag_discipline_id), @exam.difficulty, @exam.public) | |||||
| type_items = items.select{ |t_item| t_item.item_type == params[:item_type] } | |||||
| # 可选题中去掉已组卷的试题 | |||||
| choosed_item_ids = choosed_items.pluck(:item_bank_id) | |||||
| optional_item_ids = (type_items.pluck(:id) - choosed_item_ids).uniq | |||||
| # 如果可选的题数等于0则提示无可换的题 | |||||
| tip_exception("无可换的题") if optional_item_ids.size == 0 | |||||
| # 如果可选题数小于设置的题数(n),则在原来的选题中随机选n个,确保换题时能选到新的题 | |||||
| if optional_item_ids.size < exam_type_setting.count | |||||
| absence_count = exam_type_setting.count - optional_item_ids.size | |||||
| optional_item_ids = optional_item_ids + choosed_item_ids.sample(absence_count) | |||||
| end | |||||
| ActiveRecord::Base.transaction do | |||||
| # 取试题分数 | |||||
| score = choosed_items.first&.score || (params[:item_type] == "PROGRAM" ? 10 : 5) | |||||
| choosed_items.destroy_all | |||||
| optional_item_ids.sample(exam_type_setting.count).each_with_index do |item_id, index| | |||||
| new_item = ItemBank.find item_id | |||||
| @exam.item_baskets << ItemBasket.new(item_bank_id: new_item.id, position: index+1, score: score, item_type: new_item.item_type) | |||||
| end | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| private | |||||
| def find_exam | |||||
| @exam = ExaminationIntelligentSetting.find_by!(id: params[:id]) | |||||
| tip_exception(403,"无权限编辑") unless current_user.admin_or_business? || @exam.user_id == current_user.id | |||||
| end | |||||
| def form_params | |||||
| params.permit(:discipline_id, :sub_discipline_id, :difficulty, :source, tag_discipline_id: [], question_settings: %i[item_type count]) | |||||
| end | |||||
| def save_params | |||||
| params.permit(:name, :duration) | |||||
| end | |||||
| end | |||||
| @@ -1,85 +0,0 @@ | |||||
| class ExaminationItemsController < ApplicationController | |||||
| before_action :require_login | |||||
| before_action :certi_identity_auth, only: [:create, :destroy, :delete_item_type, :set_score, :batch_set_score, :adjust_position] | |||||
| before_action :validate_score, only: [:set_score, :batch_set_score] | |||||
| before_action :find_exam, only: [:create, :batch_set_score, :delete_item_type] | |||||
| before_action :find_item, except: [:create, :batch_set_score, :delete_item_type] | |||||
| before_action :edit_auth | |||||
| def create | |||||
| ExaminationItems::SaveItemService.call(current_user, create_params, @exam) | |||||
| render_ok | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def destroy | |||||
| ActiveRecord::Base.transaction do | |||||
| @exam.examination_items.where(item_type: @item.item_type).where("position > #{@item.position}").update_all("position = position -1") | |||||
| @item.destroy! | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| def delete_item_type | |||||
| items = @exam.examination_items.where(item_type: params[:item_type]) | |||||
| items.destroy_all | |||||
| render_ok | |||||
| end | |||||
| def set_score | |||||
| @item.update_attributes!(score: params[:score]) | |||||
| @questions_score = @exam.examination_items.where(item_type: @item.item_type).pluck(:score).sum | |||||
| @all_score = @exam.examination_items.pluck(:score).sum | |||||
| render_ok({questions_score: @questions_score, all_score: @all_score}) | |||||
| end | |||||
| def batch_set_score | |||||
| @exam.examination_items.where(item_type: params[:item_type]).update_all(score: params[:score]) | |||||
| @questions_score = @exam.examination_items.where(item_type: params[:item_type]).pluck(:score).sum | |||||
| @all_score = @exam.examination_items.pluck(:score).sum | |||||
| render_ok({questions_score: @questions_score, all_score: @all_score}) | |||||
| end | |||||
| def adjust_position | |||||
| same_items = @exam.examination_items.where(item_type: @item.item_type) | |||||
| max_position = same_items.size | |||||
| tip_exception("position超出范围") unless params[:position].present? && params[:position].to_i <= max_position && params[:position].to_i >= 1 | |||||
| ActiveRecord::Base.transaction do | |||||
| if params[:position].to_i > @item.position | |||||
| same_items.where("position > #{@item.position} and position <= #{params[:position].to_i}").update_all("position=position-1") | |||||
| @item.update_attributes!(position: params[:position]) | |||||
| elsif params[:position].to_i < @item.position | |||||
| same_items.where("position < #{@item.position} and position >= #{params[:position].to_i}").update_all("position=position+1") | |||||
| @item.update_attributes!(position: params[:position]) | |||||
| else | |||||
| return normal_status(-1, "排序无变化") | |||||
| end | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| private | |||||
| def find_exam | |||||
| @exam = ExaminationBank.find_by!(id: params[:exam_id]) | |||||
| end | |||||
| def create_params | |||||
| params.permit(item_ids: []) | |||||
| end | |||||
| def find_item | |||||
| @item = ExaminationItem.find_by!(id: params[:id]) | |||||
| @exam = @item.examination_bank | |||||
| end | |||||
| def validate_score | |||||
| tip_exception("分值不能为空") unless params[:score].present? | |||||
| tip_exception("分值需大于0") unless params[:score].to_f > 0 | |||||
| end | |||||
| def edit_auth | |||||
| current_user.admin_or_business? || @exam.user == current_user | |||||
| end | |||||
| end | |||||
| @@ -1,400 +0,0 @@ | |||||
| class FilesController < ApplicationController | |||||
| include MessagesHelper | |||||
| before_action :require_login, :check_auth, except: %i[index] | |||||
| before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project] | |||||
| before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public bulk_publish] | |||||
| before_action :file_validate_sort_type, only: :index | |||||
| before_action :validate_send_message_to_course_params, only: :bulk_send | |||||
| before_action :set_pagination, only: %i[index public_with_course_and_project mine_with_course_and_project] | |||||
| before_action :validate_upload_params, only: %i[upload import] | |||||
| before_action :find_file, only: %i[show setting update] | |||||
| before_action :publish_params, only: %i[upload import update] | |||||
| SORT_TYPE = %w[created_on downloads quotes] | |||||
| def index | |||||
| sort = params[:sort] || 0 # 0: 降序;1: 升序 | |||||
| sort_type = params[:sort_type] || 'created_on' # created_on:时间排序, downloads:下载次数排序; quotes: 引用次数排序 | |||||
| @course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id | |||||
| @user = current_user | |||||
| @attachments = @course_second_category_id.to_i == 0 ? @course.attachments.includes(:course_second_category) : @course.attachments.by_course_second_category_id(@course_second_category_id) | |||||
| @attachments = @attachments.includes(author: [:user_extension, :course_members]) | |||||
| .ordered(sort: sort.to_i, sort_type: sort_type.strip) | |||||
| get_category(@course, @course_second_category_id) | |||||
| @total_count = @attachments.size | |||||
| if @user.course_identity(@course) == 5 | |||||
| member = @course.course_members.find_by(user_id: current_user.id, is_active: 1) | |||||
| if member.try(:course_group_id).to_i == 0 | |||||
| @attachments = @attachments.published.unified_setting | |||||
| else | |||||
| not_atta_ids = @course.attachment_group_settings.none_published.where("course_group_id = #{member.try(:course_group_id)}").pluck(:attachment_id) | |||||
| @attachments = @attachments.where.not(id: not_atta_ids).published | |||||
| end | |||||
| elsif @user.course_identity(@course) > 5 | |||||
| @attachments = @attachments.publiced.published | |||||
| end | |||||
| @publish_count = @attachments.published.size | |||||
| @unpublish_count = @total_count - @publish_count | |||||
| @attachments = @attachments.by_keywords(params[:search]) | |||||
| @attachments = @attachments.page(@page).per(@page_size) | |||||
| end | |||||
| def bulk_publish | |||||
| return normal_status(403, "您没有权限进行操作") if current_user.course_identity(@course) >= 5 | |||||
| # tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0 | |||||
| attachments = @course.attachments.by_ids(@attachment_ids) | |||||
| ActiveRecord::Base.transaction do | |||||
| # 有分班设置时 | |||||
| # if @course.course_group_module? && @course.course_groups_count != 0 && params[:group_ids] | |||||
| # group_ids = params[:group_ids]&.reject(&:blank?) | |||||
| # charge_group_ids = @course.charge_group_ids(current_user) | |||||
| # publish_groups = charge_group_ids & group_ids if group_ids | |||||
| # | |||||
| # attachments.each do |atta| | |||||
| # if atta.published? && !atta.unified_setting || !atta.published? | |||||
| # create_atta_group_settings atta | |||||
| # atta.update_attributes!(unified_setting: 0) if atta.unified_setting | |||||
| # none_publish_settings = atta.attachment_group_settings.where(course_group_id: publish_groups).none_published | |||||
| # none_publish_settings.update_all(publish_time: Time.now) | |||||
| # end | |||||
| # end | |||||
| # end | |||||
| # 未发布的资源更新状态 | |||||
| attachments.where(is_publish: 0).update_all(is_publish: 1, publish_time: Time.now) | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| def bulk_delete | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @course.attachments.by_ids(@attachment_ids).destroy_all | |||||
| rescue Exception => e | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def bulk_send | |||||
| return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@course) | |||||
| course_ids = params[:to_course_ids] | |||||
| begin | |||||
| @attachment_ids.each do |id| | |||||
| @attachment = @course.attachments.find_by_id id | |||||
| course_ids.each do |course_id| | |||||
| course = Course.find_by_id course_id | |||||
| unless @attachment.nil? || course.nil? | |||||
| course.attachments << course.attachments.build(@attachment.attributes.except("id").merge( | |||||
| quotes: 0, | |||||
| downloads: 0, | |||||
| author_id: current_user.id, | |||||
| created_on: Time.now, | |||||
| course_second_category_id: 0 # TODO 暂时只支持发送到其他课堂的主目录 | |||||
| )) | |||||
| end | |||||
| end | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def bulk_move | |||||
| return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@course) | |||||
| to_category_id = params[:to_category_id] || 0 # 默认移动到主目录 | |||||
| unless to_category_id == 0 | |||||
| course_second_category = @course.course_second_categories.find_by_id to_category_id | |||||
| return normal_status(2, "参数to_category_id有误,该目录不存在") if course_second_category.nil? | |||||
| end | |||||
| begin | |||||
| @course.attachments.by_ids(@attachment_ids).update_all(course_second_category_id: to_category_id) | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def bulk_public | |||||
| @user = current_user | |||||
| return normal_status(403, "您没有权限进行该操作") unless @user.teacher_of_course?(@course) | |||||
| @course.attachments.by_ids(@attachment_ids).update_all(is_public: 1) | |||||
| end | |||||
| def public_with_course_and_project | |||||
| @attachments = Attachment.publiced.simple_columns | |||||
| .contains_course_and_project | |||||
| .includes(:container, author: :user_extension) | |||||
| .by_filename_or_user_name(params[:search]) | |||||
| .ordered(sort: 0, sort_type: 'created_on') | |||||
| @total_count = @attachments.size | |||||
| @attachments = @attachments.page(@page).per(@page_size) | |||||
| end | |||||
| def mine_with_course_and_project | |||||
| @current_user = current_user | |||||
| @attachments = Attachment.mine(current_user) | |||||
| .simple_columns | |||||
| .contains_course_and_project | |||||
| .by_keywords(params[:search]) | |||||
| .ordered(sort: 0, sort_type: 'created_on') | |||||
| @total_count = @attachments.size | |||||
| @attachments = @attachments.page(@page).per(@page_size) | |||||
| end | |||||
| # 上传资源 | |||||
| def upload | |||||
| attachment_ids = params[:attachment_ids] | |||||
| course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id | |||||
| # is_unified_setting = params.has_key?(:is_unified_setting) ? params[:is_unified_setting] : true | |||||
| # publish_time = params[:publish_time] | |||||
| # course_group_publish_times = params[:course_group_publish_times] || [] | |||||
| begin | |||||
| attachment_ids.each do |attchment_id| | |||||
| attachment = Attachment.find_by_id attchment_id | |||||
| unless attachment.nil? | |||||
| attachment.container = @course | |||||
| attachment.course_second_category_id = course_second_category_id | |||||
| attachment.description = params[:description] | |||||
| attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0 | |||||
| attachment.is_publish = @atta_is_publish | |||||
| attachment.delay_publish = @atta_delay_publish | |||||
| attachment.publish_time = @atta_publish_time | |||||
| attachment.unified_setting = @unified_setting | |||||
| if @unified_setting == 0 | |||||
| attachment_group_setting attachment, params[:group_settings] | |||||
| end | |||||
| # attachment.set_publish_time(publish_time) if is_unified_setting | |||||
| # attachment.set_course_group_publish_time(@course, course_group_publish_times) if @course.course_groups.size > 0 && !is_unified_setting && publish_time.blank? | |||||
| attachment.save! | |||||
| end | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| # 选用资源 & 导入资源 | |||||
| def import | |||||
| return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@course) || current_user.student_of_course?(@course) | |||||
| attachment_ids = params[:attachment_ids] | |||||
| course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id | |||||
| begin | |||||
| attachment_ids.each do |attachment_id| | |||||
| ori = Attachment.find_by_id(attachment_id) | |||||
| # 同一个资源可以多次发送到课堂 | |||||
| # @course.attachments.each do |att| | |||||
| # @exist = false | |||||
| # if att.id == ori.id || (!att.copy_from.nil? && !ori.copy_from.nil? && att.copy_from == ori.copy_from) || att.copy_from == ori.id || att.id == ori.copy_from | |||||
| # att.created_on = Time.now | |||||
| # att.save | |||||
| # @exist = true | |||||
| # break | |||||
| # end | |||||
| # end | |||||
| # | |||||
| # next if @exist | |||||
| attach_copied_obj = ori.copy | |||||
| attach_copied_obj.container = @course | |||||
| attach_copied_obj.created_on = Time.now | |||||
| attach_copied_obj.author = current_user | |||||
| attach_copied_obj.is_public = 0 | |||||
| attach_copied_obj.is_publish = @atta_is_publish | |||||
| attach_copied_obj.delay_publish = @atta_delay_publish | |||||
| attach_copied_obj.publish_time = @atta_publish_time | |||||
| attach_copied_obj.unified_setting = @unified_setting | |||||
| if @unified_setting == 0 | |||||
| attachment_group_setting attach_copied_obj, params[:group_settings] | |||||
| end | |||||
| attach_copied_obj.course_second_category_id = course_second_category_id | |||||
| attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from | |||||
| if attach_copied_obj.attachtype == nil | |||||
| attach_copied_obj.attachtype = 4 | |||||
| end | |||||
| attach_copied_obj.save | |||||
| ori.update_columns(quotes: ori.quotes.to_i + 1) | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| # 资源设置 | |||||
| def update | |||||
| return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@course) >= 5 && @file.author != current_user | |||||
| is_public = params[:is_public] | |||||
| @old_attachment = @file | |||||
| @new_attachment = Attachment.find_by_id params[:new_attachment_id] | |||||
| begin | |||||
| unless @new_attachment.nil? | |||||
| @new_attachment_history = @old_attachment.become_history | |||||
| @new_attachment_history.save! | |||||
| old_course_second_category_id = @old_attachment.course_second_category_id | |||||
| @old_attachment.copy_attributes_from_new_attachment(@new_attachment) | |||||
| @old_attachment.course_second_category_id = old_course_second_category_id | |||||
| @old_attachment.save! | |||||
| @new_attachment.delete | |||||
| end | |||||
| @old_attachment.is_public = is_public == true && @course.is_public == 1 ? 1 : 0 | |||||
| @old_attachment.is_publish = @atta_is_publish | |||||
| @old_attachment.delay_publish = @atta_delay_publish | |||||
| @old_attachment.publish_time = @atta_publish_time | |||||
| @old_attachment.unified_setting = @unified_setting | |||||
| if @unified_setting == 0 | |||||
| attachment_group_setting @old_attachment, params[:group_settings] | |||||
| else | |||||
| @old_attachment.attachment_group_settings.destroy_all | |||||
| end | |||||
| if params[:description] && !params[:description].strip.blank? && params[:description] != @old_attachment.description | |||||
| @old_attachment.description = params[:description] | |||||
| end | |||||
| # @old_attachment.set_public(is_public) | |||||
| # if is_unified_setting | |||||
| # @old_attachment.set_publish_time(publish_time) | |||||
| # @old_attachment.attachment_group_settings.destroy_all | |||||
| # end | |||||
| # if publish_time.blank? && @course.course_groups.size > 0 && !is_unified_setting | |||||
| # @old_attachment.set_course_group_publish_time(@course, course_group_publish_times) | |||||
| # end | |||||
| @old_attachment.save! | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def show | |||||
| return normal_status(403, "您没有权限进行该操作") if !current_user.teacher_of_course?(@course) && current_user != @file.author | |||||
| @attachment_histories = @file.attachment_histories | |||||
| end | |||||
| def histories | |||||
| @user = current_user | |||||
| @file = @course.attachments.find_by_id params[:id] | |||||
| return normal_status(-2, "该课程下没有id为 #{params[:id]}的资源") if @file.nil? | |||||
| return normal_status(403, "您没有权限进行该操作") if @user != @file.author && !@user.teacher_of_course?(@course) && !@file.public? | |||||
| @attachment_histories = @file.attachment_histories | |||||
| end | |||||
| def get_category(course, category_id) | |||||
| if category_id == 0 | |||||
| category = course.attachment_course_modules.first | |||||
| @category_id = category.try(:id) | |||||
| @category_name = category.try(:module_name) | |||||
| else | |||||
| category = CourseSecondCategory.find category_id | |||||
| @category_id = category.try(:id) | |||||
| @category_name = category.try(:name) | |||||
| end | |||||
| end | |||||
| private | |||||
| def find_file | |||||
| @file = Attachment.find params[:id] | |||||
| end | |||||
| def find_attachment_ids(attachment_ids = params[:attachment_ids]) | |||||
| return normal_status(-2, "参数attachment_ids不能为空!") if attachment_ids.blank? | |||||
| return normal_status(-2, "参数attachment_ids格式错误!") if !attachment_ids.is_a? Array | |||||
| end | |||||
| def find_course_second_category_id | |||||
| course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id | |||||
| if course_second_category_id != 0 | |||||
| course_second_category = CourseSecondCategory.find_by(id: course_second_category_id, category_type: "attachment") | |||||
| return normal_status(-2, "未来找到course_second_category为 #{course_second_category_id} 的目录") if course_second_category.nil? | |||||
| end | |||||
| end | |||||
| def find_ids | |||||
| @attachment_ids = params[:ids] || [] | |||||
| find_attachment_ids(@attachment_ids) | |||||
| end | |||||
| def file_validate_sort_type | |||||
| normal_status(-2, "参数sort_type暂时只支持 'created_on', 'quotes', 'downloads'") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip) | |||||
| end | |||||
| def validate_upload_params | |||||
| find_attachment_ids | |||||
| find_course_second_category_id | |||||
| end | |||||
| def publish_params | |||||
| tip_exception("缺少发布参数") if params[:delay_publish].blank? | |||||
| @unified_setting = 1 | |||||
| # if params[:delay_publish].to_i == 1 && @course.course_group_module? && @course.course_groups_count != 0 | |||||
| # tip_exception("分班发布设置不能为空") if params[:group_settings].blank? | |||||
| # min_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).min | |||||
| # max_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).max | |||||
| # tip_exception("分班发布设置不能为空") if min_publish_time.blank? | |||||
| # | |||||
| # # 分班设置中的时间一样且包含所有分班 则按统一设置处理,否则是非统一设置 | |||||
| # @unified_setting = 0 unless min_publish_time == max_publish_time && params[:group_settings].pluck(:group_id).flatten.sort == @course.course_groups.pluck(:id).sort | |||||
| # els | |||||
| if params[:delay_publish].to_i == 1 | |||||
| tip_exception("缺少延期发布的时间参数") if params[:publish_time].blank? | |||||
| min_publish_time = params[:publish_time] | |||||
| end | |||||
| @atta_is_publish = params[:delay_publish].to_i == 1 && min_publish_time.to_time > Time.now ? 0 : 1 | |||||
| @atta_delay_publish = params[:delay_publish].to_i | |||||
| @atta_publish_time = params[:delay_publish].to_i == 1 ? min_publish_time : Time.now | |||||
| end | |||||
| def create_atta_group_settings atta | |||||
| if atta.attachment_group_settings.size != @course.course_groups.size | |||||
| @course.course_groups.where.not(id: atta.attachment_group_settings.pluck(:course_group_id)).each do |group| | |||||
| atta.attachment_group_settings << AttachmentGroupSetting.new(course_group_id: group.id, course_id: @course.id, | |||||
| publish_time: atta.publish_time) | |||||
| end | |||||
| end | |||||
| end | |||||
| def attachment_group_setting attachment, group_setting | |||||
| create_atta_group_settings attachment | |||||
| group_setting.each do |setting| | |||||
| tip_exception("分班id不能为空") if setting[:group_id].length == 0 | |||||
| tip_exception("发布时间不能为空") if setting[:publish_time].blank? | |||||
| AttachmentGroupSetting.where(attachment_id: attachment.id, course_group_id: setting[:group_id]). | |||||
| update_all(publish_time: setting[:publish_time]) | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,5 +1,6 @@ | |||||
| class ForksController < ApplicationController | class ForksController < ApplicationController | ||||
| before_action :require_login, :find_project_with_id | |||||
| before_action :require_login | |||||
| before_action :load_project | |||||
| before_action :authenticate_project!, :authenticate_user! | before_action :authenticate_project!, :authenticate_user! | ||||
| def create | def create | ||||
| @@ -8,8 +9,13 @@ class ForksController < ApplicationController | |||||
| private | private | ||||
| def authenticate_project! | def authenticate_project! | ||||
| return if current_user != @project.owner | |||||
| render_result(1, "自己不能fork自己的项目") | |||||
| if current_user&.id == @project.user_id | |||||
| render_result(-1, "自己不能fork自己的项目") | |||||
| elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier) | |||||
| render_result(-1, "fork失败,你已拥有了这个项目") | |||||
| end | |||||
| # return if current_user != @project.owner | |||||
| # render_result(-1, "自己不能fork自己的项目") | |||||
| end | end | ||||
| def authenticate_user! | def authenticate_user! | ||||
| @@ -1,84 +0,0 @@ | |||||
| class GitsController < ApplicationController | |||||
| skip_before_action :check_sign | |||||
| # 说明: | |||||
| # 以下Git认证只针对新版git,Gitlab的Git认证不走该控制器 | |||||
| # 思路: | |||||
| # 1、用户通过Git客户端推送代码的时候,这个时候Git客户端肯定会强制用户输入邮箱的 | |||||
| # 2、通过web端版本库界面更新代码(如果用户邮箱不存在,则用系统备用邮箱) | |||||
| # 供 git-workhorse反向调用认证 | |||||
| def auth | |||||
| # HTTP_AUTHORIZATION: "Basic 这里base64编码的的密码(user:passwd)" | |||||
| decodes = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z) | |||||
| rand_code = decodes.sample(10).join | |||||
| logger.info("11111112222223333 HTTP_AUTHORIZATION: #{request.env["HTTP_AUTHORIZATION"]}") | |||||
| logger.info("1111111 git auth start: code is #{rand_code}, time is #{Time.now}") | |||||
| # logger.info("#########-----request_env: #{request.env}") | |||||
| # {"service"=>"git-receive-pack", "controller"=>"gits", "action"=>"auth", | |||||
| # "url"=>"forge01/cermyt39.git/info/refs"} | |||||
| # | |||||
| gituser = edu_setting('git_username') | |||||
| gitpassword = edu_setting('git_password') | |||||
| result = false | |||||
| if request.env["HTTP_AUTHORIZATION"] && request.env["HTTP_AUTHORIZATION"].split(" ").length == 2 | |||||
| username_password = Base64.decode64(request.env["HTTP_AUTHORIZATION"].split(" ")[1]) | |||||
| if username_password.split(":")[0].nil? || username_password.split(":")[1].nil? | |||||
| result = false | |||||
| else | |||||
| input_username = username_password.split(":")[0].strip() | |||||
| input_password = username_password.split(":")[1].strip() | |||||
| uid_logger("git start auth: input_username is #{input_username}") | |||||
| # Git 超级权限用户 | |||||
| if input_username.strip == gituser.strip && input_password.strip == gitpassword.strip | |||||
| result = true | |||||
| else | |||||
| # 用户是否对对象拥有权限 | |||||
| system_user = User.find_by_login(input_username) || User.find_by_mail(input_username) || User.find_by_phone(input_username) | |||||
| # 如果用户名密码错误 | |||||
| if system_user.blank? || system_user && !system_user.check_password?(input_password) | |||||
| uid_logger_error("git start: password is wrong") | |||||
| result = false | |||||
| else | |||||
| git_url = params["url"] | |||||
| username = git_url.split("/")[0] | |||||
| shixunname = git_url.split("/")[1].split(".")[0] | |||||
| repo_name = username + "/" + shixunname | |||||
| uid_logger("git start: repo_name is #{repo_name}") | |||||
| shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).where(repo_name: repo_name).first | |||||
| if shixun.blank? | |||||
| shixun_id = ShixunSecretRepository.where(repo_name: repo_name).pluck(:shixun_id).first | |||||
| logger.info("####repo_name:#{repo_name}") | |||||
| logger.info("####shixun_id:#{shixun_id}") | |||||
| shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).find_by(id: shixun_id) | |||||
| end | |||||
| uid_logger("git start auth: shixun identifier is #{shixun.try(:identifier)}") | |||||
| uid_logger("git start auth: systemuser is #{system_user.try(:login)}") | |||||
| if shixun.present? | |||||
| logger.info("#######{system_user.manager_of_shixun?(shixun)}") | |||||
| if system_user.present? && system_user.manager_of_shixun?(shixun) | |||||
| result = true | |||||
| else | |||||
| uid_logger_error("gituser is not shixun manager") | |||||
| result = false | |||||
| end | |||||
| else | |||||
| uid_logger_error("shixun is not exist") | |||||
| # result = false | |||||
| result = true # 为了测试跳出 | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| authenticate_or_request_with_http_basic do |username, password| | |||||
| result | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,755 +0,0 @@ | |||||
| class GraduationTasksController < ApplicationController | |||||
| before_action :require_login, :check_auth, except: [:index] | |||||
| before_action :find_course, except: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment, | |||||
| :cross_comment_setting, :assign_works, :commit_comment_setting, :sonar] | |||||
| before_action :find_task, only: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment, | |||||
| :cross_comment_setting, :assign_works, :commit_comment_setting, :sonar] | |||||
| before_action :user_course_identity | |||||
| before_action :task_publish, only: [:show, :show_comment, :tasks_list, :settings] | |||||
| before_action :teacher_allowed, only: [:new, :create, :edit, :update, :set_public,:multi_destroy, :publish_task, :end_task, | |||||
| :update_settings, :add_to_bank, :cross_comment_setting, :assign_works, :commit_comment_setting] | |||||
| before_action :require_id_params, only: [:set_public ,:multi_destroy, :publish_task, :end_task, :add_to_bank] | |||||
| before_action :valid_params, only: [:update_settings] | |||||
| before_action :allow_cross_comment, only: [:cross_comment_setting, :assign_works, :commit_comment_setting] | |||||
| include ExportHelper | |||||
| def index | |||||
| search = "#{params[:search].to_s.strip.downcase}" | |||||
| order = params[:order] | |||||
| page = params[:page] ? params[:page].to_i : 1 | |||||
| default_order = "IF(ISNULL(graduation_tasks.publish_time),0,1), graduation_tasks.publish_time DESC, graduation_tasks.created_at DESC" | |||||
| @identity = current_user.course_identity(@course) | |||||
| if @identity < Course::STUDENT | |||||
| @tasks = @course.graduation_tasks.where("graduation_tasks.name like ?", "%#{search}%") | |||||
| else | |||||
| @tasks = @course.graduation_tasks.where("graduation_tasks.name like ? and publish_time <= '#{Time.now}'", "%#{search}%") | |||||
| end | |||||
| if order.present? && order != "all" | |||||
| if @course.is_end | |||||
| @tasks = @tasks.none | |||||
| elsif order.to_i == 4 # 补交 | |||||
| @tasks = @tasks.where("status > 1 and allow_late = 1 and (late_time is null or late_time > '#{Time.now}')") | |||||
| else | |||||
| @tasks = @tasks.where(status: order) | |||||
| end | |||||
| end | |||||
| @member = @course.course_members.find_by(user_id: current_user.id, is_active: 1) | |||||
| @all_count = @course.graduation_tasks.size | |||||
| @published_count = @course.graduation_tasks.where("publish_time <= '#{Time.now}'").size | |||||
| @task_count = @tasks.size | |||||
| @tasks = @tasks.reorder("#{default_order}").page(page).per(15).includes(:graduation_works) | |||||
| end | |||||
| # 任务问答 | |||||
| def show | |||||
| @attachments = @task.attachments | |||||
| @current_user = current_user | |||||
| end | |||||
| # 毕设任务列表 | |||||
| def tasks_list | |||||
| # 搜索栏数据 | |||||
| @current_user = current_user | |||||
| # 分页参数 | |||||
| page = params[:page] || 1 | |||||
| limit = params[:limit] || 20 | |||||
| @work = @task.graduation_works.where(user_id: current_user.id) | |||||
| @students = @course.students | |||||
| @assign_power = @user_course_identity < Course::STUDENT && @task.cross_comment && @task.comment_status == 2 | |||||
| #end_time @task.allow_late ? @task.late_time : @task.end_time | |||||
| # 任务发布的情况下: 是老师身份或者任务已截止的情况下公开任务了作品设置的学生也能查看其他人的作品 | |||||
| if @task.published? && (@user_course_identity < Course::STUDENT || | |||||
| (@user_course_identity == Course::STUDENT && @work.present? && @work.take.work_status > 0 && | |||||
| ((!@task.allow_late && @task.status > 1) || (@task.allow_late && @task.late_time && @task.late_time < Time.now)) && | |||||
| (@task.open_work || @task.open_score))) | |||||
| _tasks_list | |||||
| # 排序 | |||||
| rorder = params[:order].blank? ? "update_time" : params[:order] | |||||
| b_order = params[:b_order].blank? ? "desc" : params[:b_order] | |||||
| if rorder == "update_time" || 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 | |||||
| @view_work = @task.open_work || @user_course_identity < Course::STUDENT | |||||
| @work_count = @work_list.count | |||||
| @work_excel = @work_list | |||||
| @work_list = @work_list.page(page).per(limit) | |||||
| if params[:format] == "xlsx" | |||||
| complete_works = @work_excel.where("work_status > 0").size | |||||
| if @user_course_identity >= Course::STUDENT | |||||
| tip_exception(403, "无权限操作") | |||||
| elsif complete_works == 0 | |||||
| normal_status(-1,"暂无用户提交") | |||||
| elsif params[:export].present? && params[:export] | |||||
| normal_status(0,"正在下载中") | |||||
| else | |||||
| respond_to do |format| | |||||
| format.xlsx{ | |||||
| set_export_cookies | |||||
| graduation_work_to_xlsx(@work_excel,@task,current_user) | |||||
| task_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@task.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" | |||||
| render xlsx: "#{task_export_name_.strip}",template: "graduation_tasks/tasks_list.xlsx.axlsx",locals: {table_columns:@head_cells_column, task_users:@task_cells_column} | |||||
| } | |||||
| end | |||||
| end | |||||
| elsif params[:format] == "zip" | |||||
| if @user_course_identity >= Course::STUDENT | |||||
| tip_exception(403, "无权限操作") | |||||
| else | |||||
| zip_works = @work_excel.where("work_status > 0") | |||||
| status = checkfileSize(zip_works) | |||||
| if status == 0 | |||||
| if params[:export].present? && params[:export] | |||||
| normal_status(0,"正在下载中") | |||||
| else | |||||
| respond_to do |format| | |||||
| format.zip{ | |||||
| set_export_cookies | |||||
| zipfile = zip_homework_common @task, zip_works | |||||
| file = decode64(zipfile[0][:base64file]) | |||||
| send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip' | |||||
| } | |||||
| end | |||||
| end | |||||
| else | |||||
| normal_status(status,status == -2 ? "500M" : "无附件可下载") | |||||
| end | |||||
| end | |||||
| end | |||||
| else | |||||
| @work_list = !@task.published? ? [] : @work | |||||
| @view_work = false | |||||
| @work_count = @work_list.count | |||||
| @all_work_count = @work_list.count | |||||
| if params[:format] == "xlsx" || params[:format] == "zip" | |||||
| normal_status(-1,"毕设任务未发布") | |||||
| end | |||||
| end | |||||
| end | |||||
| # 评论列表接口、 包含一级和二级评论的获取 | |||||
| def show_comment | |||||
| @page = params[:page] || 1 | |||||
| @limit = params[:limit] || 10 | |||||
| @parent = params[:parent_id] | |||||
| @current_user = current_user | |||||
| @messages = @task.journals_for_messages | |||||
| @messages_count = @messages.count | |||||
| if @parent | |||||
| @messages = @messages.where(m_parent_id: @parent).order("created_on asc") | |||||
| else | |||||
| @messages = @messages.parent_comment.order("created_on desc") | |||||
| end | |||||
| @messages = @messages.page(@page).per(@limit) | |||||
| end | |||||
| def create | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @graduation_task = GraduationTask.new(graduation_task_params) | |||||
| @graduation_task.course_id = @course.id | |||||
| @graduation_task.user_id = current_user.id | |||||
| @graduation_task.base_on_project = @graduation_task.task_type == 2 ? 1 : 0 | |||||
| if @graduation_task.save! | |||||
| # 为学生创建作品 | |||||
| @graduation_task.create_work_list | |||||
| Attachment.associate_container(params[:attachment_ids], @graduation_task.id, @graduation_task.class) if params[:attachment_ids] | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def new | |||||
| left_banner_content = @course.course_modules.search_by_module_type("graduation") | |||||
| if left_banner_content.present? | |||||
| banner = left_banner_content.first.course_second_categories.last | |||||
| @left_banner_id = banner.id | |||||
| @left_banner_name = banner.name | |||||
| else | |||||
| normal_status(-1,"左侧导航不存在!") | |||||
| end | |||||
| end | |||||
| def edit | |||||
| left_banner_content = @course.course_modules.search_by_module_type("graduation") | |||||
| if left_banner_content.present? | |||||
| banner = left_banner_content.first.course_second_categories.last | |||||
| @left_banner_id = banner.id | |||||
| @left_banner_name = banner.name | |||||
| end | |||||
| end | |||||
| def update | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @task.update_attributes(graduation_task_params) | |||||
| Attachment.associate_container(params[:attachment_ids], @task.id, @task.class) if params[:attachment_ids] | |||||
| normal_status(0, "更新成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # 代码检测 | |||||
| def sonar | |||||
| tip_exception(403, "无权限访问") unless current_user.admin_or_business? | |||||
| _tasks_list | |||||
| @work_list = @work_list.where("work_status > 0") | |||||
| person_list = @work_list.map do |work| | |||||
| o = { | |||||
| name: "#{work.user&.real_name}", | |||||
| uid: "#{work.user&.student_id}", | |||||
| downloadUrl: '' | |||||
| } | |||||
| attachment = work.attachments.last | |||||
| if attachment | |||||
| o[:downloadUrl] = "#{edu_setting('host_name')}"+download_url(attachment) | |||||
| end | |||||
| o | |||||
| end | |||||
| filename = "#{@task.name}_#{Time.now.strftime('%Y%m%d%H%M%S')}.json" | |||||
| json = File.open("/tmp/#{filename}", "w+") | |||||
| json.puts(person_list.to_json) | |||||
| json.close | |||||
| send_file json.path, filename: filename | |||||
| end | |||||
| # 设为公开 | |||||
| def set_public | |||||
| tip_exception("仅公开课堂才能公开毕设任务") if @course.is_public == 0 | |||||
| tasks = @course.graduation_tasks.where(id: params[:task_ids]) | |||||
| tasks.update_all(is_public: 1) | |||||
| normal_status(0, "更新成功") | |||||
| end | |||||
| # 删除多个任务 | |||||
| def multi_destroy | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| tasks = @course.graduation_tasks.where(id: params[:task_ids]) | |||||
| tasks.destroy_all | |||||
| # 这些写是因为model中的关联删除无法删除is_delete=0的作品 | |||||
| GraduationWork.where(graduation_work_id: tasks.pluck(:id)).destroy_all | |||||
| normal_status(0, "删除成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # 加入题库 | |||||
| def add_to_bank | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| tasks = @course.graduation_tasks.where(id: params[:task_ids]) | |||||
| tasks.each do |task| | |||||
| task_bank = current_user.gtask_banks.find_by(graduation_task_id: task.id) | |||||
| # 已加入的更新,未加入的新建 | |||||
| if task_bank.present? | |||||
| task_bank.update_attributes(name: task.name, description: task.description, course_list_id: @course.course_list_id, | |||||
| min_num: task.min_num, max_num: task.max_num, base_on_project: task.base_on_project) | |||||
| task_bank.attachments.destroy_all | |||||
| else | |||||
| task_bank = GtaskBank.new(name: task.name, description: task.description, user_id: current_user.id, | |||||
| task_type: task.task_type, quotes: 1, graduation_task_id: task.id, | |||||
| min_num: task.min_num, max_num: task.max_num, base_on_project: task.base_on_project, | |||||
| course_list_id: @course.course_list_id) | |||||
| task_bank.save! | |||||
| task.update_attributes!(gtask_bank_id: task_bank.id) | |||||
| end | |||||
| task.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = task_bank.user_id | |||||
| att.copy_from = attachment.id | |||||
| task_bank.attachments << att | |||||
| end | |||||
| end | |||||
| normal_status(0,"加入题库成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def publish_task | |||||
| tip_exception("缺少截止时间参数") if params[:end_time].blank? | |||||
| tip_exception("截止时间必须晚于当前时间") if params[:end_time] <= strf_time(Time.now) | |||||
| tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if | |||||
| @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) | |||||
| # ActiveRecord::Base.transaction do | |||||
| begin | |||||
| tasks = @course.graduation_tasks.where(id: params[:task_ids], status: 0). | |||||
| where("publish_time is null or publish_time > '#{Time.now}'") | |||||
| tasks.each do |task| | |||||
| task.publish_time = Time.now | |||||
| task.status = 1 | |||||
| task.end_time = params[:end_time] | |||||
| # 补交结束时间 | |||||
| task.late_time = Time.at(task.end_time.to_i + 30*24*3600) if task.allow_late && task.late_time.nil? | |||||
| task.save! | |||||
| GraduationTaskPublishNotifyJob.perform_later(task.id) | |||||
| task.act_as_course_activity | |||||
| end | |||||
| normal_status(0, "发布成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| # end | |||||
| end | |||||
| def end_task | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| tasks = @course.graduation_tasks.where(id: params[:task_ids], status: 1) | |||||
| tasks.each do |task| | |||||
| task.end_time = Time.now | |||||
| task.status = 2 | |||||
| task.save! | |||||
| end | |||||
| normal_status(0, "更新成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def settings | |||||
| @current_user = current_user | |||||
| end | |||||
| def update_settings | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| unless @course.is_end | |||||
| # 分组设置 已有提交作品或关联项目的,则“基于项目实施”不能修改, 已有提交作品的人数限制的范围只能扩大,不能缩小 | |||||
| if @task.task_type == 2 | |||||
| @task.min_num = @task.student_commit_works ? (params[:min_num].to_i > @task.min_num ? @task.min_num : params[:min_num]) | |||||
| : params[:min_num] | |||||
| @task.max_num = @task.student_commit_works ? (params[:max_num].to_i < @task.max_num ? @task.max_num : params[:max_num]) | |||||
| : params[:max_num] | |||||
| unless @task.student_relate_projects | |||||
| tip_exception("base_on_project参数不能为空") if params[:base_on_project].blank? | |||||
| @task.base_on_project = params[:base_on_project].to_i | |||||
| end | |||||
| end | |||||
| # 发布设置 | |||||
| if @task.status == 0 | |||||
| tip_exception("发布时间不能为空") if params[:publish_time].blank? | |||||
| tip_exception("截止时间不能为空") if params[:end_time].blank? | |||||
| tip_exception("发布时间不能早于当前时间") if params[:publish_time].to_time <= Time.now | |||||
| tip_exception("截止时间不能早于当前时间") if params[:end_time].to_time <= Time.now | |||||
| tip_exception("截止时间必须晚于发布时间") if params[:publish_time].to_time >= params[:end_time].to_time | |||||
| tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if | |||||
| @course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day | |||||
| @task.publish_time = params[:publish_time] | |||||
| @task.end_time = params[:end_time] | |||||
| if @task.publish_time <= Time.now | |||||
| @task.status = 1 | |||||
| send_tiding = true | |||||
| end | |||||
| elsif @task.status < 2 | |||||
| tip_exception("截止时间不能为空") if params[:end_time].blank? | |||||
| tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S") | |||||
| tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if | |||||
| @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) | |||||
| @task.end_time = params[:end_time] | |||||
| end | |||||
| # 补交设置 | |||||
| # @task.allow_late = params[:allow_late] | |||||
| # @task.late_penalty = params[:allow_late].to_i == 1 ? params[:late_penalty] : 0 | |||||
| current_late_penalty = @task.late_penalty | |||||
| if params[:allow_late].to_i == 1 | |||||
| tip_exception("补交结束时间不能为空") if params[:late_time].blank? | |||||
| tip_exception("补交结束时间不能早于截止时间") if params[:late_time] <= @task.end_time | |||||
| tip_exception("补交结束时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if | |||||
| @course.end_date.present? && params[:late_time] > strf_time(@course.end_date.end_of_day) | |||||
| tip_exception("迟交扣分应为正整数") if params[:late_penalty] && params[:late_penalty].to_i < 0 | |||||
| @task.allow_late = true | |||||
| @task.late_time = params[:late_time] | |||||
| @task.late_penalty = params[:late_penalty].to_i | |||||
| else | |||||
| @task.allow_late = false | |||||
| @task.late_penalty = 0 | |||||
| end | |||||
| # 迟交扣分有变动则更新迟交学生的成绩 | |||||
| if @task.late_penalty != current_late_penalty | |||||
| @task.graduation_works.where(work_status: 2).each do |work| | |||||
| work.late_penalty = @task.late_penalty | |||||
| work.save! | |||||
| end | |||||
| end | |||||
| # 评分设置 | |||||
| unless @task.cross_comment && @task.comment_time && @task.comment_time < Time.now | |||||
| @task.cross_comment = params[:cross_comment].to_i | |||||
| tip_exception("评阅时间不能为空") if @task.cross_comment && params[:comment_time].blank? | |||||
| tip_exception("评阅时间应当大于截止时间") if @task.cross_comment && params[:comment_time] <= @task.end_time | |||||
| @task.comment_time = @task.cross_comment ? params[:comment_time] : nil | |||||
| @task.comment_status = 2 if @task.cross_comment && @task.comment_status == 0 | |||||
| @task.graduation_work_comment_assignations.destroy_all if !@task.cross_comment | |||||
| # 去掉评阅设置 | |||||
| # @task.comment_num = @task.cross_comment ? params[:comment_num].to_i : 3 | |||||
| # @task.comment_status = @task.cross_comment ? params[:comment_status] : 0 | |||||
| # if @task.cross_comment && params[:comment_status].to_i == 4 | |||||
| # tip_exception("评阅数不能为空") if params[:comment_num].blank? | |||||
| # tip_exception("评阅数应大于0") if params[:comment_num].to_i < 1 | |||||
| # | |||||
| # @course.graduation_groups.each_with_index do |group, index| | |||||
| # ass_group = @task.graduation_task_group_assignations.find_by(graduation_group_id: group.id) | |||||
| # if ass_group.present? && params[:comment_group][index].present? && params[:comment_group][index] != "0" | |||||
| # ass_group.update_attributes(assign_graduation_group_id: params[:comment_group][index]) | |||||
| # else | |||||
| # @task.graduation_task_group_assignations << GraduationTaskGroupAssignation.new(graduation_group_id: group.id, | |||||
| # assign_graduation_group_id: params[:comment_group][index]) | |||||
| # end | |||||
| # end | |||||
| # end | |||||
| end | |||||
| # 公开设置 | |||||
| @task.open_work = params[:open_work] ? params[:open_work].to_i : 0 | |||||
| @task.open_score = params[:open_score] ? params[:open_score].to_i : 0 | |||||
| @task.save! | |||||
| if send_tiding | |||||
| GraduationTaskPublishNotifyJob.perform_later(@task.id) | |||||
| @task.act_as_course_activity | |||||
| end | |||||
| normal_status(0, "更新成功") | |||||
| else | |||||
| tip_exception("课堂已结束不能再更新") | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def cross_comment_setting | |||||
| @comment_status = params[:comment_status] || (@task.cross_comment ? @task.comment_status : 2) | |||||
| group_ids = @course.charge_group_ids(current_user) | |||||
| @course_groups = @course.course_groups.where(id: group_ids) | |||||
| # 如果传了分班id则取合集 | |||||
| group_ids = group_ids & params[:group_ids].map(&:to_i) unless params[:group_ids].blank? | |||||
| page = params[:page] ? params[:page].to_i : 1 | |||||
| limit = params[:limit] ? params[:limit].to_i : 10 | |||||
| # 取所有课堂的作品 | |||||
| if group_ids.sort == @course.course_groups.pluck(:id).sort | |||||
| @work_list = @task.graduation_works | |||||
| else | |||||
| @work_list = @task.graduation_works.joins("join course_members on graduation_works.user_id=course_members.user_id"). | |||||
| where(course_members: {course_group_id: group_ids}) | |||||
| end | |||||
| @user_count = @work_list.size | |||||
| @work_list = @work_list.page(page).per(limit).includes(user: [:user_extension]) | |||||
| @students = @course.students.where(user_id: @work_list.pluck(:user_id)) | |||||
| end | |||||
| def assign_works | |||||
| tip_exception("请先选择作品") if params[:work_ids].blank? | |||||
| tip_exception("请指定要分配的老师或答辩组") if params[:user_ids].blank? && params[:graduation_group_ids].blank? | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| works = @task.graduation_works.where(id: params[:work_ids]) | |||||
| # 手动分配:分配给老师 | |||||
| if !params[:user_ids].blank? | |||||
| @task.update_attributes(comment_status: 2) | |||||
| works.each do |work| | |||||
| # 之前分配的老师但现在未分配时需要删除 | |||||
| work.graduation_work_comment_assignations.where.not(user_id: params[:user_ids]).destroy_all | |||||
| @course.teachers.where(user_id: params[:user_ids]).pluck(:user_id).uniq.each do |user_id| | |||||
| unless work.graduation_work_comment_assignations.exists?(user_id: user_id) | |||||
| GraduationWorkCommentAssignation.create!(graduation_task_id: @task.id, graduation_work_id: work.id, | |||||
| user_id: user_id) | |||||
| end | |||||
| end | |||||
| end | |||||
| # 答辩组分配:分配答辩组 | |||||
| elsif !params[:graduation_group_ids].blank? | |||||
| @task.update_attributes(comment_status: 4) | |||||
| works.each do |work| | |||||
| work.graduation_task_group_assignations.where.not(graduation_group_id: params[:graduation_group_ids]).destroy_all | |||||
| @course.graduation_groups.where(id: params[:graduation_group_ids]).pluck(:id).uniq.each do |graduation_group_id| | |||||
| unless work.graduation_task_group_assignations.exists?(graduation_group_id: graduation_group_id) | |||||
| GraduationTaskGroupAssignation.create!(graduation_task_id: @task.id, graduation_work_id: work.id, | |||||
| graduation_group_id: graduation_group_id) | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| normal_status("分配成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def commit_comment_setting | |||||
| tip_exception("type参数有误") if params[:type].blank? || !["commit", "cancel"].include?(params[:type]) | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 提交弹框 | |||||
| # if params[:type] == "commit" | |||||
| # tip_exception("comment_status参数有误") if params[:comment_status].blank? || ![2, 4].include?(params[:comment_status].to_i) | |||||
| # @task.update_attributes(comment_status: params[:comment_status]) | |||||
| # if params[:comment_status].to_i == 2 | |||||
| # @task.temporary_graduation_work_comment_assignations.update_all(temporary: 0) # 临时数据转正 | |||||
| # @task.delete_graduation_work_comment_assignations.destroy_all # 删除置了删除位的数据 | |||||
| # @task.graduation_task_group_assignations.destroy_all # 删除答辩组分配数据 | |||||
| # else | |||||
| # @task.temporary_graduation_task_group_assignations.update_all(temporary: 0) | |||||
| # @task.delete_graduation_task_group_assignations.destroy_all | |||||
| # @task.graduation_work_comment_assignations.destroy_all | |||||
| # | |||||
| # GraduationTaskCrossCommentJob.perform_later(@task.id) | |||||
| # end | |||||
| # else | |||||
| # # 取消时删除临时数据,恢复删除位数据 | |||||
| # @task.temporary_graduation_work_comment_assignations.destroy_all # 删除临时数据 | |||||
| # @task.delete_graduation_work_comment_assignations.update_all(temporary: 0) # 恢复置了删除位的数据 | |||||
| # | |||||
| # @task.temporary_graduation_task_group_assignations.destroy_all # 删除临时数据 | |||||
| # @task.delete_graduation_task_group_assignations.update_all(temporary: 0) # 恢复置了删除位的数据 | |||||
| # end | |||||
| normal_status("操作成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| private | |||||
| def find_task | |||||
| begin | |||||
| @task = GraduationTask.find(params[:id]) | |||||
| @course = @task.course | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception("id不存在") | |||||
| end | |||||
| end | |||||
| # 未发布时非老师角色不能访问,发布后非课堂成员不能访问未公开的任务 | |||||
| def task_publish | |||||
| if (@user_course_identity >= Course::STUDENT && @task.status < 1) || | |||||
| (@user_course_identity > Course::STUDENT && (@course.is_public == 0 || !@task.is_public)) | |||||
| tip_exception(-1,"任务还未发布,无法查看") | |||||
| end | |||||
| end | |||||
| def graduation_task_params | |||||
| tip_exception("类型参数不能为空") if params[:task_type].blank? | |||||
| tip_exception("名称不能为空") if params[:name].blank? | |||||
| tip_exception("名称不能超过60个字符") if params[:name].length > 60 #6.11 -hs | |||||
| tip_exception("描述不能为空") if params[:description].blank? | |||||
| params.require(:graduation_task).permit(:task_type, :name, :description) | |||||
| end | |||||
| def require_id_params | |||||
| tip_exception("请至少选择一个毕设任务") if params[:task_ids].blank? | |||||
| tip_exception("批量设置不能超过15个") if params[:task_ids].length > 15 | |||||
| end | |||||
| def valid_params | |||||
| if @task.task_type == 2 | |||||
| tip_exception("最小人数不能为空") if params[:min_num].blank? | |||||
| tip_exception("最大人数不能为空") if params[:max_num].blank? | |||||
| tip_exception("最小人数不能少于1") if params[:min_num].to_i <= 0 | |||||
| tip_exception("最大人数不能小于最小人数要求") if params[:min_num].to_i > params[:max_num].to_i | |||||
| end | |||||
| end | |||||
| def allow_cross_comment | |||||
| tip_exception("请先开启交叉评阅再设置") unless @task.cross_comment | |||||
| end | |||||
| def _tasks_list | |||||
| # 如有有分班则看分班内的学生,否则看所有学生的作品 | |||||
| user_ids = | |||||
| if @user_course_identity < Course::STUDENT | |||||
| @course.teacher_group_user_ids(current_user.id) | |||||
| else | |||||
| course_group_id = @course.course_member(current_user.id).course_group_id | |||||
| @course.students.where(course_group_id: course_group_id).pluck(:user_id) | |||||
| end | |||||
| @work_list = @task.graduation_works.where(user_id: user_ids).includes(user: [:user_extension]) | |||||
| @all_work_count = @work_list.count | |||||
| @teachers = @course.teachers.where.not(user_id: current_user.id).includes(:user) | |||||
| # 教师评阅搜索 0: 未评, 1 已评 | |||||
| unless params[:teacher_comment].blank? | |||||
| graduation_work_ids = GraduationWorkScore.where(graduation_work_id: @work_list.map(&:id)).pluck(:graduation_work_id) | |||||
| if params[:teacher_comment].to_i == 0 | |||||
| @work_list = @work_list.where("work_status != 0") | |||||
| elsif params[:teacher_comment].to_i == 1 | |||||
| @work_list = @work_list.where("work_status != 0").where(id: graduation_work_ids) | |||||
| end | |||||
| end | |||||
| # 作品状态 0: 未提交, 1 按时提交, 2 延迟提交 | |||||
| unless params[:task_status].blank? | |||||
| @work_list = @work_list.where(work_status: params[:task_status]) | |||||
| end | |||||
| # 分班情况 | |||||
| unless params[:course_group].blank? | |||||
| group_user_ids = @course.students.where(course_group_id: params[:course_group]).pluck(:user_id) | |||||
| # 有分组只可能是老师身份查看列表 | |||||
| @work_list = @work_list.where(user_id: group_user_ids) | |||||
| end | |||||
| # 只看我的交叉评阅 | |||||
| unless params[:cross_comment].blank? | |||||
| 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 = @task.graduation_works.where(id: graduation_work_id) | |||||
| end | |||||
| # 组员、组长作品的筛选 | |||||
| if @task.task_type == 2 && !params[:member_work].blank? | |||||
| if params[:member_work].to_i == 1 | |||||
| @work_list = @work_list.where("user_id = commit_user_id") | |||||
| elsif params[:member_work].to_i == 0 | |||||
| @work_list = @work_list.where("user_id != commit_user_id") | |||||
| end | |||||
| end | |||||
| # 输入姓名和学号搜索 | |||||
| # TODO user_extension 如果修改 请调整 | |||||
| unless params[:search].blank? | |||||
| @work_list = @work_list.joins(user: :user_extension).where("concat(lastname, firstname) like ? | |||||
| or student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") | |||||
| end | |||||
| end | |||||
| # | |||||
| # def graduation_work_to_xls items | |||||
| # xls_report = StringIO.new | |||||
| # book = Spreadsheet::Workbook.new | |||||
| # sheet1 = book.create_worksheet :name => "学生成绩" | |||||
| # blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 | |||||
| # sheet1.row(0).default_format = blue | |||||
| # course = @task.course | |||||
| # count_row = 1 | |||||
| # list = 0 | |||||
| # if @task.task_type == 1 | |||||
| # if @task.cross_comment | |||||
| # sheet1.row(0).concat(["学生id","真实姓名", "登录名", "学号", "电子邮箱", "分班", "作品描述", "教师评分","交叉评分", "迟交扣分", | |||||
| # "成绩", "更新时间"]) | |||||
| # else | |||||
| # sheet1.row(0).concat(["学生id", "真实姓名", "登录名", "学号", "电子邮箱", "分班", "作品描述", "教师评分", "迟交扣分", | |||||
| # "成绩", "更新时间"]) | |||||
| # end | |||||
| # items.each do |work| | |||||
| # sheet1[count_row,list] = work.user.id | |||||
| # sheet1[count_row,list+=1] = work.user.full_name | |||||
| # sheet1[count_row,list+=1] = work.user.login | |||||
| # sheet1[count_row,list+=1] = work.user.student_id | |||||
| # sheet1[count_row,list+=1] = work.user.mail | |||||
| # sheet1[count_row,list+=1] = work.class_grouping_name | |||||
| # sheet1[count_row,list+=1] = strip_html work.description if work.description | |||||
| # sheet1[count_row,list+=1] = work.teacher_score.nil? ? "未评分" : work.teacher_score.round(1) | |||||
| # if @task.cross_comment | |||||
| # sheet1[count_row,list+=1] = work.cross_score.nil? ? "未评分" : work.cross_score.round(1) | |||||
| # end | |||||
| # sheet1[count_row,list+=1] = work.late_penalty | |||||
| # sheet1[count_row,list+=1] = work.respond_to?("work_score") ? work.work_score.nil? ? "未评分" : work.work_score.round(1) : "未评分" | |||||
| # sheet1[count_row,list+=1] = format_time(work.update_time) | |||||
| # count_row += 1 | |||||
| # list = 0 | |||||
| # end | |||||
| # elsif @task.task_type == 2 | |||||
| # if @task.cross_comment | |||||
| # sheet1.row(0).concat(["分组", "组员","分班", "作品描述", "教师评分","交叉评分","迟交扣分", "成绩", "更新时间"]) | |||||
| # else | |||||
| # sheet1.row(0).concat(["分组", "组员","分班", "作品描述", "教师评分", "迟交扣分", "成绩", "更新时间"]) | |||||
| # end | |||||
| # items.each do |work| | |||||
| # sheet1[count_row,list] = work.group_id | |||||
| # sheet1[count_row,list+=1] = work.user.full_name | |||||
| # sheet1[count_row,list+=1] = work.class_grouping_name | |||||
| # sheet1[count_row,list+=1] = strip_html work.description if work.description | |||||
| # sheet1[count_row,list+=1] = work.teacher_score.nil? ? "未评分" : work.teacher_score.round(1) | |||||
| # if @task.cross_comment | |||||
| # sheet1[count_row,list+=1] = work.cross_score.nil? ? "未评分" : work.cross_score.round(1) | |||||
| # end | |||||
| # sheet1[count_row,list+=1] = work.late_penalty | |||||
| # sheet1[count_row,list+=1] = work.respond_to?("work_score") ? work.work_score.nil? ? "未评分" : work.work_score.round(1) : "未评分" | |||||
| # sheet1[count_row,list+=1] = format_time(work.update_time) | |||||
| # count_row += 1 | |||||
| # list = 0 | |||||
| # end | |||||
| # end | |||||
| # book.write xls_report | |||||
| # xls_report.string | |||||
| # end | |||||
| end | |||||
| @@ -1,568 +0,0 @@ | |||||
| class GraduationWorksController < ApplicationController | |||||
| before_action :require_login, :check_auth | |||||
| before_action :find_task, only: [:new, :create, :search_member_list, :check_project, :relate_project, | |||||
| :cancel_relate_project, :delete_work] | |||||
| before_action :find_work, only: [:show, :edit, :update, :revise_attachment, :supply_attachments, :comment_list, | |||||
| :add_score, :delete_score, :adjust_score, :assign_teacher] | |||||
| before_action :user_course_identity | |||||
| before_action :task_public | |||||
| before_action :teacher_allowed, only: [:add_score, :adjust_score, :assign_teacher] | |||||
| before_action :course_student, only: [:new, :create, :edit, :update, :search_member_list, :relate_project, | |||||
| :cancel_relate_project, :delete_work] | |||||
| before_action :my_work, only: [:edit, :update, :revise_attachment] | |||||
| before_action :published_task, only: [:new, :create, :edit, :update, :search_member_list, :relate_project, | |||||
| :cancel_relate_project, :revise_attachment] | |||||
| before_action :edit_duration, only: [:edit, :update, :delete_work] | |||||
| before_action :open_work, only: [:show, :supply_attachments, :comment_list] | |||||
| def new | |||||
| if @task.task_type == 2 && @task.base_on_project | |||||
| work = @task.graduation_works.where(user_id: current_user.id).first | |||||
| if work.present? && (work.work_status != 0 || work.project_id == 0) | |||||
| normal_status(403, "") | |||||
| end | |||||
| end | |||||
| @user = current_user | |||||
| end | |||||
| # 搜索课堂学生 | |||||
| def search_member_list | |||||
| unless params[:search].blank? | |||||
| # 有搜索条件时搜索课堂所有学生包括已提交的 | |||||
| users = User.joins(:graduation_works).where("concat(users.lastname, users.firstname) like ? and | |||||
| graduation_task_id = #{@task.id}", "%#{params[:search]}%") | |||||
| user_ids = users.pluck(:id) - [current_user.id] | |||||
| @members = @course.students.where(user_id: user_ids) | |||||
| else | |||||
| # 没有搜索条件时搜索课堂所有未提交的学生 | |||||
| user_ids = @task.graduation_works.where("work_status = 0").pluck(:user_id) - [current_user.id] | |||||
| @members = @course.students.where(user_id: user_ids) | |||||
| end | |||||
| page = params[:page] ? params[:page].to_i : 1 | |||||
| limit = params[:limit] ? params[:limit].to_i : 10 | |||||
| # todo user_extension | |||||
| @members = @members.page(page).per(limit).includes(:course_group, user: :user_extension) | |||||
| end | |||||
| def delete_work | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| work = @task.graduation_works.find_by!(user_id: params[:user_id]) | |||||
| tip_exception("只有组长才能删除组员") if work.commit_user_id != current_user.id | |||||
| work.update!(description: nil, project_id: 0, late_penalty: 0, work_status: 0, commit_time: nil, | |||||
| update_time: nil, group_id: 0, commit_user_id: nil, final_score: nil, work_score: nil, | |||||
| teacher_score: nil, teaching_asistant_score: nil, update_user_id: nil) | |||||
| work.attachments.destroy_all | |||||
| work.tidings.destroy_all | |||||
| normal_status("删除成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| end | |||||
| end | |||||
| end | |||||
| # 判断项目是否已有其他作品关联上了 | |||||
| def check_project | |||||
| tip_exception("项目id不能为空") if params[:project_id].blank? | |||||
| work = @task.graduation_works.where(project_id: params[:project_id]).first | |||||
| @is_relate = work.present? | |||||
| @relate_user = work.present? ? work.user.real_name : "" | |||||
| end | |||||
| def relate_project | |||||
| tip_exception("项目id不能为空") if params[:project_id].blank? | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 判断项目是否存在且当前用户是项目管理员 | |||||
| project = Project.where(id: params[:project_id]).first | |||||
| member = Member.where(project_id: project.try(:id), user_id: current_user.id).first | |||||
| if project.present? && member.present? && member.member_roles.first.try(:role_id) == 3 | |||||
| work = @task.graduation_works.where("user_id = #{current_user.id}").first || | |||||
| GraduationWork.create(user_id: current_user.id, graduation_task_id: @task.id, course_id: @task.course_id) | |||||
| if work.work_status == 0 && work.project_id == 0 | |||||
| work.update!(project_id: project.id, update_time: Time.now) | |||||
| # 将老师加入项目 | |||||
| project_member = project.members.where(user_id: @task.user_id).first | |||||
| if project_member.present? | |||||
| project_member.member_roles.first.update!(role_id: 3) if project_member.member_roles.first.present? | |||||
| else | |||||
| member = Member.create(user_id: @task.user_id, project_id: project.id) | |||||
| member.member_roles << MemberRole.new(role_id: 3) | |||||
| Tiding.create(user_id: @task.user_id, trigger_user_id: current_user.id, container_id: project.id, | |||||
| container_type: 'ManagerJoinProject', belong_container_id: project.id, | |||||
| belong_container_type: "Project", tiding_type: "System", extra: 3) | |||||
| end | |||||
| normal_status("关联成功") | |||||
| else | |||||
| tip_exception("不能重复关联项目") | |||||
| end | |||||
| else | |||||
| tip_exception("该项目不存在") | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def cancel_relate_project | |||||
| work = @task.graduation_works.where(user_id: current_user.id, work_status: 0).first | |||||
| if work.present? && work.project.present? | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| member = work.project.members.where(user_id: @task.user_id).first | |||||
| member.destroy if member.present? | |||||
| Tiding.where(user_id: @task.user_id, trigger_user_id: current_user.id, container_id: work.project.id, | |||||
| container_type: 'ManagerJoinProject').destroy_all | |||||
| work.update!(project_id: 0) | |||||
| normal_status("取消关联成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| else | |||||
| tip_exception("无法取消关联") | |||||
| end | |||||
| end | |||||
| def create | |||||
| graduation_work = @task.graduation_works.where(user_id: current_user.id).first || | |||||
| GraduationWork.create(user_id: current_user.id, graduation_task_id: @task.id, course_id: @task.course_id) | |||||
| update_check graduation_work | |||||
| tip_exception("作业不可重复提交") if graduation_work.work_status != 0 | |||||
| tip_exception("已过了提交时间") if @course.is_end || (@task.end_time < Time.now && (!@task.allow_late || | |||||
| (@task.late_time.present? && @task.late_time < Time.now))) | |||||
| student_ids = [current_user.id] | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # work.update_attributes(graduation_work_params) | |||||
| graduation_work.description = params[:description] | |||||
| graduation_work.commit_time = Time.now | |||||
| graduation_work.update_time = Time.now | |||||
| graduation_work.commit_user_id = current_user.id | |||||
| graduation_work.update_user_id = current_user.id | |||||
| graduation_work.course_id = @course.id | |||||
| graduation_work.group_id = @task.task_type == 2 ? @task.graduation_works.where("work_status != 0").map(&:group_id).max.to_i + 1 : 0 | |||||
| #提交作品时,计算是否迟交 | |||||
| graduation_work.late_penalty = @task.end_time < Time.now.to_s ? @task.late_penalty : 0 | |||||
| graduation_work.work_status = @task.end_time < Time.now.to_s ? 2 : 1 | |||||
| if graduation_work.save! | |||||
| Attachment.associate_container(params[:attachment_ids], graduation_work.id, graduation_work.class) | |||||
| if @task.task_type == 2 | |||||
| members = (params[:user_ids] || []).collect(&:to_i) - [current_user.id] | |||||
| members = @course.students.pluck(:user_id) & members | |||||
| student_ids += members | |||||
| for i in 0 .. members.count-1 | |||||
| stu_work = @task.graduation_works.where(user_id: members[i].to_i).first || GraduationWork.new | |||||
| stu_work.update!(user_id: members[i].to_i, description: graduation_work.description, | |||||
| graduation_task_id: @task.id, project_id: graduation_work.project_id, | |||||
| late_penalty: graduation_work.late_penalty, work_status: graduation_work.work_status, | |||||
| commit_time: Time.now, update_time: Time.now, group_id: graduation_work.group_id, | |||||
| commit_user_id: current_user.id, update_user_id: current_user.id) | |||||
| stu_work.save! | |||||
| graduation_work.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = attachment.author_id | |||||
| stu_work.attachments << att | |||||
| end | |||||
| end | |||||
| end | |||||
| @task.update_column(:updated_at, Time.now) | |||||
| # todo 更新对应的毕设任务课堂动态 | |||||
| # update_course_activity(@taskhomework.class,@task.id) | |||||
| @work_id = graduation_work.id | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| SubmitGraduationWorkNotifyJob.perform_later(@task.id, student_ids) | |||||
| end | |||||
| end | |||||
| def edit | |||||
| @task_user = current_user | |||||
| if @task.task_type == 2 | |||||
| @commit_user_id = @work.commit_user_id | |||||
| @work_members = @course.students.where(user_id: @task.graduation_works.where(group_id: @work.group_id).pluck(:user_id)). | |||||
| order("course_members.id=#{@work.commit_user_id} desc").includes(:course_group, user: :user_extension) | |||||
| end | |||||
| end | |||||
| def update | |||||
| update_check @work | |||||
| student_ids = [] | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @work.description = params[:description] | |||||
| @work.update_time = Time.now | |||||
| @work.update_user_id = current_user.id | |||||
| # @work.commit_user_id = current_user.id | |||||
| if @work.save! | |||||
| Attachment.associate_container(params[:attachment_ids], @work.id, @work.class) | |||||
| #如果学生作品被打分后修改,应该给老师提示 | |||||
| student_ids << @work.user_id if @work.scored? | |||||
| if @task.task_type == 2 | |||||
| graduation_works = @task.graduation_works.where("group_id = #{@work.group_id} and user_id != #{@work.user_id}") | |||||
| work_user_ids = graduation_works.pluck(:user_id) | |||||
| params_user_ids = (params[:user_ids] || []).collect(&:to_i) - [@work.user_id] | |||||
| params_user_ids = @course.students.pluck(:user_id) & params_user_ids | |||||
| # 原成员更新描述、更新时间以及附件 | |||||
| @task.graduation_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work| | |||||
| work.update!(update_time: Time.now, description: @work.description, update_user_id: current_user.id) | |||||
| work.attachments.destroy_all | |||||
| @work.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = attachment.author_id | |||||
| work.attachments << att | |||||
| end | |||||
| student_ids << work.user_id if work.scored? | |||||
| end | |||||
| # 删除的成员 | |||||
| delete_user_ids = work_user_ids - params_user_ids | |||||
| @task.graduation_works.where(group_id: @work.group_id, user_id: delete_user_ids).each do |work| | |||||
| work.attachments.destroy_all | |||||
| # work.student_works_scores.destroy_all | |||||
| work.tidings.destroy_all | |||||
| end | |||||
| @task.graduation_works.where(group_id: @work.group_id, user_id: delete_user_ids). | |||||
| update_all(work_status: 0, description: nil, late_penalty: 0, commit_time: nil, update_time: nil, | |||||
| final_score: nil, teacher_score: nil, work_score: nil, project_id: 0, group_id: 0, | |||||
| commit_user_id: nil, update_user_id: nil) | |||||
| # 新增加的成员 | |||||
| (params_user_ids - work_user_ids).each do |user_id| | |||||
| stu_work = @task.graduation_works.where(user_id: user_id).empty? ? GraduationWork.new : | |||||
| @task.graduation_works.where(user_id: user_id).first | |||||
| stu_work.update!(user_id: user_id, description: @work.description, graduation_task_id: @task.id, | |||||
| project_id: @work.project_id, late_penalty: @work.late_penalty, | |||||
| work_status: @work.work_status, commit_time: Time.now, update_time: Time.now, | |||||
| group_id: @work.group_id, commit_user_id: @work.commit_user_id, update_user_id: current_user.id) | |||||
| @work.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = attachment.author_id | |||||
| stu_work.attachments << att | |||||
| end | |||||
| student_ids << user_id | |||||
| end | |||||
| end | |||||
| normal_status("更新成功") | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| SubmitGraduationWorkNotifyJob.perform_later(@task.id, student_ids) if student_ids.present? | |||||
| end | |||||
| end | |||||
| def show | |||||
| @current_user = current_user | |||||
| @is_author = @work.user_id == current_user.id | |||||
| @work_members = @task.task_type == 1 ? [] : @task.graduation_works.where.not(user_id: @work.user_id). | |||||
| where(group_id: @work.group_id).includes(:user) | |||||
| @attachments = @work.attachments.where("attachtype != 7 or attachtype is null") | |||||
| end | |||||
| def comment_list | |||||
| @current_user = current_user | |||||
| @last_comment = @work.graduation_work_scores.where(user_id: @current_user.id).last | |||||
| @comment_scores = @work.graduation_work_scores.reorder("created_at desc").includes(:user) | |||||
| end | |||||
| # 给作品评分 | |||||
| def add_score | |||||
| tip_exception("该学生的分数已经过调整,不能再评阅") if @work.ultimate_score | |||||
| tip_exception("分数和评语不能都为空") if params[:score].blank? && params[:comment].blank? | |||||
| tip_exception("分数不能超过0-100") if params[:score] && (params[:score].to_f < 0 || params[:score].to_f > 100) | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 没传score则取上次评分成绩 | |||||
| score = GraduationWorkScore.where(user_id: current_user.id, graduation_work_id: @work.id).last | |||||
| new_score = GraduationWorkScore.new | |||||
| new_score.score = params[:score].blank? ? score.try(:score) : params[:score].to_f | |||||
| new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != "" | |||||
| new_score.user_id = current_user.id | |||||
| new_score.graduation_work_id = @work.id | |||||
| new_score.graduation_task_id = @task.id | |||||
| # 如果作品是未提交的状态则更新为已提交 | |||||
| if !new_score.score.nil? && @work.work_status == 0 | |||||
| @work.update!(work_status: 1, commit_time: Time.now) | |||||
| if @task.task_type == 2 | |||||
| @work.update!(group_id: @task.graduation_works.where("work_status != 0").select("distinct group_id").count + 1) | |||||
| end | |||||
| end | |||||
| if @task.cross_comment && @work.graduation_work_comment_assignations.where(user_id: current_user.id).count > 0 | |||||
| new_score.reviewer_role = 2 | |||||
| else | |||||
| new_score.reviewer_role = 1 | |||||
| end | |||||
| if new_score.save! | |||||
| Attachment.associate_container(params[:attachment_ids], new_score.id, new_score.class) | |||||
| # 该用户的历史评阅无效 | |||||
| score.update_column('is_invalid', true) if score.present? && score.score.present? | |||||
| Tiding.create(user_id: @work.user_id, trigger_user_id: User.current.id, container_id: new_score.id, | |||||
| container_type: "GraduationWorkScore", parent_container_id: @work.id, | |||||
| parent_container_type: "GraduationWork", belong_container_id: @task.course_id, | |||||
| belong_container_type: "Course", viewed: 0, tiding_type: "GraduationTask", extra: new_score.reviewer_role) | |||||
| case new_score.reviewer_role | |||||
| when 1 #教师评分取平均分 | |||||
| ts_score = GraduationWorkScore.find_by_sql("SELECT AVG(score) AS score FROM graduation_work_scores WHERE | |||||
| graduation_work_id = #{@work.id} AND reviewer_role = 1 AND score IS NOT NULL AND is_invalid = 0") | |||||
| @work.teacher_score = ts_score.first.score.nil? ? nil : ts_score.first.score.try(:round, 2).to_f | |||||
| # 分组作业整组同评 | |||||
| if @task.task_type == 2 && params[:same_score] | |||||
| add_graduation_score_to_member @work, @task, new_score | |||||
| end | |||||
| when 2 #交叉评分显示平均分 | |||||
| ts_score = GraduationWorkScore.find_by_sql("SELECT AVG(score) AS score FROM graduation_work_scores WHERE | |||||
| graduation_work_id = #{@work.id} AND reviewer_role = 2 AND score IS NOT NULL AND is_invalid = 0") | |||||
| @work.cross_score = ts_score.first.score.nil? ? nil : ts_score.first.score.try(:round, 2).to_f | |||||
| end | |||||
| @task.update_column('updated_at', Time.now) | |||||
| # update_course_activity(@task.class, @task.id) | |||||
| @work.save! | |||||
| normal_status("提交成功") | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def adjust_score | |||||
| tip_exception("成绩不能为空") if params[:score].blank? | |||||
| tip_exception("成绩不能小于零") if params[:score].to_f < 0 | |||||
| tip_exception("成绩不能大于100") if params[:score].to_f.round(1) > 100 | |||||
| tip_exception("调分原因不能超过100个字符") if params[:comment].present? && params[:comment].length > 100 | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 分数不为空的历史评阅都置为失效 | |||||
| @work.graduation_work_scores.where.not(score: nil).update_all(is_invalid: 1) | |||||
| new_score = GraduationWorkScore.new(graduation_work_id: @work.id, score: params[:score].to_f, | |||||
| graduation_task_id: @task.id, comment: "使用调分功能调整了作业最终成绩:#{params[:comment]}", | |||||
| user_id: User.current.id, reviewer_role: 1, is_ultimate: 1) | |||||
| new_score.save! | |||||
| @work.update!(ultimate_score: 1, work_score: params[:score].to_f) | |||||
| Tiding.create!(user_id: @work.user_id, trigger_user_id: current_user.id, container_id: new_score.id, | |||||
| container_type: "AdjustScore", parent_container_id: @task.id, | |||||
| parent_container_type: "GraduationTask", belong_container_id: @course.id, | |||||
| belong_container_type: 'Course', tiding_type: "GraduationTask") | |||||
| normal_status("调分成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # 删除教师/教辅的评分记录 | |||||
| def delete_score | |||||
| score = @work.graduation_work_scores.where(id: params[:comment_id]).first | |||||
| if score.present? && (score.is_invalid || score.score.nil?) && (score.user == current_user || current_user.admin_or_business?) | |||||
| begin | |||||
| score.destroy | |||||
| normal_status("删除成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| else | |||||
| tip_exception("无法删除") | |||||
| end | |||||
| end | |||||
| def supply_attachments | |||||
| @revise_attachments = @work.attachments.where(attachtype: 7) | |||||
| @last_atta = @revise_attachments.last | |||||
| end | |||||
| def revise_attachment | |||||
| tip_exception("不在补交阶段内") if @course.is_end || @task.end_time > Time.now || !@task.allow_late || | |||||
| (@task.late_time && @task.late_time < Time.now) | |||||
| tip_exception("附件参数有误") if params[:attachment_ids].blank? || !params[:attachment_ids].is_a?(Array) | |||||
| tip_exception("补交附件原因不能为空") if params[:description].blank? | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last | |||||
| if revise_attachment.present? && @work.graduation_work_scores.where("created_at > '#{revise_attachment.created_on}' | |||||
| and score is not null").count == 0 | |||||
| revise_attachment.destroy | |||||
| end | |||||
| Attachment.associate_container(params[:attachment_ids], @work.id, @work.class, 7) | |||||
| revise_attachment = Attachment.where(attachtype: 7, container_id: @work.id, container_type: "GraduationWork").last | |||||
| revise_attachment.update!(description: params[:description]) if revise_attachment.present? | |||||
| @work.update!(update_time: Time.now) | |||||
| normal_status("提交成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # 交叉评阅分配老师 | |||||
| def assign_teacher | |||||
| tip_exception(-1, "user_id不能为空") if params[:user_id].nil? | |||||
| @work_assign_teacher = @work.graduation_work_comment_assignations.find_by(user_id: params[:user_id]) | |||||
| if @work_assign_teacher.present? | |||||
| # graduation_group_id: 已经是答辩组的需要 将答辩组清空 | |||||
| @work_assign_teacher.update!(graduation_group_id: 0) | |||||
| else | |||||
| @work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(graduation_task_id: @task.id, | |||||
| user_id: params[:user_id], | |||||
| graduation_group_id: 0) | |||||
| end | |||||
| normal_status("分配成功") | |||||
| end | |||||
| private | |||||
| def find_task | |||||
| begin | |||||
| @task = GraduationTask.find(params[:graduation_task_id]) | |||||
| @course = @task.course | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception("id不存在") | |||||
| end | |||||
| end | |||||
| def find_work | |||||
| begin | |||||
| @work = GraduationWork.find(params[:id]) | |||||
| @task = @work.graduation_task | |||||
| @course = @task.course | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception("id不存在") | |||||
| end | |||||
| end | |||||
| def task_public | |||||
| tip_exception(403,"没有操作权限") if @user_course_identity > Course::STUDENT && (@course.is_public == 0 || | |||||
| (@course.is_public == 1 && !@task.is_public)) | |||||
| end | |||||
| def course_student | |||||
| tip_exception(403,"没有操作权限") if @user_course_identity != Course::STUDENT | |||||
| end | |||||
| def my_work | |||||
| tip_exception(403,"没有操作权限") if @work.user_id != current_user.id || @work.work_status == 0 | |||||
| end | |||||
| def published_task | |||||
| tip_exception("不能在非提交时间内操作") if @task.status == 0 || (!@task.allow_late && @task.status > 1) || | |||||
| (@task.allow_late && @task.late_time && @task.late_time < Time.now) | |||||
| end | |||||
| def edit_duration | |||||
| tip_exception("已过了修改时间") if @task.end_time && @task.end_time < Time.now | |||||
| end | |||||
| # 作品是否公开 | |||||
| def open_work | |||||
| tip_exception(403,"没有操作权限") unless (@user_course_identity < Course::STUDENT || current_user == @work.user || @task.open_work) | |||||
| end | |||||
| def update_check work | |||||
| tip_exception("作品描述不能为空") if params[:description].blank? | |||||
| if @task.task_type == 2 | |||||
| tip_exception("小组成员不能为空") if params[:user_ids].blank? | |||||
| tip_exception("小组成员人数不合要求") if params[:user_ids].length > @task.max_num || params[:user_ids].length < @task.min_num | |||||
| tip_exception("请先关联项目") if @task.base_on_project && work.project_id == 0 | |||||
| end | |||||
| end | |||||
| def graduation_work_params | |||||
| params.require(:graduation_work).permit(:description) | |||||
| end | |||||
| def add_graduation_score_to_member work, task, new_score | |||||
| graduation_works = task.graduation_works.where("group_id = #{work.group_id} and id != #{work.id} and ultimate_score = 0") | |||||
| graduation_works.each do |st_work| | |||||
| st_score = GraduationWorkScore.new(user_id: new_score.user_id, score: new_score.score, | |||||
| reviewer_role: new_score.reviewer_role, comment: new_score.comment) | |||||
| st_work.graduation_work_scores << st_score | |||||
| score = GraduationWorkScore.where(user_id: new_score.user_id, graduation_work_id: st_work.id).last | |||||
| # 该用户的历史评阅无效 | |||||
| score.update_column('is_invalid', true) if score.present? && score.score.present? | |||||
| teacher_score = GraduationWorkScore.find_by_sql("SELECT AVG(score) AS score FROM graduation_work_scores WHERE | |||||
| graduation_work_id = #{work.id} AND reviewer_role = 1 AND score IS NOT NULL AND is_invalid = 0") | |||||
| st_work.teacher_score = teacher_score.first.score.nil? ? nil : teacher_score.first.score.try(:round, 2).to_f | |||||
| st_work.save! | |||||
| Tiding.create(user_id: st_work.user_id, trigger_user_id: User.current.id, container_id: st_score.id, | |||||
| container_type: "GraduationWorkScore", parent_container_id: st_work.id, | |||||
| parent_container_type: "GraduationWork", belong_container_id: task.course_id, | |||||
| belong_container_type: "Course", viewed: 0, tiding_type: "GraduationTask", extra: st_score.reviewer_role) | |||||
| # 评阅附件的复制 | |||||
| new_score.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = st_score.user_id | |||||
| st_score.attachments << att | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,38 +0,0 @@ | |||||
| class GtopicBanksController < ApplicationController | |||||
| before_action :require_login | |||||
| before_action :find_bank, :bank_visit_auth | |||||
| before_action :bank_admin, only: [:edit, :update] | |||||
| def show | |||||
| @bank_attachments = @bank.attachments | |||||
| end | |||||
| def edit | |||||
| @attachments = @bank.attachments | |||||
| end | |||||
| def update | |||||
| ActiveRecord::Base.transaction do | |||||
| @bank.update_attributes(gtopic_bank_params) | |||||
| Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids] | |||||
| normal_status(0, "更新成功") | |||||
| end | |||||
| end | |||||
| private | |||||
| def find_bank | |||||
| @bank = GtopicBank.find_by!(id: params[:id]) | |||||
| end | |||||
| def bank_admin | |||||
| tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin_or_business? | |||||
| end | |||||
| def gtopic_bank_params | |||||
| tip_exception("name参数不能为空") if params[:gtopic_bank][:name].blank? | |||||
| tip_exception("description参数不能为空") if params[:gtopic_bank][:description].blank? | |||||
| params.require(:gtopic_bank).permit(:name, :topic_type, :topic_source, :topic_property_first, :description, | |||||
| :topic_property_second, :source_unit, :topic_repeat, :province, :city) | |||||
| end | |||||
| end | |||||
| @@ -1,220 +0,0 @@ | |||||
| class HackUserLastestCodesController < ApplicationController | |||||
| before_action :require_login, except: [:listen_result] | |||||
| before_action :find_my_hack, only: [:show, :code_debug, :code_submit, :update_code, :sync_code, :add_notes, | |||||
| :listen_result, :result, :submit_records, :restore_initial_code] | |||||
| before_action :update_user_hack_status, only: [:code_debug, :code_submit] | |||||
| before_action :require_auth_identity, only: [:add_notes] | |||||
| before_action :require_manager_identity, only: [:show, :update_code, :restore_initial_code, :sync_code] | |||||
| skip_before_action :check_sign, only: [:listen_result] | |||||
| def show | |||||
| @my_hack.update_attribute(:submit_status, 0) if @my_hack.submit_status == 1 | |||||
| @modify = @my_hack.modify_time.to_i < @hack.hack_codes.first.modify_time.to_i | |||||
| end | |||||
| def update_code | |||||
| @my_hack.update_attribute(:code, params[:code]) | |||||
| render_ok | |||||
| end | |||||
| # 恢复初始代码 | |||||
| def restore_initial_code | |||||
| @my_hack.update_attribute(:code, @hack.code) | |||||
| end | |||||
| # 同步代码 | |||||
| def sync_code | |||||
| @my_hack.update_attributes(code: @hack.code, modify_time: Time.now) | |||||
| end | |||||
| # 调试代码 | |||||
| def code_debug | |||||
| exec_mode = "debug" | |||||
| error_status = 501 | |||||
| error_msg = "debug_error" | |||||
| oj_evaluate exec_mode, error_status, error_msg | |||||
| render_ok | |||||
| end | |||||
| # 提交 | |||||
| def code_submit | |||||
| exec_mode = "submit" | |||||
| error_status = 502 | |||||
| error_msg = "submit_error" | |||||
| oj_evaluate exec_mode, error_status, error_msg | |||||
| render_ok | |||||
| end | |||||
| # 提交结果显示 | |||||
| def result | |||||
| if @my_hack.submit_status == 1 | |||||
| render json: {status: 1, message: "正在评测中"} | |||||
| else | |||||
| @mode = params[:mode] | |||||
| @result = | |||||
| if @mode == "submit" | |||||
| @my_hack.hack_user_codes.last | |||||
| elsif @mode == "debug" | |||||
| @my_hack.hack_user_debug | |||||
| end | |||||
| end | |||||
| end | |||||
| # 提交记录 | |||||
| def submit_records | |||||
| records = @my_hack.hack_user_codes | |||||
| @records_count = records.count | |||||
| @records = paginate records.created_order | |||||
| end | |||||
| # 提交记录详情 | |||||
| def record_detail | |||||
| @hack_user = HackUserCode.find params[:id] | |||||
| set = HackSet.find_by(id: @hack_user.error_test_set_id) | |||||
| @pass_set_count = set ? set.position - 1 : 0 | |||||
| @set_count = @hack_user.hack.hack_sets.count | |||||
| @my_hack = @hack_user.hack_user_lastest_code | |||||
| end | |||||
| # 接收中间件返回结果接口 | |||||
| # 调试模式: status: 0 表示评测无错误,其他 表示错误(如编译出错,执行出错,超时等) | |||||
| def listen_result | |||||
| logger.info("###########listen_result:#{params}") | |||||
| begin | |||||
| ojEvaResult = JSON.parse(params[:ojEvaResult]) | |||||
| testCase = ojEvaResult['testCase'] | |||||
| # 只有编译出错时,才正则匹配错误行数 | |||||
| error_line= | |||||
| if ojEvaResult['status'] == "4" || ojEvaResult['status'] == "5" | |||||
| regular_match_error_line ojEvaResult['outPut'], @my_hack.hack.language | |||||
| end | |||||
| # debug 与submit 公用的参数 | |||||
| ds_params = {input: testCase['input'], output: testCase['output'], hack_id: @hack.id, | |||||
| code: ojEvaResult['codeFileContent'], user_id: @my_hack.user_id, error_line: error_line, | |||||
| status: ojEvaResult['status'], error_msg: ojEvaResult['outPut'], | |||||
| execute_time: ojEvaResult['executeTime'], execute_memory: ojEvaResult['executeMem']} | |||||
| ActiveRecord::Base.transaction do | |||||
| # debug模式与submit模式 | |||||
| if ojEvaResult['execMode'] == "debug" | |||||
| save_debug_data ds_params | |||||
| elsif ojEvaResult['execMode'] == "submit" | |||||
| save_submit_data ds_params.merge(expected_output: testCase['expectedOutput'], | |||||
| error_test_set_id: ojEvaResult['failCaseNum']) | |||||
| end | |||||
| # 评测完成后,还原评测中的状态 | |||||
| @my_hack.update_attribute(:submit_status, 0) | |||||
| end | |||||
| render_ok | |||||
| rescue Exception => e | |||||
| logger.error("#########listen_result: #{e.message}") | |||||
| end | |||||
| end | |||||
| def add_notes | |||||
| @my_hack.update_attribute(:notes, params[:notes]) | |||||
| render_ok | |||||
| end | |||||
| private | |||||
| def find_my_hack | |||||
| @my_hack = HackUserLastestCode.find_by(identifier: params[:identifier]) | |||||
| @hack = @my_hack.hack | |||||
| end | |||||
| def oj_evaluate exec_mode, error_status, error_msg | |||||
| request_url = "#{edu_setting('cloud_bridge')}/bridge/ojs/evaluate" | |||||
| test_sets = | |||||
| if exec_mode == "submit" | |||||
| @hack.hack_sets.map{|set| {input: set.input, output: set.output, caseId: set.id}} | |||||
| else | |||||
| [{input: params[:input]}] | |||||
| end | |||||
| testCases = Base64.encode64(test_sets.to_json) | |||||
| #codeFileContent = Base64.urlsafe_encode64(@my_hack.code) | |||||
| debug_params = {execMode: exec_mode, | |||||
| tpiID: @my_hack.identifier, | |||||
| testCases: testCases, | |||||
| platform: @my_hack.language, | |||||
| codeFileContent: @my_hack.code, | |||||
| timeLimit: @hack.time_limit, | |||||
| sec_key: Time.now.to_i} | |||||
| interface_json_post request_url, debug_params, error_status, error_msg | |||||
| # 每次评测提交数增加 | |||||
| @hack.increment!(:submit_num) | |||||
| end | |||||
| # 正则错误行数 | |||||
| def regular_match_error_line content, language | |||||
| content = Base64.decode64(content).force_encoding("utf-8") | |||||
| logger.info("######content: #{content}") | |||||
| case language | |||||
| when 'Java' | |||||
| content.scan(/.java.\d+/).map{|s| s.match(/\d+/)[0].to_i}.min | |||||
| when 'C', 'C++' | |||||
| content.scan(/\d:\d+:/).map{|s| s.match(/\d+/)[0].to_i}.min | |||||
| when 'Python' | |||||
| content.scan(/line \d+/).map{|s| s.match(/\d+/)[0].to_i}.min | |||||
| end | |||||
| end | |||||
| # 存储debug数据 | |||||
| def save_debug_data debug_params | |||||
| if @my_hack.hack_user_debug.present? | |||||
| @my_hack.hack_user_debug.update_attributes!(debug_params) | |||||
| else | |||||
| debug = HackUserDebug.new(debug_params) | |||||
| debug.hack_user_lastest_code_id = @my_hack.id | |||||
| debug.save! | |||||
| end | |||||
| end | |||||
| # 存储submit数据 | |||||
| def save_submit_data submit_params | |||||
| # 通关 | |||||
| if submit_params[:status] == "0" | |||||
| # 编程题已经发布,且之前未通关奖励积分 | |||||
| @hack.increment!(:pass_num) | |||||
| if @hack.status == 1 && !@my_hack.passed? | |||||
| reward_attrs = { container_id: @hack.id, container_type: 'Hack', score: @hack.score } | |||||
| RewardGradeService.call(@my_hack.user, reward_attrs) | |||||
| RewardExperienceService.call(@my_hack.user, reward_attrs) | |||||
| # 评测完成更新通过数 | |||||
| @my_hack.update_attributes(passed: true, passed_time: Time.now) | |||||
| end | |||||
| end | |||||
| # 创建用户评测记录 | |||||
| logger.info("###########submit_params:#{submit_params}") | |||||
| query_index = @my_hack.hack_user_codes.count +1 | |||||
| @my_hack.hack_user_codes.create!(submit_params.merge(query_index: query_index)) | |||||
| end | |||||
| # 调试或提交改变状态 | |||||
| def update_user_hack_status | |||||
| @my_hack.update_attribute(:submit_status, 1) | |||||
| end | |||||
| # 只有自己才能改动代码 | |||||
| def require_identity | |||||
| if @my_hack.user_id != current_user.id | |||||
| tip_exception(403, "..") | |||||
| end | |||||
| end | |||||
| # 老师、自己、管理可以查看他人的编程题 | |||||
| def require_manager_identity | |||||
| unless current_user.certification_teacher? || admin_or_business? || @my_hack.user_id == current_user.id | |||||
| tip_exception(403, "..") | |||||
| end | |||||
| end | |||||
| # 只有自己才能评测 | |||||
| def require_auth_identity | |||||
| unless @my_hack.user_id == current_user.id | |||||
| tip_exception(403, "..") | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,282 +0,0 @@ | |||||
| class HacksController < ApplicationController | |||||
| before_action :require_login, except: [:index] | |||||
| before_action :find_hack, only: [:edit, :update, :publish, :start, :update_set, :delete_set, :destroy, :cancel_publish] | |||||
| before_action :require_teacher_identity, only: [:create] | |||||
| before_action :require_auth_identity, only: [:update, :edit, :publish, :update_set, :delete_set, :destroy, :cancel_publish] | |||||
| # 开启编程,如果第一次开启,创建一条记录,如果已经开启过的话,直接返回标识即可 | |||||
| def start | |||||
| # 未发布的编程题,只能作者、或管理员访问 | |||||
| start_hack_auth | |||||
| user_hack = @hack.hack_user_lastest_codes.where(user_id: current_user.id).first | |||||
| logger.info("#user_hack: #{user_hack}") | |||||
| identifier = | |||||
| if user_hack.present? | |||||
| logger.info("#####user_hack_id:#{user_hack.id}") | |||||
| user_hack.identifier | |||||
| else | |||||
| user_identifier = generate_identifier HackUserLastestCode, 12 | |||||
| user_code = {user_id: current_user.id, code: @hack.code, modify_time: Time.now, | |||||
| identifier: user_identifier, language: @hack.language} | |||||
| @hack.hack_user_lastest_codes.create!(user_code) | |||||
| user_identifier | |||||
| end | |||||
| render_ok(identifier: identifier) | |||||
| end | |||||
| # 首页 | |||||
| def index | |||||
| # 筛选过滤与排序 | |||||
| params_filter_or_order | |||||
| # 我解决的编程题数 | |||||
| user_codes = HackUserLastestCode.joins(:hack).mine_hack(current_user).passed | |||||
| @simple_count = user_codes.where(hacks: {difficult: 1}).count | |||||
| @medium_count = user_codes.where(hacks: {difficult: 2}).count | |||||
| @diff_count = user_codes.where(hacks: {difficult: 3}).count | |||||
| @pass_count = @simple_count + @medium_count + @diff_count | |||||
| @hacks_count = @hacks.count("hacks.id") | |||||
| @hacks = paginate @hacks | |||||
| end | |||||
| def create | |||||
| begin | |||||
| logger.info("##########{hack_params}") | |||||
| tip_exception("一次只能增加50个测试集") if hack_sets_params.size > 50 | |||||
| tip_exception("一次只能增加50个知识点") if params[:tags].size > 50 | |||||
| hack = Hack.new(hack_params) | |||||
| hack.user_id = current_user.id | |||||
| hack.identifier = generate_identifier Hack, 8 | |||||
| tag_params = params[:tags].map{|tag| {tag_discipline_id: tag}} | |||||
| ActiveRecord::Base.transaction do | |||||
| hack.save! | |||||
| # 创建测试集与代码 | |||||
| hack.hack_sets.create!(hack_sets_params) | |||||
| # 新建知识点 | |||||
| hack.tag_discipline_containers.create!(tag_params) if tag_params.present? | |||||
| hack_codes = hack.hack_codes.new(hack_code_params) | |||||
| hack_codes.modify_time = Time.now | |||||
| hack_codes.save! | |||||
| new_item_params = item_params.merge(container: hack, item_type: 'PROGRAM', difficulty: params[:hack][:difficult], user_id: current_user.id) | |||||
| ItemBank.create!(new_item_params) | |||||
| end | |||||
| render_ok({identifier: hack.identifier}) | |||||
| rescue => e | |||||
| logger.error("########create_hack_error: #{e.message}") | |||||
| render_error("创建失败: #{e.message}") | |||||
| end | |||||
| end | |||||
| def update | |||||
| begin | |||||
| # 知识点 | |||||
| tag_discipline_ids = @hack.tag_discipline_containers.pluck(:tag_discipline_id) | |||||
| new_tag_ids = params[:tags].to_a - tag_discipline_ids | |||||
| tag_params = new_tag_ids.map{|tag| {tag_discipline_id: tag}} | |||||
| ActiveRecord::Base.transaction do | |||||
| @hack.update_attributes!(hack_params) | |||||
| set_ids = @hack.hack_sets.pluck(:id) | |||||
| # 更新 | |||||
| param_update_sets params[:update_hack_sets], set_ids | |||||
| # 新建 | |||||
| @hack.hack_sets.create!(hack_sets_params) | |||||
| # 更新代码 | |||||
| code_params = params[:hack_codes][:code] != @hack.code ? hack_code_params.merge(modify_time: Time.now) : hack_code_params | |||||
| @hack.hack_codes.first.update_attributes!(code_params) | |||||
| @hack.tag_discipline_containers.create!(tag_params) if tag_params | |||||
| @hack.tag_discipline_containers.where.not(tag_discipline_id: params[:tags]).destroy_all | |||||
| # 更新题库相关记录 | |||||
| if @hack.item_bank.present? | |||||
| update_item_params = item_params.merge({difficulty: params[:hack][:difficult]}) | |||||
| @hack.item_bank.update!(update_item_params) | |||||
| end | |||||
| end | |||||
| render_ok | |||||
| rescue Exception => e | |||||
| logger.error("####update_hack_error: #{e.message}") | |||||
| render_error("更新失败: #{e.message}") | |||||
| end | |||||
| end | |||||
| # 更新测试集接口 | |||||
| def update_set | |||||
| set = @hack.hack_sets.find_by(id: params[:id]) | |||||
| set.update_attributes!(hack_set_params) | |||||
| render_ok | |||||
| end | |||||
| # 单独删除测试集 | |||||
| def delete_set | |||||
| set = @hack.hack_sets.find_by(id: params[:id]) | |||||
| set.destroy! | |||||
| render_ok | |||||
| end | |||||
| # 发布功能 | |||||
| def publish | |||||
| @hack.update_attribute(:status, 1) | |||||
| base_attrs = { | |||||
| trigger_user_id: current_user.id, viewed: 0, tiding_type: 'System', user_id: @hack.user_id, | |||||
| parent_container_type: "HackPublish", extra: @hack.identifier | |||||
| } | |||||
| @hack.tidings.create!(base_attrs) | |||||
| render_ok | |||||
| end | |||||
| # 取消发布 | |||||
| def cancel_publish | |||||
| @hack.update_attribute(:status, 0) | |||||
| base_attrs = { | |||||
| trigger_user_id: current_user.id, viewed: 0, tiding_type: 'System', user_id: @hack.user_id, | |||||
| parent_container_type: "HackUnPublish", extra: @hack.identifier | |||||
| } | |||||
| @hack.tidings.create!(base_attrs) | |||||
| render_ok | |||||
| end | |||||
| # 发布列表 | |||||
| def unpulished_list | |||||
| limit = params[:limit] || 16 | |||||
| page = params[:page] || 1 | |||||
| hacks = Hack.where(user_id: current_user.id, status: 0) | |||||
| @hacks_count = hacks.count | |||||
| @hacks = hacks.includes(:hack_sets).page(page).per(limit) | |||||
| end | |||||
| def edit; | |||||
| end | |||||
| def new; | |||||
| end | |||||
| def destroy | |||||
| begin | |||||
| base_attrs = { | |||||
| user_id: @hack.user_id, viewed: 0, tiding_type: 'System', trigger_user_id: current_user.id, | |||||
| parent_container_type: "HackDelete", extra: "#{@hack.name}" | |||||
| } | |||||
| @hack.tidings.create!(base_attrs) | |||||
| @hack.destroy | |||||
| render_ok | |||||
| rescue => e | |||||
| logger.error("####hack_delete_error: #{e.message}") | |||||
| render_error("删除失败") | |||||
| end | |||||
| end | |||||
| private | |||||
| # 实名认证老师,管理员与运营人员权限 | |||||
| def require_teacher_identity | |||||
| unless current_user.certification_teacher? || admin_or_business? | |||||
| tip_exception(403, "..") | |||||
| end | |||||
| end | |||||
| # 只有自己,或者管理员才能更新 | |||||
| def require_auth_identity | |||||
| unless @hack.user_id == current_user.id || admin_or_business? | |||||
| tip_exception(403, "..") | |||||
| end | |||||
| end | |||||
| def find_hack | |||||
| @hack = Hack.find_by_identifier(params[:identifier]) | |||||
| end | |||||
| def hack_params | |||||
| params.require(:hack).permit(:name, :description, :difficult, :open_or_not, :time_limit, :score, :sub_discipline_id) | |||||
| end | |||||
| def item_params | |||||
| params.require(:hack).permit(:name, :sub_discipline_id) | |||||
| end | |||||
| def hack_sets_params | |||||
| params.permit(hack_sets: [:input, :output, :position])[:hack_sets] | |||||
| end | |||||
| def hack_set_params | |||||
| params.require(:hack_set).permit(:id, :input, :output, :position) | |||||
| end | |||||
| def hack_code_params | |||||
| params.require(:hack_codes).permit(:code, :language) | |||||
| end | |||||
| def publish_params | |||||
| params.require(:hack).permit(:difficult, :category, :open_or_not, :time_limit, :score) | |||||
| end | |||||
| def param_update_sets sets, all_sets_id | |||||
| delete_set_ids = all_sets_id - sets.map {|set| set[:id]} | |||||
| @hack.hack_sets.where(id: delete_set_ids).destroy_all | |||||
| logger.info("#######sets:#{sets}") | |||||
| sets.each do |set| | |||||
| logger.info("###set[:id]: #{set[:id]}") | |||||
| logger.info("###all_sets: #{all_sets_id.include?(set[:id])}") | |||||
| if all_sets_id.include?(set[:id]) | |||||
| update_attrs = {input: set[:input], output: set[:output], position: set[:position]} | |||||
| @hack.hack_sets.find_by!(id: set[:id]).update_attributes!(update_attrs) | |||||
| end | |||||
| end | |||||
| end | |||||
| def params_filter_or_order | |||||
| # 如果有来源,就不管发布公开私有 | |||||
| select_sql = "hacks.*, if(hacks.hack_user_lastest_codes_count=0, 0, hacks.pass_num/hacks.hack_user_lastest_codes_count) passed_rate" | |||||
| if params[:come_from] | |||||
| hacks = Hack.select(select_sql).mine(current_user.id) | |||||
| else | |||||
| # 全部包括已经发布的,和我的未发布的 | |||||
| if current_user.admin_or_business? | |||||
| hacks = Hack.select(select_sql) | |||||
| else | |||||
| hacks = Hack.select(select_sql).published.opening.or(Hack.select(select_sql).unpublish.mine(current_user.id)) | |||||
| end | |||||
| end | |||||
| # 搜索 | |||||
| if params[:search] | |||||
| hacks = hacks.where("name like ?", "%#{params[:search]}%") | |||||
| end | |||||
| # 难度 | |||||
| if params[:difficult] | |||||
| hacks = hacks.where(difficult: params[:difficult]) | |||||
| end | |||||
| # 状态 | |||||
| if params[:status] | |||||
| user_hacks = HackUserLastestCode.where(user_id: current_user.id) | |||||
| if params[:status].to_i == -1 | |||||
| if user_hacks.present? | |||||
| hacks = hacks.where.not(id: user_hacks.pluck(:hack_id)) | |||||
| end | |||||
| else | |||||
| hacks = hacks.joins(:hack_user_lastest_codes).where(hack_user_lastest_codes: {status: params[:status]}) | |||||
| end | |||||
| end | |||||
| # 分类 | |||||
| if params[:category] | |||||
| hacks = hacks.where(category: params[:category]) | |||||
| end | |||||
| # 语言 | |||||
| if params[:language] | |||||
| hacks = hacks.joins(:hack_codes).where(hack_codes: {language: params[:language]}) | |||||
| end | |||||
| # 排序 | |||||
| sort_by = params[:sort_by] || "hack_user_lastest_codes_count" | |||||
| sort_direction = params[:sort_direction] || "desc" | |||||
| @hacks = hacks.order("#{sort_by} #{sort_direction}") | |||||
| end | |||||
| def start_hack_auth | |||||
| return true if @hack.status == 1 | |||||
| require_auth_identity | |||||
| end | |||||
| end | |||||
| @@ -1,44 +0,0 @@ | |||||
| class HomeController < ApplicationController | |||||
| def index | |||||
| # banner图 | |||||
| images = current_laboratory.portal_images.only_online.order(position: :asc) | |||||
| images = default_laboratory.portal_images.only_online.order(position: :asc) if images.blank? # 未设置时使用EduCoder的轮播图 | |||||
| @images_url = [] | |||||
| images.each do |image| | |||||
| @images_url << {path: image.link, image_url: Util::FileManage.source_disk_file_url(image)} | |||||
| end | |||||
| # 目录分级 | |||||
| @rep_list = current_laboratory.shixun_repertoires | |||||
| shixuns = current_laboratory.shixuns | |||||
| subjects = current_laboratory.subjects | |||||
| if current_laboratory.main_site? | |||||
| shixuns = shixuns.where(homepage_show: true) | |||||
| subjects = subjects.where(homepage_show: true) | |||||
| else | |||||
| shixuns = shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { homepage: true, laboratory_id: current_laboratory.id}) | |||||
| subjects = subjects.joins(:laboratory_subjects).where(laboratory_subjects: { homepage: true, laboratory_id: current_laboratory.id}) | |||||
| end | |||||
| @shixuns = shixuns.includes(:tag_repertoires, :challenges).limit(8) | |||||
| @subjects = subjects.includes(:repertoire, :shixuns).limit(8) | |||||
| @main_shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(8) | |||||
| @main_subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(8) | |||||
| # if current_laboratory.main_site? | |||||
| # @tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc") | |||||
| # @stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc") | |||||
| # end | |||||
| end | |||||
| def search | |||||
| @fuzzy_searchs = params[:keyword].split(" ").join("%") | |||||
| @shixuns = Shixun.where("name like ?", "%#{@fuzzy_searchs}%") | |||||
| @total_count = @shixuns.count | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,96 @@ | |||||
| class HooksController < ApplicationController | |||||
| before_action :require_login | |||||
| before_action :find_project_with_id | |||||
| before_action :check_user | |||||
| before_action :set_repository | |||||
| def index | |||||
| hooks_response = Gitea::Hooks::ListService.new(@user.gitea_token, @user.login, @repository.try(:identifier)).call | |||||
| if hooks_response.status == 200 | |||||
| lists = JSON.parse(hooks_response.body) | |||||
| @hooks_size = lists.size | |||||
| @hooks = paginate(lists) | |||||
| else | |||||
| normal_status(-1, "出现错误") | |||||
| end | |||||
| end | |||||
| def create | |||||
| #根据gitea的api | |||||
| # hook_params = { | |||||
| # active: true, | |||||
| # type: "gitea", | |||||
| # branch_filter: "", | |||||
| # config: { | |||||
| # content_type: "application/json", | |||||
| # url: "#{EduSetting.get("host_name")}/repositories/#{project.id}/repo_hooks.json", | |||||
| # http_method: "post" | |||||
| # }, | |||||
| # events: ["create", "pull", "push"], | |||||
| # } | |||||
| #根据gitea上hook的字段测试的 | |||||
| # hook_params = { | |||||
| # is_active: params[:is_active] || false, | |||||
| # type: params[:type], | |||||
| # http_method: params[:http_method] || "POST", | |||||
| # content_type: params[:content_type].to_i, | |||||
| # secret: params[:secret], | |||||
| # events: { | |||||
| # push_only: params[:push_only] || false, # 是否为推送事件 | |||||
| # send_everything: params[:send_everything] || false, #是否为所有事件 | |||||
| # choose_events: params[:choose_events] || false, #是否为自定义事件 | |||||
| # branch_filter: params[:branch_filter] || "*", | |||||
| # events: { | |||||
| # create: params[:create] || false, #创建分支/标签 | |||||
| # delete: params[:delete] || false, #删除分支/标签 | |||||
| # fork: params[:fork] || false, #仓库被派生 | |||||
| # issues: params[:issues] || false, #工单 | |||||
| # issue_comment: params[:issue_comment] || false, #评论 | |||||
| # push: params[:push] || false # 推送 | |||||
| # pull_request: params[:pull_request] || false #合并请求 | |||||
| # repository: params[:repository] || false #仓库 | |||||
| # release: params[:release] || false #版本发布 | |||||
| # } | |||||
| # } | |||||
| # } | |||||
| hook_params = params[:hook_params] | |||||
| Gitea::Hooks::CreateService.new(@user, @repository.try(:identifier), hook_params).call #创建gitea的hook功能 | |||||
| Gitea::Hooks::CreateService.new(user, p.try(:identifier), hook_params).call #创建gitea的hook功能 | |||||
| end | |||||
| def update | |||||
| hook_params = params[:hook_params] | |||||
| response = Gitea::Hooks::UpdateService.new(@user, @repository.try(:identifier), hook_params, params[:id]).call | |||||
| if response.status == 200 | |||||
| normal_status(1, "更新成功") | |||||
| else | |||||
| normal_status(-1, "更新失败") | |||||
| end | |||||
| end | |||||
| def destroy | |||||
| response = Gitea::Hooks::DestroyService.new(@user, @repository.try(:identifier), params[:id]).call | |||||
| if response.status == 204 | |||||
| normal_status(1, "删除成功") | |||||
| else | |||||
| normal_status(-1, "删除失败") | |||||
| end | |||||
| end | |||||
| private | |||||
| def set_repository | |||||
| @repository = @project.repository | |||||
| @user = @project.owner | |||||
| normal_status(-1, "仓库不存在") unless @repository.present? | |||||
| normal_status(-1, "用户不存在") unless @user.present? | |||||
| end | |||||
| def check_user | |||||
| unless @project.user_id == current_user.id | |||||
| tip_exception(403, "您没有权限进入") | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,7 +0,0 @@ | |||||
| class HotKeywordsController < ApplicationController | |||||
| def index | |||||
| keywords = [] | |||||
| keywords = HotSearchKeyword.hot(8) if HotSearchKeyword.available? | |||||
| render_ok(keywords: keywords) | |||||
| end | |||||
| end | |||||
| @@ -1,5 +1,7 @@ | |||||
| class IgnoresController < ApplicationController | class IgnoresController < ApplicationController | ||||
| def index | def index | ||||
| @ignores = Ignore.search(params[:name]).without_content | |||||
| #@ignores = Ignore.search(params[:name]).without_content | |||||
| q = Ignore.ransack(name_cont: params[:name]) | |||||
| @ignores = q.result(distinct: true) | |||||
| end | end | ||||
| end | end | ||||
| @@ -11,7 +11,7 @@ class IssueDependsController < ApplicationController | |||||
| } | } | ||||
| save_issue_depend = IssueDepend.new(issue_depend) | save_issue_depend = IssueDepend.new(issue_depend) | ||||
| if save_issue_depend.save | if save_issue_depend.save | ||||
| @issue.custom_journal_detail("issue_depend","", @issue.id) | |||||
| @issue.custom_journal_detail("issue_depend","", @issue.id, current_user&.id) | |||||
| normal_status(0, "添加依赖成功") | normal_status(0, "添加依赖成功") | ||||
| else | else | ||||
| normal_status(0, "添加依赖失败") | normal_status(0, "添加依赖失败") | ||||
| @@ -23,7 +23,7 @@ class IssueDependsController < ApplicationController | |||||
| depend_issue_params = params[:id] | depend_issue_params = params[:id] | ||||
| depend_issue = IssueDepend.find(depend_issue_params) | depend_issue = IssueDepend.find(depend_issue_params) | ||||
| if depend_issue&.destroy | if depend_issue&.destroy | ||||
| @issue.custom_journal_detail("destroy_issue_depend","", @issue.id) | |||||
| @issue.custom_journal_detail("destroy_issue_depend","", @issue.id, current_user&.id) | |||||
| normal_status(0, "删除依赖成功") | normal_status(0, "删除依赖成功") | ||||
| else | else | ||||
| normal_status(-1, "删除依赖失败") | normal_status(-1, "删除依赖失败") | ||||
| @@ -1,6 +1,7 @@ | |||||
| class IssueTagsController < ApplicationController | class IssueTagsController < ApplicationController | ||||
| before_action :require_login | |||||
| before_action :set_project | |||||
| before_action :require_login, except: [:index] | |||||
| before_action :load_repository | |||||
| before_action :set_user | |||||
| before_action :check_issue_permission, except: :index | before_action :check_issue_permission, except: :index | ||||
| before_action :set_issue_tag, only: [:edit, :update, :destroy] | before_action :set_issue_tag, only: [:edit, :update, :destroy] | ||||
| @@ -37,12 +38,12 @@ class IssueTagsController < ApplicationController | |||||
| begin | begin | ||||
| issue_tag = IssueTag.new(tag_params.merge(project_id: @project.id, user_id: current_user.id)) | issue_tag = IssueTag.new(tag_params.merge(project_id: @project.id, user_id: current_user.id)) | ||||
| if issue_tag.save | if issue_tag.save | ||||
| gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call | |||||
| if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"]) | |||||
| normal_status(0, "标签创建成功") | |||||
| else | |||||
| normal_status(-1, "标签创建失败") | |||||
| end | |||||
| # gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call | |||||
| # if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"]) | |||||
| # normal_status(0, "标签创建成功") | |||||
| # else | |||||
| # normal_status(-1, "标签创建失败") | |||||
| # end | |||||
| else | else | ||||
| normal_status(-1, "标签创建失败") | normal_status(-1, "标签创建失败") | ||||
| end | end | ||||
| @@ -78,12 +79,12 @@ class IssueTagsController < ApplicationController | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| if @issue_tag.update_attributes(tag_params) | if @issue_tag.update_attributes(tag_params) | ||||
| gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call | |||||
| if gitea_tag | |||||
| normal_status(0, "标签更新成功") | |||||
| else | |||||
| normal_status(-1, "标签更新失败") | |||||
| end | |||||
| # gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call | |||||
| # if gitea_tag | |||||
| # normal_status(0, "标签更新成功") | |||||
| # else | |||||
| # normal_status(-1, "标签更新失败") | |||||
| # end | |||||
| else | else | ||||
| normal_status(-1, "标签更新失败") | normal_status(-1, "标签更新失败") | ||||
| end | end | ||||
| @@ -102,12 +103,12 @@ class IssueTagsController < ApplicationController | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| if @issue_tag.destroy | if @issue_tag.destroy | ||||
| issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call | |||||
| if issue_tag | |||||
| normal_status(0, "标签删除成功") | |||||
| else | |||||
| normal_status(-1, "标签删除失败") | |||||
| end | |||||
| # issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call | |||||
| # if issue_tag | |||||
| # normal_status(0, "标签删除成功") | |||||
| # else | |||||
| # normal_status(-1, "标签删除失败") | |||||
| # end | |||||
| else | else | ||||
| normal_status(-1, "标签删除失败") | normal_status(-1, "标签删除失败") | ||||
| end | end | ||||
| @@ -120,13 +121,8 @@ class IssueTagsController < ApplicationController | |||||
| private | private | ||||
| def set_project | |||||
| @project = Project.find_by_identifier! params[:project_id] | |||||
| @repository = @project.repository | |||||
| def set_user | |||||
| @user = @project.owner | @user = @project.owner | ||||
| normal_status(-1, "项目不存在") unless @project.present? | |||||
| normal_status(-1, "仓库不存在") unless @repository.present? | |||||
| normal_status(-1, "用户不存在") unless @user.present? | |||||
| end | end | ||||
| def check_issue_permission | def check_issue_permission | ||||
| @@ -142,4 +138,4 @@ class IssueTagsController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -11,7 +11,7 @@ class IssueTimesController < ApplicationController | |||||
| } | } | ||||
| save_issue_time = IssueTime.new(issue_time) | save_issue_time = IssueTime.new(issue_time) | ||||
| if save_issue_time.save | if save_issue_time.save | ||||
| @issue.custom_journal_detail("work_time",save_issue_time.id, "开始工作") | |||||
| @issue.custom_journal_detail("work_time",save_issue_time.id, "开始工作", current_user&.id) | |||||
| normal_status(0, "开始成功") | normal_status(0, "开始成功") | ||||
| else | else | ||||
| normal_status(0, "开始失败") | normal_status(0, "开始失败") | ||||
| @@ -22,16 +22,10 @@ class IssueTimesController < ApplicationController | |||||
| end_type = params[:end_type].to_i | end_type = params[:end_type].to_i | ||||
| end_work_time = end_type == 0 ? "" : Time.now | end_work_time = end_type == 0 ? "" : Time.now | ||||
| last_work_time = @issue.issue_times.where(user_id: current_user.id, end_time: nil) | last_work_time = @issue.issue_times.where(user_id: current_user.id, end_time: nil) | ||||
| Rails.logger.info("######________last_work_time&.last.try(:id)_____###########{last_work_time&.first.try(:id)}") | |||||
| if last_work_time.update_all(end_time: end_work_time) | if last_work_time.update_all(end_time: end_work_time) | ||||
| if end_type == 0 | |||||
| message = "取消时间跟踪" | |||||
| @issue.custom_journal_detail("cancel_time",last_work_time&.first.try(:id), "取消时间跟踪") | |||||
| else | |||||
| message = "停止工作" | |||||
| @issue.custom_journal_detail("end_time",last_work_time&.first.try(:id), "停止工作") | |||||
| end | |||||
| message = end_type == 0 ? "取消时间跟踪" : "停止工作" | |||||
| journal_time = end_type == 0 ? "cancel_time" : "end_time" | |||||
| @issue.custom_journal_detail(journal_time,last_work_time&.first.try(:id), message, current_user&.id) | |||||
| normal_status(0, message) | normal_status(0, message) | ||||
| else | else | ||||
| normal_status(0, "操作失败") | normal_status(0, "操作失败") | ||||
| @@ -1,72 +1,39 @@ | |||||
| class IssuesController < ApplicationController | class IssuesController < ApplicationController | ||||
| before_action :require_login, except: [:index, :show] | |||||
| before_action :find_project | |||||
| before_action :set_project_and_user | |||||
| before_action :require_login, except: [:index, :show, :index_chosen] | |||||
| before_action :load_project | |||||
| before_action :set_user | |||||
| before_action :check_issue_permission | |||||
| before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue] | before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue] | ||||
| before_action :check_issue_permission, except: [:index, :show, :index_chosen] | |||||
| before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue] | before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue] | ||||
| before_action :get_branches, only: [:new, :edit] | |||||
| before_action :check_token_enough, only: [:create, :update] | |||||
| include ApplicationHelper | include ApplicationHelper | ||||
| include TagChosenHelper | include TagChosenHelper | ||||
| def index | def index | ||||
| @user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user)) | |||||
| issues = @project.issues.issue_issue.includes(:user,:tracker, :priority, :version, :issue_status, :journals, :issue_times) | |||||
| @user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user)) | |||||
| issues = @project.issues.issue_issue.issue_index_includes | |||||
| issues = issues.where(is_private: false) unless @user_admin_or_member | issues = issues.where(is_private: false) unless @user_admin_or_member | ||||
| @all_issues_size = issues.size | @all_issues_size = issues.size | ||||
| @open_issues_size = issues.where.not(status_id: 5).size | @open_issues_size = issues.where.not(status_id: 5).size | ||||
| @close_issues_size = issues.where(status_id: 5).size | @close_issues_size = issues.where(status_id: 5).size | ||||
| @assign_to_me_size = issues.where(assigned_to_id: current_user&.id).size | @assign_to_me_size = issues.where(assigned_to_id: current_user&.id).size | ||||
| @my_published_size = issues.where(author_id: current_user&.id).size | @my_published_size = issues.where(author_id: current_user&.id).size | ||||
| status_type = params[:status_type].to_s #issue状态的选择 | |||||
| search_name = params[:search].to_s | |||||
| start_time = params[:start_date] | |||||
| end_time = params[:due_date] | |||||
| if status_type.to_s == "1" #表示开启中的 | |||||
| issues = issues.where.not(status_id: 5) | |||||
| elsif status_type.to_s == "2" #表示关闭中的 | |||||
| issues = issues.where(status_id: 5) | |||||
| end | |||||
| if search_name.present? | |||||
| issues = issues.where("subject like ?", "%#{search_name}%") | |||||
| end | |||||
| if start_time&.present? || end_time&.present? | |||||
| issues = issues.where("start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date) | |||||
| end | |||||
| issues = issues.where(author_id: params[:author_id]) if params[:author_id].present? && params[:author_id].to_s != "all" | |||||
| issues = issues.where(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present? && params[:assigned_to_id].to_s != "all" | |||||
| issues = issues.where(tracker_id: params[:tracker_id]) if params[:tracker_id].present? && params[:tracker_id].to_s != "all" | |||||
| issues = issues.where(status_id: params[:status_id]) if params[:status_id].present? && params[:status_id].to_s != "all" | |||||
| issues = issues.where(priority_id: params[:priority_id]) if params[:priority_id].present? && params[:priority_id].to_s != "all" | |||||
| issues = issues.where(fixed_version_id: params[:fixed_version_id]) if params[:fixed_version_id].present? && params[:fixed_version_id].to_s != "all" | |||||
| issues = issues.where(done_ratio: params[:done_ratio].to_i) if params[:done_ratio].present? && params[:done_ratio].to_s != "all" | |||||
| issues = issues.where(issue_type: params[:issue_type].to_s) if params[:issue_type].present? && params[:issue_type].to_s != "all" | |||||
| issues = issues.joins(:issue_tags).where(issue_tags: {id: params[:issue_tag_id].to_i}) if params[:issue_tag_id].present? && params[:issue_tag_id].to_s != "all" | |||||
| order_type = params[:order_type] || "desc" #或者"asc" | |||||
| order_name = params[:order_name] || "created_on" #或者"updated_on" | |||||
| @page = params[:page] | |||||
| @limit = params[:limit] || 15 | |||||
| @issues = issues.order("#{order_name} #{order_type}") | |||||
| @issues_size = issues.size | |||||
| @issues = issues.order("#{order_name} #{order_type}").page(@page).per(@limit) | |||||
| scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue") | |||||
| @issues_size = scopes.size | |||||
| @issues = paginate(scopes) | |||||
| respond_to do |format| | respond_to do |format| | ||||
| format.json | format.json | ||||
| format.xlsx{ | |||||
| set_export_cookies | |||||
| export_issues(@issues) | |||||
| export_name = "#{@project.name}_issues列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}" | |||||
| render xlsx: "#{export_name.strip}",template: "issues/index.xlsx.axlsx",locals: {table_columns:@table_columns,issues:@export_issues} | |||||
| } | |||||
| #导出功能暂未做,可以考虑隐藏 | |||||
| # format.xlsx{ | |||||
| # set_export_cookies | |||||
| # export_issues(@issues) | |||||
| # export_name = "#{@project.name}_issues列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}" | |||||
| # render xlsx: "#{export_name.strip}",template: "issues/index.xlsx.axlsx",locals: {table_columns:@table_columns,issues:@export_issues} | |||||
| # } | |||||
| end | end | ||||
| end | end | ||||
| @@ -129,8 +96,7 @@ class IssuesController < ApplicationController | |||||
| end | end | ||||
| def new | def new | ||||
| @all_branches = get_branches | |||||
| @issue_chosen = issue_left_chosen(@project, nil) | |||||
| @issue_chosen = get_associated_data(@project) | |||||
| end | end | ||||
| def create | def create | ||||
| @@ -138,31 +104,8 @@ class IssuesController < ApplicationController | |||||
| normal_status(-1, "标题不能为空") | normal_status(-1, "标题不能为空") | ||||
| elsif params[:subject].to_s.size > 255 | elsif params[:subject].to_s.size > 255 | ||||
| normal_status(-1, "标题不能超过255个字符") | normal_status(-1, "标题不能超过255个字符") | ||||
| elsif (params[:issue_type].to_s == "2") && params[:token].to_i == 0 | |||||
| normal_status(-1, "悬赏的奖金必须大于0") | |||||
| else | else | ||||
| issue_params = { | |||||
| subject: params[:subject], | |||||
| description: params[:description], | |||||
| is_private: params[:is_private] || false, | |||||
| assigned_to_id: params[:assigned_to_id], | |||||
| tracker_id: params[:tracker_id], | |||||
| status_id: params[:status_id], | |||||
| priority_id: params[:priority_id], | |||||
| fixed_version_id: params[:fixed_version_id], | |||||
| start_date: params[:start_date].to_s.to_date, | |||||
| due_date: params[:due_date].to_s.to_date, | |||||
| estimated_hours: params[:estimated_hours], | |||||
| done_ratio: params[:done_ratio], | |||||
| issue_type: params[:issue_type] || "1", | |||||
| token: params[:token], | |||||
| issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "", | |||||
| closed_on: (params[:status_id].to_i == 5) ? Time.now : nil, | |||||
| issue_classify: "issue", | |||||
| branch_name: params[:branch_name].to_s, | |||||
| author_id: current_user.id, | |||||
| project_id: @project.id | |||||
| } | |||||
| issue_params = issue_send_params(params) | |||||
| @issue = Issue.new(issue_params) | @issue = Issue.new(issue_params) | ||||
| if @issue.save! | if @issue.save! | ||||
| @@ -188,42 +131,31 @@ class IssuesController < ApplicationController | |||||
| parent_container_id: @project.id, parent_container_type: "Project", | parent_container_id: @project.id, parent_container_type: "Project", | ||||
| tiding_type: 'issue', status: 0) | tiding_type: 'issue', status: 0) | ||||
| end | end | ||||
| #为悬赏任务时, 扣除当前用户的积分 | |||||
| if params[:issue_type].to_s == "2" | |||||
| post_to_chain("minus", params[:token].to_i, current_user.try(:login)) | |||||
| end | |||||
| @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") | @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") | ||||
| normal_status(0, "创建成功") | |||||
| render json: {status: 0, message: "创建成", id: @issue.id} | |||||
| else | else | ||||
| normal_status(-1, "创建失败") | normal_status(-1, "创建失败") | ||||
| end | end | ||||
| end | end | ||||
| end | end | ||||
| def edit | def edit | ||||
| @all_branches = get_branches | |||||
| @issue_chosen = issue_left_chosen(@project, @issue.id) | |||||
| # @issue_chosen = issue_left_chosen(@project, @issue.id) | |||||
| @cannot_edit_tags = @issue.issue_type=="2" && @issue.status_id == 5 #悬赏任务已解决且关闭的状态下,不能修改 | |||||
| @issue_attachments = @issue.attachments | @issue_attachments = @issue.attachments | ||||
| end | end | ||||
| def update | def update | ||||
| issue_params = { | |||||
| subject: params[:subject], | |||||
| description: params[:description], | |||||
| is_private: params[:is_private] || false, | |||||
| assigned_to_id: params[:assigned_to_id], | |||||
| tracker_id: params[:tracker_id], | |||||
| status_id: params[:status_id], | |||||
| priority_id: params[:priority_id], | |||||
| fixed_version_id: params[:fixed_version_id], | |||||
| start_date: params[:start_date].to_s.to_date, | |||||
| due_date: params[:due_date].to_s.to_date, | |||||
| estimated_hours: params[:estimated_hours], | |||||
| done_ratio: params[:done_ratio], | |||||
| closed_on: (params[:status_id].to_i == 5) ? Time.now : nil, | |||||
| issue_type: params[:issue_type], | |||||
| issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",").to_s : "", | |||||
| token: params[:token], | |||||
| branch_name: params[:branch_name].to_s | |||||
| } | |||||
| last_token = @issue.token | |||||
| last_status_id = @issue.status_id | |||||
| if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? | if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? | ||||
| @issue&.issue_tags_relates&.destroy_all | @issue&.issue_tags_relates&.destroy_all | ||||
| params[:issue_tag_ids].each do |tag| | params[:issue_tag_ids].each do |tag| | ||||
| @@ -231,23 +163,22 @@ class IssuesController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| if @issue.update_attributes(issue_params) | |||||
| issue_files = params[:attachment_ids] | |||||
| change_files = false | |||||
| issue_file_ids = [] | |||||
| if issue_files.present? | |||||
| change_files = true | |||||
| issue_files.each do |id| | |||||
| attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | |||||
| unless attachment.blank? | |||||
| attachment.container = @issue | |||||
| attachment.author_id = current_user.id | |||||
| attachment.description = "" | |||||
| attachment.save | |||||
| end | |||||
| issue_files = params[:attachment_ids] | |||||
| change_files = false | |||||
| issue_file_ids = [] | |||||
| if issue_files.present? | |||||
| change_files = true | |||||
| issue_files.each do |id| | |||||
| attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | |||||
| unless attachment.blank? | |||||
| attachment.container = @issue | |||||
| attachment.author_id = current_user.id | |||||
| attachment.description = "" | |||||
| attachment.save | |||||
| end | end | ||||
| end | end | ||||
| end | |||||
| # if params[:issue_tag_ids].present? | # if params[:issue_tag_ids].present? | ||||
| # issue_current_tags = @issue&.issue_tags&.select(:id)&.pluck(:id) | # issue_current_tags = @issue&.issue_tags&.select(:id)&.pluck(:id) | ||||
| @@ -263,39 +194,119 @@ class IssuesController < ApplicationController | |||||
| # end | # end | ||||
| # end | # end | ||||
| if params[:status_id].to_i == 5 | |||||
| @issue.issue_times.update_all(end_time: Time.now) | |||||
| end | |||||
| @issue.create_journal_detail(change_files, issue_files, issue_file_ids) | |||||
| normal_status(0, "更新成功") | |||||
| if @issue.issue_type.to_s == "2" && params[:status_id].to_i == 5 && @issue.author_id != current_user.try(:id) | |||||
| normal_status(-1, "不允许修改为关闭状态") | |||||
| else | else | ||||
| normal_status(-1, "更新失败") | |||||
| end | |||||
| issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id) | |||||
| if @issue.update_attributes(issue_params) | |||||
| if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时 | |||||
| @issue.issue_times.update_all(end_time: Time.now) | |||||
| @issue.update_closed_issues_count_in_project! | |||||
| if @issue.issue_type.to_s == "2" && last_status_id != 5 | |||||
| if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时,才给token | |||||
| post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login)) | |||||
| else | |||||
| post_to_chain("add", @issue.token, @issue.user.try(:login)) | |||||
| end | |||||
| end | |||||
| end | |||||
| if @issue.issue_type.to_s == "2" && @issue.status_id != 5 && @issue.saved_change_to_attribute("token") | |||||
| #表示修改token值 | |||||
| change_token = last_token - @issue.token | |||||
| change_type = change_token > 0 ? "add" : "minus" | |||||
| post_to_chain(change_type, change_token.abs, current_user.try(:login)) | |||||
| end | |||||
| @issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id) | |||||
| normal_status(0, "更新成功") | |||||
| else | |||||
| normal_status(-1, "更新失败") | |||||
| end | |||||
| end | |||||
| end | end | ||||
| def show | def show | ||||
| @user_permission = current_user.present? && (!@issue.is_lock || @project.member?(current_user) || current_user.admin? || @issue.user == current_user) | |||||
| @user_permission = current_user.present? && current_user.logged? && (!@issue.is_lock || @project.member?(current_user) || current_user.admin? || @issue.user == current_user) | |||||
| @issue_attachments = @issue.attachments | @issue_attachments = @issue.attachments | ||||
| @issue_user = @issue.user | @issue_user = @issue.user | ||||
| @issue_assign_to = @issue.get_assign_user | @issue_assign_to = @issue.get_assign_user | ||||
| @join_users = join_users(@issue) | @join_users = join_users(@issue) | ||||
| #总耗时 | #总耗时 | ||||
| cost_time(@issue) | |||||
| # cost_time(@issue) | |||||
| #被依赖 | |||||
| @be_depended_issues_array = be_depended_issues(@issue) | |||||
| # #被依赖 | |||||
| # @be_depended_issues_array = be_depended_issues(@issue) | |||||
| #依赖于 | |||||
| depended_issues(@issue) | |||||
| # #依赖于 | |||||
| # depended_issues(@issue) | |||||
| end | end | ||||
| def destroy | def destroy | ||||
| if @issue.delete | |||||
| normal_status(0, "删除成功") | |||||
| else | |||||
| begin | |||||
| issue_type = @issue.issue_type | |||||
| status_id = @issue.status_id | |||||
| token = @issue.token | |||||
| login = @issue.user.try(:login) | |||||
| if @issue.destroy | |||||
| if issue_type == "2" && status_id != 5 | |||||
| post_to_chain("add", token, login) | |||||
| end | |||||
| normal_status(0, "删除成功") | |||||
| else | |||||
| normal_status(-1, "删除失败") | |||||
| end | |||||
| rescue => exception | |||||
| Rails.logger.info("#########_______exception.message_________##########{exception.message}") | |||||
| normal_status(-1, "删除失败") | normal_status(-1, "删除失败") | ||||
| else | |||||
| end | |||||
| end | |||||
| def clean | |||||
| #批量删除,暂时只能删除未悬赏的 | |||||
| issue_ids = params[:ids] | |||||
| if issue_ids.present? | |||||
| if Issue.where(id: issue_ids, issue_type: "1").destroy_all | |||||
| normal_status(0, "删除成功") | |||||
| else | |||||
| normal_status(-1, "删除失败") | |||||
| end | |||||
| else | |||||
| normal_status(-1, "请选择任务") | |||||
| end | |||||
| end | |||||
| def series_update | |||||
| update_hash = {} | |||||
| update_hash.merge!(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present? | |||||
| update_hash.merge!(fixed_version_id: params[:fixed_version_id]) if params[:fixed_version_id].present? | |||||
| # update_hash.merge!(status_id: params[:status_id]) if params[:status_id].present? | |||||
| if params[:status_id].present? | |||||
| status_id = params[:status_id].to_i | |||||
| update_hash.merge!(status_id: status_id) | |||||
| done_ratio = nil | |||||
| case status_id | |||||
| when 1 | |||||
| done_ratio = 0 | |||||
| when 3 | |||||
| done_ratio = 100 | |||||
| end | |||||
| update_hash.merge!(done_ratio: done_ratio) if done_ratio | |||||
| end | |||||
| # update_hash = params[:issue] | |||||
| issue_ids = params[:ids] | |||||
| if issue_ids.present? | |||||
| if update_hash.blank? | |||||
| normal_status(-1, "请选择批量更新内容") | |||||
| elsif Issue.where(id: issue_ids).update_all(update_hash) | |||||
| normal_status(0, "批量更新成功") | |||||
| else | |||||
| normal_status(-1, "批量更新失败") | |||||
| end | |||||
| else | |||||
| normal_status(-1, "请选择任务") | |||||
| end | end | ||||
| end | end | ||||
| @@ -317,6 +328,7 @@ class IssuesController < ApplicationController | |||||
| def close_issue | def close_issue | ||||
| type = params[:status_id].to_i || 5 | type = params[:status_id].to_i || 5 | ||||
| if type == 5 | if type == 5 | ||||
| message = "关闭" | message = "关闭" | ||||
| old_message = "重新开启" | old_message = "重新开启" | ||||
| @@ -327,18 +339,25 @@ class IssuesController < ApplicationController | |||||
| if @issue.update_attribute(:status_id, type) | if @issue.update_attribute(:status_id, type) | ||||
| if type == 5 | if type == 5 | ||||
| @issue&.project_trends&.update_all(action_type: "close") | @issue&.project_trends&.update_all(action_type: "close") | ||||
| @issue.issue_times.update_all(end_time: Time.now) | @issue.issue_times.update_all(end_time: Time.now) | ||||
| if @issue.issue_type.to_s == "2" | |||||
| post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login)) | |||||
| end | |||||
| if @issue.issue_classify.to_s == "pull_request" | |||||
| @issue&.pull_request&.update_attribute(:status, 2) | |||||
| end | |||||
| else | else | ||||
| @issue&.project_trends&.update_all(action_type: "create") | @issue&.project_trends&.update_all(action_type: "create") | ||||
| if @issue.issue_classify.to_s == "pull_request" | |||||
| @issue&.pull_request&.update_attribute(:status, 0) | |||||
| end | |||||
| end | end | ||||
| if @issue.issue_classify == "issue" | if @issue.issue_classify == "issue" | ||||
| close_message = "close_issue" | close_message = "close_issue" | ||||
| else | else | ||||
| close_message = "close_pr" | close_message = "close_pr" | ||||
| end | end | ||||
| @issue.custom_journal_detail(close_message,old_message, "#{message}") | |||||
| @issue.custom_journal_detail(close_message,old_message, "#{message}", current_user&.id) | |||||
| normal_status(0, message) | normal_status(0, message) | ||||
| else | else | ||||
| normal_status(-1, "操作失败") | normal_status(-1, "操作失败") | ||||
| @@ -350,9 +369,9 @@ class IssuesController < ApplicationController | |||||
| type = (params[:lock_type].to_i == 1) | type = (params[:lock_type].to_i == 1) | ||||
| if @issue.update_attribute(:is_lock, type) | if @issue.update_attribute(:is_lock, type) | ||||
| if type | if type | ||||
| @issue.custom_journal_detail("lock_issue","", "因为#{params[:lock_reason].present? ? params[:lock_reason].to_s : "某种原因"}而锁定,并将对话限制为协作者") | |||||
| @issue.custom_journal_detail("lock_issue","", "因为#{params[:lock_reason].present? ? params[:lock_reason].to_s : "某种原因"}而锁定,并将对话限制为协作者", current_user&.id) | |||||
| else | else | ||||
| @issue.custom_journal_detail("unlock_issue","", "解除锁定") | |||||
| @issue.custom_journal_detail("unlock_issue","", "解除锁定", current_user&.id) | |||||
| end | end | ||||
| normal_status(0, "操作成功") | normal_status(0, "操作成功") | ||||
| else | else | ||||
| @@ -365,11 +384,8 @@ class IssuesController < ApplicationController | |||||
| end | end | ||||
| private | private | ||||
| def set_project_and_user | |||||
| # @project = Project.find_by_identifier(params[:project_id]) || (Project.find params[:project_id]) || (Project.find params[:id]) | |||||
| def set_user | |||||
| @user = @project&.owner | @user = @project&.owner | ||||
| # normal_status(-1, "项目不存在") unless @project.present? | |||||
| normal_status(-1, "用户不存在") unless @user.present? | |||||
| end | end | ||||
| def check_project_public | def check_project_public | ||||
| @@ -388,7 +404,7 @@ class IssuesController < ApplicationController | |||||
| end | end | ||||
| def check_issue_permission | def check_issue_permission | ||||
| unless @project.member?(current_user) || current_user.admin? || (@project.user_id == current_user.id) | |||||
| unless @project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id))) | |||||
| normal_status(-1, "您没有权限") | normal_status(-1, "您没有权限") | ||||
| end | end | ||||
| end | end | ||||
| @@ -420,14 +436,56 @@ class IssuesController < ApplicationController | |||||
| tracker_array | tracker_array | ||||
| end | end | ||||
| def get_branches | |||||
| all_branches = [] | |||||
| get_all_branches = Gitea::Repository::BranchesService.new(@user, @project&.repository.try(:identifier)).call | |||||
| if get_all_branches && get_all_branches.size > 0 | |||||
| get_all_branches.each do |b| | |||||
| all_branches.push(b["name"]) | |||||
| end | |||||
| def issue_send_params(params) | |||||
| { | |||||
| subject: params[:subject], | |||||
| description: params[:description], | |||||
| is_private: params[:is_private] || false, | |||||
| assigned_to_id: params[:assigned_to_id], | |||||
| tracker_id: params[:tracker_id], | |||||
| status_id: params[:status_id], | |||||
| priority_id: params[:priority_id], | |||||
| fixed_version_id: params[:fixed_version_id], | |||||
| start_date: params[:start_date].to_s.to_date || Time.current.to_date, | |||||
| due_date: params[:due_date].to_s.to_date, | |||||
| estimated_hours: params[:estimated_hours], | |||||
| done_ratio: params[:done_ratio], | |||||
| issue_type: params[:issue_type] || "1", | |||||
| token: params[:token], | |||||
| issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "", | |||||
| closed_on: (params[:status_id].to_i == 5) ? Time.current : nil, | |||||
| branch_name: params[:branch_name].to_s, | |||||
| issue_classify: "issue", | |||||
| author_id: current_user.id, | |||||
| project_id: @project.id | |||||
| } | |||||
| end | |||||
| def post_to_chain(type, amount,login) | |||||
| change_params = { | |||||
| type: type, | |||||
| chain_params: { | |||||
| amount: amount, | |||||
| reponame: @project.try(:identifier), | |||||
| username: login | |||||
| } | |||||
| } | |||||
| PostChainJob.perform_later(change_params) | |||||
| end | |||||
| def check_token_enough | |||||
| if params[:issue_type].to_s == "2" && (@issue.blank? || (@issue.present? && @issue.author_id == current_user.try(:id))) | |||||
| return normal_status(-1, "悬赏的奖金必须大于0") if params[:token].to_i == 0 | |||||
| query_params = { | |||||
| type: "query", | |||||
| chain_params: { | |||||
| reponame: @project.try(:identifier), | |||||
| username: current_user.try(:login) | |||||
| } | |||||
| } | |||||
| response = Gitea::Chain::ChainGetService.new(query_params).call | |||||
| return normal_status(-1, "获取token失败,请稍后重试") if response.status != 200 | |||||
| return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i | |||||
| end | end | ||||
| all_branches | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,77 +0,0 @@ | |||||
| class ItemBanksController < ApplicationController | |||||
| include PaginateHelper | |||||
| before_action :require_login | |||||
| before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public] | |||||
| before_action :find_item, except: [:index, :create] | |||||
| before_action :edit_auth, only: [:update, :destroy, :set_public] | |||||
| before_action :identity_auth, only: [:index] | |||||
| def index | |||||
| items = ItemBankQuery.call(params) | |||||
| @items_count = items.size | |||||
| @items = paginate items.includes(:item_analysis, :user, :container) | |||||
| exam = ExaminationBank.find_by(id: params[:exam_id]) if params[:exam_id].present? | |||||
| exam_setting = ExaminationIntelligentSetting.find_by(id: params[:exam_setting_id]) if params[:exam_setting_id].present? | |||||
| @item_basket_ids = if exam | |||||
| exam.examination_items.pluck(:item_bank_id) | |||||
| elsif exam_setting | |||||
| exam_setting.item_baskets.pluck(:item_bank_id) | |||||
| else | |||||
| current_user.item_baskets.pluck(:item_bank_id) | |||||
| end | |||||
| end | |||||
| def create | |||||
| item = ItemBank.new(user: current_user) | |||||
| ItemBanks::SaveItemService.call(item, form_params) | |||||
| render_ok | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def edit | |||||
| end | |||||
| def update | |||||
| ItemBanks::SaveItemService.call(@item, form_params) | |||||
| render_ok | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def destroy | |||||
| ActiveRecord::Base.transaction do | |||||
| ApplyAction.where(container_type: "ItemBank", container_id: @item.id).destroy_all | |||||
| if @item.item_type == "PROGRAM" | |||||
| @item.container&.destroy! | |||||
| else | |||||
| @item.destroy! | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| end | |||||
| def set_public | |||||
| tip_exception(-1, "该试题已公开") if @item.public? | |||||
| tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @item.id, container_type: 'ItemBank', status: 0).exists? | |||||
| ApplyAction.create!(container_id: @item.id, container_type: 'ItemBank', user_id: current_user.id) | |||||
| # @item.update_attributes!(public: 1) | |||||
| render_ok | |||||
| end | |||||
| private | |||||
| def find_item | |||||
| @item = ItemBank.find_by!(id: params[:id]) | |||||
| end | |||||
| def edit_auth | |||||
| current_user.admin_or_business? || @item.user == current_user | |||||
| end | |||||
| def form_params | |||||
| params.permit(:discipline_id, :sub_discipline_id, :item_type, :difficulty, :name, :analysis, tag_discipline_id: [], choices: %i[choice_text is_answer]) | |||||
| end | |||||
| end | |||||
| @@ -1,96 +0,0 @@ | |||||
| class ItemBasketsController < ApplicationController | |||||
| before_action :require_login | |||||
| before_action :certi_identity_auth, only: [:create, :delete_item_type, :destroy, :set_score, :batch_set_score, :adjust_position] | |||||
| before_action :validate_score, only: [:set_score, :batch_set_score] | |||||
| helper_method :current_basket | |||||
| def index | |||||
| @item_baskets = basket_items | |||||
| @single_questions = @item_baskets.where(item_type: "SINGLE") | |||||
| @multiple_questions = @item_baskets.where(item_type: "MULTIPLE") | |||||
| @judgement_questions = @item_baskets.where(item_type: "JUDGMENT") | |||||
| @program_questions = @item_baskets.where(item_type: "PROGRAM") | |||||
| end | |||||
| def basket_list | |||||
| @basket_count = current_user.item_baskets.group(:item_type).count | |||||
| end | |||||
| def create | |||||
| ItemBaskets::SaveItemBasketService.call(current_user, create_params, exam_setting) | |||||
| render_ok | |||||
| rescue ApplicationService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| def destroy | |||||
| item = basket_items.find_by!(item_bank_id: params[:id]) | |||||
| ActiveRecord::Base.transaction do | |||||
| basket_items.where(item_type: item.item_type).where("position > #{item.position}").update_all("position = position -1") | |||||
| item.destroy! | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| def delete_item_type | |||||
| baskets = basket_items.where(item_type: params[:item_type]) | |||||
| baskets.destroy_all | |||||
| render_ok | |||||
| end | |||||
| def set_score | |||||
| current_basket.update_attributes!(score: params[:score]) | |||||
| @questions_score = basket_items.where(item_type: current_basket.item_type).pluck(:score).sum | |||||
| @all_score = basket_items.pluck(:score).sum | |||||
| end | |||||
| def batch_set_score | |||||
| basket_items.where(item_type: params[:item_type]).update_all(score: params[:score]) | |||||
| @questions_score = basket_items.where(item_type: params[:item_type]).pluck(:score).sum | |||||
| @all_score = basket_items.pluck(:score).sum | |||||
| end | |||||
| def adjust_position | |||||
| same_items = basket_items.where(item_type: current_basket.item_type) | |||||
| max_position = same_items.size | |||||
| tip_exception("position超出范围") unless params[:position].present? && params[:position].to_i <= max_position && params[:position].to_i >= 1 | |||||
| ActiveRecord::Base.transaction do | |||||
| if params[:position].to_i > current_basket.position | |||||
| same_items.where("position > #{current_basket.position} and position <= #{params[:position].to_i}").update_all("position=position-1") | |||||
| current_basket.update_attributes!(position: params[:position]) | |||||
| elsif params[:position].to_i < current_basket.position | |||||
| same_items.where("position < #{current_basket.position} and position >= #{params[:position].to_i}").update_all("position=position+1") | |||||
| current_basket.update_attributes!(position: params[:position]) | |||||
| else | |||||
| return normal_status(-1, "排序无变化") | |||||
| end | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| private | |||||
| def create_params | |||||
| params.permit(item_ids: []) | |||||
| end | |||||
| def exam_setting | |||||
| @_exam_setting = ExaminationIntelligentSetting.find_by(id: params[:exam_setting_id]) | |||||
| end | |||||
| def basket_items | |||||
| @_items = params[:exam_setting_id] ? exam_setting.item_baskets : current_user.item_baskets | |||||
| end | |||||
| def current_basket | |||||
| @_current_basket = ItemBasket.find_by!(id: params[:id]) | |||||
| tip_exception(403, "无权限编辑") unless current_user.admin_or_business? || @_current_basket.user_id.to_i == current_user.id || | |||||
| @_current_basket.examination_intelligent_setting&.user_id.to_i == current_user.id | |||||
| @_current_basket | |||||
| end | |||||
| def validate_score | |||||
| tip_exception("分值不能为空") unless params[:score].present? | |||||
| tip_exception("分值需大于0") unless params[:score].to_f > 0 | |||||
| end | |||||
| end | |||||
| @@ -1,5 +1,5 @@ | |||||
| class JournalsController < ApplicationController | class JournalsController < ApplicationController | ||||
| before_action :require_login | |||||
| before_action :require_login, except: [:index, :get_children_journals] | |||||
| before_action :set_issue | before_action :set_issue | ||||
| before_action :check_issue_permission | before_action :check_issue_permission | ||||
| before_action :set_journal, only: [:destroy, :edit, :update] | before_action :set_journal, only: [:destroy, :edit, :update] | ||||
| @@ -7,9 +7,13 @@ class JournalsController < ApplicationController | |||||
| def index | def index | ||||
| @page = params[:page] || 1 | @page = params[:page] || 1 | ||||
| @limit = params[:limit] || 10 | @limit = params[:limit] || 10 | ||||
| journals = @issue.journals.journal_includes.order("created_on desc") | |||||
| @journals_size = journals.size | |||||
| @journals = journals.parent_journals.page(@page).per(@limit) | |||||
| total_journals = @issue.journals.journal_includes | |||||
| @jounals_total = total_journals.size | |||||
| parent_journals = total_journals.parent_journals.order("created_on desc") | |||||
| @journals = parent_journals.order("created_on desc").page(@page).per(@limit) | |||||
| @journals_size = parent_journals.size | |||||
| end | end | ||||
| def create | def create | ||||
| @@ -39,8 +43,8 @@ class JournalsController < ApplicationController | |||||
| end | end | ||||
| # @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "journal") | # @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "journal") | ||||
| normal_status(0, "评论成功") | |||||
| render :json => { status: 0, message: "评论成功", id: journal.id} | |||||
| # normal_status(0, "评论成功") | |||||
| else | else | ||||
| normal_status(-1, "评论失败") | normal_status(-1, "评论失败") | ||||
| end | end | ||||
| @@ -49,6 +53,7 @@ class JournalsController < ApplicationController | |||||
| def destroy | def destroy | ||||
| if @journal.destroy #如果有子评论,子评论删除吗? | if @journal.destroy #如果有子评论,子评论删除吗? | ||||
| Journal.children_journals(@journal.id).destroy_all | |||||
| normal_status(0, "评论删除成功") | normal_status(0, "评论删除成功") | ||||
| else | else | ||||
| normal_status(-1, "评论删除失败") | normal_status(-1, "评论删除失败") | ||||
| @@ -73,6 +78,14 @@ class JournalsController < ApplicationController | |||||
| end | end | ||||
| def get_children_journals | |||||
| @page = params[:page] || 1 | |||||
| @limit = params[:limit] || 10 | |||||
| journals = Journal.children_journals(params[:id]).journal_includes.order("created_on desc") | |||||
| @journals_size = journals.size | |||||
| @children_journals = journals.page(@page).per(@limit) | |||||
| end | |||||
| private | private | ||||
| @@ -1,5 +1,7 @@ | |||||
| class LicensesController < ApplicationController | class LicensesController < ApplicationController | ||||
| def index | def index | ||||
| @licenses = License.search(params[:name]).without_content | |||||
| #@licenses = License.search(params[:name]). | |||||
| q = License.ransack(name_cont: params[:name]) | |||||
| @licenses = q.result(distinct: true) | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,13 +1,13 @@ | |||||
| class MembersController < ApplicationController | class MembersController < ApplicationController | ||||
| before_action :require_login | before_action :require_login | ||||
| before_action :find_project_with_id | |||||
| before_action :load_project | |||||
| before_action :find_user_with_id, only: %i[create remove change_role] | before_action :find_user_with_id, only: %i[create remove change_role] | ||||
| before_action :operate!, except: %i[index] | before_action :operate!, except: %i[index] | ||||
| before_action :check_member_exists!, only: %i[create] | before_action :check_member_exists!, only: %i[create] | ||||
| before_action :check_member_not_exists!, only: %i[remove change_role] | before_action :check_member_not_exists!, only: %i[remove change_role] | ||||
| def create | def create | ||||
| interactor = Projects::AddMemberInteractor.call(current_user, @project, @user) | |||||
| interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user) | |||||
| render_response(interactor) | render_response(interactor) | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -16,12 +16,17 @@ class MembersController < ApplicationController | |||||
| def index | def index | ||||
| scope = @project.members.includes(:roles, user: :user_extension) | scope = @project.members.includes(:roles, user: :user_extension) | ||||
| search = params[:search].to_s.downcase | |||||
| role = params[:role].to_s | |||||
| scope = scope.joins(:user).where("LOWER(concat(users.lastname, users.firstname, users.login, users.mail)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present? | |||||
| scope = scope.joins(:roles).where("roles.name LIKE ?", "%#{role}%") if role.present? | |||||
| @total_count = scope.size | @total_count = scope.size | ||||
| @members = paginate(scope) | @members = paginate(scope) | ||||
| end | end | ||||
| def remove | def remove | ||||
| interactor = Projects::DeleteMemberInteractor.call(current_user, @project, @user) | |||||
| interactor = Projects::DeleteMemberInteractor.call(@project.owner, @project, @user) | |||||
| render_response(interactor) | render_response(interactor) | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -29,7 +34,7 @@ class MembersController < ApplicationController | |||||
| end | end | ||||
| def change_role | def change_role | ||||
| interactor = Projects::ChangeMemberRoleInteractor.call(current_user, @project, @user, params[:role]) | |||||
| interactor = Projects::ChangeMemberRoleInteractor.call(@project.owner, @project, @user, params[:role]) | |||||
| render_response(interactor) | render_response(interactor) | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -1,199 +0,0 @@ | |||||
| class MemosController < ApplicationController | |||||
| before_action :require_login, except: [:show, :index] | |||||
| before_action :check_account, only: [:new, :create, :reply] | |||||
| before_action :set_memo, only: [:show, :edit, :update, :destroy, :sticky_or_cancel, :hidden, :more_reply] | |||||
| before_action :validate_memo_params, only: [:create, :update] | |||||
| before_action :owner_or_admin, only: [:edit, :update, :destroy] | |||||
| before_action :require_business, only: [:sticky_or_cancel, :hidden] | |||||
| include ApplicationHelper | |||||
| # GET /memos | |||||
| # GET /memos.json | |||||
| def index | |||||
| @user = current_user | |||||
| @memos = Memo.all | |||||
| s_order = (params[:order] == "replies_count" ? "all_replies_count" : params[:order]) || "updated_at" | |||||
| # @tidding_count = unviewed_tiddings(current_user) if current_user.present? | |||||
| page = params[:page] || 1 | |||||
| limit = params[:limit] || 15 | |||||
| search = params[:search] | |||||
| forum_id = params[:forum] | |||||
| tag_repertoire_id = params[:tag_repertoire_id] | |||||
| sql = | |||||
| if forum_id | |||||
| !search.blank? ? "forum_id = #{forum_id} and root_id is null and subject like '%#{search}%'" : | |||||
| "forum_id = #{forum_id} and root_id is null" | |||||
| elsif !search.blank? | |||||
| "forum_id in(3, 5, 16) and root_id is null and subject like '%#{search}%'" | |||||
| else | |||||
| "forum_id in(3, 5, 16) and root_id is null" | |||||
| end | |||||
| if tag_repertoire_id | |||||
| memo_ids = MemoTagRepertoire.where(tag_repertoire_id: tag_repertoire_id).pluck(:memo_id) | |||||
| memo_ids = memo_ids ? memo_ids.join(",") : -1 | |||||
| sql += " and #{Memo.table_name}.id in(#{memo_ids})" | |||||
| end | |||||
| if params[:order] == "updated_at" | |||||
| sql += " and all_replies_count != 0" | |||||
| end | |||||
| memos = Memo.field_for_list.where("#{sql}") | |||||
| @memos_count = memos.length | |||||
| @memos = memos.order("sticky = 1 desc, #{Memo.table_name}.#{s_order} desc").page(page).per(limit) | |||||
| @memos = @memos.includes(:praise_treads, :tag_repertoires, author: :user_extension) | |||||
| # @my_memos_count = Memo.user_posts(current_user.try(:id)).count | |||||
| @tags_info = MemoTagRepertoire.find_by_sql("SELECT tag_repertoire_id, tr.name, count(*) cnt | |||||
| FROM memo_tag_repertoires mtr join tag_repertoires tr on | |||||
| tr.id = mtr.tag_repertoire_id group by tag_repertoire_id order by cnt desc, | |||||
| tag_repertoire_id desc limit 9") | |||||
| @hot_memos = Memo.field_for_recommend.posts.hot.includes(:tag_repertoires).limit(4) | |||||
| @recommend_shixuns = DiscussesService.new.recommends | |||||
| end | |||||
| # GET /memos/1.json | |||||
| def show | |||||
| # tidding_count = unviewed_tiddings(current_user) if current_user | |||||
| @user = current_user | |||||
| @memo.update_column(:viewed_count, @memo.viewed_count+1) | |||||
| @memos = @memo.reply_for_memo.includes(:praise_treads, author: :user_extension).order("created_at desc").limit(10) | |||||
| @attachments = @memo.attachments | |||||
| @recommend_shixuns = DiscussesService.new.recommends | |||||
| end | |||||
| # GET /memos/new | |||||
| def new | |||||
| @tag_list = TagRepertoire.field_for_list.order("name asc") | |||||
| end | |||||
| # GET /memos/1/edit | |||||
| def edit | |||||
| @tag_list = TagRepertoire.field_for_list.order("name asc") | |||||
| @memo_tags = @memo.tag_repertoires.field_for_list | |||||
| @attachments = @memo.attachments | |||||
| end | |||||
| # POST /memos.json | |||||
| def create | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @memo = Memo.new(memo_params) | |||||
| @memo.author = current_user | |||||
| @memo.save! | |||||
| Attachment.associate_container(params[:attachment_ids], @memo.id, @memo.class.name) | |||||
| params[:tags].each do |tag| | |||||
| MemoTagRepertoire.create!(memo_id: @memo.id, tag_repertoire_id: tag) | |||||
| end | |||||
| render :json => {memo_id: @memo.id, status: 0, message: "帖子创建成功"} | |||||
| rescue Exception => e | |||||
| tip_exception("帖子创建失败,原因:#{e}") | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # PATCH/PUT /memos/1.json | |||||
| def update | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @memo.update_attributes!(memo_params) | |||||
| Attachment.associate_container(params[:attachment_ids], @memo.id, @memo.class.name) | |||||
| @memo.memo_tag_repertoires.destroy_all | |||||
| params[:tags].each do |tag| | |||||
| MemoTagRepertoire.create!(memo_id: @memo.id, tag_repertoire_id: tag) | |||||
| end | |||||
| normal_status("帖子更新成功") | |||||
| rescue Exception => e | |||||
| tip_exception("帖子更新失败,原因:#{e}") | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # DELETE /memos/1 | |||||
| # DELETE /memos/1.json | |||||
| def destroy | |||||
| @memo.destroy | |||||
| normal_status("删除成功") | |||||
| end | |||||
| def sticky_or_cancel | |||||
| tip_exception("只能对主贴进行置顶操作") unless @memo.parent_id.nil? | |||||
| begin | |||||
| @memo.update_attributes!(sticky: !@memo.sticky) | |||||
| normal_status("更新成功") | |||||
| rescue Exception => e | |||||
| tip_exception("更新失败,原因:#{e}") | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def hidden | |||||
| tip_exception("不能对主贴进行隐藏操作") if @memo.parent_id.nil? | |||||
| begin | |||||
| @memo.update_attributes!(hidden: @memo.hidden == 0 ? 1 : 0) | |||||
| normal_status("更新成功") | |||||
| rescue Exception => e | |||||
| tip_exception("更新失败,原因:#{e}") | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def reply | |||||
| tip_exception("parent_id不能为空") if params[:parent_id].blank? | |||||
| tip_exception("content不能为空") if params[:content].blank? | |||||
| tip_exception("内容不能超过2000字符") if params[:content].length > 2000 | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| memo = Memo.find_by!(id: params[:parent_id]) | |||||
| @reply = Memo.new | |||||
| @reply.content = params[:content] | |||||
| @reply.author = current_user | |||||
| @reply.forum_id = memo.forum_id | |||||
| @reply.subject = memo.subject | |||||
| @reply.root_id = memo.root_id || memo.id | |||||
| memo.children << @reply | |||||
| m = Memo.find_by!(id: @reply.root_id) | |||||
| m.update_attributes!(all_replies_count: m.all_replies_count + 1) | |||||
| rescue Exception => e | |||||
| tip_exception("回复失败,原因:#{e}") | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def more_reply | |||||
| @user = current_user | |||||
| page = params[:page] || 2 | |||||
| limit = params[:limit] || 10 | |||||
| offset = (page.to_i - 1) * limit | |||||
| @memos_count = Memo.where(parent_id: @memo.id).count | |||||
| @memos = Memo.limit(limit).where(parent_id: @memo.id).includes(:author, :praise_treads).order("created_at desc").offset(offset) | |||||
| end | |||||
| private | |||||
| # Use callbacks to share common setup or constraints between actions. | |||||
| def set_memo | |||||
| @memo = Memo.find(params[:id]) | |||||
| end | |||||
| def owner_or_admin | |||||
| tip_exception(403, "无权限操作") unless @memo.author == current_user || current_user.admin? || current_user.business? | |||||
| end | |||||
| # Never trust parameters from the scary internet, only allow the white list through. | |||||
| def memo_params | |||||
| params.require(:memo).permit(:subject, :content, :forum_id) | |||||
| end | |||||
| def validate_memo_params | |||||
| tip_exception("话题名称不能为空") if params[:subject].blank? | |||||
| tip_exception("话题内容不能为空") if params[:content].blank? | |||||
| tip_exception("话题类型不能为空") if params[:forum_id].blank? | |||||
| tip_exception("技术标签不能为空") if params[:forum_id].to_i == 5 && params[:tags].blank? | |||||
| end | |||||
| end | |||||
| @@ -1,225 +0,0 @@ | |||||
| class MessagesController < ApplicationController | |||||
| include MessagesHelper | |||||
| SORT_TYPE = %w[time hot] | |||||
| before_action :require_login, :check_auth, only: %i[create update sticky_top bulk_delete create destroy bulk_send bulk_move bulk_public] | |||||
| before_action :find_board, only: [:create, :index, :bulk_delete, :bulk_move, :bulk_send, :bulk_public] | |||||
| before_action :find_message, only: [:update, :destroy, :sticky_top, :reply_list, :destroy, :reply] | |||||
| before_action :validate_delete_params, only: %i[bulk_delete bulk_public] | |||||
| before_action :message_validate_create_params, only: :create | |||||
| before_action :validate_update_params, only: :update | |||||
| before_action :validate_sort_type, only: :index | |||||
| before_action :validate_send_message_to_course_params, only: :bulk_send | |||||
| before_action :validate_move_params, only: :bulk_move | |||||
| def index | |||||
| @page = params[:page] || 1 | |||||
| @page_size = params[:page_size] || 15 | |||||
| sort = params[:sort].to_i == 1 ? 'asc' : 'desc' | |||||
| sort_type = params[:sort_type] || 'time' | |||||
| if @board.parent_id == 0 | |||||
| messages = Message.where(board_id: @board.course.boards.pluck(:id)) | |||||
| else | |||||
| messages = @board.messages | |||||
| end | |||||
| messages = messages.root_nodes.by_keywords(params[:search]) | |||||
| messages = messages.reorder('(sticky = 1) DESC') # 置顶 | |||||
| messages = | |||||
| case sort_type | |||||
| when 'time' then messages.order("created_on #{sort}") | |||||
| when 'hot' then messages.order("descendants_count #{sort}") | |||||
| else messages.order("created_on #{sort}") | |||||
| end | |||||
| messages = messages.includes(:author, :board) | |||||
| @messages = Kaminari.paginate_array(messages).page(@page).per(@page_size) | |||||
| ids = @messages.map(&:id) | |||||
| @praises_count_map = Message.where(root_id: ids).group(:root_id).sum(:praises_count) | |||||
| end | |||||
| def reply_list | |||||
| @page = params[:page] || 1 | |||||
| @page_size = params[:page_size] || 10 | |||||
| @current_user = current_user || nil | |||||
| @messages = @message.children.preload_messages.includes(:message_detail, :praise_treads) | |||||
| # @messages = @messages.ordered(sort: 1) unless @message.parent_id.nil? | |||||
| @user_course_identity = current_user.course_identity(@message.board.course) | |||||
| case @user_course_identity | |||||
| when 5, 6, 7 | |||||
| @messages = @messages.visible | |||||
| end | |||||
| @messages = @messages.reorder("messages.created_on desc") | |||||
| @messages = @messages.page(@page).per(@page_size) | |||||
| end | |||||
| def reply | |||||
| return normal_status(-1, "回复内容不能为空") if params[:content].blank? | |||||
| return normal_status(-1, "回复内容不能超过2000字符") if params[:content].length > 2000 | |||||
| @reply = Message.create!(board: @message.board, root_id: @message.root_id || @message.id, | |||||
| author: current_user, parent: @message, | |||||
| message_detail_attributes: { | |||||
| content: params[:content] | |||||
| }) | |||||
| end | |||||
| def sticky_top | |||||
| return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@message.board.course) | |||||
| @message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1) | |||||
| end | |||||
| def bulk_delete | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @messages = @board.messages.by_ids(params[:ids]) | |||||
| @messages.destroy_all | |||||
| rescue Exception => e | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def new | |||||
| @message = Message.new | |||||
| end | |||||
| def show | |||||
| @message = Message.includes(:attachments, :message_detail, | |||||
| :children, :author => :user_extension, | |||||
| :board => [{course: :board_course_modules}]) | |||||
| .find_by_id params[:id] | |||||
| return normal_status(-2, "ID为#{params[:id]}的帖子不存在") if @message.nil? | |||||
| @attachment_size = @message.attachments.size | |||||
| @message.update_visits | |||||
| @current_user = current_user | |||||
| end | |||||
| def update | |||||
| return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course) | |||||
| begin | |||||
| board = @message.board&.course&.boards.find_by!(id: params[:select_board_id]) | |||||
| email_notify = @message.email_notify ? 1 : @message.board&.course.email_notify && params[:email_notify] | |||||
| send_email = !@message.email_notify && email_notify | |||||
| h = {is_md: true, email_notify: email_notify, board_id: board&.id} | |||||
| m_params = message_params.merge(h) | |||||
| @message.update_attributes(m_params) | |||||
| Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name) | |||||
| @message.update_content(params[:content]) | |||||
| notify_course_students(@message, @message.board&.course) if send_email | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def create | |||||
| return normal_status(403, "您没有权限进行该操作") unless current_user.admin_or_business? || current_user.member_of_course?(@board.course) | |||||
| begin | |||||
| @message = Message.new(message_params) | |||||
| @message.author = current_user | |||||
| @message.board_id = params[:select_board_id] | |||||
| @message.message_detail_attributes = {content: params[:content]} | |||||
| @message.email_notify = @board.course.email_notify && params[:email_notify] ? 1 : 0 | |||||
| @message.save! | |||||
| Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name) | |||||
| if @board.course.email_notify && params[:email_notify] | |||||
| notify_course_students @message, @board.course | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def destroy | |||||
| begin | |||||
| return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@message.board.course) >= 5 || @message.author != current_user | |||||
| @message.destroy! | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def bulk_send | |||||
| return normal_status(403) unless current_user.teacher_or_admin?(@board.course) | |||||
| ids = params[:ids] | |||||
| course_ids = params[:to_course_ids] | |||||
| begin | |||||
| ids.each do |id| | |||||
| @message = Message.find_by_id id | |||||
| if @message.try(:parent_id).nil? # TODO 暂时只支持目录下的跟节点发送 | |||||
| course_ids.each do |course_id| | |||||
| course = Course.find course_id | |||||
| new_message = Message.create!(board: course.course_board, | |||||
| subject: @message.subject, | |||||
| author: current_user, | |||||
| message_detail_attributes: { | |||||
| content: @message.try(:message_detail).try(:content) | |||||
| } | |||||
| ) | |||||
| @message.copy_attachments_to_new_message(new_message, current_user) | |||||
| end | |||||
| end | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| def bulk_move | |||||
| # 课堂的目录之间移动,有子栏目的才显示此项 | |||||
| return normal_status(403) unless current_user.teacher_of_course?(@board.course) | |||||
| Message.bulk_move_to_other_board(params[:ids], params[:to_board_id]) | |||||
| end | |||||
| def bulk_public | |||||
| @messages = @board.messages.root_nodes.by_ids Array(params[:ids]) | |||||
| @messages.update_all(is_public: true) | |||||
| end | |||||
| private | |||||
| def validate_sort_type | |||||
| normal_status(2, "参数sort_type暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip) | |||||
| end | |||||
| def find_message | |||||
| begin | |||||
| @message = Message.find params[:id] | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| end | |||||
| end | |||||
| def message_params | |||||
| params.require(:message).permit(:subject, :sticky) | |||||
| end | |||||
| def notify_course_students message, course | |||||
| course.students.includes(:user).each do |student| | |||||
| UserMailer.course_message_email(student&.user&.mail, message.id).deliver_later if student&.user&.mail | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,35 @@ | |||||
| class Oauth::EducoderController < Oauth::BaseController | |||||
| def bind | |||||
| begin | |||||
| login = params[:login] | |||||
| mail = params[:mail] || nil | |||||
| callback_url = params[:callback_url] | |||||
| token = params[:token] | |||||
| ::OauthEducoderForm.new({login: login, token: token, callback_url: callback_url}).validate! | |||||
| open_user= OpenUsers::Educoder.find_by(uid: login) || OpenUsers::Educoder.find_by(uid: mail) | |||||
| if open_user.present? && open_user.user.present? && open_user.user.email_binded? | |||||
| Rails.logger.info "######## open_user exist and open_user.user exsit and email is binded ok" | |||||
| successful_authentication(open_user.user) | |||||
| redirect_to callback_url | |||||
| else | |||||
| Rails.logger.info "######## open user not exits" | |||||
| user = User.find_by(login: login) || User.find_by(mail: mail) | |||||
| if user.is_a?(User) && !user.is_a?(AnonymousUser) | |||||
| OpenUsers::Educoder.create!(user: user, uid: login) | |||||
| successful_authentication(user) | |||||
| redirect_to callback_url | |||||
| else | |||||
| redirect_to oauth_register_path(login: login, mail: mail, callback_url: callback_url) | |||||
| end | |||||
| end | |||||
| rescue WechatOauth::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,4 +1,6 @@ | |||||
| class OauthController < ApplicationController | class OauthController < ApplicationController | ||||
| layout "oauth_register", only: [:register] | |||||
| DEFAULT_PASSWORD = "a12345678" | DEFAULT_PASSWORD = "a12345678" | ||||
| TOKEN_CALL_BACK = "/oauth/get_token_callback" | TOKEN_CALL_BACK = "/oauth/get_token_callback" | ||||
| USER_INFO = "/oauth/userinfo" | USER_INFO = "/oauth/userinfo" | ||||
| @@ -51,4 +53,35 @@ class OauthController < ApplicationController | |||||
| def get_token_callback | def get_token_callback | ||||
| end | end | ||||
| def register | |||||
| end | |||||
| def auto_register | |||||
| login = params[:login] | |||||
| email = params[:mail] | |||||
| password = params[:password] | |||||
| callback_url = params[:callback_url] | |||||
| platform = params[:plathform] || 'educoder' | |||||
| if User.where(mail: email).exists? | |||||
| render json: { email_exist: '该邮箱已使用过' } | |||||
| else | |||||
| result = autologin_register(login, email, password, platform) | |||||
| logger.info "[Oauth educoer] =====#{result}" | |||||
| if result[:message].blank? | |||||
| logger.info "[Oauth educoer] ====auto_register success" | |||||
| user = User.find result[:user][:id] | |||||
| successful_authentication(user) | |||||
| OpenUsers::Educoder.create!(user: user, uid: user.login) | |||||
| render json: { callback_url: callback_url } | |||||
| # redirect_to callback_url | |||||
| else | |||||
| logger.info "[Oauth educoer] ====auto_register failed." | |||||
| render :action => "auto_register" | |||||
| end | |||||
| end | |||||
| end | |||||
| end | end | ||||
| @@ -1,138 +0,0 @@ | |||||
| class PartnersController < ApplicationController | |||||
| skip_before_action :check_sign | |||||
| include Base::PaginateHelper | |||||
| include Admins::RenderHelper | |||||
| layout 'college' | |||||
| before_action :require_login, :check_partner_present!, :check_permission! | |||||
| before_action :check_admin_manager_group_permission!, except: [:customers] | |||||
| helper_method :current_partner, :manager_permission? | |||||
| def customers | |||||
| customers = CustomerQuery.call(current_partner, current_user, params) | |||||
| @customers = paginate(customers.includes(:school)) | |||||
| load_customer_extra_statistic_data | |||||
| end | |||||
| def partner_manager_groups | |||||
| @manager_groups = current_partner.partner_manager_groups.includes(users: :user_extension).to_a | |||||
| end | |||||
| def manager_group | |||||
| name = params[:manager_group_name].to_s.strip | |||||
| if params[:manager_group_id].present? | |||||
| # 重命名 | |||||
| @manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id]) | |||||
| return render_error('不能修改管理者权限组名称') if @manager_group.admin? | |||||
| @manager_group.update!(name: name) | |||||
| else | |||||
| # 新建 | |||||
| @manager_group = current_partner.partner_manager_groups.create!(name: name) | |||||
| end | |||||
| end | |||||
| def remove_manager_group | |||||
| manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id]) | |||||
| return render_error('不能删除管理者权限组') if manager_group.admin? | |||||
| manager_group.destroy! | |||||
| render_delete_success | |||||
| end | |||||
| def partner_managers | |||||
| user_ids = Array.wrap(params[:user_ids]) | |||||
| @manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id]) | |||||
| ActiveRecord::Base.transaction do | |||||
| User.where(id: user_ids).pluck(:id).each do |user_id| | |||||
| next if current_partner.partner_managers.exists?(partner_manager_group: @manager_group, user_id: user_id) | |||||
| current_partner.partner_managers.create!(partner_manager_group: @manager_group, user_id: user_id) | |||||
| end | |||||
| end | |||||
| @manager_group.reload | |||||
| end | |||||
| def remove_partner_manager | |||||
| partner_manager = current_partner.partner_managers.find(params[:manager_id]) | |||||
| return render_error('不能删除自己') if partner_manager.user_id == current_user.id && partner_manager.partner_manager_group.admin? | |||||
| partner_manager.destroy! | |||||
| render_delete_success | |||||
| end | |||||
| def customer_manager_group | |||||
| customer = current_partner.customers.find(params[:customer_id]) | |||||
| if params[:manager_group_id].present? | |||||
| manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id]) | |||||
| customer.update!(partner_manager_group: manager_group) | |||||
| else | |||||
| customer.update!(partner_manager_group_id: nil) | |||||
| end | |||||
| render_ok | |||||
| end | |||||
| private | |||||
| def current_partner | |||||
| @_current_partner ||= Partner.find(params[:id].presence || params[:partner_id]) | |||||
| end | |||||
| def check_partner_present! | |||||
| return if current_partner.present? | |||||
| redirect_to '/404' | |||||
| end | |||||
| def manager_permission? | |||||
| admin_or_business? || current_user.partner_managers.exists?(partner_id: current_partner.id) | |||||
| end | |||||
| def check_permission! | |||||
| return if manager_permission? | |||||
| redirect_to '/403' | |||||
| end | |||||
| def check_admin_manager_group_permission! | |||||
| return if admin_or_business? | |||||
| return if current_partner.admin_partner_manager_group.partner_managers.exists?(user: current_user) | |||||
| render_forbidden | |||||
| end | |||||
| def load_customer_extra_statistic_data | |||||
| school_ids = @customers.map(&:school_id) | |||||
| teacher_map = UserExtension.where(school_id: school_ids, identity: 0).group(:school_id).count | |||||
| student_map = UserExtension.where(school_id: school_ids, identity: 1).group(:school_id).count | |||||
| course_map = Course.where(school_id: school_ids, is_delete: 0).where.not(id: 1309).group(:school_id).count | |||||
| shixun_map = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id') | |||||
| .where(user_extensions: { school_id: school_ids }).group('user_extensions.school_id').count | |||||
| shixun_report_map = StudentWork.where(work_status: [1, 2]).where('myshixun_id != 0') | |||||
| .joins('left join user_extensions on user_extensions.user_id = student_works.user_id') | |||||
| .where(user_extensions: { school_id: school_ids }) | |||||
| .group('user_extensions.school_id').count | |||||
| course_time_map = Course.where(school_id: school_ids, is_delete: 0) | |||||
| .where.not(id: 1309).group(:school_id).maximum(:updated_at) | |||||
| @customers.each do |customer| | |||||
| customer._extra_data = { | |||||
| teacher_count: teacher_map[customer.school_id], | |||||
| student_count: student_map[customer.school_id], | |||||
| course_count: course_map[customer.school_id], | |||||
| shixun_count: shixun_map[customer.school_id], | |||||
| shixun_report_count: shixun_report_map[customer.school_id], | |||||
| course_time: course_time_map[customer.school_id] | |||||
| } | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -11,7 +11,7 @@ class PraiseTreadController < ApplicationController | |||||
| begin | begin | ||||
| return normal_status(2, "你已点过赞了") if current_user.liked?(@project) | return normal_status(2, "你已点过赞了") if current_user.liked?(@project) | ||||
| current_user.like!(@project) | current_user.like!(@project) | ||||
| render_ok | |||||
| render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)}) | |||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| @@ -23,7 +23,7 @@ class PraiseTreadController < ApplicationController | |||||
| begin | begin | ||||
| return normal_status(2, "你还没有点过赞噢") unless current_user.liked?(@project) | return normal_status(2, "你还没有点过赞噢") unless current_user.liked?(@project) | ||||
| current_user.unlike!(@project) | current_user.unlike!(@project) | ||||
| render_ok | |||||
| render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)}) | |||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| @@ -39,4 +39,9 @@ class PraiseTreadController < ApplicationController | |||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| end | end | ||||
| private | |||||
| def render_result | |||||
| end | |||||
| end | end | ||||
| @@ -1,11 +1,13 @@ | |||||
| class ProjectCategoriesController < ApplicationController | class ProjectCategoriesController < ApplicationController | ||||
| def index | def index | ||||
| @project_categories = ProjectCategory.search(params[:name]).without_content | |||||
| # @project_categories = ProjectCategory.search(params[:name]).without_content | |||||
| q = ProjectCategory.ransack(name_cont: params[:name]) | |||||
| @project_categories = q.result(distinct: true) | |||||
| end | end | ||||
| def group_list | def group_list | ||||
| @category_group_list = | |||||
| Project.visible.joins(:project_category).group(:project_category_id) | |||||
| .select("project_category_id, count(*) AS projects_count, project_categories.name") | |||||
| @project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc) | |||||
| # projects = Project.no_anomory_projects.visible | |||||
| # @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,5 +1,7 @@ | |||||
| class ProjectLanguagesController < ApplicationController | class ProjectLanguagesController < ApplicationController | ||||
| def index | def index | ||||
| @project_languages = ProjectLanguage.search(params[:name]).without_content | |||||
| #@project_languages = ProjectLanguage.search(params[:name]). | |||||
| q = ProjectLanguage.ransack(name_cont: params[:name]) | |||||
| @project_languages = q.result(distinct: true) | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,5 +1,5 @@ | |||||
| class ProjectTrendsController < ApplicationController | class ProjectTrendsController < ApplicationController | ||||
| before_action :find_project | |||||
| before_action :load_repository | |||||
| before_action :check_project_public | before_action :check_project_public | ||||
| def index | def index | ||||
| @@ -44,4 +44,4 @@ class ProjectTrendsController < ApplicationController | |||||
| normal_status(-1, "您没有权限") | normal_status(-1, "您没有权限") | ||||
| end | end | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -1,5 +1,7 @@ | |||||
| class Projects::BaseController < ApplicationController | class Projects::BaseController < ApplicationController | ||||
| include PaginateHelper | include PaginateHelper | ||||
| before_action :require_login, :check_auth | |||||
| before_action :load_project | |||||
| before_action :load_repository | |||||
| end | end | ||||
| @@ -1,20 +1,34 @@ | |||||
| class ProjectsController < ApplicationController | class ProjectsController < ApplicationController | ||||
| include ApplicationHelper | include ApplicationHelper | ||||
| include OperateProjectAbilityAble | include OperateProjectAbilityAble | ||||
| before_action :require_login, except: %i[index branches group_type_list] | |||||
| before_action :find_project_with_id, only: %i[show branches update destroy] | |||||
| include ProjectsHelper | |||||
| before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about] | |||||
| before_action :load_project, except: %i[index group_type_list migrate create recommend] | |||||
| before_action :authorizate_user_can_edit_project!, only: %i[update] | before_action :authorizate_user_can_edit_project!, only: %i[update] | ||||
| before_action :project_public?, only: %i[fork_users praise_users watch_users] | |||||
| def index | def index | ||||
| scope = Projects::ListQuery.call(params) | scope = Projects::ListQuery.call(params) | ||||
| @total_count = scope.size | |||||
| @projects = paginate(scope) | |||||
| # @projects = kaminari_paginate(scope) | |||||
| @projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, owner: :user_extension) | |||||
| category_id = params[:category_id] | |||||
| @total_count = | |||||
| if category_id.blank? | |||||
| ps = ProjectStatistic.first | |||||
| ps.common_projects_count + ps.mirror_projects_count unless ps.blank? | |||||
| else | |||||
| cate = ProjectCategory.find_by(id: category_id) | |||||
| cate&.projects_count || 0 | |||||
| end | |||||
| end | end | ||||
| def create | def create | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| Projects::CreateForm.new(project_params).validate! | Projects::CreateForm.new(project_params).validate! | ||||
| @project = Projects::CreateService.new(current_user, project_params).call | @project = Projects::CreateService.new(current_user, project_params).call | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -22,30 +36,48 @@ class ProjectsController < ApplicationController | |||||
| end | end | ||||
| def migrate | def migrate | ||||
| ActiveRecord::Base.transaction do | |||||
| Projects::MigrateForm.new(mirror_params).validate! | |||||
| @project = Projects::MigrateService.new(current_user, mirror_params).call | |||||
| end | |||||
| Projects::MigrateForm.new(mirror_params).validate! | |||||
| @project = Projects::MigrateService.new(current_user, mirror_params).call | |||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| end | end | ||||
| def branches | def branches | ||||
| @branches = Gitea::Repository::BranchesService.new(@project.owner, @project.identifier).call | |||||
| @branches = @project.forge? ? Gitea::Repository::Branches::ListService.new(@owner, @project.identifier).call : [] | |||||
| end | end | ||||
| def group_type_list | def group_type_list | ||||
| @project_group_list = Project.visible.group(:project_type).select('project_type, count(*) AS projects_count') | |||||
| project_statics = ProjectStatistic.first | |||||
| @project_statics_list = [ | |||||
| { | |||||
| project_type: 'common', | |||||
| name: '开源托管项目', | |||||
| projects_count: project_statics&.common_projects_count || 0 | |||||
| }, | |||||
| { | |||||
| project_type: 'mirror', | |||||
| name: '开源镜像项目', | |||||
| projects_count: project_statics&.mirror_projects_count || 0 | |||||
| } | |||||
| ] | |||||
| # projects = Project.no_anomory_projects.visible | |||||
| # @project_group_list = projects.group(:project_type).size | |||||
| end | end | ||||
| def update | def update | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| # Projects::CreateForm.new(project_params).validate! | # Projects::CreateForm.new(project_params).validate! | ||||
| private = params[:private] | private = params[:private] | ||||
| gitea_params = { | |||||
| private: private, | |||||
| default_branch: params[:default_branch] | |||||
| } | |||||
| if [true, false].include? private | if [true, false].include? private | ||||
| new_project_params = project_params.merge(is_public: !private) | new_project_params = project_params.merge(is_public: !private) | ||||
| Gitea::Repository::UpdateService.new(@project.owner, @project.repository.identifier, {private: private}).call | |||||
| Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params) | |||||
| @project.repository.update_column(:hidden, private) | @project.repository.update_column(:hidden, private) | ||||
| end | end | ||||
| @project.update_attributes!(new_project_params) | @project.update_attributes!(new_project_params) | ||||
| @@ -73,6 +105,61 @@ class ProjectsController < ApplicationController | |||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| end | end | ||||
| def watch_users | |||||
| watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct | |||||
| @watchers_count = watchers.size | |||||
| @watchers = paginate(watchers) | |||||
| end | |||||
| def praise_users | |||||
| praises = @project.praise_treads.includes(:user).order("praise_treads.created_at desc").distinct | |||||
| @praises_count = praises.size | |||||
| @praises = paginate(praises) | |||||
| end | |||||
| def fork_users | |||||
| fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct | |||||
| @forks_count = fork_users.size | |||||
| @fork_users = paginate(fork_users) | |||||
| end | |||||
| def simple | |||||
| json_response(@project, current_user) | |||||
| end | |||||
| def recommend | |||||
| @projects = Project.recommend.includes(:repository, :project_category, owner: :user_extension).limit(5) | |||||
| end | |||||
| def about | |||||
| @project_detail = @project.project_detail | |||||
| @attachments = Array(@project_detail&.attachments) if request.get? | |||||
| ActiveRecord::Base.transaction do | |||||
| if request.post? | |||||
| require_login | |||||
| authorizate_user_can_edit_project! | |||||
| unless @project_detail.present? | |||||
| @project_detail = ProjectDetail.new( | |||||
| content: params[:content], | |||||
| project_id: @project.id) | |||||
| else | |||||
| @project_detail.content = params[:content] | |||||
| end | |||||
| if @project_detail.save! | |||||
| attachment_ids = Array(params[:attachment_ids]) | |||||
| logger.info "=============> #{Array(params[:attachment_ids])}" | |||||
| @attachments = Attachment.where(id: attachment_ids) | |||||
| @attachments.update_all( | |||||
| container_id: @project_detail.id, | |||||
| container_type: @project_detail.model_name.name, | |||||
| author_id: current_user.id, | |||||
| description: "") | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| private | private | ||||
| def project_params | def project_params | ||||
| params.permit(:user_id, :name, :description, :repository_name, | params.permit(:user_id, :name, :description, :repository_name, | ||||
| @@ -80,7 +167,18 @@ class ProjectsController < ApplicationController | |||||
| end | end | ||||
| def mirror_params | def mirror_params | ||||
| params.permit(:user_id, :name, :description, :repository_name, | |||||
| :project_category_id, :project_language_id, :clone_addr, :private) | |||||
| params.permit(:user_id, :name, :description, :repository_name, :is_mirror, :auth_username, | |||||
| :auth_password, :project_category_id, :project_language_id, :clone_addr, :private) | |||||
| end | |||||
| def project_public? | |||||
| return if @project.is_public? | |||||
| if current_user | |||||
| return if current_user.admin? || @project.member?(current_user.id) | |||||
| render_forbidden('你没有权限访问.') | |||||
| else | |||||
| render_unauthorized('你还未登录.') | |||||
| end | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,76 +1,55 @@ | |||||
| class PullRequestsController < ApplicationController | class PullRequestsController < ApplicationController | ||||
| before_action :require_login | |||||
| before_action :find_project | |||||
| before_action :set_repository | |||||
| before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge] | |||||
| 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] | |||||
| include TagChosenHelper | include TagChosenHelper | ||||
| include ApplicationHelper | include ApplicationHelper | ||||
| def index | def index | ||||
| # @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取 | # @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取 | ||||
| issues = @project.issues.issue_pull_request.includes(:user,:tracker, :priority, :version, :issue_status, :journals, :issue_times) | |||||
| issues = @project.issues.issue_pull_request.issue_index_includes.includes(pull_request: :user) | |||||
| issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user)) | issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user)) | ||||
| @all_issues_size = issues.size | @all_issues_size = issues.size | ||||
| @open_issues_size = issues.where.not(status_id: 5).size | |||||
| @close_issues_size = issues.where(status_id: 5).size | |||||
| @assign_to_me_size = issues.where(assigned_to_id: current_user&.id).size | |||||
| @my_published_size = issues.where(author_id: current_user&.id).size | |||||
| @open_issues_size = issues.joins(:pull_request).where(pull_requests: {status: 0}).size | |||||
| @close_issues_size = issues.joins(:pull_request).where(pull_requests: {status: 2}).size | |||||
| @merged_issues_size = issues.joins(:pull_request).where(pull_requests: {status: 1}).size | |||||
| @user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user)) | |||||
| status_type = params[:status_type] || "1" #issue状态的选择 | |||||
| search_name = params[:search].to_s | |||||
| start_time = params[:start_date] | |||||
| end_time = params[:due_date] | |||||
| if status_type.to_s == "1" #表示开启中的 | |||||
| issues = issues.where.not(status_id: 5) | |||||
| elsif status_type.to_s == "2" #表示关闭中的 | |||||
| issues = issues.where(status_id: 5) | |||||
| end | |||||
| if search_name.present? | |||||
| issues = issues.where("subject like ?", "%#{search_name}%") | |||||
| end | |||||
| if start_time&.present? || end_time&.present? | |||||
| issues = issues.where("start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date) | |||||
| end | |||||
| issues = issues.where(author_id: params[:author_id]) if params[:author_id].present? | |||||
| issues = issues.where(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present? && params[:assigned_to_id].to_s != "all" | |||||
| issues = issues.where(tracker_id: params[:tracker_id]) if params[:tracker_id].present? | |||||
| issues = issues.where(status_id: params[:status_id]) if params[:status_id].present? | |||||
| issues = issues.where(priority_id: params[:priority_id]) if params[:priority_id].present? | |||||
| issues = issues.where(fixed_version_id: params[:fixed_version_id]) if params[:fixed_version_id].present? && params[:fixed_version_id].to_s != "all" | |||||
| issues = issues.where(done_ratio: params[:done_ratio].to_i) if params[:done_ratio].present? | |||||
| issues = issues.where(issue_type: params[:issue_type]) if params[:issue_type].present? | |||||
| issues = issues.joins(:issue_tags).where(issue_tags: {id: params[:issue_tag_id].to_i}) if params[:issue_tag_id].present? | |||||
| order_type = params[:order_type] || "desc" #或者"asc" | |||||
| order_name = params[:order_name] || "created_on" #或者"updated_on" | |||||
| @page = params[:page] | |||||
| @limit = params[:limit] || 15 | |||||
| @issues = issues.order("#{order_name} #{order_type}") | |||||
| @issues_size = issues.size | |||||
| @issues = issues.order("#{order_name} #{order_type}").page(@page).per(@limit) | |||||
| scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "PullRequest") | |||||
| @issues_size = scopes.size | |||||
| @issues = paginate(scopes) | |||||
| end | end | ||||
| def new | def new | ||||
| @all_branches = [] | |||||
| get_all_branches = Gitea::Repository::BranchesService.new(@user, @repository.try(:identifier)).call | |||||
| if get_all_branches && get_all_branches.size > 0 | |||||
| get_all_branches.each do |b| | |||||
| @all_branches.push(b["name"]) | |||||
| end | |||||
| @all_branches = PullRequests::BranchesService.new(@owner, @project).call | |||||
| @is_fork = @project.forked_from_project_id.present? | |||||
| @projects_names = [{ | |||||
| project_user_login: @owner.try(:login), | |||||
| project_name: "#{@owner.try(:show_real_name)}/#{@repository.try(:identifier)}", | |||||
| project_id: @project.identifier, | |||||
| id: @project.id | |||||
| }] | |||||
| @merge_projects = @projects_names | |||||
| fork_project = @project.fork_project if @is_fork | |||||
| if fork_project.present? | |||||
| @merge_projects.push({ | |||||
| project_user_login: fork_project.owner.try(:login), | |||||
| project_name: "#{fork_project.owner.try(:show_real_name)}/#{fork_project.repository.try(:identifier)}", | |||||
| project_id: fork_project.identifier, | |||||
| id: fork_project.id | |||||
| }) | |||||
| end | end | ||||
| @project_tags = @project.issue_tags&.select(:id,:name, :color).as_json | |||||
| @project_versions = @project.versions&.select(:id,:name, :status).as_json | |||||
| @project_members = @project.members_user_infos | |||||
| end | end | ||||
| def create | |||||
| def get_branches | |||||
| branch_result = PullRequests::BranchesService.new(@owner, @project).call | |||||
| render json: branch_result | |||||
| # return json: branch_result | |||||
| end | |||||
| def create | |||||
| if params[:title].nil? | if params[:title].nil? | ||||
| normal_status(-1, "名称不能为空") | normal_status(-1, "名称不能为空") | ||||
| elsif params[:issue_tag_ids].nil? | elsif params[:issue_tag_ids].nil? | ||||
| @@ -78,55 +57,29 @@ class PullRequestsController < ApplicationController | |||||
| else | else | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| local_params = { | |||||
| title: params[:title], #标题 | |||||
| body: params[:body], #内容 | |||||
| head: params[:head], #源分支 | |||||
| base: params[:base], #目标分支 | |||||
| milestone: 0, #里程碑,未与本地的里程碑关联 | |||||
| } | |||||
| requests_params = local_params.merge({ | |||||
| assignee: current_user.try(:login), | |||||
| assignees: ["#{params[:assigned_login].to_s}"], | |||||
| labels: params[:issue_tag_ids], | |||||
| due_date: Time.now | |||||
| }) | |||||
| issue_params = { | |||||
| author_id: current_user.id, | |||||
| project_id: @project.id, | |||||
| subject: params[:title], | |||||
| description: params[:body], | |||||
| assigned_to_id: params[:assigned_to_id], | |||||
| fixed_version_id: params[:fixed_version_id], | |||||
| issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "", | |||||
| issue_classify: "pull_request", | |||||
| issue_type: params[:issue_type] || "1", | |||||
| tracker_id: 2, | |||||
| status_id: 1, | |||||
| priority_id: 1 | |||||
| } | |||||
| pull_issue = Issue.new(issue_params) | |||||
| merge_params | |||||
| pull_issue = Issue.new(@issue_params) | |||||
| if pull_issue.save! | if pull_issue.save! | ||||
| local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: pull_issue.id)) | |||||
| pr_params = { | |||||
| user_id: current_user.try(:id), | |||||
| project_id: @project.id, | |||||
| issue_id: pull_issue.id, | |||||
| fork_project_id: params[:fork_project_id], | |||||
| is_original: params[:is_original], | |||||
| files_count: params[:files_count] || 0, | |||||
| commits_count: params[:commits_count] || 0 | |||||
| } | |||||
| local_requests = PullRequest.new(@local_params.merge(pr_params)) | |||||
| if local_requests.save | if local_requests.save | ||||
| gitea_request = Gitea::PullRequest::CreateService.new(current_user, @repository.try(:identifier), requests_params).call | |||||
| remote_pr_params = @local_params | |||||
| remote_pr_params = remote_pr_params.merge(head: "#{params[:merge_user_login]}:#{params[:head]}").compact if local_requests.is_original && params[:merge_user_login] | |||||
| gitea_request = Gitea::PullRequest::CreateService.call(current_user.try(:gitea_token), @project.owner, @repository.try(:identifier), remote_pr_params.except(:milestone)) | |||||
| if gitea_request && local_requests.update_attributes(gpid: gitea_request["number"]) | if gitea_request && local_requests.update_attributes(gpid: gitea_request["number"]) | ||||
| if params[:issue_tag_ids].present? | if params[:issue_tag_ids].present? | ||||
| params[:issue_tag_ids].each do |tag| | params[:issue_tag_ids].each do |tag| | ||||
| IssueTagsRelate.create!(issue_id: pull_issue.id, issue_tag_id: tag) | IssueTagsRelate.create!(issue_id: pull_issue.id, issue_tag_id: tag) | ||||
| end | end | ||||
| end | end | ||||
| if params[:attachment_ids].present? | |||||
| params[:attachment_ids].each do |id| | |||||
| attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | |||||
| unless attachment.blank? | |||||
| attachment.container = pull_issue | |||||
| attachment.author_id = current_user.id | |||||
| attachment.description = "" | |||||
| attachment.save | |||||
| end | |||||
| end | |||||
| end | |||||
| if params[:assigned_to_id].present? | if params[:assigned_to_id].present? | ||||
| Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id, | Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id, | ||||
| @@ -136,8 +89,9 @@ class PullRequestsController < ApplicationController | |||||
| end | end | ||||
| local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") | local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") | ||||
| if params[:title].to_s.include?("WIP:") | if params[:title].to_s.include?("WIP:") | ||||
| pull_issue.custom_journal_detail("WIP", "", "这个合并请求被标记为尚未完成的工作。完成后请从标题中移除WIP:前缀。") | |||||
| pull_issue.custom_journal_detail("WIP", "", "这个合并请求被标记为尚未完成的工作。完成后请从标题中移除WIP:前缀。", current_user&.id) | |||||
| end | end | ||||
| # render :json => { status: 0, message: "PullRequest创建成功", id: pull_issue.id} | |||||
| normal_status(0, "PullRequest创建成功") | normal_status(0, "PullRequest创建成功") | ||||
| else | else | ||||
| normal_status(-1, "PullRequest创建失败") | normal_status(-1, "PullRequest创建失败") | ||||
| @@ -155,8 +109,9 @@ class PullRequestsController < ApplicationController | |||||
| end | end | ||||
| def edit | def edit | ||||
| @issue_chosen = issue_left_chosen(@project, @issue.id) | |||||
| @issue_attachments = @issue.attachments | |||||
| @fork_project_user_name = @project&.fork_project&.owner.try(:show_real_name) | |||||
| @fork_project_user = @project&.fork_project&.owner.try(:login) | |||||
| @fork_project_identifier = @project&.fork_project&.repository.try(:identifier) | |||||
| end | end | ||||
| def update | def update | ||||
| @@ -167,25 +122,7 @@ class PullRequestsController < ApplicationController | |||||
| else | else | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| local_params = { | |||||
| title: params[:title], #标题 | |||||
| body: params[:body], #内容 | |||||
| head: params[:head], #源分支 | |||||
| base: params[:base], #目标分支 | |||||
| milestone: 0, #里程碑,未与本地的里程碑关联 | |||||
| } | |||||
| requests_params = local_params.merge({ | |||||
| assignee: current_user.try(:login), | |||||
| assignees: ["#{params[:assigned_login].to_s}"], | |||||
| labels: params[:issue_tag_ids] | |||||
| }) | |||||
| issue_params = { | |||||
| subject: params[:title], | |||||
| description: params[:body], | |||||
| assigned_to_id: params[:assigned_to_id].to_s, | |||||
| fixed_version_id: params[:fixed_version_id], | |||||
| issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "", | |||||
| } | |||||
| merge_params | |||||
| if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? | if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? | ||||
| @issue&.issue_tags_relates&.destroy_all | @issue&.issue_tags_relates&.destroy_all | ||||
| @@ -194,26 +131,10 @@ class PullRequestsController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| if @issue.update_attributes(issue_params) | |||||
| if @pull_request.update_attributes(local_params) | |||||
| gitea_request = Gitea::PullRequest::UpdateService.new(current_user, @repository.try(:identifier), requests_params, @pull_request.try(:gpid)).call | |||||
| if @issue.update_attributes(@issue_params) | |||||
| if @pull_request.update_attributes(@local_params.compact) | |||||
| gitea_request = Gitea::PullRequest::UpdateService.new(@project.owner, @repository.try(:identifier), @requests_params, @pull_request.try(:gpid)).call | |||||
| if gitea_request | if gitea_request | ||||
| issue_files = params[:attachment_ids] | |||||
| change_files = false | |||||
| issue_file_ids = [] | |||||
| if issue_files.present? | |||||
| change_files = true | |||||
| issue_files.each do |id| | |||||
| attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | |||||
| unless attachment.blank? | |||||
| attachment.container = @issue | |||||
| attachment.author_id = current_user.id | |||||
| attachment.description = "" | |||||
| attachment.save | |||||
| end | |||||
| end | |||||
| end | |||||
| if params[:issue_tag_ids].present? | if params[:issue_tag_ids].present? | ||||
| params[:issue_tag_ids].each do |tag| | params[:issue_tag_ids].each do |tag| | ||||
| IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag) | IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag) | ||||
| @@ -222,7 +143,6 @@ class PullRequestsController < ApplicationController | |||||
| if params[:status_id].to_i == 5 | if params[:status_id].to_i == 5 | ||||
| @issue.issue_times.update_all(end_time: Time.now) | @issue.issue_times.update_all(end_time: Time.now) | ||||
| end | end | ||||
| @issue.create_journal_detail(change_files, issue_files, issue_file_ids) | |||||
| normal_status(0, "PullRequest更新成功") | normal_status(0, "PullRequest更新成功") | ||||
| else | else | ||||
| normal_status(-1, "PullRequest更新失败") | normal_status(-1, "PullRequest更新失败") | ||||
| @@ -240,39 +160,47 @@ class PullRequestsController < ApplicationController | |||||
| end | end | ||||
| def refuse_merge | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @pull_request.update(status: 2) | |||||
| @pull_request.issue.update(status_id: 5) | |||||
| normal_status(1, "已拒绝") | |||||
| rescue => e | |||||
| normal_status(-1, e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def create_merge_infos | |||||
| get_relatived | |||||
| end | |||||
| def show | def show | ||||
| @user_permission = current_user.present? && (!@issue.is_lock || @project.member?(current_user) || current_user.admin? || @issue.user == current_user) | |||||
| @issue_attachments = @issue.attachments | |||||
| @issue_user = @issue.user | @issue_user = @issue.user | ||||
| @issue_assign_to = @issue.get_assign_user | @issue_assign_to = @issue.get_assign_user | ||||
| @join_users = join_users(@issue) | |||||
| #总耗时 | |||||
| cost_time(@issue) | |||||
| #被依赖 | |||||
| @be_depended_issues_array = be_depended_issues(@issue) | |||||
| #依赖于 | |||||
| depended_issues(@issue) | |||||
| end | end | ||||
| def pr_merge | def pr_merge | ||||
| return render_forbidden("你没有权限操作.") if @project.reporter?(current_user) | |||||
| if params[:do].blank? | if params[:do].blank? | ||||
| normal_status(-1, "请选择合并方式") | normal_status(-1, "请选择合并方式") | ||||
| else | else | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| requests_params = { | requests_params = { | ||||
| do: params[:do], | |||||
| Do: params[:do], | |||||
| MergeMessageField: params[:body], | MergeMessageField: params[:body], | ||||
| MergeTitleField: params[:title] | MergeTitleField: params[:title] | ||||
| } | } | ||||
| merge_pr = Gitea::PullRequest::MergeService.new(current_user, @repository.try(:identifier), @pull_request.try(:gpid), requests_params).call | |||||
| merge_pr = Gitea::PullRequest::MergeService.call(current_user.gitea_token, @project.owner.login, | |||||
| @repository.try(:identifier), @pull_request.try(:gpid), requests_params) | |||||
| if @pull_request.update_attribute(:status, 1) && merge_pr[:status].to_i == 200 | if @pull_request.update_attribute(:status, 1) && merge_pr[:status].to_i == 200 | ||||
| # @pull_request.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "merge") | |||||
| @pull_request&.project_trends&.update_all(action_type: "close") | @pull_request&.project_trends&.update_all(action_type: "close") | ||||
| @issue&.custom_journal_detail("merge", "", "该合并请求已被合并") | |||||
| @issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id) | |||||
| normal_status(1, "合并成功") | normal_status(1, "合并成功") | ||||
| else | else | ||||
| normal_status(-1, "合并失败") | normal_status(-1, "合并失败") | ||||
| @@ -285,73 +213,21 @@ class PullRequestsController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| #评审 | |||||
| def check_merge | |||||
| notes = params[:content] | |||||
| pull_request_status = params[:status] | |||||
| if notes.blank? | |||||
| normal_status(-1, "评论内容不能为空") | |||||
| else | |||||
| if @pull_request.status > 0 | |||||
| normal_status(-1, "已合并,不能评审") | |||||
| else | |||||
| if pull_request_status.to_i == 1 | |||||
| message = "评审通过:" | |||||
| elsif pull_request_status.to_i == 2 | |||||
| message = "评审请求变更:" | |||||
| else | |||||
| message = "" | |||||
| end | |||||
| journal_params = { | |||||
| journalized_id: @issue.id , | |||||
| journalized_type: "Issue", | |||||
| user_id: current_user.id , | |||||
| notes: message + notes.to_s.strip | |||||
| } | |||||
| journal = Journal.new journal_params | |||||
| if journal.save | |||||
| if pull_request_status.present? | |||||
| @pull_request.update_attribute(:status, pull_request_status.to_i) | |||||
| end | |||||
| if pull_request_status.to_i == 1 | |||||
| requests_params = { | |||||
| do: "merge", | |||||
| MergeMessageField: notes, | |||||
| MergeTitleField: "Merge PullRequest ##{@pull_request.gpid}" | |||||
| } | |||||
| merge_pr = Gitea::PullRequest::MergeService.new(current_user, @repository.try(:identifier), @pull_request.try(:gpid), requests_params).call | |||||
| if merge_pr | |||||
| @pull_request&.project_trends&.update_all(action_type: "close") | |||||
| # @pull_request.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "merge") | |||||
| @issue.custom_journal_detail("merge", "", "该合并请求已被合并") | |||||
| normal_status(1, "评审成功") | |||||
| else | |||||
| normal_status(-1, "评审失败") | |||||
| end | |||||
| end | |||||
| normal_status(0, "评审成功") | |||||
| else | |||||
| normal_status(-1, "评审失败") | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| def check_can_merge | def check_can_merge | ||||
| target_head = params[:head] #源分支 | target_head = params[:head] #源分支 | ||||
| target_base = params[:base] #目标分支 | target_base = params[:base] #目标分支 | ||||
| is_original = params[:is_original] | |||||
| if target_head.blank? || target_base.blank? | if target_head.blank? || target_base.blank? | ||||
| normal_status(-1, "请选择分支。") | |||||
| elsif target_head === target_base | |||||
| normal_status(-1, "分支内容相同,无需创建合并请求。") | |||||
| normal_status(-2, "请选择分支") | |||||
| elsif target_head === target_base && !is_original | |||||
| normal_status(-2, "分支内容相同,无需创建合并请求") | |||||
| else | else | ||||
| can_merge = @project&.pull_requests.where(user_id: current_user&.id, head: target_head, base: target_base, status: 0) | |||||
| can_merge = @project&.pull_requests.where(head: target_head, base: target_base, status: 0, is_original: is_original, fork_project_id: params[:fork_project_id]) | |||||
| if can_merge.present? | if can_merge.present? | ||||
| render json: { | render json: { | ||||
| status: -2, | status: -2, | ||||
| message: "在这些分支之间的合并请求已存在", | |||||
| pull_request_id: can_merge.first.id, | |||||
| pull_request_name: can_merge.first.try(:title) | |||||
| message: "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}/Messagecount''>#{can_merge.first.try(:title)}</a>", | |||||
| } | } | ||||
| else | else | ||||
| normal_status(0, "可以合并") | normal_status(0, "可以合并") | ||||
| @@ -360,15 +236,19 @@ class PullRequestsController < ApplicationController | |||||
| end | end | ||||
| private | |||||
| def files | |||||
| @files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gpid) | |||||
| # render json: @files_result | |||||
| end | |||||
| def commits | |||||
| @commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gpid) | |||||
| # render json: @commits_result | |||||
| end | |||||
| def set_repository | |||||
| # @project = Project.find_by_identifier! params[:id] | |||||
| @repository = @project.repository | |||||
| @user = @project.owner | |||||
| # normal_status(-1, "项目不存在") unless @project.present? | |||||
| normal_status(-1, "仓库不存在") unless @repository.present? | |||||
| normal_status(-1, "用户不存在") unless @user.present? | |||||
| private | |||||
| def load_pull_request | |||||
| @pull_request = PullRequest.find params[:id] | |||||
| end | end | ||||
| def find_pull_request | def find_pull_request | ||||
| @@ -380,4 +260,41 @@ class PullRequestsController < ApplicationController | |||||
| normal_status(-1, "您没有权限") | normal_status(-1, "您没有权限") | ||||
| end | end | ||||
| end | end | ||||
| end | |||||
| def get_relatived | |||||
| @project_tags = @project.issue_tags&.select(:id,:name, :color).as_json | |||||
| @project_versions = @project.versions&.select(:id,:name, :status).as_json | |||||
| @project_members = @project.members_user_infos | |||||
| @project_priories = IssuePriority&.select(:id,:name, :position).as_json | |||||
| end | |||||
| def merge_params | |||||
| @local_params = { | |||||
| title: params[:title], #标题 | |||||
| body: params[:body], #内容 | |||||
| head: params[:head], #源分支 | |||||
| base: params[:base], #目标分支 | |||||
| milestone: 0, #里程碑,未与本地的里程碑关联 | |||||
| } | |||||
| @requests_params = @local_params.merge({ | |||||
| assignee: current_user.try(:login), | |||||
| assignees: ["#{params[:assigned_login].to_s}"], | |||||
| labels: params[:issue_tag_ids], | |||||
| due_date: Time.now | |||||
| }) | |||||
| @issue_params = { | |||||
| author_id: current_user.id, | |||||
| project_id: @project.id, | |||||
| subject: params[:title], | |||||
| description: params[:body], | |||||
| assigned_to_id: params[:assigned_to_id], | |||||
| fixed_version_id: params[:fixed_version_id], | |||||
| issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "", | |||||
| priority_id: params[:priority_id] || "2", | |||||
| issue_classify: "pull_request", | |||||
| issue_type: params[:issue_type] || "1", | |||||
| tracker_id: 2, | |||||
| status_id: 1, | |||||
| } | |||||
| end | |||||
| end | |||||
| @@ -1,5 +0,0 @@ | |||||
| class RepertoiresController < ApplicationController | |||||
| def index | |||||
| render_ok(repertoires: Repertoire.select(:id, :name).order(:created_at).as_json) | |||||
| end | |||||
| end | |||||
| @@ -1,56 +1,254 @@ | |||||
| class RepositoriesController < ApplicationController | class RepositoriesController < ApplicationController | ||||
| include ApplicationHelper | include ApplicationHelper | ||||
| before_action :find_user, :find_repository, :authorizate! | |||||
| before_action :require_login, only: %i[edit] | |||||
| include OperateProjectAbilityAble | |||||
| before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror] | |||||
| before_action :load_repository | |||||
| before_action :authorizate!, except: [:sync_mirror, :tags, :commit] | |||||
| before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror] | |||||
| before_action :get_ref, only: %i[entries sub_entries top_counts] | |||||
| before_action :get_latest_commit, only: %i[entries sub_entries top_counts] | |||||
| before_action :get_statistics, only: %i[top_counts] | |||||
| def show | def show | ||||
| @project = @repo.project | |||||
| @branches_count = Gitea::Repository::BranchesService.new(@user, @repo.identifier).call&.size | |||||
| @commits_count = Gitea::Repository::Commits::ListService.new(@user, @repo.identifier).call[:total_count] | |||||
| @result = Gitea::Repository::GetService.new(@user, @repo.identifier).call | |||||
| @user = current_user | |||||
| @repo = @project.repository | |||||
| @result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil | |||||
| @project_fork_id = @project.try(:forked_from_project_id) | |||||
| if @project_fork_id.present? | |||||
| @fork_project = Project.find_by(id: @project_fork_id) | |||||
| @fork_project_user = @fork_project.owner | |||||
| end | |||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| end | end | ||||
| def entries | def entries | ||||
| @repo.project.increment!(:visits) | |||||
| @ref = params[:branch] || "master" | |||||
| @entries = Gitea::Repository::Entries::ListService.new(@user, @repo.identifier, ref:@ref).call | |||||
| @entries = @entries.sort_by{ |hash| hash['type'] } | |||||
| @project.increment!(:visits) | |||||
| if @project.educoder? | |||||
| @entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name) | |||||
| else | |||||
| @entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call | |||||
| @entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : [] | |||||
| @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" | |||||
| end | |||||
| end | |||||
| def top_counts | |||||
| @result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call | |||||
| end | end | ||||
| def sub_entries | def sub_entries | ||||
| file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) | file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) | ||||
| interactor = Repositories::EntriesInteractor.call(@user, @repo.identifier, file_path_uri, ref: params[:ref]) | |||||
| if interactor.success? | |||||
| @sub_entries = interactor.result | |||||
| @sub_entries = [] << @sub_entries unless @sub_entries.is_a? Array | |||||
| @sub_entries = @sub_entries.sort_by{ |hash| hash['type'] } | |||||
| if @project.educoder? | |||||
| if params[:type] === 'file' | |||||
| @sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri) | |||||
| logger.info "######### sub_entries: #{@sub_entries}" | |||||
| return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1 | |||||
| tmp_entries = [{ | |||||
| "content" => @sub_entries['data']['content'], | |||||
| "type" => "blob" | |||||
| }] | |||||
| @sub_entries = { | |||||
| "trees"=>tmp_entries, | |||||
| "commits" => [{}] | |||||
| } | |||||
| else | |||||
| @sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri}) | |||||
| end | |||||
| else | else | ||||
| render_error(interactor.error) | |||||
| interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref) | |||||
| if interactor.success? | |||||
| result = interactor.result | |||||
| @sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result | |||||
| else | |||||
| render_error(interactor.error) | |||||
| end | |||||
| end | end | ||||
| end | end | ||||
| def commits | def commits | ||||
| @hash_commit = Gitea::Repository::Commits::ListService.new(@user, @repo.identifier, sha: params[:sha], page: params[:page]).call | |||||
| @hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier, | |||||
| sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call | |||||
| end | end | ||||
| def single_commit | |||||
| @commit = Gitea::Repository::Commits::GetService.new(@user, @repo.identifier, params[:sha]).call | |||||
| def commit | |||||
| @sha = params[:sha] | |||||
| @commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token) | |||||
| @commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true}) | |||||
| end | end | ||||
| def tags | def tags | ||||
| @tags = Gitea::Repository::Tags::ListService.new(@user, @repo.identifier).call | |||||
| @tags = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}) | |||||
| end | end | ||||
| def edit | def edit | ||||
| end | end | ||||
| def create_file | |||||
| interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) | |||||
| if interactor.success? | |||||
| @file = interactor.result | |||||
| create_new_pr(params) | |||||
| else | |||||
| render_error(interactor.error) | |||||
| end | |||||
| end | |||||
| def update_file | |||||
| interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier)) | |||||
| if interactor.success? | |||||
| @file = interactor.result | |||||
| create_new_pr(params) | |||||
| render_result(1, "更新成功") | |||||
| else | |||||
| render_error(interactor.error) | |||||
| end | |||||
| end | |||||
| def delete_file | |||||
| interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier)) | |||||
| if interactor.success? | |||||
| @file = interactor.result | |||||
| render_result(1, "文件删除成功") | |||||
| else | |||||
| render_error(interactor.error) | |||||
| end | |||||
| end | |||||
| def repo_hook | |||||
| end | |||||
| def sync_mirror | |||||
| return render_error("正在镜像中..") if @repository.mirror.waiting? | |||||
| @repository.sync_mirror! | |||||
| SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id) | |||||
| render_ok | |||||
| end | |||||
| private | private | ||||
| def find_project | |||||
| @project = Project.find params[:id] | |||||
| render_not_found("未找到相关的仓库") unless @project | |||||
| end | |||||
| def find_project_with_includes | |||||
| @project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id] | |||||
| end | |||||
| def authorizate! | def authorizate! | ||||
| if @repo.hidden? && @repo.user != current_user | |||||
| return if current_user && current_user.admin? | |||||
| if @project.repository.hidden? && !@project.member?(current_user) | |||||
| render_forbidden | render_forbidden | ||||
| end | end | ||||
| end | end | ||||
| # TODO 获取最新commit信息 | |||||
| def project_commits | |||||
| Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier, | |||||
| sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call | |||||
| end | |||||
| def get_statistics | |||||
| @branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size | |||||
| @tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size | |||||
| end | |||||
| def get_ref | |||||
| @ref = params[:ref] || "master" | |||||
| end | |||||
| def get_latest_commit | |||||
| latest_commit = @project.educoder? ? nil : project_commits | |||||
| @latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil | |||||
| @commits_count = latest_commit.present? ? latest_commit[:total_count] : 0 | |||||
| end | |||||
| def content_params | |||||
| { | |||||
| filepath: params[:filepath], | |||||
| branch: params[:branch], | |||||
| new_branch: params[:new_branch], | |||||
| content: params[:content], | |||||
| message: params[:message], | |||||
| committer: { | |||||
| email: current_user.mail, | |||||
| name: current_user.login | |||||
| }, | |||||
| identifier: @project.identifier | |||||
| } | |||||
| end | |||||
| def hook_params(hook_type, params) | |||||
| # if hook_type == "push" | |||||
| # # TODO hook返回的记录中,暂时没有文件代码数量的增减,暂时根据 commits数量来计算 | |||||
| # uploadPushInfo = { | |||||
| # "sha": params["commits"].present? ? params["commits"].last : "", | |||||
| # "branch": params["ref"].to_s.split("/").last, | |||||
| # "modification_lines": params["commits"].length | |||||
| # } | |||||
| # elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作 | |||||
| # uploadPushInfo = { | |||||
| # "branch": params["base"]["ref"].to_s.split("/").last, | |||||
| # "sha": params["pull_request"]["merge_base"], | |||||
| # "modification_lines": 1 #pull_request中没有commits数量 | |||||
| # } | |||||
| # else | |||||
| # uploadPushInfo = {} | |||||
| # end | |||||
| # uploadPushInfo | |||||
| end | |||||
| def create_new_pr(params) | |||||
| if params[:new_branch].present? && params[:new_branch] != params[:branch] | |||||
| local_params = { | |||||
| title: params[:message], #标题 | |||||
| body: params[:content], #内容 | |||||
| head: params[:new_branch], #源分支 | |||||
| base: params[:branch], #目标分支 | |||||
| milestone: 0 #里程碑,未与本地的里程碑关联 | |||||
| } | |||||
| requests_params = local_params.merge({ | |||||
| assignee: current_user.try(:login), | |||||
| assignees: [], | |||||
| labels: [], | |||||
| due_date: Time.now | |||||
| }) | |||||
| issue_params = { | |||||
| author_id: current_user.id, | |||||
| project_id: @project.id, | |||||
| subject: params[:message], | |||||
| description: params[:content], | |||||
| assigned_to_id: nil, | |||||
| fixed_version_id: nil, | |||||
| issue_tags_value: nil, | |||||
| issue_classify: "pull_request", | |||||
| issue_type: "1", | |||||
| tracker_id: 2, | |||||
| status_id: 1, | |||||
| priority_id: params[:priority_id] || "2" | |||||
| } | |||||
| @pull_issue = Issue.new(issue_params) | |||||
| if @pull_issue.save! | |||||
| local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id)) | |||||
| if local_requests.save | |||||
| gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @project.owner, @project.try(:identifier), requests_params).call | |||||
| if gitea_request && local_requests.update_attributes(gpid: gitea_request["number"]) | |||||
| local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| end | |||||
| end | end | ||||
| @@ -1,4 +1,6 @@ | |||||
| class SettingsController < ApplicationController | class SettingsController < ApplicationController | ||||
| def show | def show | ||||
| @old_projects_url = nil | |||||
| @old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged? | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,896 +0,0 @@ | |||||
| class StudentWorksController < ApplicationController | |||||
| include HomeworkCommonsHelper | |||||
| include StudentWorksHelper | |||||
| before_action :require_login, :check_auth | |||||
| before_action :find_homework, only: [:new, :create, :search_member_list, :check_project, :relate_project, | |||||
| :cancel_relate_project, :delete_work] | |||||
| before_action :find_work, only: [:shixun_work_report, :adjust_review_score, :shixun_work, :commit_des, :update_des, | |||||
| :adjust_score, :show, :adjust_score, :supply_attachments, :revise_attachment, | |||||
| :comment_list, :add_score, :add_score_reply, :destroy_score, :appeal_anonymous_score, | |||||
| :deal_appeal_score, :cancel_appeal, :edit, :update, :export_shixun_work_report, | |||||
| :shixun_work_comment, :destroy_work_comment] | |||||
| before_action :user_course_identity | |||||
| before_action :allow_add_score, only: [:add_score] | |||||
| before_action :homework_publish | |||||
| before_action :teacher_allowed, only: [:adjust_score, :adjust_review_score, :deal_appeal_score, :shixun_work_comment, | |||||
| :destroy_work_comment] | |||||
| before_action :course_student, only: [:new, :commit_des, :update_des, :create, :edit, :update, :search_member_list, :relate_project, | |||||
| :cancel_relate_project, :relate_project, :delete_work] | |||||
| before_action :my_work, only: [:commit_des, :update_des, :edit, :update, :revise_attachment, :appeal_anonymous_score, | |||||
| :cancel_appeal] | |||||
| before_action :edit_duration, only: [:edit, :update, :delete_work] | |||||
| before_action :end_or_late, only: [:new, :create, :search_member_list, :commit_des, :update_des] | |||||
| before_action :require_score_id, only: [:destroy_score, :add_score_reply, :appeal_anonymous_score, :deal_appeal_score, :cancel_appeal] | |||||
| before_action :is_evaluation, :open_work, only: [:show, :supply_attachments] | |||||
| def new | |||||
| uid_logger("#######new current_user : 1111") | |||||
| @current_user = current_user | |||||
| uid_logger("#######new current_user : #{@current_user.id}") | |||||
| if @homework.homework_type == "group" && @homework.homework_detail_group.try(:base_on_project) | |||||
| work = @homework.student_works.find_by(user_id: @current_user.id) | |||||
| if work.present? && (work.work_status != 0 || work.project_id == 0) | |||||
| normal_status(403, "") | |||||
| end | |||||
| end | |||||
| end | |||||
| # 搜索课堂学生 | |||||
| def search_member_list | |||||
| # 统一设置的作业取所有学生,否则取已发布的分班学生 | |||||
| students = @homework.unified_setting? ? @course.students : @course.students.where(course_group_id: @homework.published_settings.pluck(:course_group_id)) | |||||
| if !params[:search].blank? | |||||
| @members = students.joins(user: :user_extension).where("course_members.user_id != #{current_user.id} and (concat(users.lastname, users.firstname) | |||||
| like ? or user_extensions.student_id like ?)", "%#{params[:search]}%", "%#{params[:search]}%") | |||||
| else | |||||
| # 没有搜索条件时搜索课堂所有未提交的学生 | |||||
| user_ids = @homework.student_works.where("work_status = 0").pluck(:user_id) - [current_user.id] | |||||
| @members = students.where(user_id: user_ids) | |||||
| end | |||||
| page = params[:page] ? params[:page].to_i : 1 | |||||
| limit = params[:limit] ? params[:limit].to_i : 10 | |||||
| # todo user_extension | |||||
| @members = @members.page(page).per(limit).includes(:course_group, user: :user_extension) | |||||
| end | |||||
| def delete_work | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| work = @homework.student_works.find_by!(user_id: params[:user_id]) | |||||
| tip_exception("只有组长才能删除组员") if work.commit_user_id != current_user.id | |||||
| work.update_attributes!(description: nil, project_id: 0, | |||||
| late_penalty: 0, work_status: 0, | |||||
| commit_time: nil, update_time: nil, group_id: 0, | |||||
| commit_user_id: nil, final_score: nil, work_score: nil, teacher_score: nil, teaching_asistant_score: nil) | |||||
| work.attachments.destroy_all | |||||
| work.tidings.destroy_all | |||||
| normal_status("删除成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| end | |||||
| end | |||||
| end | |||||
| def create | |||||
| student_work = @homework.student_works.find_or_create_by(user_id: current_user.id) | |||||
| tip_exception("作业不可重复提交") if student_work.work_status != 0 | |||||
| update_check student_work | |||||
| student_ids = [current_user.id] | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| student_work.description = params[:description] | |||||
| student_work.commit_time = Time.now | |||||
| student_work.update_time = Time.now | |||||
| student_work.commit_user_id = current_user.id | |||||
| student_work.update_user_id = current_user.id | |||||
| student_work.group_id = @homework.homework_type == "group" ? @homework.max_group_id : 0 | |||||
| #提交作品时,计算是否迟交 | |||||
| homework_setting = @homework.homework_group_setting(current_user.id) | |||||
| student_work.late_penalty = homework_setting.end_time < Time.now ? @homework.late_penalty : 0 | |||||
| student_work.work_status = homework_setting.end_time < Time.now ? 2 : 1 | |||||
| if student_work.save! | |||||
| Attachment.associate_container(params[:attachment_ids], student_work.id, student_work.class) | |||||
| if @homework.homework_type == "group" | |||||
| members = (params[:user_ids] || []).collect(&:to_i) - [current_user.id] | |||||
| members = @course.students.pluck(:user_id) & members | |||||
| student_ids += members | |||||
| for i in 0 .. members.count-1 | |||||
| stu_work = @homework.student_works.find_or_initialize_by(user_id: members[i].to_i) | |||||
| stu_work.update_attributes!(user_id: members[i].to_i, description: student_work.description, | |||||
| homework_common_id: @homework.id, project_id: student_work.project_id, | |||||
| late_penalty: student_work.late_penalty, work_status: student_work.work_status, | |||||
| commit_time: Time.now, update_time: Time.now, group_id: student_work.group_id, | |||||
| commit_user_id: current_user.id, update_user_id: current_user.id) | |||||
| stu_work.save! | |||||
| student_work.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = attachment.author_id | |||||
| stu_work.attachments << att | |||||
| end | |||||
| end | |||||
| end | |||||
| @homework.update_column(:updated_at, Time.now) | |||||
| # todo 更新对应的作业课堂动态 | |||||
| # update_course_activity(@taskhomework.class,@task.id) | |||||
| @work_id = student_work.id | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| SubmitStudentWorkNotifyJob.perform_later(@homework.id, student_ids) | |||||
| end | |||||
| def edit | |||||
| @current_user = current_user | |||||
| if @homework.homework_type == "group" | |||||
| # todo user_extension | |||||
| @commit_user_id = @work.commit_user_id | |||||
| @work_members = @course.students.where(user_id: @homework.student_works.where(group_id: @work.group_id).pluck(:user_id)). | |||||
| order("course_members.user_id=#{@work.commit_user_id} desc").includes(:course_group, user: :user_extension) | |||||
| end | |||||
| end | |||||
| def update | |||||
| update_check @work | |||||
| student_ids = [] | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| @work.description = params[:description] | |||||
| @work.update_time = Time.now | |||||
| @work.update_user_id = current_user.id | |||||
| # @work.commit_user_id = current_user.id | |||||
| if @work.save! | |||||
| Attachment.associate_container(params[:attachment_ids], @work.id, @work.class) | |||||
| #如果学生作品被打分后修改,应该给老师提示 | |||||
| student_ids << @work.user_id if @work.scored? | |||||
| if @homework.homework_type == "group" | |||||
| student_works = @homework.student_works.where("group_id = #{@work.group_id} and user_id != #{@work.user_id}") | |||||
| work_user_ids = student_works.pluck(:user_id) | |||||
| params_user_ids = (params[:user_ids] || []).collect(&:to_i) - [@work.user_id] | |||||
| params_user_ids = @course.students.pluck(:user_id) & params_user_ids | |||||
| # 原成员更新描述、更新时间以及附件 | |||||
| @homework.student_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work| | |||||
| # work.update_attributes(update_time: Time.now, description: @work.description, commit_user_id: current_user.id) | |||||
| work.update_attributes!(update_time: Time.now, description: @work.description, update_user_id: current_user.id) | |||||
| work.attachments.destroy_all | |||||
| @work.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = attachment.author_id | |||||
| work.attachments << att | |||||
| end | |||||
| student_ids << work.user_id if work.scored? | |||||
| end | |||||
| # 删除的成员 | |||||
| delete_user_ids = work_user_ids - params_user_ids | |||||
| @homework.student_works.where(group_id: @work.group_id, user_id: delete_user_ids).each do |work| | |||||
| work.attachments.destroy_all | |||||
| # work.student_works_scores.destroy_all | |||||
| work.tidings.destroy_all | |||||
| end | |||||
| @homework.student_works.where(group_id: @work.group_id, user_id: delete_user_ids). | |||||
| update_all(work_status: 0, description: nil, late_penalty: 0, commit_time: nil, update_time: nil, | |||||
| final_score: nil, teacher_score: nil, student_score: nil, teaching_asistant_score: nil, | |||||
| work_score: nil, project_id: 0, group_id: 0, commit_user_id: nil, update_user_id: nil) | |||||
| # 新增加的成员 | |||||
| (params_user_ids - work_user_ids).each do |user_id| | |||||
| stu_work = @homework.student_works.find_or_initialize_by(user_id: user_id) | |||||
| stu_work.update_attributes!(user_id: user_id, description: @work.description, homework_common_id: @homework.id, | |||||
| project_id: @work.project_id, late_penalty: @work.late_penalty, | |||||
| work_status: @work.work_status, commit_time: Time.now, update_time: Time.now, | |||||
| group_id: @work.group_id, commit_user_id: @work.commit_user_id, update_user_id: current_user.id) | |||||
| @work.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = attachment.author_id | |||||
| stu_work.attachments << att | |||||
| end | |||||
| student_ids << user_id | |||||
| end | |||||
| end | |||||
| normal_status(0,"更新成功") | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| ResubmitStudentWorkNotifyJob.perform_later(@homework.id, student_ids) if student_ids.present? | |||||
| end | |||||
| end | |||||
| def show | |||||
| @current_user = current_user | |||||
| @work_members = @homework.homework_type != "group" ? [] : @homework.student_works.where.not(user_id: @work.user_id). | |||||
| where(group_id: @work.group_id).includes(:user) | |||||
| @attachments = @work.attachments.where("attachtype != 7 or attachtype is null") | |||||
| end | |||||
| # 判断项目是否已有其他作品关联上了 | |||||
| def check_project | |||||
| tip_exception("项目id不能为空") if params[:project_id].blank? | |||||
| work = @homework.student_works.find_by_project_id(params[:project_id]) | |||||
| @is_relate = work.present? | |||||
| @relate_user = work.present? ? work.user.real_name : "" | |||||
| end | |||||
| def relate_project | |||||
| tip_exception("项目id不能为空") if params[:project_id].blank? | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 判断项目是否存在且当前用户是项目管理员 | |||||
| project = Project.find_by_id(params[:project_id]) | |||||
| member = Member.find_by_project_id_and_user_id(project.try(:id), current_user.id) | |||||
| if project.present? && member.present? && member.member_roles.take.try(:role_id) == 3 | |||||
| work = @homework.student_works.find_or_create_by(user_id: current_user.id) | |||||
| if work.work_status == 0 && work.project_id == 0 | |||||
| work.update_attributes!(project_id: project.id, update_time: Time.now) | |||||
| # 将老师加入项目 | |||||
| project_member = project.members.find_by_user_id(@homework.user_id) | |||||
| if project_member.present? | |||||
| project_member.member_roles.take.update_attributes!(role_id: 3) if project_member.member_roles.take.present? | |||||
| else | |||||
| member = Member.create!(user_id: @homework.user_id, project_id: project.id) | |||||
| member.member_roles << MemberRole.new(role_id: 3) | |||||
| Tiding.create(user_id: @homework.user_id, trigger_user_id: current_user.id, container_id: project.id, | |||||
| container_type: 'ManagerJoinProject', belong_container_id: project.id, | |||||
| belong_container_type: "Project", tiding_type: "System", extra: 3) | |||||
| end | |||||
| normal_status(0,"关联成功") | |||||
| else | |||||
| tip_exception("不能重复关联项目") | |||||
| end | |||||
| else | |||||
| tip_exception("该项目不存在") | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def cancel_relate_project | |||||
| work = @homework.student_works.find_by_user_id_and_work_status(current_user.id, 0) | |||||
| if work.present? && work.project.present? | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| member = work.project.members.find_by_user_id(@homework.user_id) | |||||
| member.destroy if member.present? | |||||
| Tiding.where(user_id: @homework.user_id, trigger_user_id: current_user.id, container_id: work.project.id, | |||||
| container_type: 'ManagerJoinProject').destroy_all | |||||
| work.update_attributes!(project_id: 0) | |||||
| normal_status(0,"取消关联成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| else | |||||
| tip_exception("无法取消关联") | |||||
| end | |||||
| end | |||||
| def supply_attachments | |||||
| @revise_attachments = @work.attachments.where(attachtype: 7) | |||||
| @last_atta = @revise_attachments.last | |||||
| end | |||||
| def revise_attachment | |||||
| tip_exception("不在补交阶段内") unless @homework.late_duration | |||||
| tip_exception("附件参数有误") if params[:attachment_ids].blank? || !params[:attachment_ids].is_a?(Array) | |||||
| tip_exception("补交附件原因不能为空") if params[:description].blank? | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 补交作业附件不覆盖之前上传的附件 | |||||
| # revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last | |||||
| # if revise_attachment.present? && @work.student_works_scores.where("created_at > '#{revise_attachment.created_on}' | |||||
| # and score is not null").count == 0 | |||||
| # revise_attachment.destroy | |||||
| # end | |||||
| Attachment.associate_container(params[:attachment_ids], @work.id, @work.class, 7) | |||||
| revise_attachment = Attachment.where(attachtype: 7, container_id: @work.id, container_type: "StudentWork").last | |||||
| revise_attachment.update_attributes!(description: params[:description]) if revise_attachment.present? | |||||
| @work.update_attributes!(update_time: Time.now) | |||||
| # 补交附件时给评阅过作品的教师、助教发消息 | |||||
| unless @work.student_works_scores.where.not(score: nil).where(reviewer_role: [1, 2]).pluck(:user_id).uniq.blank? | |||||
| ResubmitStudentWorkNotifyJob.perform_later(@homework.id, [current_user.id]) | |||||
| end | |||||
| normal_status(0, "提交成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| def comment_list | |||||
| @current_user = current_user | |||||
| @last_comment = @work.student_works_scores.where(user_id: @current_user.id).last | |||||
| # todo user_extension | |||||
| @comment_scores = (@user_course_identity < Course::STUDENT || current_user == @work.user) ? | |||||
| @work.student_works_scores.reorder("created_at desc") : | |||||
| @work.student_works_scores.where(user_id: current_user.id).reorder("created_at desc") | |||||
| @comment_scores = @comment_scores.includes(:student_works_scores_appeal, :attachments, journals_for_messages: :user, user: :user_extension) | |||||
| end | |||||
| # 给作品评分 | |||||
| def add_score | |||||
| tip_exception("该学生的分数已经过调整,不能再评阅") if @work.ultimate_score | |||||
| tip_exception("分数和评语不能都为空") if params[:score].blank? && params[:comment].blank? | |||||
| tip_exception("分数不能超过0-100") if params[:score] && (params[:score].to_f < 0 || params[:score].to_f > 100) | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 没传score则取上次评分成绩 | |||||
| reviewer_role = @user_course_identity == Course::STUDENT ? 3 : @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1 | |||||
| new_score = StudentWorksScore.new | |||||
| score = StudentWorksScore.where(user_id: current_user.id, student_work_id: @work.id, reviewer_role: reviewer_role).last | |||||
| new_score.score = params[:score].blank? ? score.try(:score) : params[:score].to_f | |||||
| new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != "" | |||||
| new_score.user_id = current_user.id | |||||
| new_score.student_work_id = @work.id | |||||
| # 如果作品是未提交的状态则更新为已提交 | |||||
| if @user_course_identity < Course::STUDENT && !new_score.score.nil? && @work.work_status == 0 | |||||
| @work.update_attributes!(work_status: 1, commit_time: Time.now) | |||||
| # 分组作业更新分组id | |||||
| @work.update_attributes!(group_id: @homework.max_group_id) if @homework.homework_type == "group" | |||||
| end | |||||
| new_score.reviewer_role = reviewer_role | |||||
| if new_score.save! | |||||
| Attachment.associate_container(params[:attachment_ids], new_score.id, new_score.class) | |||||
| # 该用户的历史评阅无效 | |||||
| score.update_column('is_invalid', true) if score.present? && score.score.present? | |||||
| Tiding.create(user_id: @work.user_id, trigger_user_id: User.current.id, container_id: new_score.id, | |||||
| container_type: "StudentWorksScore", parent_container_id: @work.id, | |||||
| parent_container_type: "HomeworkCommon", belong_container_id: @homework.course_id, | |||||
| belong_container_type: "Course", viewed: 0, tiding_type: new_score.reviewer_role == 3 ? "System" : "HomeworkCommon", extra: new_score.reviewer_role) | |||||
| case new_score.reviewer_role | |||||
| when 1 #教师评分:最后一个教师评分为最终评分 | |||||
| @work.teacher_score = new_score.score | |||||
| if @homework.homework_type == "group" && params[:same_score] | |||||
| add_score_to_member @work, @homework, new_score | |||||
| end | |||||
| when 2 #教辅评分 教辅评分显示平均分 | |||||
| # 助教评分:普通模式则是平均分,复审模式则是最新评分 | |||||
| if @homework.homework_detail_manual.ta_mode == 1 | |||||
| @work.teaching_asistant_score = new_score.ta_score @work.id | |||||
| else | |||||
| @work.teaching_asistant_score = new_score.score | |||||
| end | |||||
| if @homework.homework_type == "group" && params[:same_score] | |||||
| add_score_to_member @work, @homework, new_score | |||||
| end | |||||
| when 3 #学生评分 学生评分显示平均分 | |||||
| # 匿评分 | |||||
| @work.student_score = new_score.stu_score(@work.id) | |||||
| if @homework.homework_type == "group" && new_score.score.present? | |||||
| add_score_to_member @work, @homework, new_score | |||||
| end | |||||
| current_user.student_works_scores.where(student_work_id: @work.id, reviewer_role: 3, appeal_status: 1).update_all(appeal_status: 5) | |||||
| end | |||||
| @homework.update_column('updated_at', Time.now) | |||||
| # update_course_activity(@homework.class,@homework.id) | |||||
| @work.save! | |||||
| normal_status(0,"提交成功") | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # 实训作品的提交总结 | |||||
| def commit_des | |||||
| @current_user = current_user | |||||
| end | |||||
| # 实训作品的总结 | |||||
| def update_des | |||||
| @work.update_attributes!(des_params) | |||||
| tip_exception(0, "提交成功") | |||||
| end | |||||
| # 实训作品弹框 | |||||
| def shixun_work | |||||
| @myshixun = @work.myshixun | |||||
| if @myshixun.present? | |||||
| @current_user = current_user | |||||
| @work_user = @work.user | |||||
| @shixun = @homework.shixuns.take | |||||
| else | |||||
| tip_exception("作品还未提交") | |||||
| end | |||||
| end | |||||
| # 实训报告 | |||||
| def shixun_work_report | |||||
| @user = @work.user | |||||
| @shixun = @homework.shixuns.take | |||||
| # 提示: 这里如果includes outputs表的话: sum(:evaluate_count)会出现错误 | |||||
| @games = @work.myshixun.games.joins(:challenge).reorder("challenges.position asc") if @work.myshixun | |||||
| @challenges = @shixun.challenges if @shixun | |||||
| @comment = @work.shixun_work_comments.find_by(challenge_id: 0) | |||||
| # 用户最大评测次数 | |||||
| if @games | |||||
| @user_evaluate_count = @games.pluck(:evaluate_count).sum | |||||
| @games = @games.includes(:challenge, :game_codes, :outputs) | |||||
| else | |||||
| @user_evaluate_count = 0 | |||||
| end | |||||
| # 图形效率图的数据 | |||||
| @echart_data = student_efficiency(@homework, @work) if @work.myshixun | |||||
| end | |||||
| # 实训作品的评阅 | |||||
| def shixun_work_comment | |||||
| tip_exception("请至少输入一个评阅") if params[:comment].blank? && params[:hidden_comment].blank? | |||||
| ActiveRecord::Base.transaction do | |||||
| challenge = @homework.shixuns.first&.challenges.find_by(id: params[:challenge_id]) unless params[:challenge_id].blank? | |||||
| if challenge.present? | |||||
| @comment = @work.shixun_work_comments.find_by(challenge_id: challenge.id) || | |||||
| ShixunWorkComment.new(student_work_id: @work.id, user_id: current_user.id, challenge_id: challenge.id) | |||||
| else | |||||
| @comment = @work.shixun_work_comments.find_by(challenge_id: 0) || | |||||
| ShixunWorkComment.new(student_work_id: @work.id, user_id: current_user.id, challenge_id: 0) | |||||
| end | |||||
| @comment.comment = params[:comment] | |||||
| @comment.hidden_comment = params[:hidden_comment] | |||||
| @comment.save! | |||||
| if @work.work_status == 0 | |||||
| @work.update_attributes!(work_status: 1, commit_time: @homework.end_time, update_time: Time.now, work_score: 0, final_score: 0) | |||||
| end | |||||
| end | |||||
| end | |||||
| # 删除实训作品评阅 | |||||
| def destroy_work_comment | |||||
| ActiveRecord::Base.transaction do | |||||
| # tip_exception("visible_comment参数有误") if params[:visible_comment].nil? | |||||
| comment = @work.shixun_work_comments.find_by!(id: params[:comment_id]) | |||||
| comment.destroy! | |||||
| # params[:visible_comment] ? comment.comment = nil : comment.hidden_comment = nil | |||||
| # if comment.comment.nil? && comment.hidden_comment.nil? | |||||
| # comment.destroy! | |||||
| # else | |||||
| # comment.save! | |||||
| # end | |||||
| normal_status("删除成功") | |||||
| end | |||||
| end | |||||
| def export_shixun_work_report | |||||
| @user = @work.user | |||||
| @shixun = @homework.shixuns.take | |||||
| @games = @work.myshixun.games.includes(:challenge, :game_codes, :outputs) if @work.myshixun | |||||
| @challenges = @shixun.challenges if @shixun | |||||
| # 用户最大评测次数 | |||||
| @user_evaluate_count = @games.pluck(:evaluate_count).sum if @games | |||||
| # 图形效率图的数据 | |||||
| @echart_data = student_efficiency(@homework, @work) | |||||
| @myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id } | |||||
| @myself_consume = @echart_data[:consume_list].find { |item| item.last == @user.id } | |||||
| filename_ = "#{@homework.course&.user_group_name(@work.user_id)}_#{@user&.student_id}_#{@user&.real_name}_#{@shixun&.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf" | |||||
| filename = filename_.strip.tr("+/", "-_") | |||||
| stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css) | |||||
| if params[:export].present? && params[:export] | |||||
| normal_status(0,"正在下载中") | |||||
| else | |||||
| set_export_cookies | |||||
| render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false | |||||
| end | |||||
| # render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false | |||||
| end | |||||
| # 作品调分 | |||||
| def adjust_score | |||||
| tip_exception("成绩不能为空") if params[:score].blank? | |||||
| tip_exception("成绩不能小于零") if params[:score].to_f < 0 | |||||
| tip_exception("成绩不能大于100") if params[:score].to_f.round(1) > 100 | |||||
| tip_exception("调分原因不能超过100个字符") if params[:comment].present? && params[:comment].length > 100 | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 分数不为空的历史评阅都置为失效 | |||||
| @work.student_works_scores.where.not(score: nil).update_all(is_invalid: 1) | |||||
| reviewer_role = @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1 | |||||
| new_score = StudentWorksScore.new(student_work_id: @work.id, score: params[:score].to_f, comment: "使用调分功能调整了作业最终成绩:#{params[:comment]}", | |||||
| user_id: current_user.id, reviewer_role: reviewer_role, is_ultimate: 1) | |||||
| new_score.save! | |||||
| # 如果作品是未提交的状态则更新为已提交 | |||||
| if @work.work_status == 0 | |||||
| @work.work_status = 1 | |||||
| @work.commit_time = Time.now | |||||
| @work.compelete_status = 1 if @homework.homework_type == "practice" | |||||
| # 分组作业更新分组id | |||||
| @work.group_id = @homework.max_group_id if @homework.homework_type == "group" | |||||
| end | |||||
| @work.ultimate_score = true | |||||
| @work.work_score = params[:score].to_f | |||||
| @work.save! | |||||
| Tiding.create!(user_id: @work.user_id, trigger_user_id: current_user.id, container_id: new_score.id, | |||||
| container_type: "AdjustScore", parent_container_id: @homework.id, | |||||
| parent_container_type: "HomeworkCommon", belong_container_id: @course.id, | |||||
| belong_container_type: 'Course', tiding_type: "HomeworkCommon") | |||||
| normal_status(0,"调分成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| #添加评分的回复 | |||||
| def add_score_reply | |||||
| tip_exception("回复内容不能为空") if params[:comment].blank? | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| score = @work.student_works_scores.find_by!(id: params[:score_id]) | |||||
| jour = score.journals_for_messages.new(user_id: current_user.id, notes: params[:comment], reply_id: score.user_id) | |||||
| jour.save! | |||||
| normal_status(0,"回复成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| end | |||||
| # 删除教师/教辅的评分记录 | |||||
| def destroy_score | |||||
| score = @work.student_works_scores.find_by(id: params[:score_id]) | |||||
| tip_exception("该评阅记录不存在") unless score.present? | |||||
| tip_exception("该评阅记录不能删除") unless score.allow_delete(current_user) | |||||
| begin | |||||
| score.destroy | |||||
| normal_status(0,"删除成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| # 对学生匿评进行申诉 | |||||
| def appeal_anonymous_score | |||||
| tip_exception("申诉原因不能为空") if params[:comment].blank? | |||||
| score = @work.student_works_scores.find_by(id: params[:score_id].to_i) | |||||
| tip_exception("无法申诉") unless score.present? && @homework.appeal_duration && | |||||
| score.reviewer_role == 3 && score.appeal_status == 0 | |||||
| score_appeal = nil | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| score.update_attributes!(appeal_status: 1) | |||||
| score_appeal = StudentWorksScoresAppeal.create!(user_id: current_user.id, student_works_score_id: score.id, | |||||
| comment: params[:comment], appeal_status: 1) | |||||
| normal_status(0,"提交成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| # 提交后给老师和助教、匿评人发消息 | |||||
| StudentWorkScoreAppealNotifyJob.perform_later(@course.id, score_appeal.id, current_user.id) | |||||
| end | |||||
| # 撤销申诉 | |||||
| def cancel_appeal | |||||
| score = @work.student_works_scores.find_by(id: params[:score_id].to_i) | |||||
| if score.present? && score.appeal_status == 1 | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| score.update_attributes!(appeal_status: 2) | |||||
| score_appeal = score.student_works_scores_appeal | |||||
| score_appeal.update_attributes!(appeal_status: 2) | |||||
| score_appeal.tidings.destroy_all | |||||
| normal_status(0,"撤销成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| else | |||||
| tip_exception("无法撤销") | |||||
| end | |||||
| end | |||||
| # status 3 接受 4 拒绝 | |||||
| def deal_appeal_score | |||||
| tip_exception("缺少status参数") if params[:status].blank? | |||||
| tip_exception("status值不合要求") unless params[:status].to_i == 3 || params[:status].to_i == 4 | |||||
| score = @work.student_works_scores.find_by(id: params[:score_id].to_i) | |||||
| if score.present? && score.appeal_status == 1 | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| # 更新appeal_status的值 | |||||
| score.update_attributes!(appeal_status: params[:status].to_i) | |||||
| score_appeal = score.student_works_scores_appeal | |||||
| score_appeal.update_attributes!(appeal_status: params[:status].to_i) | |||||
| score_appeal.tidings.update_all(status: 1) | |||||
| if params[:status].to_i == 3 | |||||
| # 申诉成功后该评分失效 | |||||
| score.update_attributes!(is_invalid: 1) | |||||
| # 申诉成功后 扣匿评学生的违规匿评扣分 | |||||
| sw = @homework.student_works.find_by(user_id: score.user_id) | |||||
| sw.update_attributes!(appeal_penalty: @homework.homework_detail_manual.appeal_penalty + sw.appeal_penalty) if sw.present? | |||||
| # 申诉成功 重新计算申诉者的匿评分 | |||||
| if @work.student_works_scores.where("reviewer_role = 3 AND appeal_status != 3").count > 0 | |||||
| @work.student_score = score.stu_score(@work.id) | |||||
| else | |||||
| @work.student_score = nil | |||||
| end | |||||
| @work.save! | |||||
| end | |||||
| # todo tiding | |||||
| Tiding.create(user_id: score_appeal.user_id, trigger_user_id: current_user.id, container_id: score_appeal.id, | |||||
| container_type: "StudentWorksScoresAppeal", parent_container_id: @work.id, | |||||
| parent_container_type: 'UserAppealResult', belong_container_id: @course.id, | |||||
| belong_container_type: "Course", viewed: 0, status: params[:status].to_i == 3 ? 1 : 2, | |||||
| tiding_type: "HomeworkCommon") | |||||
| Tiding.create(user_id: score.user_id, trigger_user_id: current_user.id, container_id: score_appeal.id, | |||||
| container_type: "StudentWorksScoresAppeal", parent_container_id: @work.id, | |||||
| parent_container_type: 'AppealResult', belong_container_id: @course.id, belong_container_type: "Course", | |||||
| viewed: 0, status: params[:status].to_i == 3 ? 1 : 2, tiding_type: "HomeworkCommon") | |||||
| normal_status(0,"提交成功") | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception(e.message) | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| else | |||||
| tip_exception("该申诉不存在") | |||||
| end | |||||
| end | |||||
| # 查重作品调分 | |||||
| def adjust_review_score | |||||
| tip_exception("缺少type参数") if params[:type].blank? || !["review", "report"].include?(params[:type]) | |||||
| if params[:type] == "review" && (params[:score].blank? || params[:challenge_id].blank? || params[:code_rate].blank? || params[:copy_user_id].blank?) | |||||
| tip_exception("参数错误,score和challenge_id和code_rate和copy_user_id不能为空") | |||||
| elsif params[:type] == "report" && (params[:score].blank? || params[:challenge_id].blank?) | |||||
| tip_exception("参数错误,score和challenge_id不能为空") | |||||
| end | |||||
| challenge_setting = @homework.homework_challenge_settings.find_by(challenge_id: params[:challenge_id]) | |||||
| if challenge_setting | |||||
| challenge = challenge_setting&.challenge | |||||
| tip_exception("不能小于零") if params[:score].to_i < 0 | |||||
| tip_exception("不能大于关卡分值:#{challenge_setting.score}分") if challenge_setting && challenge_setting.score < params[:score].to_i | |||||
| ActiveRecord::Base.transaction do | |||||
| begin | |||||
| if params[:type] == "review" | |||||
| copy_user = User.find params[:copy_user_id] | |||||
| comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%" | |||||
| else | |||||
| comment = "根据实训报告中最终提交的代码调整第#{challenge.position}关分数" | |||||
| end | |||||
| challenge_score = @work.challenge_work_scores.create!(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score], | |||||
| comment: comment) | |||||
| challenge_score.create_tiding current_user.id | |||||
| if @work.work_status != 0 && @work.myshixun | |||||
| games = @work.myshixun.games.where(challenge_id: @homework.homework_challenge_settings.pluck(:challenge_id)) | |||||
| HomeworksService.new.update_myshixun_work_score @work, @work.myshixun, games, @homework, @homework.homework_challenge_settings | |||||
| else | |||||
| update_none_commit_work @work, @homework | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger(e.message) | |||||
| tip_exception("调分失败") | |||||
| raise ActiveRecord::Rollback | |||||
| end | |||||
| end | |||||
| else | |||||
| tip_exception("该关卡不记分") | |||||
| end | |||||
| end | |||||
| private | |||||
| def find_homework | |||||
| begin | |||||
| @homework = HomeworkCommon.find params[:homework_common_id] | |||||
| @course = @homework.course | |||||
| rescue Exception => e | |||||
| uid_logger_error("##########{e.message}") | |||||
| missing_template | |||||
| end | |||||
| end | |||||
| def find_work | |||||
| begin | |||||
| @work = StudentWork.find params[:id] | |||||
| @homework = @work.homework_common | |||||
| @course = @homework.course | |||||
| rescue Exception => e | |||||
| uid_logger_error("##########{e.message}") | |||||
| missing_template | |||||
| end | |||||
| end | |||||
| def homework_public | |||||
| tip_exception(403,"没有操作权限") unless @user_course_identity <= Course::STUDENT || | |||||
| (@course.is_public == 1 && @homework.is_public) | |||||
| end | |||||
| def course_student | |||||
| uid_logger("#########course-student") | |||||
| tip_exception(403,"没有操作权限") if @user_course_identity != Course::STUDENT | |||||
| end | |||||
| def my_work | |||||
| tip_exception(403,"没有操作权限") if @work.user_id != current_user.id || @work.work_status == 0 | |||||
| end | |||||
| def edit_duration | |||||
| tip_exception("已过了修改时间") if @homework.end_time && @homework.end_time < Time.now | |||||
| end | |||||
| def end_or_late | |||||
| tip_exception("不在提交/更新阶段") if @homework.end_or_late | |||||
| end | |||||
| def des_params | |||||
| tip_exception("description参数不能为空") if params[:description].blank? | |||||
| params.require(:student_work).permit(:description) | |||||
| end | |||||
| def require_score_id | |||||
| tip_exception("score_id参数不能为空") if params[:score_id].blank? | |||||
| end | |||||
| # 是否匿评阶段 | |||||
| def is_evaluation | |||||
| @is_author = @work.user_id == current_user.id | |||||
| @is_evaluation = @user_course_identity == Course::STUDENT && !@is_author && @homework.anonymous_comment && | |||||
| [3, 4].include?(@homework.homework_detail_manual.comment_status) | |||||
| end | |||||
| # 作品是否公开 | |||||
| def open_work | |||||
| tip_exception(403,"没有操作权限") unless (@user_course_identity < Course::STUDENT || current_user == @work.user || @homework.work_public || @is_evaluation) | |||||
| end | |||||
| def allow_add_score | |||||
| # 老师始终有评阅权限,匿评阶段内,学生对分配给该学生的作品有评阅权限 | |||||
| tip_exception(403, "没有权限") unless allow_score(@homework, @user_course_identity, current_user.id, @work) | |||||
| end | |||||
| def update_check work | |||||
| tip_exception("作品描述不能为空") if params[:description].blank? | |||||
| if @homework.homework_type == "group" | |||||
| tip_exception("小组成员不能为空") if params[:user_ids].blank? | |||||
| tip_exception("小组成员人数不合要求") if params[:user_ids].length > @homework.homework_detail_group.max_num || | |||||
| params[:user_ids].length < @homework.homework_detail_group.min_num | |||||
| tip_exception("请先关联项目") if @homework.homework_detail_group.base_on_project && work.project_id == 0 | |||||
| end | |||||
| end | |||||
| def add_score_to_member student_work, homework, new_score | |||||
| student_works = homework.student_works.where("group_id = #{student_work.group_id} and id != #{student_work.id} and ultimate_score = 0") | |||||
| student_works.each do |st_work| | |||||
| st_score = StudentWorksScore.new(user_id: new_score.user_id, score: new_score.score, | |||||
| reviewer_role: new_score.reviewer_role, comment: new_score.comment) | |||||
| score = StudentWorksScore.where(user_id: new_score.user_id, student_work_id: st_work.id, reviewer_role: new_score.reviewer_role).last | |||||
| # 该用户的历史评阅无效 | |||||
| score.update_column('is_invalid', true) if score.present? && score.score.present? | |||||
| st_work.student_works_scores << st_score | |||||
| if new_score.reviewer_role == 1 | |||||
| st_work.teacher_score = new_score.score if new_score.score.present? | |||||
| elsif new_score.reviewer_role == 2 | |||||
| if homework.homework_detail_manual.ta_mode == 1 | |||||
| st_work.teaching_asistant_score = new_score.ta_score st_work.id | |||||
| else | |||||
| st_work.teaching_asistant_score = new_score.score if new_score.score.present? | |||||
| end | |||||
| else | |||||
| st_work.student_score = student_work.student_score | |||||
| end | |||||
| st_work.save! | |||||
| Tiding.create(user_id: st_work.user_id, trigger_user_id: current_user.id, container_id: st_score.id, | |||||
| container_type: "StudentWorksScore", parent_container_id: st_work.id, parent_container_type: "StudentWork", | |||||
| belong_container_id: homework.course_id, belong_container_type: "Course", viewed: 0, | |||||
| tiding_type: "HomeworkCommon", extra: new_score.reviewer_role) | |||||
| new_score.attachments.each do |attachment| | |||||
| att = attachment.copy | |||||
| att.author_id = st_score.user_id | |||||
| st_score.attachments << att | |||||
| end | |||||
| end | |||||
| end | |||||
| def update_none_commit_work work, homework | |||||
| if work.work_status == 0 | |||||
| work.work_status = 1 | |||||
| work.compelete_status = 1 | |||||
| work.commit_time = homework.end_time | |||||
| work.update_time = Time.now | |||||
| end | |||||
| final_score = 0 | |||||
| homework.homework_challenge_settings.each do |cha_setting| | |||||
| adjust_score = work.challenge_work_scores.select{|work_score| work_score.challenge_id == cha_setting.challenge_id}.last | |||||
| final_score += adjust_score.score if adjust_score.present? | |||||
| end | |||||
| work.final_score = final_score | |||||
| work.work_score = final_score | |||||
| work.save! | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,334 @@ | |||||
| class SyncForgeController < ApplicationController | |||||
| # before_action :check_token | |||||
| def sync_range_projects | |||||
| sync_counts = params[:sync_count] || 10 | |||||
| projects = Project.includes(:project_score, :repository) | |||||
| .where(is_public: true) | |||||
| .where.not(identifier: ["educoder","trustieforge", "gitlab", "rGDBbQmOK", "socialforge"]) | |||||
| .joins(:project_score).order("project_scores.changeset_num desc").limit(sync_counts.to_i) | |||||
| projects.each do | project | | |||||
| SyncProjectMilitaryJob.perform_later(project, project.repository, project.project_score) | |||||
| end | |||||
| end | |||||
| # def create | |||||
| # ActiveRecord::Base.transaction do | |||||
| # params.permit! | |||||
| # sync_params = params[:sync_params] | |||||
| # project_user = User.where(login: sync_params[:owner_login])&.first | |||||
| # #以前已同步的项目,那么肯定存在仓库 | |||||
| # SyncLog.sync_log("=================begin_to_sync_forge: project_identifier: #{sync_params[:identifier]}========") | |||||
| # user_projects = Project.where(user_id: project_user.id) | |||||
| # if user_projects.where(id: sync_params[:id], identifier: sync_params[:identifier]).present? | |||||
| # has_project = true | |||||
| # project = user_projects.where(id: sync_params[:id], identifier: sync_params[:identifier])&.first | |||||
| # elsif user_projects.where(id: sync_params[:id]).present? | |||||
| # has_project = true | |||||
| # project = user_projects.where(id: sync_params[:id])&.first | |||||
| # elsif user_projects.where(identifier: sync_params[:identifier]).present? | |||||
| # has_project = true | |||||
| # project = user_projects.where(identifier: sync_params[:identifier])&.first | |||||
| # else | |||||
| # has_project = false | |||||
| # end | |||||
| # if has_project | |||||
| # SyncLog.sync_log("=================begin_to_update_project========") | |||||
| # check_sync_project(project, sync_params) | |||||
| # else #新建项目 | |||||
| # SyncLog.sync_log("=================begin_to_create_new_project========") | |||||
| # project_params = { | |||||
| # repository_name: sync_params[:identifier], | |||||
| # user_id: project_user.id, | |||||
| # private: !sync_params[:is_public], | |||||
| # name: sync_params[:name] | |||||
| # } | |||||
| # project = Projects::CreateService.new(project_user, project_params).call | |||||
| # if project.present? | |||||
| # if sync_params[:project_score].present? | |||||
| # sync_params.permit! | |||||
| # score_params = sync_params[:project_score].merge(project_id: project.id) | |||||
| # new_project_score = ProjectScore.create(score_params) | |||||
| # SyncLog.sync_log("=================new_project_score:#{new_project_score.try(:id)}========") | |||||
| # end | |||||
| # SyncRepositoryJob.perform_later(sync_params[:owner_login], sync_params[:identifier], sync_params[:repository], get_sudomain) if sync_params[:repository].present? | |||||
| # check_new_project(project, sync_params) | |||||
| # else | |||||
| # SyncLog.sync_project_log("=============new_project_create_failed, trustie_project_id==:#{params[:sync_params][:id]}") | |||||
| # end | |||||
| # end | |||||
| # end | |||||
| # rescue Exception => e | |||||
| # SyncLog.sync_project_log("=============sync_has_errors:==#{e.message}, project_id==:#{params[:sync_params][:id]}") | |||||
| # end | |||||
| # def sync_users | |||||
| # params.permit! | |||||
| # sync_params = params[:sync_params] | |||||
| # users_params = sync_params[:users] | |||||
| # users_params.each do |u| | |||||
| # if User.exists?(login: u[:user_params][:login]) | |||||
| # SyncLog.sync_log("=================sync_to_user_been_exists====#{u[:user_params][:login]}") | |||||
| # else | |||||
| # # new_user = User.new(u[:user_params]) | |||||
| # if u[:user_params][:mail].blank? | |||||
| # u_mail = "#{u[:user_params][:login]}@example.com" | |||||
| # else | |||||
| # u_mail = u[:user_params][:mail] | |||||
| # end | |||||
| # new_user = User.new(u[:user_params].merge(mail: u_mail)) | |||||
| # username = new_user.login | |||||
| # password = "12345678" | |||||
| # # if new_user.save! | |||||
| # # SyncLog.sync_log("=================sync_to_user_success==#{new_user.login}") | |||||
| # # else | |||||
| # # SyncLog.sync_log("=================sync_to_user_failed,user_login==#{new_user.login}") | |||||
| # # end | |||||
| # ActiveRecord::Base.transaction do | |||||
| # interactor = Gitea::RegisterInteractor.call({username: username, email: new_user.mail, password: password}) | |||||
| # if interactor.success? | |||||
| # gitea_user = interactor.result | |||||
| # result = Gitea::User::GenerateTokenService.new(username, password).call | |||||
| # new_user.gitea_token = result['sha1'] | |||||
| # new_user.gitea_uid = gitea_user['id'] | |||||
| # if new_user.save! | |||||
| # UserExtension.create!(u[:user_extensions][:user_extensions].merge(user_id: new_user.id)) if u[:user_extensions].present? && u[:user_extensions][:user_extensions].present? | |||||
| # else | |||||
| # SyncLog.sync_log("=================sync_to_user_failed,user_login==#{new_user.login}") | |||||
| # end | |||||
| # else | |||||
| # SyncLog.sync_log("=============sync_to_user_failed,user_login====#{new_user.login}") | |||||
| # SyncLog.sync_log("=================sync_to_user_failed,user_login====#{new_user.login}") | |||||
| # end | |||||
| # end | |||||
| # end | |||||
| # end | |||||
| # # normal_status(1, "completed_sync") | |||||
| # rescue Exception => e | |||||
| # SyncLog.sync_log("=================sync_user_failed====#{e}") | |||||
| # end | |||||
| # private | |||||
| # def check_sync_project(project,sync_params) | |||||
| # begin | |||||
| # gitea_main = "https://www.trustie.net/" | |||||
| # # if request.subdomain === 'testforgeplus' | |||||
| # # gitea_main = "https://ucloudtest.trustie.net/" | |||||
| # # end | |||||
| # SyncLog.sync_log("----begin_to_check_sync_project----project_id:#{project.id}---------------") | |||||
| # change_project_score(project, sync_params[:project_score], sync_params[:repository]) if sync_params[:repository].present? #更新project_score | |||||
| # change_project_issues(project, sync_params[:issues],project.id, gitea_main) | |||||
| # change_project_members(project, sync_params[:members],gitea_main) | |||||
| # change_project_versions(project, sync_params[:project_versions],gitea_main) | |||||
| # change_project_watchers(project, sync_params[:project_watchers],gitea_main) | |||||
| # change_project_praises(project, sync_params[:praise_trends],gitea_main) | |||||
| # rescue => e | |||||
| # SyncLog.sync_log("=========check_sync_project_errors:#{e}===================") | |||||
| # end | |||||
| # end | |||||
| # def check_new_project(project,sync_params) | |||||
| # SyncLog.sync_log("***8. begin_to_sync_new_project---------------") | |||||
| # sync_projects_params = { | |||||
| # type: "Project", | |||||
| # ids: sync_params[:id], | |||||
| # token: get_token, | |||||
| # sync_params: sync_params, | |||||
| # new_project_id: project.id | |||||
| # } | |||||
| # gitea_main = "https://www.trustie.net/" | |||||
| # # if request.subdomain === 'testforgeplus' | |||||
| # # gitea_main = "https://ucloudtest.trustie.net/" | |||||
| # # end | |||||
| # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) | |||||
| # SyncLog.sync_log("***8. end_to_sync_new_project---------------") | |||||
| # end | |||||
| # def change_project_praises(project, praises,gitea_main) | |||||
| # SyncLog.sync_log("***6. begin_to_sync_parises---------------") | |||||
| # forge_praises_ids = project&.praise_treads&.select(:id)&.pluck(:id) | |||||
| # diff_target_ids = praises[:ids] - forge_praises_ids | |||||
| # if diff_target_ids.size > 0 | |||||
| # sync_projects_params = { | |||||
| # type: "PraiseTread", | |||||
| # ids: diff_target_ids, | |||||
| # token: get_token, | |||||
| # parent_id: project.id | |||||
| # } | |||||
| # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | |||||
| # SyncLog.sync_log("***6. end_to_sync_parises---------------") | |||||
| # end | |||||
| # end | |||||
| # #检查repository和project_score | |||||
| # def change_project_score(project, project_scores, repository_params) | |||||
| # SyncLog.sync_log("***1. begin_to_sync_project_score---------------") | |||||
| # begin | |||||
| # pre_project_score = project.project_score | |||||
| # if pre_project_score.present? | |||||
| # change_num = 0 | |||||
| # project_scores.each do |k,v| | |||||
| # unless pre_project_score.send("#{k}") == v | |||||
| # change_num += 1 | |||||
| # pre_project_score[:"#{k}"] = v | |||||
| # end | |||||
| # if k == "changeset_num" && v.to_i > pre_project_score.changeset_num.to_i && repository_params[:url].present? | |||||
| # SyncRepositoryJob.perform_later(project.owner.try(:login), project.identifier, repository_params, get_sudomain) | |||||
| # end | |||||
| # end | |||||
| # pre_project_score.save! if change_num > 0 #如果 project_score有变化则更新 | |||||
| # else | |||||
| # ProjectScore.create!(project_scores.merge(project_id: project.id)) | |||||
| # end | |||||
| # SyncLog.sync_log("***1. end_to_sync_project_score---------------") | |||||
| # rescue Exception => e | |||||
| # SyncLog.sync_log("=========change_project_score_errors:#{e}===================") | |||||
| # end | |||||
| # end | |||||
| # def change_project_issues(project, old_issues_params,project_id, gitea_main) | |||||
| # SyncLog.sync_log("***2. begin_to_syncissues---------------") | |||||
| # begin | |||||
| # forge_issue_ids = project&.issues&.select(:id)&.pluck(:id) | |||||
| # sync_projects_params = {} | |||||
| # SyncLog.sync_log("***2--01. forge_issue_ids-#{forge_issue_ids.size.to_i}--------------") | |||||
| # if forge_issue_ids.size.to_i <= old_issues_params[:count].to_i | |||||
| # diff_issue_ids = old_issues_params[:ids] - forge_issue_ids | |||||
| # if diff_issue_ids.size == 0 #issue数量一样,判断评论是否有增减 | |||||
| # forge_journal_ids = Journal.select([:id, :journalized_id, :journalized_type]).where(journalized_id: forge_issue_ids).pluck(:id) | |||||
| # diff_journal_ids = old_issues_params[:journals][:ids] - forge_journal_ids | |||||
| # unless diff_journal_ids.size == 0 | |||||
| # sync_projects_params = { | |||||
| # type: "Journal", | |||||
| # ids: diff_journal_ids, | |||||
| # token: get_token, | |||||
| # parent_id: project_id | |||||
| # } | |||||
| # SyncLog.sync_log("***2--02. sync_projects_params-#{sync_projects_params}--------------") | |||||
| # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) | |||||
| # end | |||||
| # else | |||||
| # new_diff_ids = diff_issue_ids.in_groups_of(200).map{|k| k.reject(&:blank?)} | |||||
| # diff_len = new_diff_ids.length | |||||
| # (1..diff_len).each do |len| | |||||
| # sync_projects_params = { | |||||
| # type: "Issue", | |||||
| # ids: new_diff_ids[len-1], | |||||
| # token: get_token, | |||||
| # parent_id: project_id | |||||
| # } | |||||
| # SyncLog.sync_log("***2--030#{len}. sync_projects_params_groups-#{sync_projects_params}--------------") | |||||
| # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) | |||||
| # end | |||||
| # # sync_projects_params = { | |||||
| # # type: "Issue", | |||||
| # # ids: diff_issue_ids, | |||||
| # # token: get_token, | |||||
| # # parent_id: project_id | |||||
| # # } | |||||
| # # SyncLog.sync_log("***2--03. sync_projects_params_groups-#{sync_projects_params}--------------") | |||||
| # # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) | |||||
| # end | |||||
| # end | |||||
| # # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) if sync_projects_params.present? | |||||
| # SyncLog.sync_log("***2. end_to_syncissues---------------") | |||||
| # rescue Exception => e | |||||
| # SyncLog.sync_log("=========change_project_issues_errors:#{e}===================") | |||||
| # end | |||||
| # end | |||||
| # def change_project_watchers(project, watchers,gitea_main) | |||||
| # SyncLog.sync_log("***5. begin_to_sync_watchers---------------") | |||||
| # forge_watchers_ids = project&.watchers&.select(:id)&.pluck(:id) | |||||
| # if forge_watchers_ids.size.to_i <= watchers[:count].to_i | |||||
| # diff_target_ids = watchers[:ids] - forge_watchers_ids | |||||
| # if diff_target_ids.size > 0 | |||||
| # sync_projects_params = { | |||||
| # type: "Watcher", | |||||
| # ids: diff_target_ids, | |||||
| # token: get_token, | |||||
| # parent_id: project.id | |||||
| # } | |||||
| # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | |||||
| # end | |||||
| # end | |||||
| # SyncLog.sync_log("***5. begin_to_sync_watchers---------------") | |||||
| # end | |||||
| # def change_project_versions(project, versions,gitea_main) | |||||
| # SyncLog.sync_log("***4. begin_to_sync_versions---------------") | |||||
| # forge_version_ids = project&.versions&.select(:id)&.pluck(:id) | |||||
| # if forge_version_ids.size <= versions[:count].to_i | |||||
| # diff_version_ids = versions[:ids] - forge_version_ids | |||||
| # if diff_version_ids.size > 0 | |||||
| # sync_projects_params = { | |||||
| # type: "Version", | |||||
| # ids: diff_version_ids, | |||||
| # token: get_token, | |||||
| # parent_id: project.id | |||||
| # } | |||||
| # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | |||||
| # end | |||||
| # SyncLog.sync_log("***4. end_to_sync_versions---------------") | |||||
| # end | |||||
| # end | |||||
| # def change_project_members(project, members,gitea_main) | |||||
| # SyncLog.sync_log("***3. begin_to_sync_members---------------") | |||||
| # forge_member_ids = project&.members&.select(:id)&.pluck(:id) | |||||
| # if forge_member_ids.size <= members[:count] | |||||
| # diff_member_ids = members[:ids] - forge_member_ids | |||||
| # if diff_member_ids.size > 0 | |||||
| # sync_projects_params = { | |||||
| # type: "Member", | |||||
| # ids: diff_member_ids, | |||||
| # token: get_token, | |||||
| # parent_id: project.id | |||||
| # } | |||||
| # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | |||||
| # end | |||||
| # SyncLog.sync_log("***3. end_to_sync_members---------------") | |||||
| # end | |||||
| # end | |||||
| # def check_token | |||||
| # sync_params = params[:sync_params] | |||||
| # unless sync_params[:token] && sync_params[:token] == get_token | |||||
| # render json: {message: "token_errors"} | |||||
| # end | |||||
| # end | |||||
| # def get_token | |||||
| # "34c82f51e0b699d9d16d70fd6497c9b1e4821d6ea3e872558a6537a091076b8e" | |||||
| # end | |||||
| # def get_sudomain | |||||
| # SyncLog.sync_log("=================request.subdomain:#{request.subdomain}========") | |||||
| # gitea_main = "gitea.trustie.net" | |||||
| # if request.subdomain === 'testforgeplus' | |||||
| # gitea_main = "testgitea2.trustie.net" | |||||
| # # elsif request.subdomain === 'forgeplus' | |||||
| # # gitea_main = "gitea.trustie.net" | |||||
| # end | |||||
| # return gitea_main | |||||
| # end | |||||
| end | |||||
| @@ -1,11 +0,0 @@ | |||||
| class TagDisciplinesController < ApplicationController | |||||
| before_action :require_login | |||||
| def create | |||||
| sub_discipline = SubDiscipline.find_by!(id: params[:sub_discipline_id]) | |||||
| tip_exception("重复的知识点") if sub_discipline.tag_disciplines.exists?(name: params[:name].to_s.strip) | |||||
| tag_discipline = TagDiscipline.create!(name: params[:name].to_s.strip, sub_discipline: sub_discipline, user_id: current_user.id, | |||||
| position: sub_discipline.tag_disciplines.pluck(:position).max + 1) | |||||
| render_ok({tag_discipline_id: tag_discipline.id}) | |||||
| end | |||||
| end | |||||
| @@ -1,74 +0,0 @@ | |||||
| class TemTestsController < ApplicationController | |||||
| before_action :set_tem_test, only: [:show, :edit, :update, :destroy] | |||||
| # GET /tem_tests | |||||
| # GET /tem_tests.json | |||||
| def index | |||||
| @tem_tests = TemTest.all | |||||
| end | |||||
| # GET /tem_tests/1 | |||||
| # GET /tem_tests/1.json | |||||
| def show | |||||
| end | |||||
| # GET /tem_tests/new | |||||
| def new | |||||
| @tem_test = TemTest.new | |||||
| end | |||||
| # GET /tem_tests/1/edit | |||||
| def edit | |||||
| end | |||||
| # POST /tem_tests | |||||
| # POST /tem_tests.json | |||||
| def create | |||||
| @tem_test = TemTest.new(tem_test_params) | |||||
| respond_to do |format| | |||||
| if @tem_test.save | |||||
| format.html { redirect_to @tem_test, notice: 'Tem test was successfully created.' } | |||||
| format.json { render :show, status: :created, location: @tem_test } | |||||
| else | |||||
| format.html { render :new } | |||||
| format.json { render json: @tem_test.errors, status: :unprocessable_entity } | |||||
| end | |||||
| end | |||||
| end | |||||
| # PATCH/PUT /tem_tests/1 | |||||
| # PATCH/PUT /tem_tests/1.json | |||||
| def update | |||||
| respond_to do |format| | |||||
| if @tem_test.update(tem_test_params) | |||||
| format.html { redirect_to @tem_test, notice: 'Tem test was successfully updated.' } | |||||
| format.json { render :show, status: :ok, location: @tem_test } | |||||
| else | |||||
| format.html { render :edit } | |||||
| format.json { render json: @tem_test.errors, status: :unprocessable_entity } | |||||
| end | |||||
| end | |||||
| end | |||||
| # DELETE /tem_tests/1 | |||||
| # DELETE /tem_tests/1.json | |||||
| def destroy | |||||
| @tem_test.destroy | |||||
| respond_to do |format| | |||||
| format.html { redirect_to tem_tests_url, notice: 'Tem test was successfully destroyed.' } | |||||
| format.json { head :no_content } | |||||
| end | |||||
| end | |||||
| private | |||||
| # Use callbacks to share common setup or constraints between actions. | |||||
| def set_tem_test | |||||
| @tem_test = TemTest.find(params[:id]) | |||||
| end | |||||
| # Never trust parameters from the scary internet, only allow the white list through. | |||||
| def tem_test_params | |||||
| params.require(:tem_test).permit(:name, :email) | |||||
| end | |||||
| end | |||||
| @@ -1,5 +0,0 @@ | |||||
| class TemplatesController < ApplicationController | |||||
| def show | |||||
| @template = EcTemplate.find_by_name!(params[:name]) | |||||
| end | |||||
| end | |||||
| @@ -1,37 +0,0 @@ | |||||
| class TidingsController < ApplicationController | |||||
| include PaginateHelper | |||||
| before_action :require_login | |||||
| after_action :update_onclick_time!, only: [:index] | |||||
| def index | |||||
| tidings = current_user.tidings.visible | |||||
| @onclick_time = current_user.click_time | |||||
| tiding_types = | |||||
| case params[:type] | |||||
| when 'notice' then 'System' | |||||
| when 'apply' then 'Apply' | |||||
| when 'course' then %w(HomeworkCommon Exercise Poll GraduationTask GraduationTopic) | |||||
| when 'project' then 'Project' | |||||
| when 'interaction' then %w(Comment Mentioned Praise Fan) | |||||
| when 'project_package' then %w(Created Destroyed Bidding BiddingEnd BiddingWon BiddingLost) | |||||
| end | |||||
| tidings = tidings.where(tiding_type: tiding_types) if tiding_types.present? | |||||
| tidings = tidings.where(container_type: 'JoinCourse', status: 0) if params[:type] == 'course_apply' | |||||
| # @course_apply_count = tidings.where("created_at > '#{@onclick_time}'").where(container_type: 'JoinCourse', status: 0).count | |||||
| @course_apply_count = tidings.where(container_type: 'JoinCourse', status: 0).count | |||||
| tidings = tidings.where(container_type: 'ProjectPackage') if params[:type] == 'project_package' | |||||
| @count = tidings.count | |||||
| @tidings = paginate(tidings.order(created_at: :desc), per_page: 10) | |||||
| end | |||||
| private | |||||
| def update_onclick_time! | |||||
| current_user.onclick_time.touch(:onclick_time) | |||||
| end | |||||
| end | |||||
| @@ -1,22 +0,0 @@ | |||||
| class TrialAppliesController < ApplicationController | |||||
| before_action :require_user_login | |||||
| def create | |||||
| Users::ApplyTrailService.call(current_user, create_params) | |||||
| render_ok | |||||
| rescue Users::ApplyTrailService::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| private | |||||
| def create_params | |||||
| params.permit(:phone, :code, :reason).merge(remote_ip: request.remote_ip) | |||||
| end | |||||
| def require_user_login | |||||
| return if User.current.logged? | |||||
| render_unauthorized | |||||
| end | |||||
| end | |||||
| @@ -1,72 +0,0 @@ | |||||
| class TrustieHacksController < ApplicationController | |||||
| before_action :require_admin, :except => [:index, :entry] | |||||
| before_action :require_login, :except => [:index] | |||||
| before_action :find_hackathon | |||||
| before_action :find_hack, :except => [:create, :index, :edit_hackathon, :update_hackathon] | |||||
| def index | |||||
| ## 分页参数 | |||||
| page = params[:page] || 1 | |||||
| limit = params[:limit] || 16 | |||||
| search = params[:search] | |||||
| hacks = @hackathon.trustie_hacks | |||||
| if search | |||||
| hacks = hacks.where("name like ?", "%#{search}%") | |||||
| end | |||||
| @hackathon_users_count = hacks.blank? ? 0 : hacks.sum(:hack_users_count) | |||||
| @hacks_count = hacks.count | |||||
| @hacks = hacks.page(page).per(limit) | |||||
| end | |||||
| def edit;end | |||||
| def create | |||||
| @hackathon.trustie_hacks.create!(name: params[:name], description: params[:description]) | |||||
| render_ok | |||||
| end | |||||
| def update | |||||
| @hack.update_attributes(name: params[:name], description: params[:description]) | |||||
| render_ok | |||||
| end | |||||
| def destroy | |||||
| @hack.destroy | |||||
| render_ok | |||||
| end | |||||
| def edit_hackathon | |||||
| end | |||||
| def update_hackathon | |||||
| @hackathon.update_attributes(name: params[:name], description: params[:description]) | |||||
| render_ok | |||||
| end | |||||
| # 报名入口 | |||||
| def entry | |||||
| if @hack.hack_users.exists?(user_id: current_user.id) | |||||
| render_error('已经报名,请勿重复操作') | |||||
| else | |||||
| @hack.hack_users.create(user_id: current_user.id) | |||||
| render_ok | |||||
| end | |||||
| end | |||||
| private | |||||
| def find_hackathon | |||||
| @hackathon = TrustieHackathon.first || | |||||
| TrustieHackathon.create!(name: params[:name], description: params[:description]) | |||||
| end | |||||
| def find_hack | |||||
| @hack = TrustieHack.find params[:id] | |||||
| end | |||||
| end | |||||
| @@ -1,8 +1,11 @@ | |||||
| class UsersController < ApplicationController | class UsersController < ApplicationController | ||||
| include Ci::DbConnectable | |||||
| before_action :load_user, only: [:show, :homepage_info] | |||||
| before_action :check_user_exist, only: [:show, :homepage_info] | |||||
| before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users] | |||||
| before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users] | |||||
| before_action :require_login, only: %i[me list] | before_action :require_login, only: %i[me list] | ||||
| before_action :connect_to_ci_database, only: :get_user_info, if: -> { current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification? } | |||||
| skip_before_action :check_sign, only: [:attachment_show] | skip_before_action :check_sign, only: [:attachment_show] | ||||
| def list | def list | ||||
| @@ -11,7 +14,35 @@ class UsersController < ApplicationController | |||||
| @users = paginate(scope) | @users = paginate(scope) | ||||
| end | end | ||||
| def show;end | |||||
| def show | |||||
| #待办事项,现在未做 | |||||
| @undo_events = 0 | |||||
| #用户的组织数量 | |||||
| # @user_composes_count = @user.composes.size | |||||
| @user_composes_count = 0 | |||||
| user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? @user.projects : @user.projects.visible | |||||
| @projects_common_count = user_projects.common.size | |||||
| @projects_mirrior_count = user_projects.mirror.size | |||||
| @projects_sync_mirrior_count = user_projects.sync_mirror.size | |||||
| end | |||||
| def watch_users | |||||
| watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc") | |||||
| if params[:search].present? | |||||
| search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id) | |||||
| watchers = watchers.where(watchable_id: search_user_ids) | |||||
| end | |||||
| @watchers_count = watchers.size | |||||
| @watchers = paginate(watchers) | |||||
| end | |||||
| def fan_users | |||||
| watchers = @user.watchers.includes(:user).order("watchers.created_at desc") | |||||
| watchers = watchers.joins(:user).where("LOWER(concat(users.lastname, users.firstname, users.login)) LIKE ?", "%#{params[:search].split(" ").join('|')}%") if params[:search].present? | |||||
| @watchers_count = watchers.size | |||||
| @watchers = paginate(watchers) | |||||
| end | |||||
| def update | def update | ||||
| @user = User.find params[:id] | @user = User.find params[:id] | ||||
| @@ -29,25 +60,6 @@ class UsersController < ApplicationController | |||||
| @user = current_user | @user = current_user | ||||
| # TODO 等消息上线再打开注释 | # TODO 等消息上线再打开注释 | ||||
| #@tidding_count = unviewed_tiddings(current_user) if current_user.present? | #@tidding_count = unviewed_tiddings(current_user) if current_user.present? | ||||
| @course = | |||||
| if params[:course_id] | |||||
| Course.find params[:course_id] | |||||
| elsif params[:board_id] | |||||
| Board.find(params[:board_id]).course | |||||
| elsif params[:graduation_topic_id] | |||||
| GraduationTopic.find(params[:graduation_topic_id]).course | |||||
| elsif params[:graduation_group_id] | |||||
| GraduationGroup.find(params[:graduation_group_id]).course | |||||
| elsif params[:graduation_work_id] | |||||
| GraduationWork.find(params[:graduation_work_id]).course | |||||
| elsif params[:graduation_task_id] | |||||
| GraduationTask.find(params[:graduation_task_id]).course | |||||
| elsif params[:poll_id] | |||||
| Poll.find(params[:poll_id]).course | |||||
| elsif params[:attachment_id] | |||||
| Attachment.find(params[:attachment_id]).course | |||||
| end | |||||
| @course_identity = current_user.course_identity(@course) if @course | |||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| missing_template | missing_template | ||||
| @@ -72,14 +84,14 @@ class UsersController < ApplicationController | |||||
| # Redo: 消息总数缓存 | # Redo: 消息总数缓存 | ||||
| def get_navigation_info | def get_navigation_info | ||||
| @old_domain = edu_setting('old_edu_host') | |||||
| @user = current_user | |||||
| # 新消息数 | |||||
| @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0 | |||||
| @user_url = "/users/#{@user.login}" | |||||
| @career = Career.where(status: true).order("created_at asc").pluck(:id, :name) | |||||
| @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil | |||||
| # @old_domain = edu_setting('old_edu_host') | |||||
| # @user = current_user | |||||
| # # 新消息数 | |||||
| # @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0 | |||||
| # | |||||
| # @user_url = "/users/#{@user.login}" | |||||
| # @career = Career.where(status: true).order("created_at asc").pluck(:id, :name) | |||||
| # @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil | |||||
| end | end | ||||
| # 用户回复功能 | # 用户回复功能 | ||||
| @@ -104,8 +116,14 @@ class UsersController < ApplicationController | |||||
| @projects = projects.select(:id, :name) | @projects = projects.select(:id, :name) | ||||
| end | end | ||||
| # 个人主页信息 | |||||
| def homepage_info;end | |||||
| #TODO 个人主页信息,forge上弃用-hs, 0602 | |||||
| def homepage_info | |||||
| #待办事项,现在未做 | |||||
| @undo_events = 10 | |||||
| #用户的组织数量 | |||||
| # @user_composes_count = @user.composes.size | |||||
| @user_composes_count = 10 | |||||
| end | |||||
| def brief_introduction | def brief_introduction | ||||
| content = params[:content].to_s.strip | content = params[:content].to_s.strip | ||||
| @@ -122,17 +140,98 @@ class UsersController < ApplicationController | |||||
| render_error(ex.message) | render_error(ex.message) | ||||
| end | end | ||||
| # 其他平台登录后,必须将token同步到forge平台,实现sso登录功能 | |||||
| def sync_token | |||||
| return render_error('未找相关用户!') unless @user | |||||
| token = Token.get_or_create_permanent_login_token(@user, 'autologin') | |||||
| token.update_column(:value, params[:token]) | |||||
| render_ok | |||||
| end | |||||
| def trustie_related_projects | |||||
| projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc") | |||||
| projects_json = [] | |||||
| domain_url = EduSetting.get('host_name') + '/projects' | |||||
| if projects.present? | |||||
| projects.each do |p| | |||||
| project_url = "/#{p.owner.login}/#{p.identifier}" | |||||
| pj = { | |||||
| id: p.id, | |||||
| name: p.name, | |||||
| is_public: p.is_public, | |||||
| updated_on: p.updated_on.strftime("%Y-%m-%d"), | |||||
| status: p.status, | |||||
| is_member: p.member?(current_user.try(:id)), | |||||
| owner: { | |||||
| name: p.owner.try(:show_real_name), | |||||
| login: p.owner.login | |||||
| }, | |||||
| members_count: p&.members.size, | |||||
| issues_count: p.issues_count - p.pull_requests_count, | |||||
| commits_count: p&.project_score&.changeset_num.to_i, | |||||
| http_url: domain_url + project_url, | |||||
| http_collaborator_url: domain_url + project_url + "/setting/collaborator", | |||||
| http_issues_url: domain_url + project_url + "/issues", | |||||
| http_commits_url: domain_url + project_url + "/commits", | |||||
| project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {} | |||||
| } | |||||
| projects_json.push(pj) | |||||
| end | |||||
| end | |||||
| Rails.logger.info("==========projects_json========+########{projects_json}") | |||||
| render json: { projects: projects_json.present? ? projects_json : {} } | |||||
| end | |||||
| def trustie_projects | |||||
| user_id = User.select(:id, :login).where(login: params[:login])&.first&.id | |||||
| projects = Project.visible | |||||
| projects = projects.joins(:members).where(members: { user_id: user_id }) | |||||
| search = params[:search].to_s.strip | |||||
| projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present? | |||||
| projects = projects.select(:id, :name).limit(10).as_json | |||||
| render json: { projects: projects } | |||||
| end | |||||
| def projects | |||||
| is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id) | |||||
| scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user) | |||||
| @total_count = scope.size | |||||
| @projects = paginate(scope) | |||||
| end | |||||
| # TODO 其他平台登录时同步修改gitea平台对应用户的密码 | |||||
| # 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题 | |||||
| def sync_gitea_pwd | |||||
| return render_error("未找到相关的用户") if @user.blank? | |||||
| flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) | |||||
| flag ? render_ok : render_error('同步失败!') | |||||
| end | |||||
| # TODO | |||||
| # 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除 | |||||
| def sync_salt | |||||
| user = User.find_by_login params[:login] | |||||
| return if user.blank? | |||||
| user.update_column(:salt, params[:salt]) | |||||
| render_ok | |||||
| end | |||||
| private | private | ||||
| def load_user | def load_user | ||||
| @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id]) | @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id]) | ||||
| end | end | ||||
| def user_params | def user_params | ||||
| params.require(:user).permit(:nickname, :lastname, :show_realname, | |||||
| params.require(:user).permit(:nickname, :lastname, :show_realname,:login,:mail, | |||||
| user_extension_attributes: [ | user_extension_attributes: [ | ||||
| :gender, :location, :location_city, | :gender, :location, :location_city, | ||||
| :occupation, :technical_title, | :occupation, :technical_title, | ||||
| :school_id, :department_id] | |||||
| :school_id, :department_id,:identity, :student_id, :description] | |||||
| ) | ) | ||||
| end | end | ||||
| @@ -1,27 +0,0 @@ | |||||
| class UsersForPartnersController < ApplicationController | |||||
| include Base::PaginateHelper | |||||
| before_action :check_partner_manager_permission! | |||||
| def index | |||||
| params[:sort_by] = params[:sort_by].presence || 'created_on' | |||||
| params[:sort_direction] = params[:sort_direction].presence || 'desc' | |||||
| users = Admins::UserQuery.call(search_params) | |||||
| @users = paginate users.includes(user_extension: :school) | |||||
| end | |||||
| private | |||||
| def search_params | |||||
| params.permit(:name, :sort_by, :sort_direction) | |||||
| end | |||||
| def check_partner_manager_permission! | |||||
| partner = Partner.find(params[:partner_id]) | |||||
| return if admin_or_business? | |||||
| return if partner.admin_partner_manager_group.partner_managers.exists?(user: current_user) | |||||
| render_forbidden | |||||
| end | |||||
| end | |||||
| @@ -1,6 +1,6 @@ | |||||
| class VersionReleasesController < ApplicationController | class VersionReleasesController < ApplicationController | ||||
| before_action :find_project | |||||
| before_action :set_user_and_project | |||||
| before_action :load_repository | |||||
| before_action :set_user | |||||
| before_action :require_login, except: [:index] | before_action :require_login, except: [:index] | ||||
| before_action :find_version , only: [:edit, :update, :destroy] | before_action :find_version , only: [:edit, :update, :destroy] | ||||
| @@ -8,13 +8,13 @@ class VersionReleasesController < ApplicationController | |||||
| version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call | version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call | ||||
| @version_releases = version_releases | @version_releases = version_releases | ||||
| @user_permission = current_user.present? && (current_user == @user || current_user.admin?) | @user_permission = current_user.present? && (current_user == @user || current_user.admin?) | ||||
| @forge_releases = @repository.version_releases.select(:id,:version_gid).includes(:attachments) | |||||
| end | end | ||||
| def new | def new | ||||
| #获取所有的分支 | #获取所有的分支 | ||||
| @all_branches = [] | @all_branches = [] | ||||
| get_all_branches = Gitea::Repository::BranchesService.new(@user, @repository.try(:identifier)).call | |||||
| get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier)).call | |||||
| if get_all_branches && get_all_branches.size > 0 | if get_all_branches && get_all_branches.size > 0 | ||||
| get_all_branches.each do |b| | get_all_branches.each do |b| | ||||
| @all_branches.push(b["name"]) | @all_branches.push(b["name"]) | ||||
| @@ -34,14 +34,7 @@ class VersionReleasesController < ApplicationController | |||||
| else | else | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| version_params = { | |||||
| body: params[:body], | |||||
| draft: params[:draft] || false, | |||||
| name: params[:name], | |||||
| prerelease: params[:prerelease] || false, | |||||
| tag_name: params[:tag_name], | |||||
| target_commitish: params[:target_commitish] || "master" #分支 | |||||
| } | |||||
| version_params = releases_params | |||||
| version_release = VersionRelease.new(version_params.merge(user_id: current_user.id, repository_id: @repository.id)) | version_release = VersionRelease.new(version_params.merge(user_id: current_user.id, repository_id: @repository.id)) | ||||
| if version_release.save! | if version_release.save! | ||||
| git_version_release = Gitea::Versions::CreateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params).call | git_version_release = Gitea::Versions::CreateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params).call | ||||
| @@ -54,6 +47,9 @@ class VersionReleasesController < ApplicationController | |||||
| } | } | ||||
| version_release.update_attributes!(update_params) | version_release.update_attributes!(update_params) | ||||
| version_release.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") | version_release.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") | ||||
| if params[:attachment_ids].present? | |||||
| create_attachments(params[:attachment_ids], version_release) | |||||
| end | |||||
| normal_status(0, "发布成功") | normal_status(0, "发布成功") | ||||
| else | else | ||||
| normal_status(-1, "发布失败") | normal_status(-1, "发布失败") | ||||
| @@ -70,7 +66,7 @@ class VersionReleasesController < ApplicationController | |||||
| end | end | ||||
| def edit | def edit | ||||
| @version_attachments = @version.attachments | |||||
| end | end | ||||
| def update | def update | ||||
| @@ -81,19 +77,15 @@ class VersionReleasesController < ApplicationController | |||||
| else | else | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| version_params = { | |||||
| body: params[:body], | |||||
| draft: params[:draft] || false, | |||||
| name: params[:name], | |||||
| prerelease: params[:prerelease], | |||||
| tag_name: params[:tag_name], | |||||
| target_commitish: params[:target_commitish] || "master" #分支 | |||||
| } | |||||
| version_params = releases_params | |||||
| if @version.update_attributes!(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 | 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 | unless git_version_release | ||||
| raise Error, "更新失败" | raise Error, "更新失败" | ||||
| end | end | ||||
| normal_status(0, "更新成功") | normal_status(0, "更新成功") | ||||
| else | else | ||||
| normal_status(-1, "更新失败") | normal_status(-1, "更新失败") | ||||
| @@ -131,14 +123,8 @@ class VersionReleasesController < ApplicationController | |||||
| private | private | ||||
| def set_user_and_project | |||||
| # @project = Project.find_by_id(params[:project_id]) | |||||
| @repository = @project.repository #项目的仓库 | |||||
| @user = @project.owner | |||||
| unless @user.present? && @project.present? && @repository.present? | |||||
| normal_status(-1, "仓库不存在") | |||||
| end | |||||
| def set_user | |||||
| @user = @repository.user | |||||
| end | end | ||||
| def find_version | def find_version | ||||
| @@ -148,4 +134,27 @@ class VersionReleasesController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| def releases_params | |||||
| { | |||||
| body: params[:body], | |||||
| draft: params[:draft] || false, | |||||
| name: params[:name], | |||||
| prerelease: params[:prerelease] || false, | |||||
| tag_name: params[:tag_name], | |||||
| target_commitish: params[:target_commitish] || "master" #分支 | |||||
| } | |||||
| end | |||||
| def create_attachments(attachment_ids, target) | |||||
| attachment_ids.each do |id| | |||||
| attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | |||||
| unless attachment.blank? | |||||
| attachment.container = target | |||||
| attachment.author_id = current_user.id | |||||
| attachment.description = "" | |||||
| attachment.save | |||||
| end | |||||
| end | |||||
| end | |||||
| end | end | ||||
| @@ -1,6 +1,6 @@ | |||||
| class VersionsController < ApplicationController | class VersionsController < ApplicationController | ||||
| before_action :require_login | |||||
| before_action :find_project | |||||
| before_action :require_login, except: [:index, :show] | |||||
| before_action :load_repository | |||||
| before_action :check_issue_permission, except: [:show, :index] | before_action :check_issue_permission, except: [:show, :index] | ||||
| before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status] | before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status] | ||||
| @@ -166,4 +166,4 @@ class VersionsController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -1,17 +1,18 @@ | |||||
| class WatchersController < ApplicationController | class WatchersController < ApplicationController | ||||
| before_action :require_login, except: %i[index] | before_action :require_login, except: %i[index] | ||||
| before_action :find_project_with_id | |||||
| # before_action :find_project_with_id | |||||
| before_action :get_target | |||||
| def index | def index | ||||
| scope = @project.watchers.includes(:user) | |||||
| scope = @target.watchers.includes(:user) | |||||
| @watchers = paginate(scope) | @watchers = paginate(scope) | ||||
| end | end | ||||
| def unfollow | def unfollow | ||||
| begin | begin | ||||
| return normal_status(2, "你还没有关注哦") unless current_user.watched?(@project) | |||||
| current_user.unwatch!(@project) | |||||
| render_ok | |||||
| return normal_status(2, "你还没有关注哦") unless current_user.watched?(@target) | |||||
| current_user.unwatch!(@target) | |||||
| render_ok({watchers_count: @target.watchers_count, watched: false}) | |||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| @@ -21,9 +22,9 @@ class WatchersController < ApplicationController | |||||
| def follow | def follow | ||||
| begin | begin | ||||
| return normal_status(2, "你已关注了") if current_user.watched?(@project) | |||||
| current_user.watch!(@project) | |||||
| render_ok | |||||
| return normal_status(2, "你已关注了") if current_user.watched?(@target) | |||||
| current_user.watch!(@target) | |||||
| render_ok({watchers_count: @target.watchers_count, watched: true}) | |||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| @@ -32,11 +33,28 @@ class WatchersController < ApplicationController | |||||
| end | end | ||||
| def check_watch | def check_watch | ||||
| is_watch = current_user.watched?(@project) | |||||
| is_watch = current_user.watched?(@target) | |||||
| render_result(is_watch ? 1 : 0) | render_result(is_watch ? 1 : 0) | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| tip_exception(e.message) | tip_exception(e.message) | ||||
| end | end | ||||
| private | |||||
| def get_target | |||||
| target_type = params[:target_type].to_s | |||||
| case target_type | |||||
| when "project" | |||||
| @target = target_type.capitalize.constantize.find_by(id: params[:id]) | |||||
| else | |||||
| @target = target_type.capitalize.constantize.find_by(login: params[:id]) #用户 | |||||
| end | |||||
| unless @target.present? | |||||
| normal_status(-1, "目标不存在") | |||||
| end | |||||
| end | |||||
| end | end | ||||