From af289d1f5efb710e605dd40892a0ffd1a005039e Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 5 Mar 2021 15:52:50 +0800 Subject: [PATCH 001/643] Update changelog --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..8aad86982 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +## [v3.0.0](https://github.com/go-gitea/gitea/releases/tag/v1.13.1) - 2020-12-29 + +* BUGFIXES + * Fix pull reqeust的访问权限问题 (#14156) (#14171) + * Fix 部分页面访问403的问题 + * Fix 合并请求失败的问题 + * Fix 代码目录页面,文件夹和文件图片不显示的问题 + * Fix Issue列表中按‘负责人’过滤筛选时,部分项目成员不在搜索范围没的问题 + * Fix 项目更新时间不同步的问题, 添加了定时任务 +* ENHANCEMENTS + * 提升获取版本库目录代码查询速度 (#43296) + * tag 列表慢查询速度问题 (#43332) + * API builder 模版中 render partial builder的性能问题 From 6063c7c414e658d2d0e9246bdefef15ff6168f16 Mon Sep 17 00:00:00 2001 From: jasder <2053003901@qq.com> Date: Thu, 11 Mar 2021 14:58:44 +0800 Subject: [PATCH 002/643] =?UTF-8?q?fix=20=E6=9B=B4=E6=96=B0api=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b75fcd647..928b5475d 100644 --- a/README.md +++ b/README.md @@ -93,26 +93,26 @@ http://localhost:3000/ - 代码库 -![](docs/figs/code.png) +![](docs/figs/code.png?raw=true) - 任务管理 -![](docs/figs/issue_manage.png) +![](docs/figs/issue_manage.png?raw=true) - 任务查看 -![](docs/figs/issue_view.png) +![](docs/figs/issue_view.png?raw=true) - 任务指派 -![](docs/figs/issue_assign2.png) +![](docs/figs/issue_assign2.png?raw=true) - 里程碑 -![](docs/figs/milestone.png) +![](docs/figs/milestone.png?raw=true) ### API -- [API](api_document.md) +- [API](https://forgeplus.trustie.net/docs/api) - [API](showdoc.com.cn) 账号:forgeplus@admin.com 密码:forge123 From bd46d2dcc7f058fd2fdf3caddea767d8b085d3d0 Mon Sep 17 00:00:00 2001 From: jasder <2053003901@qq.com> Date: Thu, 11 Mar 2021 14:59:21 +0800 Subject: [PATCH 003/643] fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 928b5475d..de1f91bac 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ http://localhost:3000/ ![](docs/figs/milestone.png?raw=true) ### API -- [API](https://forgeplus.trustie.net/docs/api) +- [API文档](https://forgeplus.trustie.net/docs/api) - [API](showdoc.com.cn) 账号:forgeplus@admin.com 密码:forge123 From b43926f69ffcddef5ad2f5fae0dd7c521ef0675c Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 15 Mar 2021 19:01:35 +0800 Subject: [PATCH 004/643] add: new project detail --- app/controllers/projects_controller.rb | 5 +- app/controllers/repositories_controller.rb | 16 +- app/models/project.rb | 145 +++++++++--------- app/models/repository.rb | 2 + .../repository/contributors/get_service.rb | 22 +++ app/services/gitea/versions/create_service.rb | 3 +- app/services/projects/create_service.rb | 2 + app/services/repositories/create_service.rb | 1 + app/services/repositories/detail_service.rb | 64 ++++++++ app/views/repositories/detail.json.jbuilder | 90 +++++++++++ app/views/repositories/entries.json.jbuilder | 2 +- config/routes.rb | 1 + .../20210315093350_add_website_to_projects.rb | 6 + 13 files changed, 284 insertions(+), 75 deletions(-) create mode 100644 app/services/gitea/repository/contributors/get_service.rb create mode 100644 app/services/repositories/detail_service.rb create mode 100644 app/views/repositories/detail.json.jbuilder create mode 100644 db/migrate/20210315093350_add_website_to_projects.rb diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index c8f3027de..5358a554e 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -73,7 +73,8 @@ class ProjectsController < ApplicationController private = params[:private] gitea_params = { private: private, - default_branch: params[:default_branch] + default_branch: params[:default_branch], + website: params[:website] } if [true, false].include? private new_project_params = project_params.except(:private).merge(is_public: !private) @@ -162,7 +163,7 @@ class ProjectsController < ApplicationController private def project_params - params.permit(:user_id, :name, :description, :repository_name, + params.permit(:user_id, :name, :description, :repository_name, :website, :project_category_id, :project_language_id, :license_id, :ignore_id, :private) end diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 6683dde4e..e327554a7 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -11,6 +11,20 @@ class RepositoriesController < ApplicationController before_action :get_latest_commit, only: %i[entries sub_entries top_counts] before_action :get_statistics, only: %i[top_counts] + # 新版项目详情 + def detail + @user = current_user + @result = Repositories::DetailService.call(@owner, @repository, @user) + @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 + uid_logger_error(e.message) + tip_exception(e.message) + end + def show @user = current_user @repo = @project.repository @@ -187,7 +201,7 @@ class RepositoriesController < ApplicationController end def get_ref - @ref = params[:ref] || "master" + @ref = params[:ref] || @project.default_branch end def get_latest_commit diff --git a/app/models/project.rb b/app/models/project.rb index a5beb448d..5b05def1c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,73 +1,76 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(4294967295) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# license_id :integer -# ignore_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# - +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(4294967295) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# license_id :integer +# ignore_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# default_branch :string(255) default("master") +# website :string(255) +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + + class Project < ApplicationRecord @@ -116,6 +119,8 @@ class Project < ApplicationRecord scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)} scope :recommend, -> { visible.project_statics_select.where(recommend: true) } + delegate :content, to: :project_detail, allow_nil: true + delegate :name, to: :license, prefix: true, allow_nil: true def self.search_project(search) diff --git a/app/models/repository.rb b/app/models/repository.rb index 934eaa0e3..b6d2321fc 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -41,6 +41,8 @@ class Repository < ApplicationRecord validates :identifier, presence: true + delegate :default_branch, to: :project, allow_nil: true + def to_param self.identifier.parameterize end diff --git a/app/services/gitea/repository/contributors/get_service.rb b/app/services/gitea/repository/contributors/get_service.rb new file mode 100644 index 000000000..1ee1c3955 --- /dev/null +++ b/app/services/gitea/repository/contributors/get_service.rb @@ -0,0 +1,22 @@ +class Gitea::Repository::Contributors::GetService < Gitea::ClientService + attr_reader :owner, :repo_name + + def initialize(owner, repo_name) + @owner = owner + @repo_name = repo_name + end + + def call + response = get(url, params) + render_status(response) + end + + private + def params + Hash.new.merge(token: owner.gitea_token) + end + + def url + "/repos/#{owner.login}/#{repo_name}/contributors" + end +end \ No newline at end of file diff --git a/app/services/gitea/versions/create_service.rb b/app/services/gitea/versions/create_service.rb index de21ad97a..04fed00f2 100644 --- a/app/services/gitea/versions/create_service.rb +++ b/app/services/gitea/versions/create_service.rb @@ -18,7 +18,8 @@ class Gitea::Versions::CreateService < Gitea::ClientService end def call - post(url, request_params) + response = post(url, request_params) + render_status(response) end private diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index dc14d10d0..25053e953 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -36,6 +36,7 @@ class Projects::CreateService < ApplicationService is_public: repo_is_public, ignore_id: params[:ignore_id], license_id: params[:license_id], + website: params[:website], identifier: params[:repository_name] #新增,hs } end @@ -44,6 +45,7 @@ class Projects::CreateService < ApplicationService { hidden: !repo_is_public, user_id: params[:user_id], + website: params[:website], identifier: params[:repository_name] } end diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb index 4c5519f2e..18e726440 100644 --- a/app/services/repositories/create_service.rb +++ b/app/services/repositories/create_service.rb @@ -62,6 +62,7 @@ class Repositories::CreateService < ApplicationService project.update_columns( gpid: gitea_repository["id"], identifier: repository.identifier, + default_branch: gitea_repository["default_branch"], forked_count: gitea_repository["forks_count"]) end end diff --git a/app/services/repositories/detail_service.rb b/app/services/repositories/detail_service.rb new file mode 100644 index 000000000..0dbbb490b --- /dev/null +++ b/app/services/repositories/detail_service.rb @@ -0,0 +1,64 @@ +class Repositories::DetailService < ApplicationService + include Repository::LanguagesPercentagable + attr_reader :owner, :repo, :user + def initialize(owner, repo, user) + @owner = owner + @repo = repo + @user = user + end + + def call + if @repo.project.educoder? + return { + repo: {}, + release: [], + branch: [], + tag: [], + contributor: [], + language: {}, + readme: {} + } + else + return { + repo: repo_suitable, + release: release_suitable, + branch: branch_suitable, + tag: tag_suitable, + contributor: contributor_suitable, + language: language_suitable, + readme: readme_suitable + } + end + end + + private + def repo_suitable + Gitea::Repository::GetService.call(@owner, @repo.identifier) + end + + def release_suitable + Gitea::Versions::ListService.call(@owner.gitea_token, @owner.try(:login), @repo.try(:identifier)) + end + + def branch_suitable + Gitea::Repository::Branches::ListService.call(@owner, @repo.identifier) + end + + def tag_suitable + Gitea::Repository::Tags::ListService.call(@user&.gitea_token, @owner.login, @repo.identifier) + end + + def contributor_suitable + Gitea::Repository::Contributors::GetService.call(@owner, @repo.identifier) + end + + def language_suitable + result = Gitea::Repository::Languages::ListService.call(@owner.login, @repo.identifier, @user&.gitea_token) + result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil + end + + def readme_suitable + result = Gitea::Repository::Readme::GetService.call(@owner.login, @repo.identifier, @repo.default_branch, @owner.gitea_token) + result[:status] === :success ? result[:body] : nil + end +end \ No newline at end of file diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder new file mode 100644 index 000000000..0931802ec --- /dev/null +++ b/app/views/repositories/detail.json.jbuilder @@ -0,0 +1,90 @@ +json.content @project.content +json.website @project.website +json.readme @result[:readme].merge(content: readme_render_decode64_content(@result[:readme]["content"], nil)) +json.identifier render_identifier(@project) +json.name @project.name +json.project_id @project.id +json.repo_id @repository.id +json.issues_count @project.issues_count.to_i - @project.pull_requests_count.to_i +json.pull_requests_count @project.pull_requests_count +json.project_identifier render_identifier(@project) +json.praises_count @project.praises_count.to_i +json.forked_count @project.forked_count.to_i +json.watchers_count @project.watchers_count.to_i +json.versions_count @project.versions_count #里程碑数量 +json.version_releases_count @project.releases_size(@user.try(:id), "all") +json.version_releasesed_count @project.releases_size(@user.try(:id), "released") #已发行的版本 +json.permission render_permission(@user, @project) +json.mirror_url @project&.repository.mirror_url +json.mirror @project&.repository.mirror_url.present? +json.type @project.numerical_for_project_type +json.open_devops @project.open_devops? + +unless @project.common? + json.mirror_status @repository.mirror_status + json.mirror_num @repository.mirror_num + json.first_sync @repository.first_sync? +end + +json.watched @project.watched_by? @user +json.praised @project.praised_by? @user +json.status @project.status +json.forked_from_project_id @project_fork_id +json.fork_info do + if @fork_project.present? + json.fork_form_name @fork_project.try(:name) + json.fork_project_user_login @fork_project_user.try(:login) + json.fork_project_identifier @fork_project.identifier + json.fork_project_user_name @fork_project_user.try(:show_real_name) + end +end +if @result[:repo] + json.size replace_bytes_to_b(number_to_human_size(@result[:repo]['size'].to_i*1024)) + json.ssh_url @result[:repo]['ssh_url'] + json.clone_url @result[:repo]['clone_url'] + json.default_branch @result[:repo]['default_branch'] + json.empty @result[:repo]['empty'] + json.full_name @result[:repo]['full_name'] + json.private @result[:repo]['private'] +end +json.license_name @project.license_name +json.release_versions do + json.list @result[:release].each do |release| + forge_version = VersionRelease.find_by(version_gid: release["id"]) + json.id forge_version.id + json.name release["name"] + json.tag_name release["tag_name"] + json.created_at format_time(release["created_at"].to_time) + end + json.total_count @result[:release].size +end +json.branches do + json.list @result[:branch].each do |branch| + json.name branch["name"] + end + json.total_count @result[:branch].size +end +json.tags do + json.list @result[:tag].each do |tag| + json.name tag["name"] + end + json.total_count @result[:tag].size +end +json.contributors do + total_count = @result[:contributor].size + json.list @result[:contributor].each do |contributor| + user = User.find_by(gitea_uid: contributor["id"]) + if contributor["login"] == "root" + total_count -= 1 + next + end + json.contributions contributor["contributions"] + json.gid contributor["id"] + json.login user.login + json.type user&.type + json.name user.real_name + json.image_url url_to_avatar(user) + end + json.total_count total_count +end +json.languages @result[:language] diff --git a/app/views/repositories/entries.json.jbuilder b/app/views/repositories/entries.json.jbuilder index 9efa0c113..6964c1c54 100644 --- a/app/views/repositories/entries.json.jbuilder +++ b/app/views/repositories/entries.json.jbuilder @@ -41,7 +41,7 @@ if @project.forge? end #json.tags_count @tags_count #json.branches_count @branches_count - #json.commits_count @commits_count + json.commits_count @commits_count json.zip_url render_zip_url(@project, @ref) json.tar_url render_tar_url(@project, @ref) json.entries do diff --git a/config/routes.rb b/config/routes.rb index 228c546c9..4f350314b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -380,6 +380,7 @@ Rails.application.routes.draw do resource :repositories, path: '/', only: [:show, :create, :edit] do member do + get :detail get :archive get :top_counts get :entries diff --git a/db/migrate/20210315093350_add_website_to_projects.rb b/db/migrate/20210315093350_add_website_to_projects.rb new file mode 100644 index 000000000..a3918ddab --- /dev/null +++ b/db/migrate/20210315093350_add_website_to_projects.rb @@ -0,0 +1,6 @@ +class AddWebsiteToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :default_branch, :string, default: 'master' + add_column :projects, :website, :string + end +end From 34d95451b5926896eb2d09dc1c6803c43137030b Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 16 Mar 2021 10:25:37 +0800 Subject: [PATCH 005/643] add: get project all files --- app/controllers/repositories_controller.rb | 9 ++++++- .../gitea/repository/files/get_service.rb | 25 +++++++++++++++++++ config/routes.rb | 3 ++- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 app/services/gitea/repository/files/get_service.rb diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index e327554a7..5fb7b7681 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -7,10 +7,17 @@ class RepositoriesController < ApplicationController 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_ref, only: %i[entries sub_entries top_counts file] before_action :get_latest_commit, only: %i[entries sub_entries top_counts] before_action :get_statistics, only: %i[top_counts] + + + def files + result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@project.owner, @project.identifier, @ref) + render json: result + end + # 新版项目详情 def detail @user = current_user diff --git a/app/services/gitea/repository/files/get_service.rb b/app/services/gitea/repository/files/get_service.rb new file mode 100644 index 000000000..e5b96e7ba --- /dev/null +++ b/app/services/gitea/repository/files/get_service.rb @@ -0,0 +1,25 @@ +class Gitea::Repository::Files::GetService < Gitea::ClientService + attr_reader :owner, :repo_name, :ref, :q, :token + + def initialize(owner, repo_name, ref, q=nil, token=nil) + @owner = owner + @repo_name = repo_name + @ref = ref + @q = q + @token = token + end + + def call + response = get(url, params) + render_status(response) + end + + private + def params + Hash.new.merge(token: token, ref: ref, q: q) + end + + def url + "/repos/#{owner.login}/#{repo_name}/find" + end +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 4f350314b..9aed0ca5e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -378,8 +378,9 @@ Rails.application.routes.draw do end end - resource :repositories, path: '/', only: [:show, :create, :edit] do + resource :repositories, path: '/', only: [:show, :create, :edit] do member do + get :files get :detail get :archive get :top_counts From f17e436d62d5d7276091391978caeb9cb4e7a4fe Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 16 Mar 2021 11:10:58 +0800 Subject: [PATCH 006/643] add: doc --- .../slate/source/includes/_repositories.md | 244 +++++++ public/docs/api.html | 686 +++++++++++++++--- 2 files changed, 830 insertions(+), 100 deletions(-) diff --git a/app/docs/slate/source/includes/_repositories.md b/app/docs/slate/source/includes/_repositories.md index b57df90f6..862e96cea 100644 --- a/app/docs/slate/source/includes/_repositories.md +++ b/app/docs/slate/source/includes/_repositories.md @@ -97,6 +97,182 @@ await octokit.request('GET /api/jasder/jasder_test/simple.json') } ``` +## 仓库详情(新版) +仓库详情 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/yystopf/ceshi/detail.json +``` + +```javascript +await octokit.request('GET /api/yystopf/ceshi/detail.json') +``` + +### HTTP 请求 +`GET /api/:owner/:repo/detail` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | + + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|content |string |仓库简介 | +|website |string |仓库网址 | +|readme |string |readme文件| +|identifier |string |项目标识 | +|name |string |项目名称 | +|issues_count |int |项目issue数量| +|pull_requests_count |int |项目issue数量| +|project_identifier |int |项目issue数量| +|praises_count |int |项目issue数量| +|forked_count |int |项目issue数量| +|watchers_count |int |项目issue数量| +|versions_count |int |项目里程碑数量| +|version_releases_count |int |项目发行版数量| +|version_releasesed_count |int |项目发行版已发行数量| +|permission |string |项目权限| +|mirror_url |string |镜像地址| +|mirror |bool |是否为镜像项目| +|type |int |项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目| +|open_devops |int |是否开启devops| +|watched |bool |是否关注| +|praised |bool |是否点赞| +|status |int |项目状态| +|forked_from_project_id |int |fork项目id| +|fork_info |object |fork项目信息| +|size |string |仓库大小| +|ssh_url |string |项目ssh地址| +|clone_url |string |项目克隆地址| +|default_branch |string |仓库默认分支| +|empty |bool |仓库是否为空| +|full_name |string |仓库全称| +|private |bool |仓库是否为私有项目| +|license_name |string |许可证名称| +|release_versions.list.name |string |项目issue数量| +|release_versions.list.tag_name |string |发行版标签名称| +|release_versions.list.created_at |string |发行版创建时间| +|release_versions.total_count |int |发行版数量| +|branches.list.name |string |分支名称| +|branches.total_count |int |分支数量| +|tags.list.name |string |标签名称| +|tags.total_count |int |标签数量| +|contributors.list.contributions|int |贡献数量| +|contributors.list.login |string |贡献者登录名| +|contributors.list.name |string |贡献者用户名称| +|contributors.list.image_url |string |贡献者头像| +|languages |object |项目语言占比| + +> 返回的JSON示例: + +```json +{ + "content": "仓库简介", + "website": "仓库网址", + "readme": { + "type": "file", + "encoding": "base64", + "size": 9, + "name": "README.md", + "path": "README.md", + "content": "# ceshi\n\n", + "sha": "" + }, + "identifier": "ceshi", + "name": "测试项目", + "project_id": 2, + "repo_id": 2, + "issues_count": 0, + "pull_requests_count": 0, + "project_identifier": "ceshi", + "praises_count": 0, + "forked_count": 0, + "watchers_count": 0, + "versions_count": 0, + "version_releases_count": 0, + "version_releasesed_count": 0, + "permission": "Reporter", + "mirror_url": null, + "mirror": false, + "type": 0, + "open_devops": false, + "watched": false, + "praised": false, + "status": 1, + "forked_from_project_id": 1, + "fork_info": { + "fork_form_name": "测试项目", + "fork_project_user_login": "ceshi_org", + "fork_project_identifier": "ceshi", + "fork_project_user_name": "ceshi_org" + }, + "size": "25.0 KB", + "ssh_url": "virus@localhost:yystopf/ceshi.git", + "clone_url": "http://localhost:10080/yystopf/ceshi.git", + "default_branch": "master", + "empty": false, + "full_name": "yystopf/ceshi", + "private": false, + "license_name": "gnu-javamail-exception", + "release_versions": { + "list": [ + { + "id": 2, + "name": "vvvv", + "tag_name": "v1.1", + "created_at": "2019-07-18 10:16" + } + ], + "total_count": 1 + }, + "branches": { + "list": [ + { + "name": "master" + } + ], + "total_count": 1 + }, + "tags": { + "list": [ + { + "name": "v1.1" + }, + { + "name": "v1.0" + } + ], + "total_count": 2 + }, + "contributors": { + "list": [ + { + "contributions": 1, + "gid": 2, + "login": "yystopf", + "type": "User", + "name": "yystopf", + "image_url": "avatars/User/b" + } + ], + "total_count": 1 + }, + "languages": { + "HTML": "50.9%", + "Ruby": "25.6%", + "JavaScript": "21.4%", + "CSS": "1.3%", + "CoffeeScript": "0.7%", + "Shell": "0.1%" + } +} +``` ## 编辑仓库信息 编辑仓库信息 @@ -463,6 +639,74 @@ await octokit.request('GET /api/jasder/jasder_test/collaborators.json') Success Data. +## 获取仓库所有文件 +获取仓库所有文件 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/yystopf/ceshi/files.json +``` + +```javascript +await octokit.request('GET /api/yystopf/ceshi/files.json') +``` + +### HTTP 请求 +`GET /api/:owner/:repo/files` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | + + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|name |string |文件名称| +|path |string |文件路径| +|sha |string |文件标识| +|type |string |文件类型| +|size |int |文件大小| +|url |string |文件地址| + + +> 返回的JSON示例: + +```json +[ + { + "name": ".gitignore", + "path": ".gitignore", + "sha": "f83922d01ae60f6e637a1a2b9f08871b4f87dfc8", + "type": "file", + "size": 63, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/.gitignore?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/.gitignore" + }, + { + "name": "LICENSE", + "path": "LICENSE", + "sha": "8f3b9ab0d08afd3a624d822e3971a2f42b3bc2b9", + "type": "file", + "size": 341, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/LICENSE?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/LICENSE" + }, + { + "name": "README.md", + "path": "README.md", + "sha": "1bc8a60ac6ddc876ebc4b60fc68991435bfad93e", + "type": "file", + "size": 9, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/README.md?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/README.md" + } +] +``` + ## 获取仓库代码目录 获取仓库代码目录 diff --git a/public/docs/api.html b/public/docs/api.html index c33cad0d4..64f96b9f3 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -368,6 +368,9 @@
  • 仓库详情(简版)
  • +
  • + 仓库详情(新版) +
  • 编辑仓库信息
  • @@ -389,6 +392,9 @@
  • 获取仓库成员列表
  • +
  • + 获取仓库所有文件 +
  • 获取仓库代码目录
  • @@ -1590,16 +1596,16 @@ http://localhost:3000/api/projects/migrate.json "repo_id": 75073, "repo_identifier": "mirror_demo" } -

    编辑仓库信息

    -

    编辑仓库信息

    +

    仓库详情(新版)

    +

    仓库详情

    示例:

    -
    curl -X GET http://localhost:3000/api/jasder/jasder_test/edit.json
    -
    await octokit.request('GET /api/jasder/jasder_test/edit.json')
    +
    curl -X GET http://localhost:3000/api/yystopf/ceshi/detail.json
    +
    await octokit.request('GET /api/yystopf/ceshi/detail.json')
     

    HTTP 请求

    -

    GET /api/:owner/:repo/edit.json

    +

    GET /api/:owner/:repo/detail

    请求参数:

    @@ -1634,6 +1640,379 @@ http://localhost:3000/api/projects/migrate.json + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    contentstring仓库简介
    websitestring仓库网址
    readmestringreadme文件|
    identifierstring项目标识
    namestring项目名称
    issues_countint项目issue数量
    pull_requests_countint项目issue数量
    project_identifierint项目issue数量
    praises_countint项目issue数量
    forked_countint项目issue数量
    watchers_countint项目issue数量
    versions_countint项目里程碑数量
    version_releases_countint项目发行版数量
    version_releasesed_countint项目发行版已发行数量
    permissionstring项目权限
    mirror_urlstring镜像地址
    mirrorbool是否为镜像项目
    typeint项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目
    open_devopsint是否开启devops
    watchedbool是否关注
    praisedbool是否点赞
    statusint项目状态
    forked_from_project_idintfork项目id
    fork_infoobjectfork项目信息
    sizestring仓库大小
    ssh_urlstring项目ssh地址
    clone_urlstring项目克隆地址
    default_branchstring仓库默认分支
    emptybool仓库是否为空
    full_namestring仓库全称
    privatebool仓库是否为私有项目
    license_namestring许可证名称
    release_versions.list.namestring项目issue数量
    release_versions.list.tag_namestring发行版标签名称
    release_versions.list.created_atstring发行版创建时间
    release_versions.total_countint发行版数量
    branches.list.namestring分支名称
    branches.total_countint分支数量
    tags.list.namestring标签名称
    tags.total_countint标签数量
    contributors.list.contributionsint贡献数量
    contributors.list.loginstring贡献者登录名
    contributors.list.namestring贡献者用户名称
    contributors.list.image_urlstring贡献者头像
    languagesobject项目语言占比
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "content": "仓库简介",
    +    "website": "仓库网址",
    +    "readme": {
    +        "type": "file",
    +        "encoding": "base64",
    +        "size": 9,
    +        "name": "README.md",
    +        "path": "README.md",
    +        "content": "# ceshi\n\n",
    +        "sha": ""
    +    },
    +    "identifier": "ceshi",
    +    "name": "测试项目",
    +    "project_id": 2,
    +    "repo_id": 2,
    +    "issues_count": 0,
    +    "pull_requests_count": 0,
    +    "project_identifier": "ceshi",
    +    "praises_count": 0,
    +    "forked_count": 0,
    +    "watchers_count": 0,
    +    "versions_count": 0,
    +    "version_releases_count": 0,
    +    "version_releasesed_count": 0,
    +    "permission": "Reporter",
    +    "mirror_url": null,
    +    "mirror": false,
    +    "type": 0,
    +    "open_devops": false,
    +    "watched": false,
    +    "praised": false,
    +    "status": 1,
    +    "forked_from_project_id": 1,
    +    "fork_info": {
    +        "fork_form_name": "测试项目",
    +        "fork_project_user_login": "ceshi_org",
    +        "fork_project_identifier": "ceshi",
    +        "fork_project_user_name": "ceshi_org"
    +    },
    +    "size": "25.0 KB",
    +    "ssh_url": "virus@localhost:yystopf/ceshi.git",
    +    "clone_url": "http://localhost:10080/yystopf/ceshi.git",
    +    "default_branch": "master",
    +    "empty": false,
    +    "full_name": "yystopf/ceshi",
    +    "private": false,
    +    "license_name": "gnu-javamail-exception",
    +    "release_versions": {
    +        "list": [
    +            {
    +                "id": 2,
    +                "name": "vvvv",
    +                "tag_name": "v1.1",
    +                "created_at": "2019-07-18 10:16"
    +            }
    +        ],
    +        "total_count": 1
    +    },
    +    "branches": {
    +        "list": [
    +            {
    +                "name": "master"
    +            }
    +        ],
    +        "total_count": 1
    +    },
    +    "tags": {
    +        "list": [
    +            {
    +                "name": "v1.1"
    +            },
    +            {
    +                "name": "v1.0"
    +            }
    +        ],
    +        "total_count": 2
    +    },
    +    "contributors": {
    +        "list": [
    +            {
    +                "contributions": 1,
    +                "gid": 2,
    +                "login": "yystopf",
    +                "type": "User",
    +                "name": "yystopf",
    +                "image_url": "avatars/User/b"
    +            }
    +        ],
    +        "total_count": 1
    +    },
    +    "languages": {
    +        "HTML": "50.9%",
    +        "Ruby": "25.6%",
    +        "JavaScript": "21.4%",
    +        "CSS": "1.3%",
    +        "CoffeeScript": "0.7%",
    +        "Shell": "0.1%"
    +    }
    +}
    +

    编辑仓库信息

    +

    编辑仓库信息

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/jasder/jasder_test/edit.json
    +
    await octokit.request('GET /api/jasder/jasder_test/edit.json')
    +

    HTTP 请求

    +

    GET /api/:owner/:repo/edit.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    +

    返回字段说明:

    + + + + + + + + @@ -1702,9 +2081,9 @@ http://localhost:3000/api/projects/migrate.json -d"private=true"\ http://localhost:3000/api/jasder/jasder_test.json
    await octokit.request('PATCH /api/jasder/jasder_test.json')
    -

    HTTP 请求

    +

    HTTP 请求

    PATCH /api/:owner/:repo

    -

    请求参数:

    +

    请求参数:

    参数类型字段说明
    identifier string 仓库标识
    @@ -1764,7 +2143,7 @@ http://localhost:3000/api/jasder/jasder_test.json
    参数项目是否私有, true:为私有,false: 公开,默认为公开
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1829,9 +2208,9 @@ http://localhost:3000/api/jasder/jasder_test.json
    curl -X DELETE http://localhost:3000/api/jasder/jasder_test.json
     
    await octokit.request('DELETE /api/jasder/jasder_test.json')
    -

    HTTP 请求

    +

    HTTP 请求

    PATCH /api/:owner/:repo

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -1856,7 +2235,7 @@ http://localhost:3000/api/jasder/jasder_test.json
    参数项目标识identifier
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1897,83 +2276,8 @@ http://localhost:3000/api/jasder/jasder_test.json -d"user_id=12"\ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    await octokit.request('POST /api/jasder/jasder_test/collaborators.json')
    -

    HTTP 请求

    -

    POST /api/:owner/:repo/collaborators.json

    -

    请求参数:

    -
    参数
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    user_idint用户id
    -

    返回字段说明:

    - - - - - - - - - - - - - - - - - -
    参数类型字段说明
    statusint返回状态, 0: 表示操作成功
    messagestring返回信息说明
    - -
    -

    返回的JSON示例:

    -
    -
    {
    -  "status": 0,
    -  "message": "success"
    -}
    -
    - -

    删除仓库成员

    -

    仓库中删除成员操作

    - -
    -

    示例:

    -
    -
    curl -X DELETE \
    --d "user_id=12" \
    -http://localhost:3000/api/jasder/jasder_test/collaborators.json
    -
    await octokit.request('DELETE /api/jasder/jasder_test/collaborators.json')
     

    HTTP 请求

    -

    DELETE /api/:owner/:repo/collaborators.json

    +

    POST /api/:owner/:repo/collaborators.json

    请求参数:

    @@ -2026,6 +2330,81 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    +
    +

    返回的JSON示例:

    +
    +
    {
    +  "status": 0,
    +  "message": "success"
    +}
    +
    + +

    删除仓库成员

    +

    仓库中删除成员操作

    + +
    +

    示例:

    +
    +
    curl -X DELETE \
    +-d "user_id=12" \
    +http://localhost:3000/api/jasder/jasder_test/collaborators.json
    +
    await octokit.request('DELETE /api/jasder/jasder_test/collaborators.json')
    +

    HTTP 请求

    +

    DELETE /api/:owner/:repo/collaborators.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    user_idint用户id
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    statusint返回状态, 0: 表示操作成功
    messagestring返回信息说明
    +

    返回的JSON示例:

    @@ -2048,9 +2427,9 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json -d "role=Developer" \ http://localhost:3000/api/jasder/jasder_test/change_role.json
    await octokit.request('PUT /api/jasder/jasder_test/change_role.json')
    -

    HTTP 请求

    +

    HTTP 请求

    PUT /api/:owner/:repo/change_role.json

    -

    请求参数:

    +

    请求参数:

    @@ -2089,7 +2468,7 @@ http://localhost:3000/api/jasder/jasder_test/change_role.json
    参数取值范围:"Manager", "Developer", "Reporter";分别为项目管理人员(拥有所有操作权限)、项目开发人员(只拥有读写权限)、项目报告人员(只拥有读权限)
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -2131,9 +2510,9 @@ http://localhost:3000/api/jasder/jasder_test/change_role.json -d"limit=5"\ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    await octokit.request('GET /api/jasder/jasder_test/collaborators.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/collaborators.json

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -2172,7 +2551,7 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    参数每页多少条数据,默认15条
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -2250,7 +2629,114 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json -

    获取仓库代码目录

    +

    获取仓库所有文件

    +

    获取仓库所有文件

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/yystopf/ceshi/files.json
    +
    await octokit.request('GET /api/yystopf/ceshi/files.json')
    +

    HTTP 请求

    +

    GET /api/:owner/:repo/files

    +

    请求参数:

    +
    参数
    + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    namestring文件名称
    pathstring文件路径
    shastring文件标识
    typestring文件类型
    sizeint文件大小
    urlstring文件地址
    + +
    +

    返回的JSON示例:

    +
    +
    [
    +    {
    +        "name": ".gitignore",
    +        "path": ".gitignore",
    +        "sha": "f83922d01ae60f6e637a1a2b9f08871b4f87dfc8",
    +        "type": "file",
    +        "size": 63,
    +        "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/.gitignore?ref=master",
    +        "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/.gitignore"
    +    },
    +    {
    +        "name": "LICENSE",
    +        "path": "LICENSE",
    +        "sha": "8f3b9ab0d08afd3a624d822e3971a2f42b3bc2b9",
    +        "type": "file",
    +        "size": 341,
    +        "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/LICENSE?ref=master",
    +        "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/LICENSE"
    +    },
    +    {
    +        "name": "README.md",
    +        "path": "README.md",
    +        "sha": "1bc8a60ac6ddc876ebc4b60fc68991435bfad93e",
    +        "type": "file",
    +        "size": 9,
    +        "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/README.md?ref=master",
    +        "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/README.md"
    +    }
    +]
    +

    获取仓库代码目录

    获取仓库代码目录

    @@ -2260,9 +2746,9 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json -d "ref=develop" \ http://localhost:3000//api/jasder/jasder_test/entries.json
    await octokit.request('GET /api/jasder/jasder_test/entries.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/entries.json

    -

    请求参数:

    +

    请求参数:

    @@ -2294,7 +2780,7 @@ http://localhost:3000//api/jasder/jasder_test/entries.json
    参数分支名称、tag名称或是提交记录id,默认为master分支
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -2408,9 +2894,9 @@ http://localhost:3000//api/jasder/jasder_test/entries.json -d"filepath=file"\ http://localhost:3000//api/jasder/jasder_test/sub_entries.json
    await octokit.request('GET /api/jasder/jasder_test/sub_entries.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/sub_entries.json

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -2449,7 +2935,7 @@ http://localhost:3000//api/jasder/jasder_test/sub_entries.json
    参数分支名称、tag名称或是提交记录id,默认为master分支
    -

    返回字段说明:

    +

    返回字段说明:

    From a14459da50452fd46d2586b55706c8de4910a481 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 17 Mar 2021 11:52:36 +0800 Subject: [PATCH 007/643] add: project menu list --- .../projects/project_units_controller.rb | 20 ++ app/controllers/projects_controller.rb | 17 +- app/controllers/repositories_controller.rb | 4 +- app/docs/slate/source/includes/_projects.md | 89 ++++++++ .../slate/source/includes/_repositories.md | 20 +- app/helpers/projects_helper.rb | 5 + app/models/concerns/project_operable.rb | 3 + app/models/project.rb | 1 + app/models/project_unit.rb | 35 ++++ app/services/projects/create_service.rb | 1 + config/routes.rb | 2 + .../20210317012035_create_project_units.rb | 10 + public/docs/api.html | 197 +++++++++++++++--- spec/models/project_unit_spec.rb | 5 + 14 files changed, 373 insertions(+), 36 deletions(-) create mode 100644 app/controllers/projects/project_units_controller.rb create mode 100644 app/models/project_unit.rb create mode 100644 db/migrate/20210317012035_create_project_units.rb create mode 100644 spec/models/project_unit_spec.rb diff --git a/app/controllers/projects/project_units_controller.rb b/app/controllers/projects/project_units_controller.rb new file mode 100644 index 000000000..ddb90fce2 --- /dev/null +++ b/app/controllers/projects/project_units_controller.rb @@ -0,0 +1,20 @@ +class Projects::ProjectUnitsController < Projects::BaseController + def create + if current_user.admin? || @project.owner?(current_user) + ActiveRecord::Base.transaction do + ProjectUnit.update_by_unit_types!(@project, unit_types) + render_ok + end + else + render_forbidden('你没有权限操作') + end + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def unit_types + params.fetch(:unit_types, []) + end +end \ No newline at end of file diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 5358a554e..573dbba80 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -2,11 +2,26 @@ class ProjectsController < ApplicationController include ApplicationHelper include OperateProjectAbilityAble 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 :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about menu_list] 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 :project_public?, only: %i[fork_users praise_users watch_users] + def menu_list + menu = [] + + menu.append(menu_hash_by_name("home")) + menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code") + menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues") + menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") + menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") + menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") + menu.append(menu_hash_by_name("activity")) + menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.owner?(current_user) + + render json: menu + end + def index scope = Projects::ListQuery.call(params) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 5fb7b7681..3410ddb3e 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -11,10 +11,8 @@ class RepositoriesController < ApplicationController before_action :get_latest_commit, only: %i[entries sub_entries top_counts] before_action :get_statistics, only: %i[top_counts] - - def files - result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@project.owner, @project.identifier, @ref) + result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token) render json: result end diff --git a/app/docs/slate/source/includes/_projects.md b/app/docs/slate/source/includes/_projects.md index 1fbbd0dab..0e2fc13fd 100644 --- a/app/docs/slate/source/includes/_projects.md +++ b/app/docs/slate/source/includes/_projects.md @@ -168,6 +168,55 @@ Remember — a happy kitten is an authenticated kitten! +## 项目导航 +获取项目导航信息 + +> 示例: + +```shell +curl -X GET \ +http://localhost:3000/api/yystopf/ceshi/menu_list | jq +``` + +```javascript +await octokit.request('GET /api/yystopf/ceshi/menu_list') +``` + +### HTTP 请求 +`GET api/:owner/:repo/menu_list` + +### 请求参数 +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +owner |是| |string |用户登录名 +repo |是| |string |项目标识identifier + +### 返回字段说明 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +menu_name |string|导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置 + + +> 返回的JSON示例: + +```json +[ + { + "menu_name": "home" + }, + { + "menu_name": "code" + }, + { + "menu_name": "pulls" + }, + { + "menu_name": "activity" + } +] +``` + + ## 项目主页 获取项目主页信息 @@ -212,6 +261,46 @@ attachments |array|附件 Remember — a happy kitten is an authenticated kitten! +## 更改项目导航 +更改项目导航信息 + +> 示例: + +```shell +curl -X POST \ +-H "accept: application/json" \ +-H "Content-Type: application/json" \ +-d "{ \"unit_typs\": [\"code\", \"pulls\"]}" \ +http://localhost:3000/api/yystopf/ceshi/project_units.json +``` + +```javascript +await octokit.request('POST /api/yystopf/ceshi/project_units') +``` + +### HTTP 请求 +`POST /api/yystopf/ceshi/project_units` + +### 请求参数 +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑 | + + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|status |int|返回状态, 0: 表示操作成功 | +|message |string|返回信息说明| + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` ## 创建项目 创建项目 diff --git a/app/docs/slate/source/includes/_repositories.md b/app/docs/slate/source/includes/_repositories.md index 862e96cea..40d3ba2ff 100644 --- a/app/docs/slate/source/includes/_repositories.md +++ b/app/docs/slate/source/includes/_repositories.md @@ -129,11 +129,11 @@ await octokit.request('GET /api/yystopf/ceshi/detail.json') |identifier |string |项目标识 | |name |string |项目名称 | |issues_count |int |项目issue数量| -|pull_requests_count |int |项目issue数量| -|project_identifier |int |项目issue数量| -|praises_count |int |项目issue数量| -|forked_count |int |项目issue数量| -|watchers_count |int |项目issue数量| +|pull_requests_count |int |项目合并请求数量| +|project_identifier |int |项目标识| +|praises_count |int |项目点赞数量| +|forked_count |int |项目复刻数量| +|watchers_count |int |项目关注数量| |versions_count |int |项目里程碑数量| |version_releases_count |int |项目发行版数量| |version_releasesed_count |int |项目发行版已发行数量| @@ -645,7 +645,9 @@ await octokit.request('GET /api/jasder/jasder_test/collaborators.json') > 示例: ```shell -curl -X GET http://localhost:3000/api/yystopf/ceshi/files.json +curl -X GET \ +-d "ref=develop" \ +http://localhost:3000/api/yystopf/ceshi/files.json ``` ```javascript @@ -658,8 +660,10 @@ await octokit.request('GET /api/yystopf/ceshi/files.json') ### 请求参数: 参数 | 必选 | 默认 | 类型 | 字段说明 --------- | ------- | ------- | -------- | ---------- -|owner |是| |string |用户登录名 | -|repo |是| |string |项目标识identifier | +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|search |否| |string |文件搜索关键词 | +|ref |是| |string |分支名,默认为仓库默认分支 | ### 返回字段说明: diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 6fbc22eb5..b212b50e4 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -1,4 +1,9 @@ module ProjectsHelper + def menu_hash_by_name(name) + { + menu_name: name + } + end def render_zh_project_type(project_type) case project_type diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index 5e8bf43d9..e151613d5 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -89,4 +89,7 @@ module ProjectOperable member.member_roles.create!(role: role) end + def has_menu_permission(unit_type) + self.project_units.where(unit_type: unit_type).exists? + end end diff --git a/app/models/project.rb b/app/models/project.rb index 5b05def1c..cde2f1011 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -113,6 +113,7 @@ class Project < ApplicationRecord has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position" has_one :project_detail, dependent: :destroy has_many :team_projects, dependent: :destroy + has_many :project_units, dependent: :destroy after_save :check_project_members scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} diff --git a/app/models/project_unit.rb b/app/models/project_unit.rb new file mode 100644 index 000000000..b5b4fe290 --- /dev/null +++ b/app/models/project_unit.rb @@ -0,0 +1,35 @@ +# == Schema Information +# +# Table name: project_units +# +# id :integer not null, primary key +# project_id :integer +# unit_type :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_project_units_on_project_id (project_id) +# + +class ProjectUnit < ApplicationRecord + belongs_to :project + + enum unit_type: {code: 1, issues: 2, pulls: 3, devops: 4, versions: 5} + + validates :unit_type, uniqueness: { scope: :project_id} + + def self.init_types(project_id) + ProjectUnit::unit_types.each do |_, v| + self.create!(project_id: project_id, unit_type: v) + end + end + + def self.update_by_unit_types!(project, types) + project.project_units.where.not(unit_type: types).each(&:destroy!) + types.each do |type| + project.project_units.find_or_create_by!(unit_type: type) + end + end +end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 25053e953..c6e5b213b 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -13,6 +13,7 @@ class Projects::CreateService < ApplicationService ActiveRecord::Base.transaction do if @project.save! Project.update_common_projects_count! + ProjectUnit.init_types(@project.id) Repositories::CreateService.new(user, @project, repository_params).call else Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}") diff --git a/config/routes.rb b/config/routes.rb index 9aed0ca5e..27af236a5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -369,6 +369,7 @@ Rails.application.routes.draw do resource :projects, path: '/', except: [:show, :edit] do member do + get :menu_list get :branches get :simple get :watchers, to: 'projects#watch_users' @@ -528,6 +529,7 @@ Rails.application.routes.draw do scope module: :projects do resources :teams, only: [:index, :create, :destroy] + resources :project_units, only: [:create] scope do get( '/blob/*id/diff', diff --git a/db/migrate/20210317012035_create_project_units.rb b/db/migrate/20210317012035_create_project_units.rb new file mode 100644 index 000000000..6b89154f9 --- /dev/null +++ b/db/migrate/20210317012035_create_project_units.rb @@ -0,0 +1,10 @@ +class CreateProjectUnits < ActiveRecord::Migration[5.2] + def change + create_table :project_units do |t| + t.references :project + t.integer :unit_type + + t.timestamps + end + end +end diff --git a/public/docs/api.html b/public/docs/api.html index 64f96b9f3..0f67e27c5 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -342,9 +342,15 @@
  • 推荐项目
  • +
  • + 项目导航 +
  • 项目主页
  • +
  • + 更改项目导航 +
  • 创建项目
  • @@ -972,17 +978,17 @@ http://localhost:3000/api/projects/recommend | jq -

    项目主页

    -

    获取项目主页信息

    +

    项目导航

    +

    获取项目导航信息

    示例:

    curl -X GET \
    -http://localhost:3000/api/jasder/forgeplus/about  | jq
    -
    await octokit.request('GET /api/jasder/forgeplus/about')
    +http://localhost:3000/api/yystopf/ceshi/menu_list  | jq
    +
    await octokit.request('GET /api/yystopf/ceshi/menu_list')
     

    HTTP 请求

    -

    GET api/:owner/:repo/about

    +

    GET api/:owner/:repo/menu_list

    请求参数

    参数
    @@ -1017,6 +1023,74 @@ http://localhost:3000/api/jasder/forgeplus/about | jq + + + + +
    menu_namestring导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
    + +
    +

    返回的JSON示例:

    +
    +
    [
    +    {
    +        "menu_name": "home"
    +    },
    +    {
    +        "menu_name": "code"
    +    },
    +    {
    +        "menu_name": "pulls"
    +    },
    +    {
    +        "menu_name": "activity"
    +    }
    +]
    +

    项目主页

    +

    获取项目主页信息

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +http://localhost:3000/api/jasder/forgeplus/about  | jq
    +
    await octokit.request('GET /api/jasder/forgeplus/about')
    +

    HTTP 请求

    +

    GET api/:owner/:repo/about

    +

    请求参数

    + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    +

    返回字段说明

    + + + + + + + + @@ -1045,7 +1119,66 @@ http://localhost:3000/api/jasder/forgeplus/about | jq -

    创建项目

    +

    更改项目导航

    +

    更改项目导航信息

    + +
    +

    示例:

    +
    +
    curl -X POST \
    +-H  "accept: application/json" \
    +-H  "Content-Type: application/json" \
    +-d "{ \"unit_typs\": [\"code\", \"pulls\"]}" \
    +http://localhost:3000/api/yystopf/ceshi/project_units.json
    +
    await octokit.request('POST /api/yystopf/ceshi/project_units')
    +

    HTTP 请求

    +

    POST /api/yystopf/ceshi/project_units

    +

    请求参数

    +
    参数类型字段说明
    identifier string project's identifier
    + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    unit_typesarray项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    statusint返回状态, 0: 表示操作成功
    messagestring返回信息说明
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "status": 0,
    +    "message": "success"
    +}
    +

    创建项目

    创建项目

    @@ -1062,9 +1195,9 @@ Remember — a happy kitten is an authenticated kitten! -d "license_id=1" \ http://localhost:3000/api/projects.json
    await octokit.request('GET /api/projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST api/projects

    -

    请求参数

    +

    请求参数

    @@ -1138,7 +1271,7 @@ http://localhost:3000/api/projects.json
    参数项目是否私有, true:为私有,false: 公开,默认为公开
    -

    返回字段说明

    +

    返回字段说明

    @@ -1180,9 +1313,9 @@ http://localhost:3000/api/projects.json -d"project_language_id=2"\ http://localhost:3000/api/projects/migrate.json
    await octokit.request('GET /api/projects/migrate.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST api/projects/migrate.json

    -

    请求参数

    +

    请求参数

    参数
    @@ -1270,7 +1403,7 @@ http://localhost:3000/api/projects/migrate.json
    参数项目是否私有, true:为私有,false: 非私有,默认为公开
    -

    返回字段说明

    +

    返回字段说明

    @@ -1305,9 +1438,9 @@ http://localhost:3000/api/projects/migrate.json
    curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror.json
     
    await octokit.request('POST /api/repositories/1244/sync_mirror.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST api/repositories/:id/sync_mirror.json

    -

    请求参数

    +

    请求参数

    参数
    @@ -1325,7 +1458,7 @@ http://localhost:3000/api/projects/migrate.json
    参数仓库id
    -

    返回字段说明

    +

    返回字段说明

    @@ -1360,9 +1493,9 @@ http://localhost:3000/api/projects/migrate.json
    curl -X POST http://localhost:3000/api/jasder/forgeplus/forks.json
     
    await octokit.request('POST /api/jaser/jasder_test/forks.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST api/:owner/:repo/forks.json

    -

    请求参数

    +

    请求参数

    参数
    @@ -1387,7 +1520,7 @@ http://localhost:3000/api/projects/migrate.json
    参数项目标识identifier
    -

    返回字段说明

    +

    返回字段说明

    @@ -1672,27 +1805,27 @@ http://localhost:3000/api/projects/migrate.json - + - + - + - + - + @@ -2635,7 +2768,9 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json

    示例:

    -
    curl -X GET http://localhost:3000/api/yystopf/ceshi/files.json
    +
    curl -X GET \
    +-d "ref=develop" \
    +http://localhost:3000/api/yystopf/ceshi/files.json
     
    await octokit.request('GET /api/yystopf/ceshi/files.json')
     

    HTTP 请求

    GET /api/:owner/:repo/files

    @@ -2663,6 +2798,20 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    + + + + + + + + + + + + + +
    参数
    pull_requests_count int项目issue数量项目合并请求数量
    project_identifier int项目issue数量项目标识
    praises_count int项目issue数量项目点赞数量
    forked_count int项目issue数量项目复刻数量
    watchers_count int项目issue数量项目关注数量
    versions_countstring 项目标识identifier
    searchstring文件搜索关键词
    refstring分支名,默认为仓库默认分支

    返回字段说明:

    diff --git a/spec/models/project_unit_spec.rb b/spec/models/project_unit_spec.rb new file mode 100644 index 000000000..d95607ca6 --- /dev/null +++ b/spec/models/project_unit_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ProjectUnit, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 8f98a833793050d2e26515991c13fd85ff5d30a4 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 17 Mar 2021 13:50:26 +0800 Subject: [PATCH 008/643] add: project unit list --- .../projects/project_units_controller.rb | 4 ++ app/docs/slate/source/includes/_projects.md | 42 ++++++++++++++++++- .../project_units/index.json.jbuilder | 3 ++ config/routes.rb | 2 +- 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 app/views/projects/project_units/index.json.jbuilder diff --git a/app/controllers/projects/project_units_controller.rb b/app/controllers/projects/project_units_controller.rb index ddb90fce2..90bc64a71 100644 --- a/app/controllers/projects/project_units_controller.rb +++ b/app/controllers/projects/project_units_controller.rb @@ -1,4 +1,8 @@ class Projects::ProjectUnitsController < Projects::BaseController + def index + @project_units = @project.project_units + end + def create if current_user.admin? || @project.owner?(current_user) ActiveRecord::Base.transaction do diff --git a/app/docs/slate/source/includes/_projects.md b/app/docs/slate/source/includes/_projects.md index 0e2fc13fd..0a46d8cc7 100644 --- a/app/docs/slate/source/includes/_projects.md +++ b/app/docs/slate/source/includes/_projects.md @@ -261,8 +261,46 @@ attachments |array|附件 Remember — a happy kitten is an authenticated kitten! -## 更改项目导航 -更改项目导航信息 +## 项目模块信息 +项目模块信息 + +> 示例: + +```shell +curl -X GET \ +http://localhost:3000/api/yystopf/ceshi/project_units.json +``` + +```javascript +await octokit.request('GET /api/yystopf/ceshi/project_units') +``` + +### HTTP 请求 +`GET /api/yystopf/ceshi/project_units` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|type |string|模块名称 | + +> 返回的JSON示例: + +```json +[ + { + "type": "code" + }, + { + "type": "pulls" + }, + { + "type": "issues" + } +] +``` + +## 更改项目模块展示 +更改项目模块展示 > 示例: diff --git a/app/views/projects/project_units/index.json.jbuilder b/app/views/projects/project_units/index.json.jbuilder new file mode 100644 index 000000000..e88393876 --- /dev/null +++ b/app/views/projects/project_units/index.json.jbuilder @@ -0,0 +1,3 @@ +json.array! @project_units do |unit| + json.type unit.unit_type +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 27af236a5..fd3b22ec9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -529,7 +529,7 @@ Rails.application.routes.draw do scope module: :projects do resources :teams, only: [:index, :create, :destroy] - resources :project_units, only: [:create] + resources :project_units, only: [:index, :create] scope do get( '/blob/*id/diff', From 187ad1d263c243c9bc5e381ee279b511c316a170 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 17 Mar 2021 13:51:08 +0800 Subject: [PATCH 009/643] fix --- public/docs/api.html | 61 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/public/docs/api.html b/public/docs/api.html index 0f67e27c5..1b75a97a2 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -349,7 +349,10 @@ 项目主页
  • - 更改项目导航 + 项目模块信息 +
  • +
  • + 更改项目模块展示
  • 创建项目 @@ -1119,8 +1122,48 @@ http://localhost:3000/api/jasder/forgeplus/about | jq -

    更改项目导航

    -

    更改项目导航信息

    +

    项目模块信息

    +

    项目模块信息

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +http://localhost:3000/api/yystopf/ceshi/project_units.json
    +
    await octokit.request('GET /api/yystopf/ceshi/project_units')
    +

    HTTP 请求

    +

    GET /api/yystopf/ceshi/project_units

    +

    返回字段说明:

    +
  • + + + + + + + + + + + +
    参数类型字段说明
    typestring模块名称
    + +
    +

    返回的JSON示例:

    +
    +
    [
    +    {
    +        "type": "code"
    +    },
    +    {
    +        "type": "pulls"
    +    },
    +    {
    +        "type": "issues"
    +    }
    +]
    +

    更改项目模块展示

    +

    更改项目模块展示

    示例:

    @@ -1131,7 +1174,7 @@ Remember — a happy kitten is an authenticated kitten! -d "{ \"unit_typs\": [\"code\", \"pulls\"]}" \ http://localhost:3000/api/yystopf/ceshi/project_units.json
    await octokit.request('POST /api/yystopf/ceshi/project_units')
    -

    HTTP 请求

    +

    HTTP 请求

    POST /api/yystopf/ceshi/project_units

    请求参数

    @@ -1151,7 +1194,7 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json
    项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1195,7 +1238,7 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json -d"license_id=1"\ http://localhost:3000/api/projects.json
    await octokit.request('GET /api/projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST api/projects

    请求参数

    参数
    @@ -1313,7 +1356,7 @@ http://localhost:3000/api/projects.json -d"project_language_id=2"\ http://localhost:3000/api/projects/migrate.json
    await octokit.request('GET /api/projects/migrate.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST api/projects/migrate.json

    请求参数

    @@ -1438,7 +1481,7 @@ http://localhost:3000/api/projects/migrate.json
    curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror.json
     
    await octokit.request('POST /api/repositories/1244/sync_mirror.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST api/repositories/:id/sync_mirror.json

    请求参数

    @@ -1493,7 +1536,7 @@ http://localhost:3000/api/projects/migrate.json
    curl -X POST http://localhost:3000/api/jasder/forgeplus/forks.json
     
    await octokit.request('POST /api/jaser/jasder_test/forks.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST api/:owner/:repo/forks.json

    请求参数

    From a627ab4d824abec516643cec1416cc68d97e3c5f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 18 Mar 2021 09:51:56 +0800 Subject: [PATCH 010/643] fix --- app/views/repositories/detail.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 0931802ec..6980d4b25 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -51,7 +51,7 @@ json.license_name @project.license_name json.release_versions do json.list @result[:release].each do |release| forge_version = VersionRelease.find_by(version_gid: release["id"]) - json.id forge_version.id + json.id forge_version&.id json.name release["name"] json.tag_name release["tag_name"] json.created_at format_time(release["created_at"].to_time) From 25186b4e81bc835793cbe000531bf45ce8e1e7ae Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 18 Mar 2021 09:55:58 +0800 Subject: [PATCH 011/643] fix --- app/services/repositories/detail_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/repositories/detail_service.rb b/app/services/repositories/detail_service.rb index 0dbbb490b..58b286ec5 100644 --- a/app/services/repositories/detail_service.rb +++ b/app/services/repositories/detail_service.rb @@ -45,7 +45,7 @@ class Repositories::DetailService < ApplicationService end def tag_suitable - Gitea::Repository::Tags::ListService.call(@user&.gitea_token, @owner.login, @repo.identifier) + Gitea::Repository::Tags::ListService.call(@owner&.gitea_token, @owner.login, @repo.identifier) end def contributor_suitable From 6a7ef2a1a72bbda89abe310ad3cbd6e7ecbcc658 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 18 Mar 2021 16:35:40 +0800 Subject: [PATCH 012/643] add: repo contributors --- app/controllers/repositories_controller.rb | 4 ++++ .../repositories/contributors.json.jbuilder | 17 +++++++++++++++++ config/routes.rb | 1 + 3 files changed, 22 insertions(+) create mode 100644 app/views/repositories/contributors.json.jbuilder diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 3410ddb3e..cd07803d6 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -106,6 +106,10 @@ class RepositoriesController < ApplicationController @tags = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}) end + def contributors + @contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier) + end + def edit return render_forbidden if !@project.manager?(current_user) && !current_user.admin? end diff --git a/app/views/repositories/contributors.json.jbuilder b/app/views/repositories/contributors.json.jbuilder new file mode 100644 index 000000000..a5edb37e0 --- /dev/null +++ b/app/views/repositories/contributors.json.jbuilder @@ -0,0 +1,17 @@ +total_count = @contributors.size +json.contributors @contributors.each do |contributor| + user = User.find_by(gitea_uid: contributor["id"]) + if contributor["login"] == "root" + total_count -= 1 + next + end + json.contributions contributor["contributions"] + json.gid contributor["id"] + json.login user.login + json.type user&.type + json.name user.real_name + json.image_url url_to_avatar(user) +end +json.total_count total_count + + diff --git a/config/routes.rb b/config/routes.rb index fd3b22ec9..9e9e3d7a8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -389,6 +389,7 @@ Rails.application.routes.draw do match :sub_entries, :via => [:get, :put] get :commits get :tags + get :contributors post :create_file put :update_file delete :delete_file From 495de925ddf5a900886bdcca17e61d8610ca044f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 19 Mar 2021 11:29:31 +0800 Subject: [PATCH 013/643] add: sync mulan repo --- lib/tasks/sync_mulan_repo.rake | 46 +++++++++++++++++++++++++++++++++ public/mulan_repo.xlsx | Bin 0 -> 20757 bytes 2 files changed, 46 insertions(+) create mode 100644 lib/tasks/sync_mulan_repo.rake create mode 100644 public/mulan_repo.xlsx diff --git a/lib/tasks/sync_mulan_repo.rake b/lib/tasks/sync_mulan_repo.rake new file mode 100644 index 000000000..e1ab8ddbe --- /dev/null +++ b/lib/tasks/sync_mulan_repo.rake @@ -0,0 +1,46 @@ +namespace :create_mulan_repository do + desc "sync mulan repository from gitee.com" + task sync_from_gitee: :environment do + doc = SimpleXlsxReader.open("#{Rails.root}/public/mulan_repo.xlsx") + data = doc.sheets.first.rows + data.each_with_index do |row, index| + next if index == 0 + begin + user = User.find_by(login: row[1]) + unless user.present? + username = row[1] + email = "#{row[1]}@forge.com" + password = "Mr123456." + user = User.new(nickname: row[0], login: username, mail: email, password: password, type: 'User') + interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) + gitea_user = interactor.result + result = Gitea::User::GenerateTokenService.call(username, password) + user.gitea_token = result['sha1'] + user.gitea_uid = gitea_user[:body]['id'] + user.save! + UserExtension.create!(user_id: user.id) + end + project = user.projects.find_by(identifier: row[4]) + unless project.present? + p_category = ProjectCategory.find_or_create_by(name: row[6]) + p_language = ProjectLanguage.find_or_create_by(name: row[7].split("/")[0]) + p_license = License.find_by(name: row[8]) + + mirror_params = { + user_id: user.id, + name: row[5], + description: row[9], + repository_name: row[4], + project_category_id: p_category.id, + project_language_id: p_language.id, + clone_addr: row[10] + } + Projects::MigrateService.call(user, mirror_params) + end + puts "sync mulan repository from gitee.com Success repo: #{row[5]} username: #{row[0]}" + rescue Exception => e + puts "sync mulan repository from gitee.com Error repo: #{row[5]} username: #{row[0]}" + end + end + end +end \ No newline at end of file diff --git a/public/mulan_repo.xlsx b/public/mulan_repo.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1c9e45851dabc2525521874ceffa6a5e0f11489e GIT binary patch literal 20757 zcmZ^~1CVGjyDiv0ZQHhO+qP}nJZ;;yZQC|a+cu~FduOKJee)(&yRvs`eO1ZImoLdm zw!9QD2qeINQmE`c|9|rTCqewa7~2`iJKEVh(aHb9kbeun{|hFd7C*oO2mrtg1ONd4 zzrqac?P=X@th3|$C4m``MP34b;2Z1~Q4uK8kp+gbfvY=W(%EeENg>9a%)bDC_}Of= z!ELoW@9mU7p_!28%G(^>^sWzjoFHMG|xOuT3JOrI8B{ODOR;NURHqt zTQ_FjFsl=#2So;c!4X&5Z|eW~i>lh}{m;AJ0YUv%=!CMGcqCfKUNlN-kc}mql-0f{-Gk6ITF)`cx`ci+Ez_*{$euJ>F~$o!RE!+$sm&1 zyqsP3W$knG4$^@wLB!QCE53uUQKo%^!}`Gsvv zvUl*gwy`v5cHVI8WX9nrAhaHPZNMe2#05->5eOE$I*Y(XeRKXmINT)|!@D~GvTuA? zo+kUsF6`^+q{p3CC%5aBmgQQ$kOb4{cY#T zUJx~XiHb=d%t3#Q5#OxEABwrBYwTLEl#hr@De^63TaxOAvuJ8`Iagx8uY2?J_OD!@ zdc&zw=+?bi2z&u6fPOk0o*@1wv)PQ@B%i;G`u?(u^goz&adNh^`7i&ClaU&thv&Zu z{2@5ZA&pjME50(^+>ZPMy4sz}ybZ&QM{Lm?_OqR|{B-T$K6o&Vya~q=sKHJbO>2+= z4<3A6lKQSZ&^m}~gMXX9=);CdBiRNH*SdTqbGILbLM#4HK-pYxzzLjnbnT&0K3k4( zB_4XDoOWnFyAA_vT*T_NC>S;k(J}VzFi2rc*X4G9^5j;}#O_t|BsO$-WUJyeo=#t0 z;F;vpy0OHDDS@EF2u4yulgM=x7k(XH&}!py{ooo3sFPL++_`lBOs;lTVN;HKDG~dl z&|ZNj)Vt}1w=E(es({%5LV|o!J>W+^zz?bdsMaENRAu)+Wc{B50`M}_GQ4ZI`~^$9 zQ%?=ZDoet_LN2a9y(B^MaMDw3947!F8U?^LQ`+kVCHHPrr_nwg`P3QX=ds*Aw$f;rQ;T-P>Gz525}F-(MXNKrs8T<(anoZL<>g=Uq-OwBtTHr11c0cR*&xXw;WrnJ7 zG#O1>N5?DHqURc$yNhD;l^hrMUgJ4G?Fz5)>3XkdO7%?kyjSNq^QyA-=0WxQ*yNqs z#-}<~Wf<;{ARam)QmXNW8B47M1HAy3Is>sJX?4BJB6 zhj;RgZpE?dPH#2wr@H6O?u=8sfRUSmDclWb@2g#cz#M|S&b?Ue_dhD&P@7@Q`@zQ;dgrmqK zSxYY`k7|>th-CJpA3g5ljQZ@z(MPYRm$$vC-X84t{yZm!O*^;YgL?2EbFVtc7}fii zWlQ(<8@*gh2cH#f=L$%bZrBj8?<0NpWiFO~RUSX)w0?S0z1^2jw$UJF)5R7lXTK)i z?q_hHnTdh_DM)Vr^r`MT_49F2)YEhk?Z_)MbD58}6?!na7dH!lS+Qywe zx~Y8ITZmZVr*tfF)&py*aR0J*p2Pcg`ukcslmI8z*}rUJZxxY(*$(Oz`dP&}5bB)T zi^hl?j)g%ir-;Kj`0qld;-K_LbRubLCDM;WhbFx@*)DfSulp&dNNqYsEecjm z94NQu_AX-X31JTfZ;Q&)eR!?AAXZKI8U?tE(6zR0go^YUh0T3~}Ou%V0fQ9~CC45So5;)Bb-$cIq= zFnRtbi7p@<;IMv6|NLIPhd2FM+PEU#3?z;i7BFGR$e-B38Fqx#S-Hs|HjoKayuTe- z{GAMl;y3m~<`t0ZlosIl;|`lU!~O-(5b-CiQL!h)dZuu!hrvOySu3rRwK-K%y0%^` z-5>>`K>HxQ&nu8-J6BGsm1|!sJ&gfSbQbbQ-e%xOS`CUg(YF>76Ty0xC@cTJt^Z^5 zhqNuP06NKqa$=PXEJwrO_#wQ?p=oL{Df)8j2!KW8L#)nCP5FhzFgP@T z8P1i#vH%&uKqxLQie!bpcFsjj7=YdR0HNX(14c!pZJ`8+6vK3)l7LwNPZH4-bN;6| zb6Aiz1xX9{Bf{vQ%j>=}H!CjN5_4FTzQIdF6^JCl=irbz6v_x|uoTJ+@?>-Yu;p76 z@+UpO&f*5LNeOvENY=>8W=}4G8&UxTM+0MjB=4Y;74`5k+*J!==Yc_~Ii-w>kY^y| z+2po6p31)6_6)=ceL|B0v&l^aWaJg(vv*b@EN9hhDGZ5rOTLpKR_cE$mAY8o)R2?v-|cA& z)`XSe|DoT`G1pg&fRtsnx?*ibRafF1i3Wmdr{5M1alX_huIbXZA#OH_8V<#@g;6{a z{!qt2DBa7z|2_d79fsq^S!E0+HGU@h5gq52d9rF=5dY3C7cq4ZxHc#U(;O|O(=hR} zM;Y|pu>CXQFDTYJIx5halkT<%6wqQiNZI6dbQqS(t>~D%FF5uTwj0?W0Uw6Uqtfue zMNb@}ULyqA1TM#{R;Q9zOMLf=s`XJ>%_X%oc$Xlp=%_yXBsTwJ&^Z7EOMXVwbnN8~ zy(Xh|dv$85q^6en-sLIYq%XGm*MQYr-Qnz|6g05%!ULPo)mg-vr={9cC^!vodL%46 z7<5V?9mpkEW#T{}7VQ4eJ)XzuvD!?O9v1}Wg6?Z)Y?DdC4;>C%Ni{T>f^IapTuki5 zK{}1mDKPC6xr~agWuwS=`CK@f!_Er^*e0(sA|pVxmu=vF@E?K!q>XqQSQUdogr;y> z0V=TT2yotvGiq5S6>G*lfr8P>vS(T_L}g?orw+lk&VTXzTRUk96wojV8^gZVrB?`f zHMPy=%1RlZ6OZN&Q=QBl^*GeR~jOar<~GaZN5%zH{t4Yk^9rjBs?Ew~*krA9O4lF{mx}t!F5q4o|Yy~4> zcIN0Y;EU#nz^==~8UNT>LABI$P=c1a^QR=1Kr5|yFvVP4OcY9Ksm0wZ^^0on)3>@E zmOw8npw>JI{ic3>WTatRgGRHlOPr#$QVqG#uyubm)U(R=jF0epR8 zeV9hZDR&IQqC5}aIrX4FX9v(zHV)`;mDOU3V66dQ$u5>oHV^1PQXGN)MZC!J;wb-@ zmh9>SJE`yw=Yc4V3P z0D}QjpNc{zfNRKbL3!nFKz-Lj?1583S};r%4HB}d8VU=M^{j3bh+5HB7(K~$8oh~% za9Rc$@bg>w2S{Bb6I2r^S-p;|Y)53(UIhi2%eFjOHjiCpJZwD?j-g~_S!mhlylsm-SU3lSpAanZwcHd>-A8koz(`b9YA5qzSf!R*L=CD*t`o~(u!iDDtOp`vRQok1=s7~qYDaPTHtSS`$jlW(yRQki*6t7 zyq9&2s6>AZ6VFuy7`+#6D8{i!Adv&5gSN*O2KiUb2w%!6`^J z&QaeQ4g}zXs7OJN2Is|iqXXucdRCX7Y2M5JxtKElecjD}`t5e&@YnzJ8>jv&xGJ2qNsYFJ^iz6e}? zqjm$P%kpo}*VK*e(PSz7_Y7i;heWzgG}IM@h*a`%3{uCn9T>rt=*@z9b{W8K?@R2^ z1#TN8)0=R5(U2#rr!K?JmnhHFh^UVZ)Y36^hx&Jf^d2RqPdz5B&rIQW$jzy&{Cf7z zhDfJ})uMl^J)+CBht(6-*rvcBqGWGtaN!bW_9%g&71K##+PEI=>&`=hHV#luzJyRO`uX+OR+m;QxJN7B=e5E8`SQpOLCY|Z=;wbdZkC?ZcUz`Ubjv9Bd_0aa=7zuT6h+u3T75-djkj*)YrX37R4*EZbgOvMm4-}r=9c6RUgt)Kh|6)K z6p*x#AHA7mZ{MhuvrV#2ijKOrT-0i5v43aO_8ym$KfE^G@kaaoxD`5~OSOfrycDaD z)^8OTzl^d{@u42oNI&Qp0lM~F)Z%C@eG7;dJJV)cuDy}|8n8$%=PH~;yj;8iT+acOE6j}(V0b=-L!T% z_}J02Xiu^HNw2y0lNVpuL0+uE^V8NfvHJ1)w*e?&tm zDRSk(knGr{QysqCg0JYMp%-bom^*^QAeW^3WY@W2?7kUa_luUP^U7)|6>0j}uTvf>XoSY9wA<}}d;y~Ip5#cpP;O9Jjz9OC zVoR6i#cWjFHGF} zX``p7#B|hrG3nW4&cdc`w(GVNI$j$cUC-6fQWYY5`e{_ZEy0BeRo7Y1T5JNisd4?) zu$?@7Qk9fwN%dk=vZvY3xtRfx-^1XHsJg515nf>;=LmoG*;Bvldb7$l;5+cNpZfIt zCjGvit(SSrRKu5>iGM+bA{y(;^R05NlETXzVc_QCb96*z*(G7NdkDTSy6Vcd`u-Dj z0jJSo;aIh~EE?&W{izaZ^X;C?%Gu)8*dup~#FAoh=;>uDz5F$$RNM^8_s=VluPR~$ ztK|9=WA@7PF7|D5aJ9JW)q|+@Gkwd4_@%?cp=9;+I)$QGCp4?3HPh$KOMPc0?bWM#T%GRw5vdeNb)$=paou`~z7xv| z_-D}ZFz&2|yF0^V`=rVtZ*lZcw9nPYOIKW2^=&7!Hpeu&y3VV`*0sr8MDtU=_j|4q zwR7E6rHlD(wY0co|BBPSX;r9|@5WgAp7$g+Q{|c9eM{Ycd;Y21EfUOo*Nk!cQ)`84 zhcO#%xa5OyGWD8U$JvD7jo2)YEydK$$7XXj`8kt1wWYSFdvTE1qoE}pV#3aXVlw?| zSW*@yb+Dh#u4xq;_LTQiNEW#kmZgWz)$!H!$${cxQTq3*1N-&+*7Ei}w`fd=08Yg+ zey514v#dk-`z%{F%kSss|6e=%kC^_eojIGE*qHopV!AX=%G@R>002J5f9sL|FYLd- z|0RfBX~@`NvB7tvo%*R?cE=lE5HS+|Y2n=`bww1GjKD6}u}np9YsaVH>OdK<=MN~b zn3oFJ@g&~>6Zh9$&^uri$pm_X!f{liQY^3>9V4JI)FZym{C6;Q3)9}=_+%j1Z8QaH zU@=;&Q}K=~3yhk;eE#Yt78FbSkrPJ_gJ42&{pv*hS=ou_YY%!ghEBEy{GoiA7lS92 zex*!F=x;zwTMu1&Ydzo|NbG&2Kyr8r@=4m%pi<3B1wmMTQ%nxn+DeLqsPE_YuSKrk zjWPrioE(p`)Ex&))(Vo~xIn7iEy{c}6hqLJaR9FPMuC`^`}9@i>qO19R(Vd=K==qu zYtT0D2eNYjKg;%v!-JWYta=se=~(wn54cQw^hxW>v{&PO5dayaZXql3tg(J~=Y|Ec z3UGpt)B8oU`zj-Z?bEK-VaKY>52{w6{pTIim;O``nWhWu=ye3MN7v5A73>l#XxfA45MSi+}atroDv67_(#^gQvt831@c4+Sy@O!$1(y!>Zn9hY7Thh z4}d&>1hE7U$LuW#sC=)E@OT>1O`LGO@?suNRMg3vJpRhxrKlWm_HpCU-W-B81gY9u zz0cS8VWyj>$kNi-oLt`bqsP00MKQjU9_m5hB+-(8l{dYwADeRBy*WNF=i_R&UG#Uo zKacCbvGfdVfLD{z^X+MoFNe?PZTiIT`*sL$_rTnGK#aJ5pfg;qi;Fs-`K)hk>MpG} zeVANysDYp1)wS(YQ}J(2-*>q9xcT{P>!PBl}4}_yrV1dJMgZF5i$~o3*WjdTsn87Czo}6W+Xs zAyGTAQtGVGP+It9y#<@7#PI;E1ZL)1>@czz~YR4>U zU}s(yX|YK_85z^{*b&QA)jQ728HhnOBmQNIE*UY8Qr82<&ZO(;?!i#I2dwIlC(<<^ z`8*G^l%3HU$_34Nw_vZD`Hx@iT;}ur=IT)~a*$-@puX?^%E^uK!JU^NInD&faHwEz zA1HI4JwVWetRAO>2hOD7YndyfwEjQBn5O8_^v~cicl1JN*&7x;j&R|BoQS$3AX}JE zb&IV7iyDqY1D`7zmE~Bbw75XyNAArEF@wKe0G1}Id%=hO?G*=X=lVdR_BMjZp_FnS z6=>_rgddxsXx)fB2F-_l^gs@N)+bj+0LKGuE3I{{2HUVeOEZVq!>#v z@?=`VMDA}W;yHG&k>pY%A(sRQCxEL3iIoC^#K*WK5~FI9bc_5-)dU$@Hc%k{vPo9K zG(1+v1QxD{55__MEJ$}U6cA?nfriXB54S0$=uR|~JL=7U@Nt=Db1|nKDSyK8F zAlycjrid{S->NnsH<)}?GnWXuPOk=b{JnP&ZbV1H8Ag7WpzlGk`sT@hvlx?)*ovL@bXZOvttRWY7P*lC@KMnyqqvD$D2I+C>xaWay{BWRg$XpVLo zHdpGU;;;oxv(-_Syb}bZD=N3}BBzi5eJLeTV+r}d1w%DMCu*bHsJ@S>EW1?ID23iL7L=wm1YcS*u3K)wI;O?})a| zlUrqIN%^~uoYgrO>d^z?EYw?T-{)#Af4?PWH~1Q;^#Vw<3<~WJKY}iX_v?I&pR@*L z-1IqaWmccwY4Bvb2lwswG^%Ifz@NNCs+B8HKWH{7tnD}od)8koA0;kJKcVO`EfV?DOmZL2~K z%ahpZ#kS54^?dF};S4QJdt)u~KJawL&7;#~GAtEh$OMqw(}6NAASfJ&g22mDz`EI| ztl2VzT|cX?x)k7BVG5^fukT>?RBu^4`TJppOK)Da=j;PV<4;gVt5n+6bB&zzdfZ(S zbYGMm!36k7*HtB2C3*E{`)oS!IM$Cj*Zsha=};}Q4s4W>O|jkF<|)umBYrZ;7#1?k z_A9c!2(CuS6bcfXE+v}_#dr90_VPKNRwHtQo*uI+{V_YQUqLE(ikK;D97|`j>U2;; zt-VYpPn$0XmWDtsYYw zimOFpK97LZ2oittoRcmPl zquFic9t}n!VefHa^k+x~7V8?^NO{wk0JfjQx)+|=6E&E$iIb!))EBvm8bphbVDXc*_MNrI)#9JAFY+7sZ zUKOG^X(|g|zFx)hk^*g!SE;ehlv)$Xhws2j&fM2J-xe>Fj|xy(I=-i(sQPYBp? zA_Pkdt(?zgv-Lxddf-v>jSE%ugyGiogaJ{%`Dze@upEAjfA&xUx=qMtV+Mf=HZlL> z5)ajqI3d=OIRAd0|45aBhL5+*$o-50*{suJhHk|fO7(;yd*wC!u6h-a8N3}ai$Tp4 z^@x)QG5Kt=!~+X?t9;j{YHh3B`PoZnSKviaFrM3d0{5jT{$z{sQ!e&E(8OL`vXyH? z_wxCAsO+wzKEv9*cc)BB!lu1t{nPG&tz#p-0z~Grz8|2ingtA4cj8UV`=1oE1s&)m zNKcp0XP)`D>AAqu1+AP5Et}lyO7Z}sRC+{Hr2Kf3HMBT6B7_7==jS(OMIq*eJpyZE z68$X1o8)1&5CdCdWc5tLrI`-#vi_bpY>e{7Xs(9|5TS)&N5rEt2ow@dEt(v1J$*9i zoZH~8G(DFGXtE-im{SQ!*}3riv_Z*96nex8!|(Xu$Jy?9P1|_o`BR`*41)FoNGkP zzoY{rLs?*%(2hb>lYzeA5TJz+*$W6N6#{F!s2niX;SnI5RNO9HD?E-^#Pu~|e|hb@g>tnykXyPC~JG#G|p zw&ZM?3o0P+a>3|$R))!6QzjHT@;sd-V>3GwPU_rU~=%vcwVv@78DXVe>lL;xhmRd~Y4 ztUXV)X^s7P@OeC?Fs7`cw6;xbj8XRHH^bRDbde%t-2SZ-!xh*mZv-4|S`)lcIK>=6gm%eiYx2_51AaemE;8m%HQj zH0Z3BPa%(#@zB4gEFN+@0ohJO$`W*cK$F17+!&HuK7Ng`K5#OT0x-dhZtQQTKhR0( zEMCk_ZV09TvP9nsOt>h|xUKx?CF!<6QLD7ut?6@4E0F%a>KfIx!^O{o`{(0HzAmGC z?BfDXw?i{xTbm$bRm{-jV|RSp=OiBw-p_ezqF)!EAEk!-FS@yE%7Y!lDw1Nd&_r!npkj)k7=7sUA`If*|p=z&#-%mh{};$SJ4#A#&j z69hz^)Cx=;P3in>rD3>68C$DK^;D1CfvOg+B$%^QlZ~eG8r?=YwOQlLNAN zanYu8^i3~Xw}SB7(=(&b{82H>HqoBnG~XtL@Hl>2w$$W{vw3qdv- z-_QE&p5x%doQ31Hv_1|;ky5L@(!sTU>0P#RcACI{3=Nld*1i{VyS|HaN2E@wl6}dx zU($I}kw%%+U%6b;(X%PAV{@E_IypK&QM#qaLkIlj`niaTK9tTI8`_0&9pncMQ~`1ThOJfESv1R%>Aa; z+fA(MrL1EkdvvWx29eEtzfR1Bsm-9)>l<~bz6yG4EB-zAc6PwnJ<9GSA}KzA1w(CC z^_Ls2MzGK;j5(t)+7Ym>SO zFf3TX^qOt`Y(FVmPe)wKd>Y`%VY=EP_;Hl8g#GbXyd%LS$@3gn2jaBSwS^&*`EBCL zwVO$w-T+jF3M@X%w^RWUdZ4M02$Jb%fXA7qmKmXjj+TxYdF7F?mD#0(nQ}Hlp|D5_ zO??YNi*6;AV7)marQOI)bEwuqe^EIte7O)qtHp~o2btVeG`93$t+ly(mUU#ZfFh{% zhIF<)Ia(b&G9$;y)8hUD6$69Cw6#_t#r}r`T$m0Llt38Y&z&5E!>vFA#=!nW8BYpo zZCLYOcQ*qitXx$rRLB8RP}S;#kOMO;DVpPjH<@sK+_+|Bp`rOQ2QMwQoCHIDZdaRq z+of*YxQ5q|MSa`ZB@fX>-8NA}ZFZusmlJy4e7)F10iV^H(WbX&z2A~&&-BGmAL|#- z5)78w81y^~Pj`VG+-6n{!bU^exP922M!erY?30ME1H(g(apUviC&S(I4FG|vY+Gvb zp3LDkgKqVD-kGpO1%~eecBep*VYE(MFn|fq9u@C+%ASH{LxbTB%|RB|=U@&G$&Q|V zL$n!C$CZ7r)uk9YZ)bHjstr=>zD8ypZILB z{`^RNM5I6B@F{15G3rqK)I2bJFue7IGK4nz`7f#AMWV$ut)NEJCeMik;O z-9dt`)oU!ZXn$V#U5uJV5g+w2RKq*g+j&0*<>+aIOABo;j+h)_cZ#jBdXT!gLN2*j zk&0~SF&qn-(oio()#bBtTl7w<(g81y2yJrF17!Lnse_C$)Ct0Wz&b2qpVWxeXk9*O z8!!{}LdiBf`Osy`g2Px6_4bLzAzLzfhK$05Iy=H}|2^h6HfmBLo)>JWuZs(1a~AQ0 z)9{o?;=scLvtp{E-0(yh)SDp%LO9-S9$eCLb@HL5>Ta}C*aNnt?Gg|gypZ-W56Ka+ zau-5u4DK)(gU|^cO!FrK+JS;4h-`9b*sF@+3x!^TQBb) zo*CCB=mZ!WQsncmw1ndg7m4me3zl$rE?R>_CyV9^@b8yRJmncs5=9=bM!P4gJE{9; zFDn2vAb{!7HT%dYg_p9M9C3KAZ2qZ9F(0m>Wp*o}#SSuA?f7j~?d4_2 zf0Rcz|2{VQjj=D_GEOH8X4(6)EHx|JxHyQ{GQ`As35^CD`cKCH<MvpcA5sL- z4kGC~D0=On*dHVi=cID4TbpH$zeM-=nA~QNju5l0>@N`*rZBGMNs%C#(_!oTR$Vw{ z&)X_y7w#+O&}4!~jo0~+8je^LdFhP$q)SY%2u*y42(+3+?mVjzP<3d)&If)mV8d$- z=xIb16LE`L2Hjhu2G(l$IR$9-q9t*YC^2S`>s5&p2d-&==)l38bGn7>+ax7QQK3vp zEq^{3&aq4HwAG4YNe&GZylDb|4tUhgigh_2{Gaeo?6cF z*BAVc!OI4obD1$R5gp|Ei+jXSf5(oLMc2Bs*!EFD+cPxQG6z}rOuau(w~}uMODYMS z%VE3JP>@To0KU~7&E+sAU-qNz7hIUySk$R6|Dg{$O{@pimpT=gWo@Gx>f27~PDaL8 zvF{)#fk&bB;o{c2I?VtM_w9r=c3Q?3(HrWIq2z3_3j^_S%!@J#-CQxh>Yun$_{;K9 zVcRgl%c{}Q;diET4J1;5jj4q^6EdRwx-}NVjx#=Xh4jj;FEBZ~`X>@1k>k2zFlA!^ z?dWGQ^j!TX>H%t~OGG{!Aq&t=GIH-r9w9e|e6Lq0Y`-OOEvC$2^@fabMj|HM0LklpN1|^rB*CDZ zt+^?BJP|OQloigU|HGIF3alEp_N9enGyaIPYQWgB9e*jbDUPYbgYS?xGW5S~0ZE;Z zt~)d{ovh-)nrq`M1e@?|+tur6I1Qx8=WD7W`S=>Zfoq}#IHe{C9%CdohhRPtkx=V0 zj-mmKuY4sYO3^cnc_<5?Z5TX8_j7?L`rbdZIk%?xmr~nNrOj+n#t2FEad@u8Gqjad zXzE}aH-ZI&$W(}?7kIV0D*c~g^thmfH(*2t-S|$zN0e&{E$nW4*4-_CSGrSUO36#K zWC-piKLd*inK&Q+)(6{>lA7sIA2F5$(7;uRbMQ!in&e%;+nIM7iq`U0z@#0=QeOAR z)X~|xf($z7i4`?AZ#D7@pIRM)!fb$EQ_(%J2?uP|urwWachz9*Ye)nPNJI$lxg$6X zhfv5zB=kc6!9mF2(z-At(9yjfX=kd5Plg8S944+>PD8&yI>1ARB5RIzOet-dl2oJI z<0{BeX~*{q#LSDKU*gOf+uq$4ZqqvEAId!yr8sMJ)7@|Q=gMrMn4)Ji{sv=etPEjD z$Up|wP7z-$%z+%(7+3>EpmbySNR)oJ=m}ZQGm!d7pxv@?<=#PIgoy9Z;` z3S$9A++Yv0Pm)FMgFsAxI-?DmuKX_-#R7G4T2Dt3n&v206skRaf72lu^XF9hbMAK9 z?VR3g-17hfY@3Llrvz?^E;bNoer-^5J2*9-Z#L1ipkoHLd%(w#;Kur<4knN&_%$vn ziMp)4LcIa{(c~U$jA31CF--bLH>B+`wKZ%fc4pB6B-ikqg6qm`$K_~ZFJZBEPJA>0 zRyFx7Rqb3EDG!^J*3DSOF3MV zk0EFL`+$e7rlVu<688kW_CcACsEABu0)!F}9rO?=wUNsmOE3E--ars-+(@BbC(6RR zOqBT}>Jc?DbMv>c@r*P{K`((cWiOS%G0uMnUZxw&x@GyM`a8!;w;1cCdlL7muH^g0 zIM;Dq+F%W)A5l-xs$(+?+_HzB%e0Ic;pM1HII$<{O-c`JA~r*{;U_5E#mB6# z_utlt_q(q}Q!nn0{|Cdj4+pu3g3n>(1puHzbo zMpuiAFrqtIz+=OmLiL+(>^~A0Ixq^% z|DNVBk2LL7RGM9>ufAUHPZ8dyrc8+`R7hAdlpU8u73=c@!c^s@{yk7mcN5Kj1QJ$Y zc(#&XQh-E`ns7X7J$|u#S#>#IO2YA0cu-h3o?bNx*Ksb&CzwvpZ2g239 za%sCBWLL&yWi>bcvNox;B_`q%?)7IWxS8kL@>#sLam_}3@WRj==ifm=cK zaNoSm{#@R?I)W58h3OA$$d`346cu*&!&7r_Pu8&F@PlaH$P1`vQqWj_g%d3__DtTm zTst<;-w1>E;Zde_tsQ0)}2#j8|=ovm&TL7FC^B!lYfqSF2GKC89+;mp@4RKzv zBk~!ETU0&k0Y3t9*Kq1uSX)05tl<4Xs-z~GQD9B`X3>+x!qN{VCB=<2=nGNE)mDnFqi9&~W6s{3K`G?zC`anDf z;!sLYvYa#If*?BLX4tL*VasL|aE*YAG)^GExuv6x_K& zc$=LE@-%)!hLs0|KjKn*zpCbrBKj89LP4;$*%`+R)Cbs>j4ia()ZQ+gCEhb81kgSQ z>ShQ##2-KHbBgy2;ZyH{0cS_Pj6!>uMGgs^&?v0sx3`0_EztV?Z6uT`P*GIk)`TME z32dCaExTbIqte7O-gSbPV}Ib9YHZBR4YjirT`!S-~8R`OLF{1`|YtUmM5PneyXGWgIuK{1!HY_!f676GOuo%KtgWig64sjoom-rlvvb1nIGfht>WR^(tUPtW)q2zoFjUzjh&aazd}F#Lw`4-Vf++5}#Im z`Bu@(TX`g=mvDZAz0syp>;gG2xG0Yj&$0*Ps@ioWtKaQdE6Y zg&~DeK96AP?Z^YILf~^}Mt~X(B&%F;ATka=t9s&OpRxdcyIoX2V9d{8<@nnqyH5I$ zCIu---tmJ-%3bR0$Hy>LL4cL8%;Q&REaNrI=AgwR%#&QcMH>{w&dL#SA9OvQV4;;l zt(DH*l|RRfFw9I<`?0l%x}GpnIUYmv~Ag0l5+&IsYkknM?_x$AQJH+NVdsu^jUA>a}g;^piV(;l8 z(3m}Q@6tThkJ$;I&XF8pmIiq+B#5W3GI_8+U!m*JwG(x*N@FVr^MmkeG_OQBH>KV5 z;j&ifflx^SvTrlU3-hoN6x{!wCzuD6Xt#7a9h<96?~0D@zVJ4jnf{rBw|gD3NZ+K6*yJHs=A-q+6A>=57Ktq6 zyCyO#%7x?Is{=y_tV!X)KKI8>CgpX`R}-3ywABUE4A!>9EGD7U!5*3-ml9^Pa2kIF`-pFK)l&Iih3t zUfI#QU>C8wW_a^C@jdt8$~ZlZ+U>+B>vkjBis(sZ+&s+&5xgUMlRBA);PvK2V)HpB zVulmen(Tr@(|jw2cv_6^S-7BmjiwJx*Nh;L023R$MtJ>>LzkB8w1zAT+c*NbwX&a6 z(52;S)~_f_1%fN*$BZ-piWNW;_bcNEoE)1BvqyHs*_1|Wmj_cC`<2(YQhPp`O# z_>19+5LjgUUi3=!CNPzi?f4SapZ@mN>NpUj9x2;~V^eEyDZMMyNd2)8tl=I>fP|_6 znr+EJ_pIRUd?bDx`t6q%_X$Fdvu3E@5~raoU>Po;MEFnEW$OVbKHxwQF^3nJZ;X39 z#`<$a4js?MO6pKRLr%Bc=`U;Wex=06DMtsd)%mq*<%b7uxVU@AId){L8_<#9JZD55 za_o7zP~>CD+D8+T(#~*ji|ND6Arv^mCB?3QNg5;{23K)LuKh9s7rK|Aa`!tK3gDS| zCQkgCkqemJpV7;6kkNTv#L$&-$a1xUKNQvVxsrpFR;FlwAuuG?X5RUi&&be#ul~t% zi{@&F3Y8#4g>Ky5xstDAu>ITU^dWAD&DMr@O*r~9^r%{c9p6u0S#iI;a+}1$ZV?^J zMYaiTo7Ypmv&V-ZAP<>RQ^kg4({rppV9k(Wh{NEm@{+a)*S70q%?;v^A4rsiYRT27 z$Y%aev0hp=!D9q1q_kb?^Dr>{1ExhAxHc7vU?mhgixQj;VyTnk@wmgT<5Rqc@Zn$m zhTn)*w)ob0(a*n-s2OG0#nQ_?%8ug`&*gUhHXMw?3@t#HKv(l_9J^3JxZcNul?9Lh z&yBaIb;P!>oq5jxtC1@YhjRPlGeefL-bi9-v2R(fosfN*35{wHYOD>0F%=gPV+)gg zZ@4IB`zcF>u@)gzC@CZ&B#eE(Gv*de-Jaiho|*TLIiK(MJ)d))c|Y%S&i6yhe>p88 zU;z1*DM|g)pIrww^X~9GhS2raG&^5dD5tgZFLup;abG$~LI|!?NxaMgQTHe~vgU3U zGxz!x$K9}un;*ITHse%{fUkzEZd#*H60o)J4~qw^-WR87%2b>H(?ADd-;J>c@HO!xLB^N8fn zdn`b$Z+p|5@@*f0%{TFoY>+;*suX$CscEvk#d$H}h?tXc3KVVU91`EkXXNecUu_AB zjIe4cFFn`5rPm8f=9=sX84mN(*P~TPdXYPF7JfiCIJ7xp&e`R3m7Vv|gDmiQ;NvLf zi?S->#B~)pYxqI#Gea7@#l?wrzQUHl3ef^U`BMTK3a$EgUzfjn#1EGFx*?~SyOw+1 zg|90Z#^}H(7gXFhSPweqyx~^xryI)A2MAw4pt%_4-Iw-OEvrr+nM_D5_B|^rFUZm6 z0OiJ&3d6#L%nIeu@8%o=ltK@OBkw+E5wl(OxRc;*`%nP8T4LUfEy`eF8bbyl@9!%- z-dMllXBI<0ROqaoJSsVc9Vr>ucE7OX&UH+63%>NREZnL^Z_4v2;OR?&GXg;cMg zQ2CP`AJkKGv^(X*M_{qHF1yBXMg{xj^wzR1=+eu>B{YLsSbnhquezx4Nf6)mH8%cd#o zO_47EAs*m-k>1!U{bA;_zu{S!WNW5OZ0)pg+q?e9)7`8>mk`pX_R1nmQmYExbTur~ ztjDv$-DWBxfy_|`CF0Z575u&MB;)Qf8c|P1`>YFmHswNZ>`}k z!K5wR__0ovjfFt;(7nY0&Av5Z(=gANku3tkqMT(gd+n>tOdZ#{&9b)L|QRDO=HSS!F3-dKKB%jbv0Ju zI!IXd{PY_$hky5EcbPf-iq^~rs$y2O002S=060dW^(VxRvBNgM?P(CyJ0-Tz>3v@U zq%p}ZZ(X`1COD$!%yO77^%_jkKcV*(X7*_7%f#Em*-iUZmmr?Tx%)hNb1(o|w`(JI-YGweo!#x<|Pz8d(#ci50&M zi|B@2t6cVyoqhDVHAuV}QyKKUxdRzlFs2WKUL~eIH+1>?HQzbqX`55Yn|tNrof)SN z)k$oHT7jxiypI60_I>A{_MC8HooXGA<4MG%ZVeI_qukegWG6X0%N1tvR-9wiQQ%(Y zub8~%p(uC$O1HjajzgYXPW#Mw7~edM1khvCV^0KfK!~B2*F+B9TLRL3Ud*yCcyPH6 z{kR2`PRIyN zf9UPVWk>Uz$u@&qO-tfQi8i)jp0Ok$2Cg!)cF}^FzD0Sz7}6XUW+zeBsZ9*QY4pi9 zI0SK<84#Gm0dPP}e&cfj<@hc0=e0P9;8VbL&XlfQU6RAzO~bgpqcru(CcYprR}c|g^+@~}Trwg2O|Lqw zPv!a%N$z!?z)99jPl(%DBj1r6J)pQ33HtQ7 zF3k=exro_phd#lpAG)%_`lE=sJ8S9XL=rH}q~aQ~(T|lj${pk2j&pL)NZX4 znDoSvHw1OM2YL!^7tR5pf8FjcbmWguCgM3$u%{cm>E*3x9=x1cy(A5%uM5ftzb+)b z26^Bf0L4p)K;Cu}|FWYmr8~UY&{B?dC|`oA6v6m|d8#F|01Swa;t}{4($T|=q-aUCe3VGBCdcq`5ye@*SoxtgoW7GbesK}2h_Eon0tX^ zs9G-oe3W*kt$8JHX|AKBu}pNKb?;QihcU^Meg6650}C~=6}1x8bM^bpV<3oQ z`;-sGKa6^2NRtBq0uGbD+l_uXPm}<^b{!%MC`uz+kvVDa$f+NbQVS|FhLSY$J7)U< z^}A$bg+XcLWaPHXBJIa~)Fx@<&Xjz@yJ7!YrcqNw?fUV=C8$VGRdC=^n$300s{SNRWOQkxy=3SP=(oDRA6E!<<=;+5%x>6D9U%2B zQ@^I|1YkJ1op(2Fzq@I&a~GwNXIPdp!@Gps@33T{NNHs37U?)2X?5(vev^$qj-6UK uk|R*&T}JQM5vXJ&H5b(8VmkqCej3hBC{yD-+y5W?Nl%D0Qa=Y1GVUKeMq7XY literal 0 HcmV?d00001 From 39f0811f0ae18730f61d8d7c9f4d5a347d9b7fab Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 19 Mar 2021 14:58:25 +0800 Subject: [PATCH 014/643] fix:simple unit --- app/views/projects/project_units/index.json.jbuilder | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/views/projects/project_units/index.json.jbuilder b/app/views/projects/project_units/index.json.jbuilder index e88393876..73a558a78 100644 --- a/app/views/projects/project_units/index.json.jbuilder +++ b/app/views/projects/project_units/index.json.jbuilder @@ -1,3 +1 @@ -json.array! @project_units do |unit| - json.type unit.unit_type -end \ No newline at end of file +json.array! @project_units.pluck(:unit_type) \ No newline at end of file From db2ba95e24aab3a0615bfef666e9850aaf7c470d Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 19 Mar 2021 15:05:09 +0800 Subject: [PATCH 015/643] fadd: repo edit unit --- app/views/repositories/edit.json.jbuilder | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/repositories/edit.json.jbuilder b/app/views/repositories/edit.json.jbuilder index 355823b1a..aea21f7b6 100644 --- a/app/views/repositories/edit.json.jbuilder +++ b/app/views/repositories/edit.json.jbuilder @@ -5,3 +5,4 @@ json.project_description @project.description json.project_category_id @project.project_category_id json.project_language_id @project.project_language_id json.private !@project.is_public +json.project_units @project.project_units.pluck(:unit_type) \ No newline at end of file From 553a5841212dea35cd97ca33158b1d53df9aea27 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 19 Mar 2021 17:37:25 +0800 Subject: [PATCH 016/643] fix: migrate create unit fix --- app/services/projects/migrate_service.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/projects/migrate_service.rb b/app/services/projects/migrate_service.rb index 2f7725db6..d1e14088f 100644 --- a/app/services/projects/migrate_service.rb +++ b/app/services/projects/migrate_service.rb @@ -9,6 +9,7 @@ class Projects::MigrateService < ApplicationService def call @project = Project.new(project_params) if @project.save! + ProjectUnit.init_types(@project.id) Project.update_mirror_projects_count! Repositories::MigrateService.new(user, @project, repository_params).call else From f1ed61c68733514b06e182f0d4e14f1b26423d49 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 19 Mar 2021 18:01:29 +0800 Subject: [PATCH 017/643] add: menu permission control --- app/controllers/issues_controller.rb | 1 + app/controllers/pull_requests_controller.rb | 1 + app/controllers/repositories_controller.rb | 1 + app/controllers/versions_controller.rb | 1 + 4 files changed, 4 insertions(+) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index d6ee5a56a..a3b5fe923 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -12,6 +12,7 @@ class IssuesController < ApplicationController include TagChosenHelper def index + return render_not_found unless @project.has_menu_permission("issues") @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 diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index df3e484f6..126639015 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -8,6 +8,7 @@ class PullRequestsController < ApplicationController def index + return render_not_found unless @project.has_menu_permission("pulls") # @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取 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)) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index cd07803d6..b66a53736 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -18,6 +18,7 @@ class RepositoriesController < ApplicationController # 新版项目详情 def detail + return render_not_found unless @project.has_menu_permission("code") @user = current_user @result = Repositories::DetailService.call(@owner, @repository, @user) @project_fork_id = @project.try(:forked_from_project_id) diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb index 5ec769e94..02700fdf5 100644 --- a/app/controllers/versions_controller.rb +++ b/app/controllers/versions_controller.rb @@ -5,6 +5,7 @@ class VersionsController < ApplicationController before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status] def index + return render_not_found unless @project.has_menu_permission("versions") @user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user)) order_name = params[:order_name] || "created_on" order_type = params[:order_type] || "desc" From 223755a9658160f84c65d9deed2b55cd22923f1f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 19 Mar 2021 18:36:55 +0800 Subject: [PATCH 018/643] fix: languages filter 0.0% --- app/controllers/concerns/repository/languages_percentagable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/concerns/repository/languages_percentagable.rb b/app/controllers/concerns/repository/languages_percentagable.rb index 620d93bf9..dc6abcb9c 100644 --- a/app/controllers/concerns/repository/languages_percentagable.rb +++ b/app/controllers/concerns/repository/languages_percentagable.rb @@ -14,6 +14,6 @@ module Repository::LanguagesPercentagable hash.transform_values { |v| ActionController::Base.helpers .number_to_percentage((v * 100.0 / total_byte_size), precision: 1) - } + }.select{|k,v| v != "0.0%"} end end From 0909223867e4e4b11bf05d6a76f4dc5186feec30 Mon Sep 17 00:00:00 2001 From: jasder Date: Sun, 21 Mar 2021 11:24:34 +0800 Subject: [PATCH 019/643] FIX get readme api method --- app/views/repositories/detail.json.jbuilder | 22 ++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 6980d4b25..e06ccdd85 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -1,6 +1,10 @@ json.content @project.content json.website @project.website -json.readme @result[:readme].merge(content: readme_render_decode64_content(@result[:readme]["content"], nil)) +if @result[:readme].blank? + json.readme nil! +else + json.readme @result[:readme].merge(content: readme_render_decode64_content(@result[:readme]["content"], nil)) +end json.identifier render_identifier(@project) json.name @project.name json.project_id @project.id @@ -48,7 +52,7 @@ if @result[:repo] json.private @result[:repo]['private'] end json.license_name @project.license_name -json.release_versions do +json.release_versions do json.list @result[:release].each do |release| forge_version = VersionRelease.find_by(version_gid: release["id"]) json.id forge_version&.id @@ -58,23 +62,23 @@ json.release_versions do end json.total_count @result[:release].size end -json.branches do +json.branches do json.list @result[:branch].each do |branch| json.name branch["name"] end json.total_count @result[:branch].size end -json.tags do - json.list @result[:tag].each do |tag| +json.tags do + json.list @result[:tag].each do |tag| json.name tag["name"] end - json.total_count @result[:tag].size + json.total_count @result[:tag].size end -json.contributors do - total_count = @result[:contributor].size +json.contributors do + total_count = @result[:contributor].size json.list @result[:contributor].each do |contributor| user = User.find_by(gitea_uid: contributor["id"]) - if contributor["login"] == "root" + if contributor["login"] == "root" total_count -= 1 next end From 0d8ddc34cc48a16428e3a68693114ebf5e8c7f0c Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 22 Mar 2021 09:50:24 +0800 Subject: [PATCH 020/643] FIX update Changelog --- CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aad86982..4345e60b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Changelog -## [v3.0.0](https://github.com/go-gitea/gitea/releases/tag/v1.13.1) - 2020-12-29 +## [v3.0.1](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-03-19 + +* BUGFIXES + * Fix pull reqeust模块中用户头像显示问题 + * Fix 解决issue模块中,指派用户的问题 + * Fix 解决合并请求失败的后显示message信息不正确 + * Fix 代码目录页面,readme文件提供单独的api + +* ENHANCEMENTS + * 重构项目详情页面 + +## [v3.0.0](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2020-12-29 * BUGFIXES * Fix pull reqeust的访问权限问题 (#14156) (#14171) From 8c2a543e612c9137b0272c8b830856cfbf6e2853 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 22 Mar 2021 11:16:35 +0800 Subject: [PATCH 021/643] fix: project code change to default --- app/controllers/repositories_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index b66a53736..cd07803d6 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -18,7 +18,6 @@ class RepositoriesController < ApplicationController # 新版项目详情 def detail - return render_not_found unless @project.has_menu_permission("code") @user = current_user @result = Repositories::DetailService.call(@owner, @repository, @user) @project_fork_id = @project.try(:forked_from_project_id) From 8bbfea20791b6a1ffe3a4b47a4e542cd11120389 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 22 Mar 2021 11:18:04 +0800 Subject: [PATCH 022/643] fix --- app/controllers/projects_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 573dbba80..1fd858be5 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -11,7 +11,7 @@ class ProjectsController < ApplicationController menu = [] menu.append(menu_hash_by_name("home")) - menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code") + menu.append(menu_hash_by_name("code")) menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues") menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") @@ -26,7 +26,7 @@ class ProjectsController < ApplicationController scope = Projects::ListQuery.call(params) # @projects = kaminari_paginate(scope) - @projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner) + @projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units) category_id = params[:category_id] @total_count = From 5c864acb64d038eec1c6312927a458cbee41b23b Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 22 Mar 2021 15:50:08 +0800 Subject: [PATCH 023/643] fix: create repo not use website --- app/services/projects/create_service.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index c6e5b213b..f014b8d7f 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -46,7 +46,6 @@ class Projects::CreateService < ApplicationService { hidden: !repo_is_public, user_id: params[:user_id], - website: params[:website], identifier: params[:repository_name] } end From aa23762b2fa362581f074c8b5703cce4b48cee2b Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 22 Mar 2021 17:58:15 +0800 Subject: [PATCH 024/643] FIX update setting api for nav bar url --- app/controllers/settings_controller.rb | 7 ++++++- app/models/site.rb | 23 +++++++++++++++++++++++ app/views/settings/show.json.jbuilder | 7 +++++++ config/routes.rb | 3 +-- db/migrate/20210322084619_create_sites.rb | 12 ++++++++++++ 5 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 app/models/site.rb create mode 100644 db/migrate/20210322084619_create_sites.rb diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index bb031c7b6..7e5e94d5e 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -1,6 +1,11 @@ class SettingsController < ApplicationController def show - @old_projects_url = nil + @old_projects_url = nil @old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged? + + @add = Site.add + @personal = User.current.logged? ? Site.personal : [] + + # @sites = Site.group(:site_type).select(:name, :url, :key) end end diff --git a/app/models/site.rb b/app/models/site.rb new file mode 100644 index 000000000..0ed8d8020 --- /dev/null +++ b/app/models/site.rb @@ -0,0 +1,23 @@ +# == Schema Information +# +# Table name: sites +# +# id :integer not null, primary key +# name :string(255) +# url :string(255) +# key :string(255) +# site_type :integer +# created_at :datetime not null +# updated_at :datetime not null +# + +class Site < ApplicationRecord + # add: 添加类链接 + # personal: 个人名下类链接, + # common: 普通链接 + enum site_type: { add: 0, personal: 1, common: 2 } + + def self.set_default + + end +end diff --git a/app/views/settings/show.json.jbuilder b/app/views/settings/show.json.jbuilder index 7de12345d..4202283bd 100644 --- a/app/views/settings/show.json.jbuilder +++ b/app/views/settings/show.json.jbuilder @@ -47,5 +47,12 @@ json.setting do json.new_course default_course_links json.old_projects_url @old_projects_url + json.add do + json.array! @add, :name, :url, :key + end + + json.personal do + json.array! @personal, :name, :url, :key + end end diff --git a/config/routes.rb b/config/routes.rb index 9e9e3d7a8..daef12bb4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -23,7 +23,6 @@ Rails.application.routes.draw do resources :edu_settings - resources :edu_settings scope '/api' do namespace :ci do resources :languages, only: [:index, :show] do @@ -379,7 +378,7 @@ Rails.application.routes.draw do end end - resource :repositories, path: '/', only: [:show, :create, :edit] do + resource :repositories, path: '/', only: [:show, :create, :edit] do member do get :files get :detail diff --git a/db/migrate/20210322084619_create_sites.rb b/db/migrate/20210322084619_create_sites.rb new file mode 100644 index 000000000..e05784ec9 --- /dev/null +++ b/db/migrate/20210322084619_create_sites.rb @@ -0,0 +1,12 @@ +class CreateSites < ActiveRecord::Migration[5.2] + def change + create_table :sites do |t| + t.string :name, comment: "中文名称" + t.string :url, comment: "具体链接" + t.string :key, comment: "标识" + t.integer :site_type, comment: "分类,按照分类编排链接" + + t.timestamps + end + end +end From 18ae3853d76fbb36641f84350b570ed7a5e4961a Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 23 Mar 2021 11:42:22 +0800 Subject: [PATCH 025/643] FIX update setting api --- app/controllers/settings_controller.rb | 15 +++++++++++++-- app/views/settings/show.json.jbuilder | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 7e5e94d5e..4f4122c00 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -4,8 +4,19 @@ class SettingsController < ApplicationController @old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged? @add = Site.add - @personal = User.current.logged? ? Site.personal : [] - + @personal = + if User.current.logged? + arr =[] + Site.personal.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| + hash = {} + site.each {|k, v| + hash.merge!("#{k}": v.to_s.include?("current_user") ? v.split('current_user').join(current_user&.login) : v) + } + arr << hash + end + else + [] + end # @sites = Site.group(:site_type).select(:name, :url, :key) end end diff --git a/app/views/settings/show.json.jbuilder b/app/views/settings/show.json.jbuilder index 4202283bd..fb03c6377 100644 --- a/app/views/settings/show.json.jbuilder +++ b/app/views/settings/show.json.jbuilder @@ -50,9 +50,9 @@ json.setting do json.add do json.array! @add, :name, :url, :key end - + json.personal do - json.array! @personal, :name, :url, :key + json.array! @personal end end From 815b3644281081db3238cf201a32938586a6cce3 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 23 Mar 2021 15:42:56 +0800 Subject: [PATCH 026/643] ADD common url with setting api --- app/controllers/settings_controller.rb | 12 ++++++++++-- app/views/settings/show.json.jbuilder | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 4f4122c00..a4eb551d9 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -3,7 +3,7 @@ class SettingsController < ApplicationController @old_projects_url = nil @old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged? - @add = Site.add + @add = Site.add.select(:id, :name, :url, :key) @personal = if User.current.logged? arr =[] @@ -17,6 +17,14 @@ class SettingsController < ApplicationController else [] end - # @sites = Site.group(:site_type).select(:name, :url, :key) + + @common = [] + Site.common.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| + hash = {} + site.each {|k, v| + hash.merge!("#{k}": v.to_s.include?("current_user") ? v.split('current_user').join(current_user&.login) : v) + } + @common << hash + end end end diff --git a/app/views/settings/show.json.jbuilder b/app/views/settings/show.json.jbuilder index fb03c6377..697e1dd5d 100644 --- a/app/views/settings/show.json.jbuilder +++ b/app/views/settings/show.json.jbuilder @@ -47,6 +47,7 @@ json.setting do json.new_course default_course_links json.old_projects_url @old_projects_url + json.add do json.array! @add, :name, :url, :key end @@ -55,4 +56,7 @@ json.setting do json.array! @personal end + json.common do + json.array! @common + end end From 8b656fd4093386f12ba42938314c624d5c993762 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 23 Mar 2021 15:47:01 +0800 Subject: [PATCH 027/643] FIX bug --- app/controllers/settings_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index a4eb551d9..34f951cea 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -22,6 +22,7 @@ class SettingsController < ApplicationController Site.common.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| hash = {} site.each {|k, v| + next if v.to_s.include?("current_user") && !User.current_user.logged? hash.merge!("#{k}": v.to_s.include?("current_user") ? v.split('current_user').join(current_user&.login) : v) } @common << hash From 0f67944911dc0076d7884cbf7f8f4337e161ebe0 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 23 Mar 2021 15:58:12 +0800 Subject: [PATCH 028/643] FIX code bug --- app/controllers/settings_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 34f951cea..65a5786d1 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -20,9 +20,9 @@ class SettingsController < ApplicationController @common = [] Site.common.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| + next if site["url"].to_s.include?("current_user") && !User.current.logged? hash = {} site.each {|k, v| - next if v.to_s.include?("current_user") && !User.current_user.logged? hash.merge!("#{k}": v.to_s.include?("current_user") ? v.split('current_user').join(current_user&.login) : v) } @common << hash From 15f9004f63989acc247b238d09804e20b94d72b7 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 24 Mar 2021 10:50:47 +0800 Subject: [PATCH 029/643] add: edit permit website --- app/views/repositories/edit.json.jbuilder | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/repositories/edit.json.jbuilder b/app/views/repositories/edit.json.jbuilder index aea21f7b6..328bc4900 100644 --- a/app/views/repositories/edit.json.jbuilder +++ b/app/views/repositories/edit.json.jbuilder @@ -5,4 +5,5 @@ json.project_description @project.description json.project_category_id @project.project_category_id json.project_language_id @project.project_language_id json.private !@project.is_public +json.website @project.website json.project_units @project.project_units.pluck(:unit_type) \ No newline at end of file From 9ee42e805bf6f1e99420c21e231c3877c5878c7b Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 24 Mar 2021 13:50:17 +0800 Subject: [PATCH 030/643] fix: update error --- app/controllers/projects_controller.rb | 11 ++++++----- app/views/projects/update.json.jbuilder | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 1fd858be5..c073d5846 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -85,18 +85,19 @@ class ProjectsController < ApplicationController def update ActiveRecord::Base.transaction do # Projects::CreateForm.new(project_params).validate! - private = params[:private] + private = params[:private] || false + + new_project_params = project_params.except(:private).merge(is_public: !private) + @project.update_attributes!(new_project_params) gitea_params = { private: private, - default_branch: params[:default_branch], - website: params[:website] + default_branch: @project.default_branch, + website: @project.website } if [true, false].include? private - new_project_params = project_params.except(:private).merge(is_public: !private) Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params) @project.repository.update_column(:hidden, private) end - @project.update_attributes!(new_project_params) end rescue Exception => e uid_logger_error(e.message) diff --git a/app/views/projects/update.json.jbuilder b/app/views/projects/update.json.jbuilder index 20fa3e07d..ef09d5d85 100644 --- a/app/views/projects/update.json.jbuilder +++ b/app/views/projects/update.json.jbuilder @@ -5,3 +5,4 @@ json.description @project.description json.project_category_id @project.project_category_id json.project_language_id @project.project_language_id json.is_public @project.is_public +json.website @project.website \ No newline at end of file From 66608b3baac32d05e7584d84067210c70f06c8b6 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 24 Mar 2021 13:59:24 +0800 Subject: [PATCH 031/643] add: detail project description --- app/views/repositories/detail.json.jbuilder | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index e06ccdd85..366a2f408 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -7,6 +7,7 @@ else end json.identifier render_identifier(@project) json.name @project.name +json.description @project.description json.project_id @project.id json.repo_id @repository.id json.issues_count @project.issues_count.to_i - @project.pull_requests_count.to_i From 70c7b1da0c51fd8e1ae188390d1e4446675a8166 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 24 Mar 2021 15:42:57 +0800 Subject: [PATCH 032/643] add: auto counter rake --- lib/tasks/sync_count_cache.rake | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/tasks/sync_count_cache.rake diff --git a/lib/tasks/sync_count_cache.rake b/lib/tasks/sync_count_cache.rake new file mode 100644 index 000000000..b32496b95 --- /dev/null +++ b/lib/tasks/sync_count_cache.rake @@ -0,0 +1,15 @@ +namespace :sync_count_cache do + desc "更新项目自动计数字段" + task projects: :environment do + Project.includes(:praise_treads, :fork_users, :issues, :watchers, :issues, :pull_requests, :versions, :issue_tags).find_each do |project| + project.update(forked_count: project.fork_users.size, closed_issues_count: project.issues.where(status_id: 5).size) + + Project.reset_counters(project.id, :praise_treads) + Project.reset_counters(project.id, :watchers) + Project.reset_counters(project.id, :issues) + Project.reset_counters(project.id, :pull_requests) + Project.reset_counters(project.id, :versions) + Project.reset_counters(project.id, :issue_tags) + end + end +end \ No newline at end of file From 7f28f07665f943a9ae574b7f3c879850c85ca43d Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 25 Mar 2021 11:31:15 +0800 Subject: [PATCH 033/643] fix: readme error --- app/helpers/repositories_helper.rb | 52 +++++++++++---------- app/views/repositories/detail.json.jbuilder | 2 +- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 07646c07a..2889b6fc8 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -33,34 +33,38 @@ module RepositoriesHelper def readme_render_decode64_content(str, path) return nil if str.blank? - content = Base64.decode64(str).force_encoding('UTF-8') + begin + content = Base64.decode64(str).force_encoding('UTF-8') - c_regex = /\!\[.*?\]\((.*?)\)/ - src_regex = /src=\"(.*?)\"/ - ss = content.to_s.scan(c_regex) - ss_src = content.to_s.scan(src_regex) - total_images = ss + ss_src - if total_images.length > 0 - total_images.each do |s| - image_title = /\"(.*?)\"/ - r_content = s[0] - remove_title = r_content.to_s.scan(image_title) - if remove_title.length > 0 - r_content = r_content.gsub(/#{remove_title[0]}/, "").strip + c_regex = /\!\[.*?\]\((.*?)\)/ + src_regex = /src=\"(.*?)\"/ + ss = content.to_s.scan(c_regex) + ss_src = content.to_s.scan(src_regex) + total_images = ss + ss_src + if total_images.length > 0 + total_images.each do |s| + image_title = /\"(.*?)\"/ + r_content = s[0] + remove_title = r_content.to_s.scan(image_title) + if remove_title.length > 0 + r_content = r_content.gsub(/#{remove_title[0]}/, "").strip + end + if r_content.include?("?") + new_r_content = r_content + "&raw=true" + else + new_r_content = r_content + "?raw=true" + end + unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:") + new_r_content = "#{path}" + new_r_content + end + content = content.gsub(/#{r_content}/, new_r_content) end - if r_content.include?("?") - new_r_content = r_content + "&raw=true" - else - new_r_content = r_content + "?raw=true" - end - unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:") - new_r_content = "#{path}" + new_r_content - end - content = content.gsub(/#{r_content}/, new_r_content) end + + return content + rescue + return str end - - return content end # unix_time values for example: 1604382982 diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 366a2f408..58bc9abce 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -1,7 +1,7 @@ json.content @project.content json.website @project.website if @result[:readme].blank? - json.readme nil! + json.readme nil else json.readme @result[:readme].merge(content: readme_render_decode64_content(@result[:readme]["content"], nil)) end From ad4617288d931c374d0dc0c0e73b21b216c2b439 Mon Sep 17 00:00:00 2001 From: jasder Date: Sat, 27 Mar 2021 23:54:14 +0800 Subject: [PATCH 034/643] FIX repositories detail api bug --- app/controllers/repositories_controller.rb | 8 +++--- app/services/repositories/detail_service.rb | 32 +++++++++++---------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index cd07803d6..f4dd3c8f0 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -17,15 +17,15 @@ class RepositoriesController < ApplicationController end # 新版项目详情 - def detail - @user = current_user + def detail + @user = current_user @result = Repositories::DetailService.call(@owner, @repository, @user) @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) tip_exception(e.message) end @@ -210,7 +210,7 @@ class RepositoriesController < ApplicationController end def get_ref - @ref = params[:ref] || @project.default_branch + @ref = params[:ref] || @project&.default_branch end def get_latest_commit diff --git a/app/services/repositories/detail_service.rb b/app/services/repositories/detail_service.rb index 58b286ec5..b4b2b9d87 100644 --- a/app/services/repositories/detail_service.rb +++ b/app/services/repositories/detail_service.rb @@ -1,14 +1,14 @@ -class Repositories::DetailService < ApplicationService +class Repositories::DetailService < ApplicationService include Repository::LanguagesPercentagable - attr_reader :owner, :repo, :user + attr_reader :owner, :repo, :user def initialize(owner, repo, user) - @owner = owner - @repo = repo - @user = user + @owner = owner + @repo = repo + @user = user end - def call - if @repo.project.educoder? + def call + if @repo.project.educoder? return { repo: {}, release: [], @@ -31,7 +31,7 @@ class Repositories::DetailService < ApplicationService end end - private + private def repo_suitable Gitea::Repository::GetService.call(@owner, @repo.identifier) end @@ -41,24 +41,26 @@ class Repositories::DetailService < ApplicationService end def branch_suitable - Gitea::Repository::Branches::ListService.call(@owner, @repo.identifier) + branches = Gitea::Repository::Branches::ListService.call(@owner, @repo.identifier) + branches.is_a?(Hash) && branches[:status] == :error ? [] : branches end def tag_suitable - Gitea::Repository::Tags::ListService.call(@owner&.gitea_token, @owner.login, @repo.identifier) + tags = Gitea::Repository::Tags::ListService.call(@owner&.gitea_token, @owner.login, @repo.identifier) + tags.is_a?(Hash) && tags[:status] == -1 ? [] : tags end - - def contributor_suitable + + def contributor_suitable Gitea::Repository::Contributors::GetService.call(@owner, @repo.identifier) end - def language_suitable + def language_suitable result = Gitea::Repository::Languages::ListService.call(@owner.login, @repo.identifier, @user&.gitea_token) result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil end - def readme_suitable + def readme_suitable result = Gitea::Repository::Readme::GetService.call(@owner.login, @repo.identifier, @repo.default_branch, @owner.gitea_token) result[:status] === :success ? result[:body] : nil end -end \ No newline at end of file +end From 63d91919ae476e8590abffcfb056a2176d4e0e4f Mon Sep 17 00:00:00 2001 From: jasder Date: Sun, 28 Mar 2021 19:44:23 +0800 Subject: [PATCH 035/643] FIX repo detail api bug --- app/services/repositories/detail_service.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/services/repositories/detail_service.rb b/app/services/repositories/detail_service.rb index b4b2b9d87..39fa57412 100644 --- a/app/services/repositories/detail_service.rb +++ b/app/services/repositories/detail_service.rb @@ -37,7 +37,8 @@ class Repositories::DetailService < ApplicationService end def release_suitable - Gitea::Versions::ListService.call(@owner.gitea_token, @owner.try(:login), @repo.try(:identifier)) + releases = Gitea::Versions::ListService.call(@owner.gitea_token, @owner.try(:login), @repo.try(:identifier)) + releases.is_a?(Hash) && releases[:status] == -1 ? [] : releases end def branch_suitable @@ -51,7 +52,8 @@ class Repositories::DetailService < ApplicationService end def contributor_suitable - Gitea::Repository::Contributors::GetService.call(@owner, @repo.identifier) + contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repo.identifier) + contributors.is_a?(Hash) && contributors.key?(:status) ? [] : contributors end def language_suitable From 0211d6152e362a08fb6fdc4926ff064d076a4052 Mon Sep 17 00:00:00 2001 From: jasder Date: Sun, 28 Mar 2021 19:56:11 +0800 Subject: [PATCH 036/643] fix conflict --- app/controllers/projects_controller.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index c073d5846..93b6dc3bd 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -11,14 +11,14 @@ class ProjectsController < ApplicationController menu = [] menu.append(menu_hash_by_name("home")) - menu.append(menu_hash_by_name("code")) + menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code") menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues") menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") menu.append(menu_hash_by_name("activity")) menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.owner?(current_user) - + render json: menu end @@ -59,7 +59,10 @@ class ProjectsController < ApplicationController end def branches - @branches = @project.forge? ? Gitea::Repository::Branches::ListService.new(@owner, @project.identifier).call : [] + return @branches = [] unless @project.forge? + + result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier) + @branches = result.is_a?(Hash) && result.key?(:status) ? [] : result end def group_type_list @@ -86,7 +89,7 @@ class ProjectsController < ApplicationController ActiveRecord::Base.transaction do # Projects::CreateForm.new(project_params).validate! private = params[:private] || false - + new_project_params = project_params.except(:private).merge(is_public: !private) @project.update_attributes!(new_project_params) gitea_params = { From c4560ebb664d4fbb8cfe9210b6d66003e2295776 Mon Sep 17 00:00:00 2001 From: jasder Date: Sun, 28 Mar 2021 20:05:13 +0800 Subject: [PATCH 037/643] FIX tags api bug --- app/controllers/repositories_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index f4dd3c8f0..10b352ae6 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -103,7 +103,9 @@ class RepositoriesController < ApplicationController end def tags - @tags = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}) + result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}) + + @tags = result.is_a?(Hash) && result.key?(:status) ? [] : result end def contributors From 9195d43a3454cd0029f0620ce45dffcc671a0e95 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 30 Mar 2021 15:15:17 +0800 Subject: [PATCH 038/643] Update readme and deply doc --- README.md | 53 +++++++++++++++++++++++++++++++++++++++-------------- deploy.md | 13 +++++++++---- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index de1f91bac..a05721591 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,32 @@ Trustie (确实)是一个以大众化协同开发、开放式资源共享、 ## 部署 -### 1. 安装依赖包 +### Depends Versions -```bash -bundle install +* Ruby 2.4.5 + +* Rails ~> 5.2 + +* MySql ~> 5.6 + +* Redis 5+ + +* NodeJS > 13.0.0 + +### Steps + +#### 1. 克隆稳定版本 +``` +git clone -b standalone https://git.trustie.net/jasder/forgeplus.git ``` -### 2. 配置初始化文件 +#### 2. 安装依赖包 + +```bash +cd forgeplus && bundle install +``` + +#### 3. 配置初始化文件 进入项目根目录执行一下命令: ```bash @@ -27,10 +46,10 @@ touch config/redis.yml touch config/elasticsearch.yml ``` -### 3. 配置gitea服务(可选) +#### 3. 配置gitea服务(可选) **如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/** -**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary +**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary** #### 配置gitea服务步骤 1. 部署gitea服务,并注册root账户 @@ -44,45 +63,51 @@ gitea: base_url: '/api/v1' ``` -### 4. 安装redis环境 +#### 4. 安装redis环境 **请自行搜索各平台如何安装部署redis环境** -### 5. 创建数据库 +#### 5. 创建数据库 ```bash rails db:create ``` -### 6. 导入数据表结构 +#### 6. 导入数据表结构 ```bash bundle exec rake sync_table_structure:import_csv ``` -### 7. 执行migrate迁移文件 +#### 7. 执行migrate迁移文件 **开发环境为development, 生成环境为production** ```bash rails db:migrate RAILS_ENV=development ``` -### 8. 启动redis(此处已mac系统为例) +#### 8. clone前端代码 +**将前端代码克隆到public/react目录下,目录结构应该是: public/react/build** +```bash +git clone -b standalone https://git.trustie.net/jasder/build.git +``` + +#### 9. 启动redis(此处已mac系统为例) ```bash redis-server& ``` -### 9. 启动sidekiq +#### 10. 启动sidekiq **开发环境为development, 生成环境为production** ```bash bundle exec sidekiq -C config/sidekiq.yml -e production -d ``` -### 10. 启动rails服务 +#### 11. 启动rails服务 ```bash rails s ``` -### 11. 浏览器访问 +#### 12. 浏览器访问 在浏览器中输入如下地址访问: ```bash http://localhost:3000/ diff --git a/deploy.md b/deploy.md index 12faea24e..fe4cd80f7 100644 --- a/deploy.md +++ b/deploy.md @@ -16,13 +16,18 @@ ## Steps -### 1. 安装依赖包 +### 1. 克隆稳定版本仓库 +``` +git clone -b standalone https://git.trustie.net/jasder/forgeplus.git +``` + +### 2. 安装依赖包 ```bash bundle install ``` -### 2. 配置初始化文件 +### 3. 配置初始化文件 进入项目根目录执行一下命令: ```bash @@ -74,7 +79,7 @@ rails db:migrate RAILS_ENV=development ### 8. clone前端代码 **将前端代码克隆到public/react目录下,目录结构应该是: public/react/build** ```bash -git clone -b dev_trustie https://git.trustie.net/jasder/build.git +git clone -b standalone https://git.trustie.net/jasder/build.git ``` ### 9. 启动redis(此处已mac系统为例) @@ -88,7 +93,7 @@ redis-server& bundle exec sidekiq -C config/sidekiq.yml -e production -d ``` -### 1`. 启动rails服务 +### 11. 启动rails服务 ```bash rails s ``` From d7a459bad2e3ffa2c8c4243bb355543a5e6bb43f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 30 Mar 2021 16:33:21 +0800 Subject: [PATCH 039/643] add: dir md --- dir.md | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 dir.md diff --git a/dir.md b/dir.md new file mode 100644 index 000000000..a4443ded3 --- /dev/null +++ b/dir.md @@ -0,0 +1,135 @@ +forgeplus +├── app(应用目录) +│   ├── assets(应用静态资源目录) +│   ├── channels(actioncable的频道目录) +│   │   └── application_cable(父类) +│   ├── constraint +│   ├── controllers(应用控制器目录) +│   │   ├── admins(后台管理控制器) +│   │   ├── callbacks +│   │   ├── ci(工作流相关控制器) +│   │   ├── concerns(可反复使用的抽象方法) +│   │   │   ├── admins(对应后台管理模块) +│   │   │   ├── base(父类) +│   │   │   ├── ci(对应工作流模块) +│   │   │   └── repository(对应仓库模块) +│   │   ├── oauth(oauth验证控制器) +│   │   ├── organizations(组织模块控制器) +│   │   ├── projects(项目模块控制器) +│   │   └── users(用户模块控制器) +│   ├── decorators +│   ├── docs(api文档插件) +│   ├── forms(表单验证) +│   │   ├── ci(工作流模块) +│   │   ├── contents(仓库文件模块) +│   │   ├── gitea(gitea模块) +│   │   │   └── user(gitea用户模块) +│   │   ├── project_packages(竞标模块) +│   │   ├── projects(项目模块) +│   │   ├── protected_branches(保护分支模块) +│   │   ├── repositories(仓库模块) +│   │   ├── users(用户模块) +│   │   └── validate(公共模块) +│   ├── helpers(一些控制器帮助方法) +│   ├── imports(导入文件处理) +│   ├── interactors(流程处理器,和service类似,比如注册,创建项目) +│   ├── jobs(异步任务) +│   ├── libs(应用扩展目录) +│   │   ├── ci(工作流模块) +│   │   │   └── drone +│   │   ├── gitea +│   │   ├── limit_forbid_control +│   │   ├── omniauth +│   │   │   └── strategies +│   │   ├── trustie +│   │   ├── util +│   │   ├── wechat +│   │   └── wechat_oauth +│   ├── mailers(用来存放实现发送邮件功能的文件) +│   ├── models(模型目录) +│   ├── queries(模型查询的封装) +│   │   ├── admins(后台管理模块) +│   │   ├── ci(工作流模块) +│   │   ├── projects(项目模块) +│   │   ├── statistic(统计模块) +│   │   └── users(用户模块) +│   ├── services(业务逻辑的封装) +│   │   ├── admins(后台管理模块) +│   │   ├── branches(仓库分支模块) +│   │   ├── concerns(可反复使用的抽象方法) +│   │   ├── educoder(educoder仓库模块) +│   │   │   └── repository(仓库) +│   │   │   ├── commits(提交) +│   │   │   └── entries(文件) +│   │   ├── gitea(gitea接口封装) +│   │   │   ├── activity(项目统计模块) +│   │   │   ├── chain +│   │   │   ├── hooks(webhook模块) +│   │   │   ├── labels +│   │   │   ├── oauth2 +│   │   │   ├── organization(组织模块) +│   │   │   │   ├── organization_user(组织成员) +│   │   │   │   ├── repository(组织仓库) +│   │   │   │   ├── team(组织团队) +│   │   │   │   ├── team_project(组织团队项目) +│   │   │   │   └── team_user(组织团队成员) +│   │   │   ├── pull_request(合并请求模块) +│   │   │   ├── repository(仓库模块) +│   │   │   │   ├── branches(分支) +│   │   │   │   ├── commits(提交) +│   │   │   │   ├── contributors(贡献数) +│   │   │   │   ├── entries(文件) +│   │   │   │   ├── files(所有文件) +│   │   │   │   ├── languages(语言) +│   │   │   │   ├── members(仓库成员) +│   │   │   │   ├── protected_branches(分支保护) +│   │   │   │   ├── readme +│   │   │   │   └── tags(标签) +│   │   │   ├── user(用户) +│   │   │   └── versions(发行版) +│   │   ├── issues(易修) +│   │   ├── libraries +│   │   ├── oauth +│   │   ├── organizations(组织) +│   │   │   └── teams(组织团队) +│   │   ├── private_messages +│   │   ├── project_packages(项目竞标) +│   │   ├── projects(项目) +│   │   ├── protected_branches(分支保护) +│   │   ├── pull_requests(合并请求) +│   │   ├── repositories(仓库) +│   │   └── users(用户) +│   ├── tasks(可执行任务目录) +│   └── views(控制器对应视图文件目录) +├── bin(存放运行程序的 rails 脚本,以及其他用来部署或运行程序的脚本) +├── cable(actioncable配置目录) +├── config(配置的文件目录) +│   ├── admins(后台管理配置) +│   ├── environments(rails程序的不同运行环境的配置) +│   ├── harmonious_dictionary +│   ├── initializers(加载完gem后会自动加载此目录) +│   └── locales(i18n语言设置目录) +├── db(存放当前数据库的模式,以及数据库迁移文件) +│   └── migrate(用来存放数据库的迁移文件) +├── lib(程序的扩展模块) +│   ├── assets(通常是放置我们使用的插件中用到的assets) +│   ├── educoder +│   └── tasks(可执行任务目录) +├── log(日志目录) +├── public(唯一对外开放的文件夹,其他人可以直接访问这个目录中的东西) +│   ├── assets(编译好的静态资源目录) +│   ├── docs(api文档生成目录) +│   ├── echart(图表目录) +│   ├── editormd(富文本编辑器静态资源目录) +│   ├── fonts(字体目录) +│   ├── images(图片目录) +│   ├── javascripts(脚本目录) +│   ├── options(仓库许可证、gitignore、readme文件目录) +│   ├── react +│   │   └── build(前端编译好的文件目录) +│   └── stylesheets(层叠样式表目录) +├── spec(spec测试目录) +├── test(用于存放单元测试、功能测试及整合测试文件等测试文件) +├── tmp(临时文件,例如缓存,PID,会话文件) +├── vendor(存放第三方代码。经常用来放第三方 gem) +├──   └── assets(通常是放置一些我们从别的地方借用的assets) \ No newline at end of file From d0a65775aaf2b8828bf00840bec8ccda6753bdd3 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 30 Mar 2021 16:34:12 +0800 Subject: [PATCH 040/643] fix: not show commiter avatar --- app/helpers/repositories_helper.rb | 2 +- app/views/repositories/_author.json.jbuilder | 1 + app/views/repositories/_commit.json.jbuilder | 4 ++-- app/views/repositories/_commit_author.json.jbuilder | 5 ++++- app/views/repositories/commits.json.jbuilder | 9 ++++++++- app/views/repositories/detail.json.jbuilder | 4 +++- 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 2889b6fc8..a6426083e 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -28,7 +28,7 @@ module RepositoriesHelper def render_commit_author(author_json) return nil if author_json.blank? - find_user_by_login author_json['login'] + find_user_by_login author_json['name'] end def readme_render_decode64_content(str, path) diff --git a/app/views/repositories/_author.json.jbuilder b/app/views/repositories/_author.json.jbuilder index 1dbcc4ebc..e37a50e44 100644 --- a/app/views/repositories/_author.json.jbuilder +++ b/app/views/repositories/_author.json.jbuilder @@ -1,5 +1,6 @@ json.author do if @project.forge? + json.id user.id json.login user.login json.type user&.type json.name user.real_name diff --git a/app/views/repositories/_commit.json.jbuilder b/app/views/repositories/_commit.json.jbuilder index 079473b3d..95cb03412 100644 --- a/app/views/repositories/_commit.json.jbuilder +++ b/app/views/repositories/_commit.json.jbuilder @@ -26,9 +26,9 @@ if @project.forge? end json.author do - json.partial! 'commit_author', user: render_commit_author(commit['author']) + json.partial! 'commit_author', user: render_commit_author(commit['commit']['author']), name: commit['commit']['author']['name'] end json.committer do - json.partial! 'commit_author', user: render_commit_author(commit['committer']) + json.partial! 'commit_author', user: render_commit_author(commit['commit']['committer']), name: commit['commit']['committer']['name'] end end diff --git a/app/views/repositories/_commit_author.json.jbuilder b/app/views/repositories/_commit_author.json.jbuilder index 77d9b655c..d57e7c534 100644 --- a/app/views/repositories/_commit_author.json.jbuilder +++ b/app/views/repositories/_commit_author.json.jbuilder @@ -4,5 +4,8 @@ if user json.name user.real_name json.image_url url_to_avatar(user) else - json.nil! + json.id nil + json.login name + json.name name + json.image_url File.join("avatars/User","b") end diff --git a/app/views/repositories/commits.json.jbuilder b/app/views/repositories/commits.json.jbuilder index 7cbf34c4d..82cd17133 100644 --- a/app/views/repositories/commits.json.jbuilder +++ b/app/views/repositories/commits.json.jbuilder @@ -5,6 +5,7 @@ else json.total_count @hash_commit[:total_count] json.commits do json.array! @hash_commit[:body] do |commit| + json.commit1 commit commiter = commit['committer'] if commiter.present? commit_user_id = commiter['id'] @@ -17,7 +18,13 @@ else if forge_user json.partial! 'author', user: forge_user else - json.author nil + json.author do + json.id nil + json.login commit['commit']['author']['name'] + json.type nil + json.name commit['commit']['author']['name'] + json.image_url File.join("avatars/User","b") + end end end end diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 58bc9abce..28a64e50a 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -61,7 +61,7 @@ json.release_versions do json.tag_name release["tag_name"] json.created_at format_time(release["created_at"].to_time) end - json.total_count @result[:release].size + json.total_count @repository&.version_releases.size end json.branches do json.list @result[:branch].each do |branch| @@ -93,3 +93,5 @@ json.contributors do json.total_count total_count end json.languages @result[:language] + +json.partial! 'author', locals: { user: @project.owner } From ffa2782637a619ff23a3a217bf9c4d49cb80febe Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 30 Mar 2021 16:34:31 +0800 Subject: [PATCH 041/643] fix: detail release version limit --- app/services/gitea/versions/list_service.rb | 7 ++++--- app/services/repositories/detail_service.rb | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/services/gitea/versions/list_service.rb b/app/services/gitea/versions/list_service.rb index 40db0d149..5d160fc3e 100644 --- a/app/services/gitea/versions/list_service.rb +++ b/app/services/gitea/versions/list_service.rb @@ -1,12 +1,13 @@ # Get a list of all commits from a repository class Gitea::Versions::ListService < Gitea::ClientService - attr_reader :token, :user_name, :repo + attr_reader :token, :user_name, :repo, :args # sha: SHA or branch to start listing commits from (usually 'master') - def initialize(token, user_name, repo) + def initialize(token, user_name, repo, args={}) @token = token @user_name = user_name @repo = repo + @args = args end def call @@ -16,7 +17,7 @@ class Gitea::Versions::ListService < Gitea::ClientService private def params - Hash.new.merge(token: token) + args.merge(token: token) end def url diff --git a/app/services/repositories/detail_service.rb b/app/services/repositories/detail_service.rb index 39fa57412..d8853cf45 100644 --- a/app/services/repositories/detail_service.rb +++ b/app/services/repositories/detail_service.rb @@ -37,7 +37,7 @@ class Repositories::DetailService < ApplicationService end def release_suitable - releases = Gitea::Versions::ListService.call(@owner.gitea_token, @owner.try(:login), @repo.try(:identifier)) + releases = Gitea::Versions::ListService.call(@owner.gitea_token, @owner.try(:login), @repo.try(:identifier), {page: 1, limit: 1}) releases.is_a?(Hash) && releases[:status] == -1 ? [] : releases end From 8952f6a9447468041c6bf35c802fd8c50655ebc0 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 30 Mar 2021 17:13:58 +0800 Subject: [PATCH 042/643] fix: menu manager allow visit --- app/controllers/projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 93b6dc3bd..34b60cd0e 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -17,7 +17,7 @@ class ProjectsController < ApplicationController menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") menu.append(menu_hash_by_name("activity")) - menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.owner?(current_user) + menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.manager?(current_user) render json: menu end From 9394d15752afa6be8e05145d654c7ba3c3c4cccc Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 30 Mar 2021 17:27:50 +0800 Subject: [PATCH 043/643] fix: menu manager allow visit --- app/controllers/projects/project_units_controller.rb | 2 +- app/controllers/projects_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/project_units_controller.rb b/app/controllers/projects/project_units_controller.rb index 90bc64a71..e21fa388f 100644 --- a/app/controllers/projects/project_units_controller.rb +++ b/app/controllers/projects/project_units_controller.rb @@ -4,7 +4,7 @@ class Projects::ProjectUnitsController < Projects::BaseController end def create - if current_user.admin? || @project.owner?(current_user) + if current_user.admin? || @project.manager?(current_user) ActiveRecord::Base.transaction do ProjectUnit.update_by_unit_types!(@project, unit_types) render_ok diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 34b60cd0e..f6ab38369 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -111,7 +111,7 @@ class ProjectsController < ApplicationController end def destroy - if current_user.admin? || @project.owner?(current_user) + if current_user.admin? || @project.manager?(current_user) ActiveRecord::Base.transaction do Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call @project.destroy! From 386952962061bdbb41ed7711a08a8070f37c9b3e Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 31 Mar 2021 09:49:05 +0800 Subject: [PATCH 044/643] Update setting api --- app/controllers/settings_controller.rb | 62 +++++++--- app/models/project.rb | 143 +++++++++++----------- app/models/site.rb | 53 +++++++- app/views/settings/show.json.jbuilder | 4 +- db/migrate/20210322084619_create_sites.rb | 2 + 5 files changed, 171 insertions(+), 93 deletions(-) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 65a5786d1..f0a436d94 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -1,31 +1,57 @@ class SettingsController < ApplicationController def show @old_projects_url = nil - @old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged? + get_add_menu + get_common_menu + get_personal_menu + end - @add = Site.add.select(:id, :name, :url, :key) - @personal = + private + def get_add_menu + @add = [] + Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| + hash = {} + site.each {|k, v| + hash.merge!("#{k}": set_site_url(k, v)) + } + @add << hash + end + end + + def get_common_menu + @common = [] + Site.common.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| + next if site["url"].to_s.include?("current_user") && !User.current.logged? + hash = {} + site.each {|k, v| + hash.merge!("#{k}": set_site_url(k, v)) + } + @common << hash + end + end + + def get_personal_menu + @personal = [] if User.current.logged? - arr =[] Site.personal.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| hash = {} site.each {|k, v| - hash.merge!("#{k}": v.to_s.include?("current_user") ? v.split('current_user').join(current_user&.login) : v) + hash.merge!("#{k}": set_site_url(k, v)) } - arr << hash + @personal << hash end - else - [] end - - @common = [] - Site.common.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| - next if site["url"].to_s.include?("current_user") && !User.current.logged? - hash = {} - site.each {|k, v| - hash.merge!("#{k}": v.to_s.include?("current_user") ? v.split('current_user').join(current_user&.login) : v) - } - @common << hash end - end + + def set_site_url(key, value) + value = + if value.to_s.include?("current_user") + split_arr = value.split('current_user') + split_arr.length > 1 ? split_arr.join(current_user&.login) : (split_arr << current_user&.login).join('') + else + value + end + + key.to_s === "url" && !value.to_s.start_with?("http") ? [request.protocol, request.host_with_port, value].join('') : value + end end diff --git a/app/models/project.rb b/app/models/project.rb index cde2f1011..828a259dc 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,74 +1,75 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(4294967295) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# license_id :integer -# ignore_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# default_branch :string(255) default("master") -# website :string(255) -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(4294967295) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# license_id :integer +# ignore_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# default_branch :string(255) default("master") +# website :string(255) +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + diff --git a/app/models/site.rb b/app/models/site.rb index 0ed8d8020..58daddf14 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -17,7 +17,56 @@ class Site < ApplicationRecord # common: 普通链接 enum site_type: { add: 0, personal: 1, common: 2 } - def self.set_default - + def self.set_default_menu + set_add_menu! + set_personal_menu! + set_common_menu! end + + private + def self.set_add_menu! + adds= [ + {name: '新建镜像项目', key: 'add_mirror_project', url: '/projects/mirror/new'}, + {name: '新建托管项目', key: 'add_common', url: '/projects/deposit/new'}, + {name: '新建组织', key: 'add_r', url: '/organize/new'}] + + adds.each { |ele| + Site.find_or_create_by(key: ele[:key]) do |site| + site.name = ele[:name] + site.url = ele[:url] + site.site_type = Site.site_types[:add] + end + } + end + + def self.set_personal_menu! + personals = [ + {name: '个人中心', key: 'my_page', url: '/users/current_user'}, + {name: '我的组织', key: 'my_organizes', url: '/users/current_user/organizes'} + ] + + personals.each { |ele| + Site.find_or_create_by(key: ele[:key]) do |site| + site.name = ele[:name] + site.url = ele[:url] + site.site_type = Site.site_types[:personal] + end + } + end + + def self.set_common_menu! + commons = [ + {name: '通知', key: 'notice', url: '/users/current_user/user_messages'}, + {name: '找回密码', key: 'lost_password', url: '/account/lost_password'}, + {name: '注册', key: 'register', url: '/login?login=false'} + ] + + commons.each { |ele| + Site.find_or_create_by(key: ele[:key]) do |site| + site.name = ele[:name] + site.url = ele[:url] + site.site_type = Site.site_types[:common] + end + } + end end diff --git a/app/views/settings/show.json.jbuilder b/app/views/settings/show.json.jbuilder index 697e1dd5d..39b152fa7 100644 --- a/app/views/settings/show.json.jbuilder +++ b/app/views/settings/show.json.jbuilder @@ -45,11 +45,11 @@ json.setting do json.main_site current_laboratory.main_site? json.new_course default_course_links - json.old_projects_url @old_projects_url json.add do - json.array! @add, :name, :url, :key + # json.array! @add, :name, :url, :key + json.array! @add end json.personal do diff --git a/db/migrate/20210322084619_create_sites.rb b/db/migrate/20210322084619_create_sites.rb index e05784ec9..9d5c58ba2 100644 --- a/db/migrate/20210322084619_create_sites.rb +++ b/db/migrate/20210322084619_create_sites.rb @@ -8,5 +8,7 @@ class CreateSites < ActiveRecord::Migration[5.2] t.timestamps end + + Site.set_default_menu end end From 62b99c517ea0583a9c41c519ba95885b1a2f5573 Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 31 Mar 2021 10:08:20 +0800 Subject: [PATCH 045/643] Update deploy doc --- README.md | 32 +++++++++++++++++++++++--------- config/database.yml.example | 3 +-- deploy.md | 34 ++++++++++++++++++++++++---------- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a05721591..d04ae98f7 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,21 @@ touch config/redis.yml touch config/elasticsearch.yml ``` -#### 3. 配置gitea服务(可选) +#### 4. 配置数据库 +数据库配置信息请查看/config/database.yml文件, +项目默认采用mysql数据库, 如需更改,请自行修改配置信息, +默认配置如下: + +```bash +default: &default + adapter: mysql2 + host: 127.0.0.1 + encoding: utf8 + username: root + password: 123456 +``` + +#### 5. 配置gitea服务(可选) **如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/** **因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary** @@ -63,46 +77,46 @@ gitea: base_url: '/api/v1' ``` -#### 4. 安装redis环境 +#### 6. 安装redis环境 **请自行搜索各平台如何安装部署redis环境** -#### 5. 创建数据库 +#### 7. 创建数据库 ```bash rails db:create ``` -#### 6. 导入数据表结构 +#### 8. 导入数据表结构 ```bash bundle exec rake sync_table_structure:import_csv ``` -#### 7. 执行migrate迁移文件 +#### 9. 执行migrate迁移文件 **开发环境为development, 生成环境为production** ```bash rails db:migrate RAILS_ENV=development ``` -#### 8. clone前端代码 +#### 10. clone前端代码 **将前端代码克隆到public/react目录下,目录结构应该是: public/react/build** ```bash git clone -b standalone https://git.trustie.net/jasder/build.git ``` -#### 9. 启动redis(此处已mac系统为例) +#### 11. 启动redis(此处已mac系统为例) ```bash redis-server& ``` -#### 10. 启动sidekiq +#### 12. 启动sidekiq **开发环境为development, 生成环境为production** ```bash bundle exec sidekiq -C config/sidekiq.yml -e production -d ``` -#### 11. 启动rails服务 +#### 13. 启动rails服务 ```bash rails s ``` diff --git a/config/database.yml.example b/config/database.yml.example index 26e752e45..dae8f8816 100644 --- a/config/database.yml.example +++ b/config/database.yml.example @@ -11,6 +11,7 @@ # default: &default adapter: mysql2 + host: 127.0.0.1 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root @@ -51,5 +52,3 @@ test: production: <<: *default database: forge_production - username: educoderplus - password: <%= ENV['EDUCODERPLUS_DATABASE_PASSWORD'] %> diff --git a/deploy.md b/deploy.md index fe4cd80f7..527625054 100644 --- a/deploy.md +++ b/deploy.md @@ -37,7 +37,21 @@ touch config/redis.yml touch config/elasticsearch.yml ``` -### 3. 配置gitea服务(可选) +### 4. 配置数据库 +数据库配置信息请查看/config/database.yml文件, +项目默认采用mysql数据库, 如需更改,请自行修改配置信息, +默认配置如下: + +```bash +default: &default + adapter: mysql2 + host: 127.0.0.1 + encoding: utf8 + username: root + password: 123456 +``` + +### 4. 配置gitea服务(可选) **如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/** **因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary** @@ -54,51 +68,51 @@ gitea: base_url: '/api/v1' ``` -### 4. 安装redis环境 +### 5. 安装redis环境 **请自行搜索各平台如何安装部署redis环境** -### 5. 创建数据库 +### 6. 创建数据库 ```bash rails db:create ``` -### 6. 导入数据表结构 +### 7. 导入数据表结构 ```bash bundle exec rake sync_table_structure:import_csv ``` -### 7. 执行migrate迁移文件 +### 8. 执行migrate迁移文件 **开发环境为development, 生成环境为production** ```bash rails db:migrate RAILS_ENV=development ``` -### 8. clone前端代码 +### 9. clone前端代码 **将前端代码克隆到public/react目录下,目录结构应该是: public/react/build** ```bash git clone -b standalone https://git.trustie.net/jasder/build.git ``` -### 9. 启动redis(此处已mac系统为例) +### 10. 启动redis(此处已mac系统为例) ```bash redis-server& ``` -### 10. 启动sidekiq +### 11. 启动sidekiq **开发环境为development, 生成环境为production** ```bash bundle exec sidekiq -C config/sidekiq.yml -e production -d ``` -### 11. 启动rails服务 +### 12. 启动rails服务 ```bash rails s ``` -### 12. 浏览器访问 +### 13. 浏览器访问 在浏览器中输入如下地址访问: ```bash http://localhost:3000/ From 9393ceb8b78aa581425d501a23494e068e78398f Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 31 Mar 2021 10:30:39 +0800 Subject: [PATCH 046/643] Update readme and deploy --- README.md | 2 +- deploy.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d04ae98f7..358e03f8a 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ default: &default #### 5. 配置gitea服务(可选) **如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/** -**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary** +**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/Trustie/gitea-binary** #### 配置gitea服务步骤 1. 部署gitea服务,并注册root账户 diff --git a/deploy.md b/deploy.md index 527625054..24b2613da 100644 --- a/deploy.md +++ b/deploy.md @@ -54,7 +54,7 @@ default: &default ### 4. 配置gitea服务(可选) **如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/** -**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary** +**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/Trustie/gitea-binary** #### 配置gitea服务步骤 1. 部署gitea服务,并注册root账户 From 7d0b05f975d161db5576525e1c9f366dafa23d6d Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 31 Mar 2021 12:43:06 +0800 Subject: [PATCH 047/643] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 358e03f8a..d3abcd100 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,9 @@ gitea: #### 7. 创建数据库 - +**开发环境为development, 生成环境为production** ```bash -rails db:create +rails db:create RAILS_ENV=development ``` #### 8. 导入数据表结构 From d2293a27780ae9643649eb02d83b52ff2e17ab13 Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 31 Mar 2021 12:44:40 +0800 Subject: [PATCH 048/643] FIX setting api bug --- app/controllers/settings_controller.rb | 34 ++++++++++++-------------- app/views/settings/show.json.jbuilder | 5 +--- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index f0a436d94..638dc4722 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -4,6 +4,8 @@ class SettingsController < ApplicationController get_add_menu get_common_menu get_personal_menu + + puts @com end private @@ -12,21 +14,17 @@ class SettingsController < ApplicationController Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| hash = {} site.each {|k, v| - hash.merge!("#{k}": set_site_url(k, v)) + hash.merge!("#{k}": get_site_url(k, v)) } @add << hash end end def get_common_menu - @common = [] - Site.common.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| + @common = {} + Site.common.select(:url, :key).to_a.map(&:serializable_hash).each do |site| next if site["url"].to_s.include?("current_user") && !User.current.logged? - hash = {} - site.each {|k, v| - hash.merge!("#{k}": set_site_url(k, v)) - } - @common << hash + @common.merge!("#{site["key"]}": reset_site_url(site['url'])) end end @@ -36,22 +34,22 @@ class SettingsController < ApplicationController Site.personal.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| hash = {} site.each {|k, v| - hash.merge!("#{k}": set_site_url(k, v)) + hash.merge!("#{k}": get_site_url(k, v)) } @personal << hash end end end - def set_site_url(key, value) - value = - if value.to_s.include?("current_user") - split_arr = value.split('current_user') - split_arr.length > 1 ? split_arr.join(current_user&.login) : (split_arr << current_user&.login).join('') - else - value - end + def get_site_url(key, value) + url = reset_site_url(value) + key.to_s === "url" && !value.to_s.start_with?("http") ? [request.protocol, request.host_with_port, value].join('') : url + end - key.to_s === "url" && !value.to_s.start_with?("http") ? [request.protocol, request.host_with_port, value].join('') : value + def reset_site_url(url) + return url unless url.to_s.include?("current_user") + + split_arr = url.split('current_user') + split_arr.length > 1 ? split_arr.join(current_user&.login) : (split_arr << current_user&.login).join('') end end diff --git a/app/views/settings/show.json.jbuilder b/app/views/settings/show.json.jbuilder index 39b152fa7..330966aa1 100644 --- a/app/views/settings/show.json.jbuilder +++ b/app/views/settings/show.json.jbuilder @@ -48,7 +48,6 @@ json.setting do json.add do - # json.array! @add, :name, :url, :key json.array! @add end @@ -56,7 +55,5 @@ json.setting do json.array! @personal end - json.common do - json.array! @common - end + json.common @common end From 5f5b3805146850e67be3354d6b3b7b1422a93b92 Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 31 Mar 2021 13:35:40 +0800 Subject: [PATCH 049/643] FIX conflict --- app/controllers/settings_controller.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 638dc4722..03f3c69da 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -22,9 +22,9 @@ class SettingsController < ApplicationController def get_common_menu @common = {} - Site.common.select(:url, :key).to_a.map(&:serializable_hash).each do |site| + Site.common.select(:url, :key).each do |site| next if site["url"].to_s.include?("current_user") && !User.current.logged? - @common.merge!("#{site["key"]}": reset_site_url(site['url'])) + @common.merge!("#{site["key"]}": append_http(reset_site_url(site["url"]))) end end @@ -52,4 +52,8 @@ class SettingsController < ApplicationController split_arr = url.split('current_user') split_arr.length > 1 ? split_arr.join(current_user&.login) : (split_arr << current_user&.login).join('') end + + def append_http(url) + url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('') + end end From b89501822fe000f7a16d611ef83be00d628257c2 Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 31 Mar 2021 14:53:50 +0800 Subject: [PATCH 050/643] FIX code bug --- app/controllers/settings_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 03f3c69da..3ef739042 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -5,7 +5,6 @@ class SettingsController < ApplicationController get_common_menu get_personal_menu - puts @com end private From e638dccfa56e81abc97a213c08e387c091e79108 Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 31 Mar 2021 16:08:00 +0800 Subject: [PATCH 051/643] update readme --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d3abcd100..2a607e2ad 100644 --- a/README.md +++ b/README.md @@ -121,12 +121,20 @@ bundle exec sidekiq -C config/sidekiq.yml -e production -d rails s ``` -#### 12. 浏览器访问 +#### 14. 浏览器访问 在浏览器中输入如下地址访问: ```bash http://localhost:3000/ ``` +#### 15. 浏览器访问 +在浏览器中输入如下地址访问: +```bash +http://localhost:3000/ +``` + +#### 15. 其他说明 +通过页面注册都第一个用户为平台管理员用户 ## 页面展示 From 0b6ebb7b3682bf0c55b0175f78beb812195c8922 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 1 Apr 2021 15:04:17 +0800 Subject: [PATCH 052/643] FIX get site url bug with setting api --- app/controllers/settings_controller.rb | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 3ef739042..b6662f661 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -41,18 +41,17 @@ class SettingsController < ApplicationController end def get_site_url(key, value) - url = reset_site_url(value) - key.to_s === "url" && !value.to_s.start_with?("http") ? [request.protocol, request.host_with_port, value].join('') : url - end + key.to_s === "url" ? append_http(reset_site_url(value)) : reset_site_url(value) + end - def reset_site_url(url) - return url unless url.to_s.include?("current_user") + def reset_site_url(url) + return url unless url.to_s.include?("current_user") - split_arr = url.split('current_user') - split_arr.length > 1 ? split_arr.join(current_user&.login) : (split_arr << current_user&.login).join('') - end + split_arr = url.split('current_user') + split_arr.length > 1 ? split_arr.join(current_user&.login) : (split_arr << current_user&.login).join('') + end - def append_http(url) - url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('') - end + def append_http(url) + url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('') + end end From 254718e39084243a3bb0ca737d66e29d43ff19b7 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 1 Apr 2021 20:33:05 +0800 Subject: [PATCH 053/643] Update db/structure.sql --- db/structure.sql | 73 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/db/structure.sql b/db/structure.sql index dd8544fd4..26208e576 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -3445,12 +3445,77 @@ INSERT INTO `roles` (`id`, `name`, `position`, `assignable`, `builtin`, `permiss (15, 'Contestant', 13, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :notificationcomment_contestnotifications\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :browse_repository\n- :view_changesets\n', 'default'); COMMIT; + +-- ---------------------------- +-- Records of ci_languages +-- ---------------------------- +BEGIN; +INSERT INTO `ci_languages` (`id`, `name`, `content`, `usage_amount`, `created_at`, `updated_at`, `cover_id`) VALUES +(1, 'C', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdjYwogIGNvbW1hbmRzOgogIC0gLi9jb25maWd1cmUKICAtIG1h\na2UKICAtIG1ha2UgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(2, 'C++', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdjYwogIGNvbW1hbmRzOgogIC0gLi9jb25maWd1cmUKICAtIG1h\na2UKICAtIG1ha2UgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(3, 'Docker', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgdm9sdW1lczoKICAtIG5hbWU6IGRvY2tl\ncnNvY2sKICAgIHBhdGg6IC92YXIvcnVuL2RvY2tlci5zb2NrCiAgICBjb21t\nYW5kczoKICAgIC0gZG9ja2VyIHBzIC1hCgp2b2x1bWVzOgotIG5hbWU6IGRv\nY2tlcnNvY2sKICBob3N0OgogICAgcGF0aDogL3Zhci9ydW4vZG9ja2VyLnNv\nY2s=\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:35:20', 351688), +(4, 'Java', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hdmVuOjMtamRrLTEwCiAgY29tbWFuZHM6CiAgLSBtdm4gaW5z\ndGFsbCAtRHNraXBUZXN0cz10cnVlIC1EbWF2ZW4uamF2YWRvYy5za2lwPXRy\ndWUgLUIgLVYKICAtIG12biB0ZXN0IC1C\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(5, 'R', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHItYmFzZQogIGNvbW1hbmRzOgogIC0gUiAtZSAnaW5zdGFsbC5w\nYWNrYWdlcyhjKCdwYWNrYWdlMScsJ3BhY2thZ2UyJykpJwogIC0gUiBDTUQg\nYnVpbGQgLg==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(6, 'Ruby', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1YnkKICBjb21tYW5kczoKICAtIGJ1bmRsZSBpbnN0YWxsIC0t\nam9icz0zIC0tcmV0cnk9MwogIC0gcmFrZQ==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(7, 'PHP', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiBpbnN0YWxs\nCiAgaW1hZ2U6IGNvbXBvc2VyCiAgY29tbWFuZHM6CiAgLSBjb21wb3NlciBp\nbnN0YWxsCgotIG5hbWU6IHRlc3QKICBpbWFnZTogcGhwOjcKICBjb21tYW5k\nczoKICAtIHZlbmRvci9iaW4vcGhwdW5pdCAtLWNvbmZpZ3VyYXRpb24gY29u\nZmlnLnhtbA==\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:37:04', 351690), +(8, 'Python', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHB5dGhvbgogIGNvbW1hbmRzOgogIC0gcGlwIGluc3RhbGwgLXIg\ncmVxdWlyZW1lbnRzLnR4dAogIC0gcHl0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:40:00', 351693), +(9, 'MySQL', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG15c3FsCiAgY29tbWFuZHM6CiAgLSBzbGVlcCAxNQogIC0gbXlz\ncWwgLXUgcm9vdCAtaCBkYXRhYmFzZSAtLWV4ZWN1dGU9J1NFTEVDVCBWRVJT\nSU9OKCk7JwoKc2VydmljZXM6Ci0gbmFtZTogZGF0YWJhc2UKICBpbWFnZTog\nbXlzcWwKICBlbnZpcm9ubWVudDoKICAgIE1ZU1FMX0FMTE9XX0VNUFRZX1BB\nU1NXT1JEOiAneWVzJwogICAgTVlTUUxfREFUQUJBU0U6IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(10, 'MongoDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiBwaW5nCiAg\naW1hZ2U6IG1vbmdvOjQKICBjb21tYW5kczoKICAtIHNsZWVwIDUKICAtIG1v\nbmdvIC0taG9zdCBtb25nbyAtLWV2YWwgJ2RiLnZlcnNpb24oKScKCnNlcnZp\nY2VzOgotIG5hbWU6IG1vbmdvCiAgaW1hZ2U6IG1vbmdvOjQKICBjb21tYW5k\nOiBbIC0tc21hbGxmaWxlcyBd\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(11, 'Clojure', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNsb2p1cmUKICBjb21tYW5kczoKICAtIGxlaW4gdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(12, 'CouchDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNvdWNoZGI6Mi4yCiAgY29tbWFuZHM6CiAgLSBzbGVlcCAxNQog\nIC0gY3VybCBodHRwOi8vZGF0YWJhc2U6NTk4NAoKc2VydmljZXM6Ci0gbmFt\nZTogZGF0YWJhc2UKICBpbWFnZTogY291Y2hkYjoyLjI=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(13, 'Crystal', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNyeXN0YWxsYW5nL2NyeXN0YWwKICBjb21tYW5kczoKICAtIHNo\nYXJkcyBpbnN0YWxsCiAgLSBjcnlzdGFsIHNwZWMuMg==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(14, 'D', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRsYW5ndWFnZS9kbWQKICBjb21tYW5kczoKICAtIGR1YiB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(15, 'Dart', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdvb2dsZS9kYXJ0CiAgY29tbWFuZHM6CiAgLSBwdWIgZ2V0CiAg\nLSBwdWIgcnVuIHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(16, 'Docker (dind)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgdm9sdW1lczoKICAtIG5hbWU6IGRvY2tl\ncnNvY2sKICAgIHBhdGg6IC92YXIvcnVuCiAgICBjb21tYW5kczoKICAgIC0g\nc2xlZXAgNSAjIGdpdmUgZG9ja2VyIGVub3VnaCB0aW1lIHRvIHN0YXJ0CiAg\nICAtIGRvY2tlciBwcyAtYQoKc2VydmljZXM6Ci0gbmFtZTogZG9ja2VyCiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgcHJpdmlsZWdlZDogdHJ1ZQogIHZvbHVt\nZXM6CiAgLSBuYW1lOiBkb2NrZXJzb2NrCiAgICBwYXRoOiAvdmFyL3J1bgoK\ndm9sdW1lczoKLSBuYW1lOiBkb2NrZXJzb2NrCiAgdGVtcDoge30=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(17, 'Elasticsearch', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGFscGluZTozLjgKICBjb21tYW5kczoKICAtIGFwayBhZGQgY3Vy\nbAogIC0gc2xlZXAgNDUKICAtIGN1cmwgaHR0cDovL2RhdGFiYXNlOjkyMDAK\nCnNlcnZpY2VzOgotIG5hbWU6IGRhdGFiYXNlCiAgaW1hZ2U6IGVsYXN0aWNz\nZWFyY2g6NS1hbHBpbmU=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(18, 'Elixir', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGVsaXhpcjoxLjUKICBjb21tYW5kczoKICAtIG1peCBsb2NhbC5y\nZWJhciAtLWZvcmNlCiAgLSBtaXggbG9jYWwuaGV4IC0tZm9yY2UKICAtIG1p\neCBkZXBzLmdldAogIC0gbWl4IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(19, 'Erlang', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGVybGFuZzoyMQogIGNvbW1hbmRzOgogIC0gcmViYXIgZ2V0LWRl\ncHMKICAtIHJlYmFyIGNvbXBpbGUKICAtIHJlYmFyIHNraXBfZGVwcz10cnVl\nIGV1bml0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(20, '20.Go (with Gopath)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0Cgp3b3Jrc3BhY2U6CiAgYmFzZTogL2dv\nCiAgcGF0aDogc3JjL2hlbGxvLXdvcmxkCgpzdGVwczoKLSBuYW1lOiB0ZXN0\nCiAgaW1hZ2U6IGdvbGFuZwogIGNvbW1hbmRzOgogIC0gZ28gZ2V0CiAgLSBn\nbyB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(21, '21.Go (with Modules)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdvbGFuZwogIGNvbW1hbmRzOgogIC0gZ28gdGVzdAogIC0gZ28g\nYnVpbGQ=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(22, 'Gradle', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdyYWRsZTpqZGsxMAogIGNvbW1hbmRzOgogIC0gZ3JhZGxlIGFz\nc2VtYmxlCiAgLSBncmFkbGUgY2hlY2s=\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:36:17', 351689), +(23, 'Groovy', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdyYWRsZToyLjUtamRrOAogIGNvbW1hbmRzOgogIC0gLi9ncmFk\nbGV3IGFzc2VtYmxlCiAgLSAuL2dyYWRsZXcgY2hlY2s=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(24, 'Haskell', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGhhc2tlbGwKICBjb21tYW5kczoKICAtIGNhYmFsIGluc3RhbGwg\nLS1vbmx5LWRlcGVuZGVuY2llcyAtLWVuYWJsZS10ZXN0cwogIC0gY2FiYWwg\nY29uZmlndXJlIC0tZW5hYmxlLXRlc3RzCiAgLSBjYWJhbCBidWlsZAogIC0g\nY2FiYWwgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(25, 'Haxe', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGhheGUKICBjb21tYW5kczoKICAtIGhheGVsaWIgaW5zdGFsbCBi\ndWlsZC5oeG1sCiAgLSBoYXhlIGJ1aWxkLmh4bWw=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(26, 'MariaDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hcmlhZGIKICBjb21tYW5kczoKICAtIHNsZWVwIDE1CiAgLSBt\neXNxbCAtdSByb290IC1oIGRhdGFiYXNlIC0tZXhlY3V0ZT0nU0VMRUNUIFZF\nUlNJT04oKTsnCgpzZXJ2aWNlczoKLSBuYW1lOiBkYXRhYmFzZQogIGltYWdl\nOiBtYXJpYWRiCiAgZW52aXJvbm1lbnQ6CiAgICBNWVNRTF9BTExPV19FTVBU\nWV9QQVNTV09SRDogJ3llcycKICAgIE1ZU1FMX0RBVEFCQVNFOiB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(27, 'Maven', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hdmVuOjMtamRrLTEwCiAgY29tbWFuZHM6CiAgLSBtdm4gaW5z\ndGFsbCAtRHNraXBUZXN0cz10cnVlIC1EbWF2ZW4uamF2YWRvYy5za2lwPXRy\ndWUgLUIgLVYKICAtIG12biB0ZXN0IC1C\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(28, 'Memcached', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHVidW50dQogIGNvbW1hbmRzOgogIC0gYXB0LWdldCB1cGRhdGUg\nLXFxCiAgLSBhcHQtZ2V0IGluc3RhbGwgLXkgLXFxIHRlbG5ldCA+IC9kZXYv\nbnVsbAogIC0gKHNsZWVwIDE7IGVjaG8gJ3N0YXRzJzsgc2xlZXAgMjsgZWNo\nbyAncXVpdCc7KSB8IHRlbG5ldCBjYWNoZSAxMTIxMSB8fCB0cnVlCgpzZXJ2\naWNlczoKLSBuYW1lOiBjYWNoZQogIGltYWdlOiBtZW1jYWNoZWQ6YWxwaW5l\nCiAgY29tbWFuZDogWyAtdnYgXQ==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(29, 'Nats', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1Ynk6MgogIGNvbW1hbmRzOgogIC0gZ2VtIGluc3RhbGwgbmF0\ncwogIC0gbmF0cy1wdWIgLXMgdGNwOi8vbmF0czo0MjIyIGdyZWV0aW5nICdo\nZWxsbycKICAtIG5hdHMtcHViIC1zIHRjcDovL25hdHM6NDIyMiBncmVldGlu\nZyAnd29ybGQnCgpzZXJ2aWNlczoKLSBuYW1lOiBuYXRzCiAgaW1hZ2U6IG5h\ndHM6MS4zLjA=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(30, 'Node', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG5vZGUKICBjb21tYW5kczoKICAtIG5wbSBpbnN0YWxsCiAgLSBu\ncG0gdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(31, 'Perl', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHBlcmwKICBjb21tYW5kczoKICAtIGNwYW5tIC0tcXVpZXQgLS1p\nbnN0YWxsZGVwcyAtLW5vdGVzdCAuCiAgLSBwZXJsIEJ1aWxkLlBMCiAgLSAu\nL0J1aWxkIHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(32, 'Postgres', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHBvc3RncmVzOjktYWxwaW5lCiAgY29tbWFuZHM6CiAgLSBwc3Fs\nIC1VIHBvc3RncmVzIC1kIHRlc3QgLWggZGF0YWJhc2UKCnNlcnZpY2VzOgot\nIG5hbWU6IGRhdGFiYXNlCiAgaW1hZ2U6IHBvc3RncmVzOjktYWxwaW5lCiAg\nZW52aXJvbm1lbnQ6CiAgICBQT1NUR1JFU19VU0VSOiBwb3N0Z3JlcwogICAg\nUE9TVEdSRVNfREI6IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(33, 'Redis', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJlZGlzCiAgY29tbWFuZHM6CiAgLSBzbGVlcCA1CiAgLSByZWRp\ncy1jbGkgLWggcmVkaXMgcGluZwogIC0gcmVkaXMtY2xpIC1oIHJlZGlzIHNl\ndCBGT08gYmFyCiAgLSByZWRpcy1jbGkgLWggcmVkaXMgZ2V0IEZPTwoKc2Vy\ndmljZXM6Ci0gbmFtZTogcmVkaXMKICBpbWFnZTogcmVkaXM=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(34, 'RethinkDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG5vZGU6OQogIGNvbW1hbmRzOgogIC0gbnBtIGluc3RhbGwgLXMg\nLWcgcmVjbGkKICAtIHJlY2xpIC1oIGRhdGFiYXNlIC1qICdyLmRiKCdyZXRo\naW5rZGInKS50YWJsZSgnc3RhdHMnKScKCnNlcnZpY2VzOgotIG5hbWU6IGRh\ndGFiYXNlCiAgaW1hZ2U6IHJldGhpbmtkYjoyCiAgY29tbWFuZDogWyByZXRo\naW5rZGIsIC0tYmluZCwgYWxsIF0=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(35, 'Rust', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1c3Q6MS4zMAogIGNvbW1hbmRzOgogIC0gY2FyZ28gYnVpbGQg\nLS12ZXJib3NlIC0tYWxsCiAgLSBjYXJnbyB0ZXN0IC0tdmVyYm9zZSAtLWFs\nbA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(36, 'Swift', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHN3aWZ0OjQKICBjb21tYW5kczoKICAtIHN3aWZ0IGJ1aWxkCiAg\nLSBzd2lmdCB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(37, 'Vault', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHZhdWx0OjEuMC4wLWJldGEyCiAgZW52aXJvbm1lbnQ6CiAgICBW\nQVVMVF9BRERSOiBodHRwOi8vdmF1bHQ6ODIwMAogICAgVkFVTFRfVE9LRU46\nIGR1bW15CiBjb21tYW5kczoKIC0gc2xlZXAgNQogLSB2YXVsdCBrdiBwdXQg\nc2VjcmV0L215LXNlY3JldCBteS12YWx1ZT1zM2NyM3QKIC0gdmF1bHQga3Yg\nZ2V0IHNlY3JldC9teS1zZWNyZXQKCnNlcnZpY2VzOgotIG5hbWU6IHZhdWx0\nCiAgaW1hZ2U6IHZhdWx0OjEuMC4wLWJldGEyCiAgZW52aXJvbm1lbnQ6CiAg\nICBWQVVMVF9ERVZfUk9PVF9UT0tFTl9JRDogZHVtbXk=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL); +COMMIT; + -- ---------------------------- -- Records of ci_templates -- ---------------------------- BEGIN; -INSERT INTO `ci_templates` VALUES (2,'linux/amd64','init','初始化','kind: pipeline\r\ntype: docker\r\nname: default\r\nplatform:\r\n os: linux\r\n arch: amd64','2021-01-12 02:44:23','2021-01-12 02:44:23',NULL),(3,'linux/arm64','init','初始化','kind: pipeline\r\ntype: docker\r\nname: default\r\nplatform:\r\n os: linux\r\n arch: arm64','2021-01-12 02:45:17','2021-01-12 02:45:17',NULL),(4,'maven','build','Java','- name: maven\r\n image: maven:3-jdk-10\r\n commands:\r\n - mvn install -DskipTests=true','2021-01-12 02:53:29','2021-01-12 02:53:29','编译构建'),(5,'maven单元测试','customize','Java','- name: maven\r\n image: maven:3-jdk-10\r\n commands:\r\n - mvn test','2021-01-12 02:53:29','2021-01-12 02:53:29','单元测试'),(6,'golang单元测试','customize','Golang','- name: golang单元测试\r\n image: golang\r\n commands:\r\n - go test','2021-01-12 03:03:35','2021-01-12 03:03:35','单元测试'),(9,'gradle单元测试','customize','Java','- name: gradle\r\n image: gradle:jdk10\r\n commands:\r\n - gradle test','2021-01-12 03:05:33','2021-01-12 03:05:33','单元测试'),(7,'golang编译','build','Golang','- name: golang编译\r\n image: golang\r\n commands:\r\n - go build','2021-01-12 03:03:35','2021-01-12 03:03:35','编译构建'),(8,'gradle','build','Java','- name: gradle\r\n image: gradle:jdk10\r\n commands:\r\n - gradle build -x test','2021-01-12 03:05:33','2021-01-12 03:05:33','编译构建'),(10,'远程主机部署','deploy','部署','# 根据实际情况修改主机ip、账号、密码\r\n# 需要将软件包与部署脚本提前上传到远程主机(见文件上传模板)\r\n\r\n- name: 远程主机部署\r\n image: appleboy/drone-ssh\r\n settings:\r\n host: 192.168.1.1\r\n username: username\r\n password: \'pasword\'\r\n port: 22\r\n commands:\r\n - chmod +x /home/deploy.sh\r\n - ./home/deploy.sh','2021-01-12 03:32:46','2021-01-12 03:32:46','部署'),(11,'远程命令','customize','工具','- name: 远程命令\r\n image: appleboy/drone-ssh\r\n settings:\r\n host: 192.168.0.1\r\n username: username\r\n password: \'pwd\'\r\n port: 22\r\n script:\r\n - echo \'hello world!\'','2021-01-12 03:40:38','2021-01-12 03:40:38','其他'),(12,'上传文件','customize','工具','# 修改目标服务器的ip、账号密码以及上传路径\r\n# 本模板示例为上传软件包和部署脚本到home目录\r\n\r\n- name: 上传文件\r\n image: appleboy/drone-scp\r\n settings:\r\n host: 192.168.1.1\r\n username: username\r\n password: \'password\'\r\n port: 22\r\n target: /home\r\n source: \r\n - target/*.jar\r\n - deploy.sh','2021-01-12 03:40:55','2021-01-12 03:40:55','其他'),(17,'make-c','build','C语言','- name: 编译\r\n image: gcc\r\n commands:\r\n - ./configure\r\n - make','2021-01-15 01:19:38','2021-01-15 01:19:38','编译构建'),(19,'make-c++','build','C++','- name: 编译构建\r\n image: gcc\r\n commands:\r\n - ./configure\r\n - make','2021-01-15 01:21:05','2021-01-15 01:21:05','编译构建'),(20,'python','build','Python','- name: 编译构建\r\n image: python\r\n commands:\r\n - pip install -r requirements.txt','2021-01-15 01:22:36','2021-01-15 01:22:36','编译构建'),(21,'Docker镜像构建','build','Docker镜像构建','# 构建Docker镜像并推送到仓库\r\n# 定义镜像Hub路径以及账号密码\r\n- name: Docker镜像构建\r\n image: plugins/docker\r\n settings:\r\n username: username\r\n password: pwd\r\n repo: repoUrl\r\n tags: latest','2021-01-15 01:23:16','2021-01-15 01:23:16','编译构建'),(22,'空白模板','customize','customize','','2021-01-15 02:53:02','2021-01-15 02:53:02','其他'),(23,'空白模板','build','自定义','','2021-01-15 03:27:33','2021-01-15 03:27:33','编译构建'); +INSERT INTO `ci_templates` (`id`, `template_name`, `stage_type`, `category`, `content`, `created_at`, `updated_at`, `parent_category`, `login`) VALUES +(2, 'linux/amd64', 'init', '初始化', 'kind: pipeline\r\ntype: docker\r\nname: {name}\r\nplatform:\r\n os: linux\r\n arch: amd64', '2021-01-12 02:44:23', '2021-02-02 10:51:36', '初始化', 'admin'), +(3, 'linux/arm64', 'init', '初始化', 'kind: pipeline\r\ntype: docker\r\nname: {name}\r\nplatform:\r\n os: linux\r\n arch: arm64', '2021-01-12 02:45:17', '2021-02-02 10:51:47', '初始化', 'admin'), +(4, 'maven', 'build', 'Java', '- name: maven\r\n image: maven:3-jdk-10\r\n commands:\r\n - mvn install -DskipTests=true', '2021-01-12 02:53:29', '2021-01-12 02:53:29', '编译构建', 'admin'), +(5, 'maven单元测试', 'customize', 'Java', '- name: maven\r\n image: maven:3-jdk-10\r\n commands:\r\n - mvn test', '2021-01-12 02:53:29', '2021-01-12 02:53:29', '单元测试', 'admin'), +(6, 'golang单元测试', 'customize', 'Golang', '- name: golang单元测试\r\n image: golang\r\n commands:\r\n - go test', '2021-01-12 03:03:35', '2021-01-12 03:03:35', '单元测试', 'admin'), +(8, 'gradle', 'build', 'Java', '- name: gradle\r\n image: gradle:jdk10\r\n commands:\r\n - gradle build -x test', '2021-01-12 03:05:33', '2021-01-12 03:05:33', '编译构建', 'admin'), +(9, 'gradle单元测试', 'customize', 'Java', '- name: gradle\r\n image: gradle:jdk10\r\n commands:\r\n - gradle test', '2021-01-12 03:05:33', '2021-01-12 03:05:33', '单元测试', 'admin'), +(10, '远程主机部署', 'deploy', '部署', '# 需要将软件包与部署脚本提前上传到远程主机(见文件上传模板)\r\n# host、username、password可在参数管理中配置\r\n- name: 远程主机部署\r\n image: appleboy/drone-ssh\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n script:\r\n - chmod +x /home/deploy.sh\r\n - ./home/deploy.sh', '2021-01-12 03:32:46', '2021-03-05 06:22:02', '部署', 'admin'), +(11, '远程命令', 'customize', '其他', '# host、username、password可在参数管理中配置\r\n- name: 远程命令\r\n image: appleboy/drone-ssh\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n script:\r\n - echo ''hello world!''', '2021-01-12 03:40:38', '2021-03-05 06:19:44', '其他', 'admin'), +(12, '上传文件', 'customize', '其他', '# 本模板示例为上传软件包和部署脚本到home目录\r\n# host、username、password可在参数管理中配置\r\n- name: 上传文件\r\n image: appleboy/drone-scp\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n target: /home\r\n source: \r\n - target/*.jar\r\n - deploy.sh', '2021-01-12 03:40:55', '2021-03-05 06:22:22', '其他', 'admin'), +(17, 'make-c', 'build', 'C', '- name: 编译\r\n image: gcc\r\n commands:\r\n - ./configure\r\n - make', '2021-01-15 01:19:38', '2021-02-02 10:52:15', '编译构建', 'admin'), +(19, 'make-c++', 'build', 'C++', '- name: 编译构建\r\n image: gcc\r\n commands:\r\n - ./configure\r\n - make', '2021-01-15 01:21:05', '2021-01-15 01:21:05', '编译构建', 'admin'), +(20, 'python', 'build', 'Python', '- name: 编译构建\r\n image: python\r\n commands:\r\n - pip install -r requirements.txt', '2021-01-15 01:22:36', '2021-01-15 01:22:36', '编译构建', 'admin'), +(21, 'Docker', 'build', 'Docker', '# 构建Docker镜像并推送到仓库\r\n# 定义镜像Hub路径以及账号密码\r\n- name: Docker镜像构建\r\n image: plugins/docker\r\n settings:\r\n username: username\r\n password: pwd\r\n repo: repoUrl\r\n tags: latest', '2021-01-15 01:23:16', '2021-02-03 03:40:49', '编译构建', 'admin'), +(22, '空白模板', 'customize', 'customize', '', '2021-01-15 02:53:02', '2021-01-15 02:53:02', '其他', 'admin'), +(25, 'Go (with Gopath)', 'build', 'Go', '- name: golang\r\n image: golang\r\n commands:\r\n - go get\r\n - go test', '2021-02-03 00:57:32', '2021-02-03 03:36:15', '编译构建', 'admin'), +(26, 'PHP', 'build', 'PHP', '- name: install\r\n image: composer\r\n commands:\r\n - composer install', '2021-02-03 00:59:15', '2021-02-03 00:59:15', '编译构建', 'admin'), +(27, 'Ruby', 'build', 'Ruby', '- name: ruby\r\n image: ruby\r\n commands:\r\n - bundle install --jobs=3 --retry=3\r\n - rake', '2021-02-03 00:59:52', '2021-02-03 00:59:52', '编译构建', 'admin'), +(29, 'Go (with Modules)', 'build', 'Go', '- name: test\r\n image: golang\r\n commands:\r\n - go test\r\n - go build', '2021-02-03 03:35:45', '2021-02-03 03:35:45', '编译构建', 'admin'), +(30, 'Node', 'build', 'Node', '- name: Node编译\r\n image: node\r\n commands:\r\n - npm install\r\n - npm test', '2021-02-03 03:37:31', '2021-02-03 03:37:31', '编译构建', 'admin'), +(31, 'Perl ', 'build', 'Perl', '- name: perl\r\n image: perl\r\n commands:\r\n - cpanm --quiet --installdeps --notest .\r\n - perl Build.PL\r\n - ./Build test', '2021-02-03 03:38:06', '2021-02-03 03:38:06', '编译构建', 'admin'), +(32, 'Rust ', 'build', 'Rust', '- name: rust\r\n image: rust:1.30\r\n commands:\r\n - cargo build --verbose --all\r\n - cargo test --verbose --all', '2021-02-03 03:38:37', '2021-02-03 03:38:37', '编译构建', 'admin'), +(33, 'test', 'init', '初始化', 'qqqq', '2021-02-04 09:02:42', '2021-02-04 09:02:42', '初始化', 'admin'); COMMIT; - - -SET FOREIGN_KEY_CHECKS = 1; From 02d26df1722422bad023288b87d5d8e44594281c Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 2 Apr 2021 15:53:17 +0800 Subject: [PATCH 054/643] FIX query builds api bug --- app/queries/ci/builds/list_query.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/queries/ci/builds/list_query.rb b/app/queries/ci/builds/list_query.rb index 7091723a4..e548c3a45 100644 --- a/app/queries/ci/builds/list_query.rb +++ b/app/queries/ci/builds/list_query.rb @@ -25,7 +25,7 @@ class Ci::Builds::ListQuery < ApplicationQuery scope end - builds = scope.by_branch(params[:branch]) if params[:branch] + builds = builds.by_branch(params[:branch]) if params[:branch] custom_sort(builds, params[:sort_by], params[:sort_direction]) end From 50fb8d39839cc74de71c9f46f7008b5864466c46 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 2 Apr 2021 18:18:52 +0800 Subject: [PATCH 055/643] ADD sync user info api --- app/controllers/users_controller.rb | 22 +++++++++++++++++++++- config/routes.rb | 5 +++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6c5c10fb3..ca0988ea0 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,7 +4,7 @@ class UsersController < ApplicationController 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 sync_user_info] before_action :connect_to_ci_db, only: [:get_user_info] skip_before_action :check_sign, only: [:attachment_show] @@ -233,6 +233,26 @@ class UsersController < ApplicationController render_ok end + def sync_user_info + user = User.find_by_mail params[:email] + return render_forbidden unless user === current_user + + sync_params = { + email: params[:email], + password: params[:password] + } + + Users::UpdateInfoForm.new(sync_params).validate! + + interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params) + if interactor.success? + user.update!(password: params[:password], mail: params[:email], status: User::STATUS_EDIT_INFO) + render_ok + else + render_error(interactor.error) + end + end + private def load_user @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id]) diff --git a/config/routes.rb b/config/routes.rb index daef12bb4..66c9d97af 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -72,12 +72,12 @@ Rails.application.routes.draw do end resources :statistic, only: [:index] do - collection do + collection do get :platform_profile get :platform_code get :active_project_rank get :active_developer_rank - end + end end resources :sync_forge, only: [:create] do collection do @@ -218,6 +218,7 @@ Rails.application.routes.draw do post :sync_salt get :trustie_projects get :trustie_related_projects + post :sync_user_info scope '/ci', module: :ci do scope do From e022e429d429244710f42660834e65db59a3ee39 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 2 Apr 2021 18:22:21 +0800 Subject: [PATCH 056/643] FIX code bug --- app/forms/users/update_info_form.rb | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 app/forms/users/update_info_form.rb diff --git a/app/forms/users/update_info_form.rb b/app/forms/users/update_info_form.rb new file mode 100644 index 000000000..131a6fd93 --- /dev/null +++ b/app/forms/users/update_info_form.rb @@ -0,0 +1,8 @@ +class Users::UpdateInfoForm + include ActiveModel::Model + + attr_accessor :email, :password + + validates :email, presence: true, format: { with: CustomRegexp::EMAIL } + validates :password, presence: true +end From 6ce4b2604714d5d97dc75ba023966c942b8b1d28 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 2 Apr 2021 18:40:26 +0800 Subject: [PATCH 057/643] FIX api bug --- app/controllers/users_controller.rb | 2 +- app/forms/users/update_info_form.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index ca0988ea0..91258678e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -234,7 +234,7 @@ class UsersController < ApplicationController end def sync_user_info - user = User.find_by_mail params[:email] + user = User.find_by_login params[:login] return render_forbidden unless user === current_user sync_params = { diff --git a/app/forms/users/update_info_form.rb b/app/forms/users/update_info_form.rb index 131a6fd93..088db06d3 100644 --- a/app/forms/users/update_info_form.rb +++ b/app/forms/users/update_info_form.rb @@ -1,8 +1,9 @@ class Users::UpdateInfoForm include ActiveModel::Model - attr_accessor :email, :password + attr_accessor :email, :password, :login validates :email, presence: true, format: { with: CustomRegexp::EMAIL } validates :password, presence: true + validates :login, presence: true end From c175fa1339982b5e39e2f96f96dcbd47aed7f124 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 2 Apr 2021 18:53:53 +0800 Subject: [PATCH 058/643] fix: commit author and fork create units --- app/services/projects/fork_service.rb | 2 ++ app/views/pull_requests/_commit.json.jbuilder | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb index 3204e5fc7..8ae787c52 100644 --- a/app/services/projects/fork_service.rb +++ b/app/services/projects/fork_service.rb @@ -24,6 +24,8 @@ class Projects::ForkService < ApplicationService new_repository.identifier = @project.identifier new_repository.save! + ProjectUnit.init_types(clone_project.id) + result = Gitea::Repository::ForkService.new(@project.owner, @target_owner, @project.identifier, @organization).call @project.update_column('forked_count', @project&.forked_count.to_i + 1) diff --git a/app/views/pull_requests/_commit.json.jbuilder b/app/views/pull_requests/_commit.json.jbuilder index 0b7db5893..072e53c91 100644 --- a/app/views/pull_requests/_commit.json.jbuilder +++ b/app/views/pull_requests/_commit.json.jbuilder @@ -1,11 +1,11 @@ json.author do author = User.find_by(login: commit['Author']['Name']) - json.partial! 'repositories/commit_author', locals: { user: author } + json.partial! 'repositories/commit_author', locals: { user: author, name: commit['Committer']['Name'] } end json.committer do author = User.find_by(login: commit['Committer']['Name']) - json.partial! 'repositories/commit_author', locals: { user: author } + json.partial! 'repositories/commit_author', locals: { user: author, name: commit['Committer']['Name'] } end json.timestamp render_unix_time(commit['Committer']['When']) json.time_from_now time_from_now(commit['Committer']['When']) From e6b84350374be7c0c17d37b58a55058e73c55c45 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 2 Apr 2021 18:56:44 +0800 Subject: [PATCH 059/643] FIX gug --- app/controllers/users_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 91258678e..14c296906 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -242,7 +242,7 @@ class UsersController < ApplicationController password: params[:password] } - Users::UpdateInfoForm.new(sync_params).validate! + Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate! interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params) if interactor.success? From c417fa736915f2a701d86bb7fa35d0ddbfd02215 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 6 Apr 2021 13:38:44 +0800 Subject: [PATCH 060/643] add: project list author type --- app/views/projects/index.json.jbuilder | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/projects/index.json.jbuilder b/app/views/projects/index.json.jbuilder index 5556cfe27..0e23ac03d 100644 --- a/app/views/projects/index.json.jbuilder +++ b/app/views/projects/index.json.jbuilder @@ -25,6 +25,7 @@ json.projects @projects do |project| json.image_url render_educoder_avatar_url(project.project_educoder) else user = project.owner + json.type user.type json.name user.try(:show_real_name) json.login user.login json.image_url render_avatar_url(user) From b11fd350da8b5ac4b794ddd7a90a7135e95d1b7a Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 6 Apr 2021 15:41:53 +0800 Subject: [PATCH 061/643] fix: project permission --- app/helpers/repositories_helper.rb | 1 - app/models/project.rb | 152 +++++++++++++++-------------- 2 files changed, 77 insertions(+), 76 deletions(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index a6426083e..e704acb83 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -1,7 +1,6 @@ module RepositoriesHelper def render_permission(user, project) return "Admin" if user&.admin? - return "Owner" if user === project.owner project.get_premission(user) end diff --git a/app/models/project.rb b/app/models/project.rb index 828a259dc..bc340f5e5 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,75 +1,75 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(4294967295) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# license_id :integer -# ignore_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# default_branch :string(255) default("master") -# website :string(255) -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# - +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(4294967295) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# license_id :integer +# ignore_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# default_branch :string(255) default("master") +# website :string(255) +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + @@ -242,10 +242,12 @@ class Project < ApplicationRecord end def get_premission user - permission = "Reporter" - member = members.find_by(user: user) + return "Owner" if owner?(user) + return "Manager" if manager?(user) + return "Developer" if develper?(user) + return "Reporter" if reporter?(user) - member&.roles&.last&.name || permission + return "Reporter" end def fork_project From a66e5b876d6da6a52a5b0104e8cf13402760f830 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 6 Apr 2021 16:33:14 +0800 Subject: [PATCH 062/643] fix --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index bc340f5e5..9aa6283f6 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -247,7 +247,7 @@ class Project < ApplicationRecord return "Developer" if develper?(user) return "Reporter" if reporter?(user) - return "Reporter" + return "" end def fork_project From d6c3bcfaf1fce40b4a183f9920f1775105c62158 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 6 Apr 2021 17:17:51 +0800 Subject: [PATCH 063/643] add: org add nickname --- app/controllers/organizations/organizations_controller.rb | 8 +++++--- app/models/organization.rb | 8 +++++--- app/services/organizations/create_service.rb | 2 +- .../organizations/organizations/_detail.json.jbuilder | 1 + 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index e03ddf121..73335cf11 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -36,8 +36,10 @@ class Organizations::OrganizationsController < Organizations::BaseController def update ActiveRecord::Base.transaction do login = @organization.login - @organization.update!(login: organization_params[:name]) if organization_params[:name].present? - @organization.organization_extension.update_attributes!(organization_params.except(:name)) + @organization.login = organization_params[:name] if organization_params[:name].present? + @organization.nickname = organization_params[:nickname] if organization_params[:nickname].present? + @organization.save! + @organization.organization_extension.update_attributes!(organization_params.except(:name, :nickname)) Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload) Util.write_file(@image, avatar_path(@organization)) if params[:image].present? end @@ -82,7 +84,7 @@ class Organizations::OrganizationsController < Organizations::BaseController def organization_params params.permit(:name, :description, :website, :location, :repo_admin_change_team_access, :visibility, - :max_repo_creation) + :max_repo_creation, :nickname) end def password diff --git a/app/models/organization.rb b/app/models/organization.rb index a541b203f..48dab55a2 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -78,8 +78,8 @@ class Organization < Owner scope :with_visibility, ->(visibility) { joins(:organization_extension).where(organization_extensions: {visibility: visibility}) if visibility.present? } - def self.build(name, gitea_token=nil) - self.create!(login: name, gitea_token: gitea_token) + def self.build(name, nickname, gitea_token=nil) + self.create!(login: name, nickname: nickname, gitea_token: gitea_token) end def can_create_project?(user_id) @@ -113,7 +113,9 @@ class Organization < Owner end def real_name - login + name = lastname + firstname + name = name.blank? ? (nickname.blank? ? login : nickname) : name + name.gsub(/\s+/, '').strip #6.11 -hs end def show_real_name diff --git a/app/services/organizations/create_service.rb b/app/services/organizations/create_service.rb index 2d2b29e0f..96bb3f46a 100644 --- a/app/services/organizations/create_service.rb +++ b/app/services/organizations/create_service.rb @@ -47,7 +47,7 @@ class Organizations::CreateService < ApplicationService end def create_org_and_extension - @organization = Organization.build(params[:name], user.gitea_token) + @organization = Organization.build(params[:name], params[:nickname], user.gitea_token) org_extension = OrganizationExtension.build(organization.id, description, website, location, repo_admin_change_team_access, visibility, max_repo_creation) diff --git a/app/views/organizations/organizations/_detail.json.jbuilder b/app/views/organizations/organizations/_detail.json.jbuilder index e7aafd4e9..64feadca1 100644 --- a/app/views/organizations/organizations/_detail.json.jbuilder +++ b/app/views/organizations/organizations/_detail.json.jbuilder @@ -1,5 +1,6 @@ json.id organization.id json.name organization.login +json.nickname organization.nickname json.description organization.description json.website organization.website json.location organization.location From cf224bc9fe4191aea8629a057906f8e46b8c2036 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 6 Apr 2021 17:26:48 +0800 Subject: [PATCH 064/643] add: project menulist resources --- app/controllers/projects_controller.rb | 1 + app/models/project_unit.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f6ab38369..2ca3ff462 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -16,6 +16,7 @@ class ProjectsController < ApplicationController menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") + menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") menu.append(menu_hash_by_name("activity")) menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.manager?(current_user) diff --git a/app/models/project_unit.rb b/app/models/project_unit.rb index b5b4fe290..0f4275345 100644 --- a/app/models/project_unit.rb +++ b/app/models/project_unit.rb @@ -16,7 +16,7 @@ class ProjectUnit < ApplicationRecord belongs_to :project - enum unit_type: {code: 1, issues: 2, pulls: 3, devops: 4, versions: 5} + enum unit_type: {code: 1, issues: 2, pulls: 3, devops: 4, versions: 5, resources: 6} validates :unit_type, uniqueness: { scope: :project_id} From 04a1376820b1056bb2a58bce1902a16aadb1106f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 8 Apr 2021 15:13:35 +0800 Subject: [PATCH 065/643] add: project's lesson_url --- app/controllers/projects_controller.rb | 2 +- app/views/projects/update.json.jbuilder | 3 ++- app/views/repositories/detail.json.jbuilder | 1 + app/views/repositories/edit.json.jbuilder | 3 ++- db/migrate/20210408070123_add_lesson_url_to_projects.rb | 5 +++++ 5 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20210408070123_add_lesson_url_to_projects.rb diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 2ca3ff462..ca66b4361 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -183,7 +183,7 @@ class ProjectsController < ApplicationController private def project_params - params.permit(:user_id, :name, :description, :repository_name, :website, + params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :project_category_id, :project_language_id, :license_id, :ignore_id, :private) end diff --git a/app/views/projects/update.json.jbuilder b/app/views/projects/update.json.jbuilder index ef09d5d85..01e70377e 100644 --- a/app/views/projects/update.json.jbuilder +++ b/app/views/projects/update.json.jbuilder @@ -5,4 +5,5 @@ json.description @project.description json.project_category_id @project.project_category_id json.project_language_id @project.project_language_id json.is_public @project.is_public -json.website @project.website \ No newline at end of file +json.website @project.website +json.lesson_url @project.lesson_url \ No newline at end of file diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 28a64e50a..fc1dc830b 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -1,5 +1,6 @@ json.content @project.content json.website @project.website +json.lesson_url @project.lesson_url if @result[:readme].blank? json.readme nil else diff --git a/app/views/repositories/edit.json.jbuilder b/app/views/repositories/edit.json.jbuilder index 328bc4900..076ac3aa8 100644 --- a/app/views/repositories/edit.json.jbuilder +++ b/app/views/repositories/edit.json.jbuilder @@ -6,4 +6,5 @@ json.project_category_id @project.project_category_id json.project_language_id @project.project_language_id json.private !@project.is_public json.website @project.website -json.project_units @project.project_units.pluck(:unit_type) \ No newline at end of file +json.project_units @project.project_units.pluck(:unit_type) +json.lesson_url @project.lesson_url \ No newline at end of file diff --git a/db/migrate/20210408070123_add_lesson_url_to_projects.rb b/db/migrate/20210408070123_add_lesson_url_to_projects.rb new file mode 100644 index 000000000..149383485 --- /dev/null +++ b/db/migrate/20210408070123_add_lesson_url_to_projects.rb @@ -0,0 +1,5 @@ +class AddLessonUrlToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :lesson_url, :string + end +end From dcd4457cf5447c0e80cec34896c6d9a45fa37c29 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 13 Apr 2021 10:16:18 +0800 Subject: [PATCH 066/643] =?UTF-8?q?FIX=20=E5=BC=80=E6=94=BE=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E7=AE=A1=E7=90=86=E5=91=98=E5=8F=AF=E4=BB=A5=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E6=89=80=E6=9C=89=E5=9B=A2=E9=98=9F=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/organizations/base_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/organizations/base_controller.rb b/app/controllers/organizations/base_controller.rb index 2e8ae0cf9..e6163bf8c 100644 --- a/app/controllers/organizations/base_controller.rb +++ b/app/controllers/organizations/base_controller.rb @@ -21,7 +21,7 @@ class Organizations::BaseController < ApplicationController end def team_not_found_condition - @team.team_users.where(user_id: current_user.id).blank? && !@organization.is_owner?(current_user.id) + !current_user&.admin? && @team.team_users.where(user_id: current_user.id).blank? && !@organization.is_owner?(current_user.id) end def user_mark @@ -31,4 +31,4 @@ class Organizations::BaseController < ApplicationController def project_mark params[:repo_name] || params[:id] end -end \ No newline at end of file +end From 1fe9ea126a408a61999ae2b8ca78e791a269ef88 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 13 Apr 2021 11:53:06 +0800 Subject: [PATCH 067/643] fix: permission with organization --- app/controllers/members_controller.rb | 4 ++-- app/controllers/pull_requests_controller.rb | 2 +- app/models/user.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 2964eb1af..bea4a0d29 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -47,7 +47,7 @@ class MembersController < ApplicationController end def member_exists? - @project.member?(params[:user_id]) + @project.members.exists?(params[:user_id]) end def operate! @@ -59,6 +59,6 @@ class MembersController < ApplicationController end def check_member_not_exists! - return render_result(1, "user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists? + return render_result(1, "user_id为#{params[:user_id]}的用户还不是项目成员") unless @project.member?(params[:user_id]) end end diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 126639015..c59a196b5 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -140,7 +140,7 @@ class PullRequestsController < ApplicationController end def pr_merge - return render_forbidden("你没有权限操作.") if @project.reporter?(current_user) + return render_forbidden("你没有权限操作.") unless current_user.project_manager?(@project) if params[:do].blank? normal_status(-1, "请选择合并方式") diff --git a/app/models/user.rb b/app/models/user.rb index 5bfe3b6e6..bf4ec1048 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -203,7 +203,7 @@ class User < Owner end def project_manager?(project) - project.managers.exists?(user: self) || self.admin? + project.manager?(self) || self.admin? end # 学号 From 506ab1722da95d58b7a5326d2a8908292bd1e82f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 10:54:36 +0800 Subject: [PATCH 068/643] add: team nickname --- app/controllers/organizations/teams_controller.rb | 2 +- app/models/team.rb | 1 + app/views/organizations/teams/_detail.json.jbuilder | 1 + db/migrate/20210419023310_add_nickname_to_teams.rb | 5 +++++ 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20210419023310_add_nickname_to_teams.rb diff --git a/app/controllers/organizations/teams_controller.rb b/app/controllers/organizations/teams_controller.rb index 5bc01fe39..04b748c8a 100644 --- a/app/controllers/organizations/teams_controller.rb +++ b/app/controllers/organizations/teams_controller.rb @@ -60,7 +60,7 @@ class Organizations::TeamsController < Organizations::BaseController private def team_params - params.permit(:name, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types => []) + params.permit(:name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types => []) end def load_organization diff --git a/app/models/team.rb b/app/models/team.rb index 82a3e88c1..d17827da8 100644 --- a/app/models/team.rb +++ b/app/models/team.rb @@ -14,6 +14,7 @@ # gtid :integer # created_at :datetime not null # updated_at :datetime not null +# nickname :string(255) # # Indexes # diff --git a/app/views/organizations/teams/_detail.json.jbuilder b/app/views/organizations/teams/_detail.json.jbuilder index 4f3588cb9..cb0507b5a 100644 --- a/app/views/organizations/teams/_detail.json.jbuilder +++ b/app/views/organizations/teams/_detail.json.jbuilder @@ -1,5 +1,6 @@ json.id team.id json.name team.name +json.nickname team.nickname json.description team.description json.authorize team.authorize json.includes_all_project team.includes_all_project diff --git a/db/migrate/20210419023310_add_nickname_to_teams.rb b/db/migrate/20210419023310_add_nickname_to_teams.rb new file mode 100644 index 000000000..ed80f1935 --- /dev/null +++ b/db/migrate/20210419023310_add_nickname_to_teams.rb @@ -0,0 +1,5 @@ +class AddNicknameToTeams < ActiveRecord::Migration[5.2] + def change + add_column :teams, :nickname, :string + end +end From 5a20842edb947cd1c2b8a02c0d6c3ad87628aec2 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 11:26:30 +0800 Subject: [PATCH 069/643] fix: org not need create member --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 9aa6283f6..ecaf588cd 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -161,7 +161,7 @@ class Project < ApplicationRecord #创建项目管理员 def check_project_members - unless members.present? && members.exists?(user_id: self.user_id) + unless members.present? && member?(user_id) member_params = { user_id: self.user_id, project_id: self.id From 1920cb5ce3135a991feaac3d34ed6398dc466ecc Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 11:35:12 +0800 Subject: [PATCH 070/643] fix: org not need create member --- app/models/project.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index ecaf588cd..4b96ab2b2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -161,7 +161,8 @@ class Project < ApplicationRecord #创建项目管理员 def check_project_members - unless members.present? && member?(user_id) + return if owner.is_a?(Organization) + unless members.present? && members.exists?(user_id: self.user_id) member_params = { user_id: self.user_id, project_id: self.id From 9300483c1a0a8bcdd8ccb850d482c95363b35f46 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 11:40:38 +0800 Subject: [PATCH 071/643] fix --- app/views/organizations/teams/_detail.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/organizations/teams/_detail.json.jbuilder b/app/views/organizations/teams/_detail.json.jbuilder index cb0507b5a..68572814f 100644 --- a/app/views/organizations/teams/_detail.json.jbuilder +++ b/app/views/organizations/teams/_detail.json.jbuilder @@ -1,6 +1,6 @@ json.id team.id json.name team.name -json.nickname team.nickname +json.nickname team.nickname.blank? ? team.name : team.nickname json.description team.description json.authorize team.authorize json.includes_all_project team.includes_all_project From 1c6982d15b10d250378d3e8e688dee7616e7677a Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 12:07:12 +0800 Subject: [PATCH 072/643] add: org valid --- app/controllers/organizations/organizations_controller.rb | 1 + app/controllers/organizations/teams_controller.rb | 5 ++++- app/forms/organizations/create_form.rb | 8 ++++++++ app/forms/organizations/create_team_form.rb | 8 ++++++++ .../organizations/organizations/_detail.json.jbuilder | 2 +- 5 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 app/forms/organizations/create_form.rb create mode 100644 app/forms/organizations/create_team_form.rb diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index 73335cf11..09c12fd5a 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -25,6 +25,7 @@ class Organizations::OrganizationsController < Organizations::BaseController def create ActiveRecord::Base.transaction do + Organizations::CreateForm.new(organization_params).validate! @organization = Organizations::CreateService.call(current_user, organization_params) Util.write_file(@image, avatar_path(@organization)) if params[:image].present? end diff --git a/app/controllers/organizations/teams_controller.rb b/app/controllers/organizations/teams_controller.rb index 04b748c8a..a8d06ce46 100644 --- a/app/controllers/organizations/teams_controller.rb +++ b/app/controllers/organizations/teams_controller.rb @@ -33,7 +33,10 @@ class Organizations::TeamsController < Organizations::BaseController end def create - @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) + ActiveRecord::Base.transaction do + Organizations::CreateTeamForm.new(team_params).validate! + @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) + end rescue Exception => e uid_logger_error(e.message) tip_exception(e.message) diff --git a/app/forms/organizations/create_form.rb b/app/forms/organizations/create_form.rb new file mode 100644 index 000000000..00c1dd15e --- /dev/null +++ b/app/forms/organizations/create_form.rb @@ -0,0 +1,8 @@ +class Organizations::CreateForm < BaseForm + NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 + attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname + + validates :name, :nickname, :visibility, presence: true + validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + +end diff --git a/app/forms/organizations/create_team_form.rb b/app/forms/organizations/create_team_form.rb new file mode 100644 index 000000000..67b81c5f2 --- /dev/null +++ b/app/forms/organizations/create_team_form.rb @@ -0,0 +1,8 @@ +class Organizations::CreateTeamForm < BaseForm + NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 + attr_accessor :name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types + + validates :name, :nickname, :authorize, :includes_all_project, presence: true + validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + +end diff --git a/app/views/organizations/organizations/_detail.json.jbuilder b/app/views/organizations/organizations/_detail.json.jbuilder index 64feadca1..4a8b512b9 100644 --- a/app/views/organizations/organizations/_detail.json.jbuilder +++ b/app/views/organizations/organizations/_detail.json.jbuilder @@ -1,6 +1,6 @@ json.id organization.id json.name organization.login -json.nickname organization.nickname +json.nickname organization.nickname.blank? ? organization.name : organization.nickname json.description organization.description json.website organization.website json.location organization.location From 01f32ae2d7d04b99c3b30e16d72dd64d3810680a Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 12:09:38 +0800 Subject: [PATCH 073/643] fix --- app/forms/organizations/create_team_form.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/forms/organizations/create_team_form.rb b/app/forms/organizations/create_team_form.rb index 67b81c5f2..898d69a1d 100644 --- a/app/forms/organizations/create_team_form.rb +++ b/app/forms/organizations/create_team_form.rb @@ -2,7 +2,7 @@ class Organizations::CreateTeamForm < BaseForm NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 attr_accessor :name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types - validates :name, :nickname, :authorize, :includes_all_project, presence: true + validates :name, :nickname, :authorize, presence: true validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } end From 8055ae2c07e9310313e5cebc9d3183c523ff78bb Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 12:14:11 +0800 Subject: [PATCH 074/643] fix: org team nickname change error --- app/services/organizations/teams/update_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/organizations/teams/update_service.rb b/app/services/organizations/teams/update_service.rb index 71c82c40b..b5b273d8a 100644 --- a/app/services/organizations/teams/update_service.rb +++ b/app/services/organizations/teams/update_service.rb @@ -27,7 +27,7 @@ class Organizations::Teams::UpdateService < ApplicationService if team.authorize == "owner" update_params = params.slice(:description) else - update_params = params.slice(:name, :description, :authorize, :includes_all_project, :can_create_org_project) + update_params = params.slice(:name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project) end update_params end From 002ae9f32728279a1aae33a7bf0a8cf9971916e2 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 19 Apr 2021 15:06:56 +0800 Subject: [PATCH 075/643] ADD auto generate user avatar --- .gitignore | 4 +++- Gemfile | 2 ++ Gemfile.lock | 2 ++ app/helpers/application_helper.rb | 7 +----- app/models/concerns/.keep | 0 app/models/user.rb | 1 + app/models/user/avatar.rb | 32 ++++++++++++++++++++++++++++ config/initializers/letter_avatar.rb | 7 ++++++ 8 files changed, 48 insertions(+), 7 deletions(-) delete mode 100644 app/models/concerns/.keep create mode 100644 app/models/user/avatar.rb create mode 100644 config/initializers/letter_avatar.rb diff --git a/.gitignore b/.gitignore index 77104d20a..6b4fd25c1 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ public/react/yarn.lock /.idea/* # Ignore react node_modules +public/system/* public/react/* /public/react/.cache /public/react/node_modules/ @@ -82,4 +83,5 @@ docker/ educoder.sql redis_data/ Dockerfile -dump.rdb \ No newline at end of file +dump.rdb +.tags* diff --git a/Gemfile b/Gemfile index 281dd705a..713eb860f 100644 --- a/Gemfile +++ b/Gemfile @@ -126,3 +126,5 @@ gem 'request_store' gem 'harmonious_dictionary', '~> 0.0.1' gem 'parallel', '~> 1.19', '>= 1.19.1' + +gem 'letter_avatar' diff --git a/Gemfile.lock b/Gemfile.lock index cbd598f59..015c0a515 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -162,6 +162,7 @@ GEM activerecord kaminari-core (= 1.2.0) kaminari-core (1.2.0) + letter_avatar (0.3.8) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -456,6 +457,7 @@ DEPENDENCIES jbuilder (~> 2.5) jquery-rails kaminari (~> 1.1, >= 1.1.1) + letter_avatar listen (>= 3.0.5, < 3.2) mysql2 (>= 0.4.4, < 0.6.0) oauth2 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 30953bf57..18523d700 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -149,12 +149,7 @@ module ApplicationHelper File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" end elsif source.class.to_s == 'User' - str = source.user_extension.try(:gender).to_i == 0 ? "b" : "g" - File.join(relative_path, "#{source.class}", str) - elsif source.class.to_s == 'Subject' - File.join("images","educoder", "index", "subject", "subject#{rand(17)}.jpg") - elsif source.class.to_s == 'Shixun' - File.join("images","educoder", "index", "shixun", "shixun#{rand(23)}.jpg") + source.letter_avatar_url end end diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/models/user.rb b/app/models/user.rb index bf4ec1048..20b3a8543 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -66,6 +66,7 @@ class User < Owner include Likeable include BaseModel include Droneable + include User::Avatar # include Searchable::Dependents::User # devops step diff --git a/app/models/user/avatar.rb b/app/models/user/avatar.rb new file mode 100644 index 000000000..4b62c28fb --- /dev/null +++ b/app/models/user/avatar.rb @@ -0,0 +1,32 @@ +require 'letter_avatar/has_avatar' + +class User + module Avatar + extend ActiveSupport::Concern + include LetterAvatar::HasAvatar + + def name + lastname.blank? ? login : Pinyin.t(lastname) + end + + def letter_avatar_url(size = :lg) + avatar_url(avatar_size(size)) + end + + # 返回头像尺寸 + # xs: 22px + # sm: 32px + # md: 48px + # lg: 120px + def avatar_size(size) + case size + when :xs then 22 + when :sm then 32 + when :md then 48 + when :lg then 120 + else size + end + end + + end +end diff --git a/config/initializers/letter_avatar.rb b/config/initializers/letter_avatar.rb new file mode 100644 index 000000000..88f3851e9 --- /dev/null +++ b/config/initializers/letter_avatar.rb @@ -0,0 +1,7 @@ +LetterAvatar.setup do |config| + config.fill_color = 'rgba(255, 255, 255, 1)' # default is 'rgba(255, 255, 255, 0.65)' + config.cache_base_path = 'public/system/lets' # default is 'public/system' + config.colors_palette = :iwanthue # default is :google + config.annotate_position = '-0+10' # default is -0+5 + config.letters_count = 2 # default is 1 +end From 9cddda7fd48bd969e54b8f7e412d3a37e2fc2de8 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 19 Apr 2021 15:38:51 +0800 Subject: [PATCH 076/643] Update render user avatar url in projects api --- app/views/projects/_project_detail.json.jbuilder | 2 +- app/views/projects/index.json.jbuilder | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/_project_detail.json.jbuilder b/app/views/projects/_project_detail.json.jbuilder index 94aee427e..d0b62aaa3 100644 --- a/app/views/projects/_project_detail.json.jbuilder +++ b/app/views/projects/_project_detail.json.jbuilder @@ -26,7 +26,7 @@ json.author do json.name user.try(:show_real_name) json.type user&.type json.login user.login - json.image_url render_avatar_url(user) + json.image_url url_to_avatar(user) end end diff --git a/app/views/projects/index.json.jbuilder b/app/views/projects/index.json.jbuilder index 0e23ac03d..96ab89c00 100644 --- a/app/views/projects/index.json.jbuilder +++ b/app/views/projects/index.json.jbuilder @@ -28,7 +28,7 @@ json.projects @projects do |project| json.type user.type json.name user.try(:show_real_name) json.login user.login - json.image_url render_avatar_url(user) + json.image_url url_to_avatar(user) end end From b6e8a135f0afbaf0288875dfa25f5c8fc3f57a11 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 19 Apr 2021 15:42:54 +0800 Subject: [PATCH 077/643] FIX url_to_avatar bug --- app/helpers/application_helper.rb | 2 +- app/helpers/projects_helper.rb | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 18523d700..3af7a5296 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -144,7 +144,7 @@ module ApplicationHelper if File.exist?(disk_filename(source&.class, source&.id)) ctime = File.ctime(disk_filename(source.class, source.id)).to_i if %w(User Organization).include?(source.class.to_s) - File.join(relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" + File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" else File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index b212b50e4..aec4b38d7 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -90,8 +90,4 @@ module ProjectsHelper def render_educoder_avatar_url(project_educoder) [Rails.application.config_for(:configuration)['educoder']['cdn_url'], project_educoder&.image_url].join('/') end - - def render_avatar_url(owner) - ['images', url_to_avatar(owner)].join('/') - end end From 21befb64864e30de72ec81ebb89f4c1a0d46fb40 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 19 Apr 2021 17:28:57 +0800 Subject: [PATCH 078/643] FIX auto generate avatar bug --- app/helpers/application_helper.rb | 2 +- app/models/user/avatar.rb | 13 +++++++++---- config/initializers/letter_avatar.rb | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3af7a5296..b22954bb1 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -149,7 +149,7 @@ module ApplicationHelper File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" end elsif source.class.to_s == 'User' - source.letter_avatar_url + source.get_letter_avatar_url end end diff --git a/app/models/user/avatar.rb b/app/models/user/avatar.rb index 4b62c28fb..7a1a174c3 100644 --- a/app/models/user/avatar.rb +++ b/app/models/user/avatar.rb @@ -1,18 +1,23 @@ require 'letter_avatar/has_avatar' +require 'chinese_pinyin' class User module Avatar extend ActiveSupport::Concern include LetterAvatar::HasAvatar - def name - lastname.blank? ? login : Pinyin.t(lastname) + def username + self.lastname.blank? ? self.login : Pinyin.t(self.lastname) end - def letter_avatar_url(size = :lg) - avatar_url(avatar_size(size)) + def get_letter_avatar_url(size = :lg) + avatar_path(size).split('public/')&.last end + def avatar_path(size) + LetterAvatar.generate self.username, avatar_size(size) + end + # 返回头像尺寸 # xs: 22px # sm: 32px diff --git a/config/initializers/letter_avatar.rb b/config/initializers/letter_avatar.rb index 88f3851e9..3276e2a61 100644 --- a/config/initializers/letter_avatar.rb +++ b/config/initializers/letter_avatar.rb @@ -3,5 +3,5 @@ LetterAvatar.setup do |config| config.cache_base_path = 'public/system/lets' # default is 'public/system' config.colors_palette = :iwanthue # default is :google config.annotate_position = '-0+10' # default is -0+5 - config.letters_count = 2 # default is 1 + # config.letters_count = 2 # default is 1 end From 8a55e84372843682ed14a40d7de40ef347db748c Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 19 Apr 2021 18:34:18 +0800 Subject: [PATCH 079/643] =?UTF-8?q?FIX=20=E8=B0=83=E6=95=B4=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E7=94=9F=E6=88=90=E5=A4=B4=E5=83=8F=E4=B8=AD=E5=AD=97?= =?UTF-8?q?=E6=AF=8D=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/initializers/letter_avatar.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/initializers/letter_avatar.rb b/config/initializers/letter_avatar.rb index 3276e2a61..d3b0ec098 100644 --- a/config/initializers/letter_avatar.rb +++ b/config/initializers/letter_avatar.rb @@ -2,6 +2,8 @@ LetterAvatar.setup do |config| config.fill_color = 'rgba(255, 255, 255, 1)' # default is 'rgba(255, 255, 255, 0.65)' config.cache_base_path = 'public/system/lets' # default is 'public/system' config.colors_palette = :iwanthue # default is :google + # config.weight = 500 # default is 300 config.annotate_position = '-0+10' # default is -0+5 # config.letters_count = 2 # default is 1 + config.pointsize = 300 end From de6ae5b7205d8d2afdb5d6e28c11502759ec4c6b Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 19 Apr 2021 18:36:02 +0800 Subject: [PATCH 080/643] Upate models Schema Information --- app/models/attachment.rb | 8 +-- app/models/chart_rule.rb | 18 ++++++ app/models/ci/stage.rb | 19 ++++++ app/models/ci/user.rb | 12 ++-- app/models/discuss.rb | 35 +++++++++++ app/models/forge_activity.rb | 21 ++++++- app/models/help.rb | 16 ++++- app/models/laboratory.rb | 6 ++ app/models/laboratory_setting.rb | 4 ++ app/models/license.rb | 1 - app/models/live_link.rb | 24 ++++++++ app/models/member.rb | 1 - app/models/message_detail.rb | 15 +++++ app/models/organization.rb | 12 ++-- app/models/project.rb | 9 +-- app/models/project_category.rb | 5 -- app/models/repository.rb | 1 - app/models/school.rb | 36 ++++++++++++ app/models/trustie/course.rb | 85 ++++++++++++++++++++++++++- app/models/trustie/course_group.rb | 24 +++++++- app/models/trustie/homework_common.rb | 53 ++++++++++++++++- app/models/user.rb | 16 +++-- app/models/user_action.rb | 4 +- app/models/user_agent.rb | 5 +- app/models/user_extension.rb | 3 + 25 files changed, 393 insertions(+), 40 deletions(-) diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 461c835fe..1ca173458 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -17,7 +17,7 @@ # disk_directory :string(255) # attachtype :integer default("1") # is_public :integer default("1") -# copy_from :integer +# copy_from :string(255) # quotes :integer default("0") # is_publish :integer default("1") # publish_time :datetime @@ -26,15 +26,15 @@ # cloud_url :string(255) default("") # course_second_category_id :integer default("0") # delay_publish :boolean default("0") +# link :string(255) +# clone_id :integer # # Indexes # # index_attachments_on_author_id (author_id) +# index_attachments_on_clone_id (clone_id) # index_attachments_on_container_id_and_container_type (container_id,container_type) -# index_attachments_on_course_second_category_id (course_second_category_id) # index_attachments_on_created_on (created_on) -# index_attachments_on_is_public (is_public) -# index_attachments_on_quotes (quotes) # class Attachment < ApplicationRecord diff --git a/app/models/chart_rule.rb b/app/models/chart_rule.rb index a0b344e07..26c7f8084 100644 --- a/app/models/chart_rule.rb +++ b/app/models/chart_rule.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: chart_rules +# +# id :integer not null, primary key +# rule_type :string(255) +# content :text(65535) +# created_at :datetime not null +# updated_at :datetime not null +# competition_id :integer +# competition_stage_id :integer +# +# Indexes +# +# index_chart_rules_on_competition_id (competition_id) +# index_chart_rules_on_competition_stage_id (competition_stage_id) +# + class ChartRule < ApplicationRecord validates :content, length: { maximum: 1000, too_long: "不能超过1000个字符" } diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb index 2309f05d4..536e51cf6 100644 --- a/app/models/ci/stage.rb +++ b/app/models/ci/stage.rb @@ -1,3 +1,22 @@ +# == Schema Information +# +# Table name: stages +# +# id :integer not null +# subject_id :integer +# name :string(255) +# description :text(65535) +# user_id :integer +# position :integer +# created_at :datetime not null +# updated_at :datetime not null +# shixuns_count :integer default("0") +# +# Indexes +# +# index_stages_on_subject_id (subject_id) +# + class Ci::Stage < Ci::RemoteBase self.primary_key = 'stage_id' diff --git a/app/models/ci/user.rb b/app/models/ci/user.rb index cd6246753..fc82596c4 100644 --- a/app/models/ci/user.rb +++ b/app/models/ci/user.rb @@ -39,13 +39,14 @@ # business :boolean default("0") # profile_completed :boolean default("0") # laboratory_id :integer -# platform :string(255) default("0") -# gitea_token :string(255) -# gitea_uid :integer # is_shixun_marker :boolean default("0") +# admin_visitable :boolean default("0") +# collaborator :boolean default("0") +# gitea_uid :integer # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") +# gitea_token :string(255) # # Indexes # @@ -53,8 +54,9 @@ # index_users_on_homepage_engineer (homepage_engineer) # index_users_on_homepage_teacher (homepage_teacher) # index_users_on_laboratory_id (laboratory_id) -# index_users_on_login (login) -# index_users_on_mail (mail) +# index_users_on_login (login) UNIQUE +# index_users_on_mail (mail) UNIQUE +# index_users_on_phone (phone) UNIQUE # index_users_on_type (type) # diff --git a/app/models/discuss.rb b/app/models/discuss.rb index a4c833b55..1a2efc606 100644 --- a/app/models/discuss.rb +++ b/app/models/discuss.rb @@ -1,3 +1,38 @@ +# == Schema Information +# +# Table name: discusses +# +# id :integer not null, primary key +# user_id :integer +# dis_type :string(255) +# dis_id :integer +# content :text(65535) +# parent_id :integer +# root_id :integer +# praise_count :integer +# created_at :datetime not null +# updated_at :datetime not null +# challenge_id :integer +# reward :integer +# hidden :boolean default("0") +# last_reply_id :integer +# position :integer +# praises_count :integer default("0") +# sticky :boolean default("0") +# course_sticky :boolean default("0") +# course_hidden :boolean default("0") +# copy_message_id :integer +# +# Indexes +# +# index_discusses_on_challenge_id (challenge_id) +# index_discusses_on_copy_message_id (copy_message_id) +# index_discusses_on_course_hidden (course_hidden) +# index_discusses_on_course_sticky (course_sticky) +# index_discusses_on_dis_id_and_dis_type (dis_id,dis_type) +# index_discusses_on_user_id (user_id) +# + class Discuss < ApplicationRecord default_scope { order(created_at: :desc) } diff --git a/app/models/forge_activity.rb b/app/models/forge_activity.rb index 77103d0ff..b9f11c5a8 100644 --- a/app/models/forge_activity.rb +++ b/app/models/forge_activity.rb @@ -1,5 +1,24 @@ +# == Schema Information +# +# Table name: forge_activities +# +# id :integer not null, primary key +# user_id :integer +# project_id :integer +# forge_act_id :integer +# forge_act_type :string(255) +# org_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# forge_act_index (project_id,forge_act_id,created_at,forge_act_type) +# index_forge_activities_on_forge_act_id (forge_act_id) +# + class ForgeActivity < ApplicationRecord belongs_to :user belongs_to :project belongs_to :forge_act, polymorphic: true -end \ No newline at end of file +end diff --git a/app/models/help.rb b/app/models/help.rb index 2b8bf5813..5a4c480b4 100644 --- a/app/models/help.rb +++ b/app/models/help.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: helps +# +# id :integer not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# about_us :text(65535) +# agreement :text(65535) +# status :text(65535) +# help_center :text(65535) +# join_us :text(65535) +# + class Help < ApplicationRecord -end \ No newline at end of file +end diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb index 73002a841..9d3ca07dd 100644 --- a/app/models/laboratory.rb +++ b/app/models/laboratory.rb @@ -10,6 +10,12 @@ # sync_course :boolean default("0") # sync_subject :boolean default("0") # sync_shixun :boolean default("0") +# is_local :boolean default("0") +# +# Indexes +# +# index_laboratories_on_identifier (identifier) UNIQUE +# index_laboratories_on_school_id (school_id) # class Laboratory < ApplicationRecord diff --git a/app/models/laboratory_setting.rb b/app/models/laboratory_setting.rb index 5013dd547..61c677def 100644 --- a/app/models/laboratory_setting.rb +++ b/app/models/laboratory_setting.rb @@ -6,6 +6,10 @@ # laboratory_id :integer # config :text(65535) # +# Indexes +# +# index_laboratory_settings_on_laboratory_id (laboratory_id) +# class LaboratorySetting < ApplicationRecord belongs_to :laboratory diff --git a/app/models/license.rb b/app/models/license.rb index dcd5528fb..0a14fb85e 100644 --- a/app/models/license.rb +++ b/app/models/license.rb @@ -7,7 +7,6 @@ # content :text(65535) # created_at :datetime not null # updated_at :datetime not null -# is_secret :boolean default("0") # class License < ApplicationRecord diff --git a/app/models/live_link.rb b/app/models/live_link.rb index 9c6531f87..c1c0bf750 100644 --- a/app/models/live_link.rb +++ b/app/models/live_link.rb @@ -1,3 +1,27 @@ +# == Schema Information +# +# Table name: live_links +# +# id :integer not null, primary key +# course_id :integer +# user_id :integer +# url :string(255) +# description :text(65535) +# on_status :boolean default("0") +# created_at :datetime not null +# updated_at :datetime not null +# course_name :string(255) +# platform :string(255) +# live_time :datetime +# duration :integer +# position :integer +# +# Indexes +# +# index_live_links_on_course_id (course_id) +# index_live_links_on_user_id (user_id) +# + class LiveLink < ApplicationRecord # belongs_to :course belongs_to :user diff --git a/app/models/member.rb b/app/models/member.rb index 408710a03..e72ae7c6b 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -11,7 +11,6 @@ # course_group_id :integer default("0") # is_collect :integer default("1") # graduation_group_id :integer default("0") -# is_apply_signature :boolean default("0") # # Indexes # diff --git a/app/models/message_detail.rb b/app/models/message_detail.rb index 51f4b17a9..c009b4744 100644 --- a/app/models/message_detail.rb +++ b/app/models/message_detail.rb @@ -1,3 +1,18 @@ +# == Schema Information +# +# Table name: message_details +# +# id :integer not null, primary key +# content :text(4294967295) +# message_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_message_details_on_message_id (message_id) +# + class MessageDetail < ApplicationRecord # belongs_to :message, :touch => true validates :content, length: { maximum: 10000, too_long: "内容不能超过10000个字符" } diff --git a/app/models/organization.rb b/app/models/organization.rb index 48dab55a2..fbf3def79 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -39,13 +39,14 @@ # business :boolean default("0") # profile_completed :boolean default("0") # laboratory_id :integer -# platform :string(255) default("0") -# gitea_token :string(255) -# gitea_uid :integer # is_shixun_marker :boolean default("0") +# admin_visitable :boolean default("0") +# collaborator :boolean default("0") +# gitea_uid :integer # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") +# gitea_token :string(255) # # Indexes # @@ -53,8 +54,9 @@ # index_users_on_homepage_engineer (homepage_engineer) # index_users_on_homepage_teacher (homepage_teacher) # index_users_on_laboratory_id (laboratory_id) -# index_users_on_login (login) -# index_users_on_mail (mail) +# index_users_on_login (login) UNIQUE +# index_users_on_mail (mail) UNIQUE +# index_users_on_phone (phone) UNIQUE # index_users_on_type (type) # diff --git a/app/models/project.rb b/app/models/project.rb index 9aa6283f6..a25d540cc 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -37,8 +37,6 @@ # rep_identifier :string(255) # project_category_id :integer # project_language_id :integer -# license_id :integer -# ignore_id :integer # praises_count :integer default("0") # watchers_count :integer default("0") # issues_count :integer default("0") @@ -52,8 +50,11 @@ # open_devops_count :integer default("0") # recommend :boolean default("0") # platform :integer default("0") +# license_id :integer +# ignore_id :integer # default_branch :string(255) default("master") # website :string(255) +# lesson_url :string(255) # # Indexes # @@ -70,10 +71,6 @@ # index_projects_on_updated_on (updated_on) # - - - - class Project < ApplicationRecord include Matchable include Publicable diff --git a/app/models/project_category.rb b/app/models/project_category.rb index 3a9819816..67b802998 100644 --- a/app/models/project_category.rb +++ b/app/models/project_category.rb @@ -8,11 +8,6 @@ # projects_count :integer default("0") # created_at :datetime not null # updated_at :datetime not null -# ancestry :string(255) -# -# Indexes -# -# index_project_categories_on_ancestry (ancestry) # class ProjectCategory < ApplicationRecord diff --git a/app/models/repository.rb b/app/models/repository.rb index b6d2321fc..978bc3c57 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -25,7 +25,6 @@ # # Indexes # -# index_repositories_on_identifier (identifier) # index_repositories_on_project_id (project_id) # index_repositories_on_user_id (user_id) # diff --git a/app/models/school.rb b/app/models/school.rb index f3b7ac0ab..5b30be9a5 100644 --- a/app/models/school.rb +++ b/app/models/school.rb @@ -1,3 +1,39 @@ +# == Schema Information +# +# Table name: schools +# +# id :integer not null, primary key +# name :string(255) +# province :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# logo_link :string(255) +# pinyin :string(255) +# school_type :integer default("0") +# city :string(255) +# address :string(255) +# auto_users_trial :boolean default("0") +# shool_code :string(255) +# authorization_time :datetime +# ec_auth :integer default("0") +# identifier :string(255) +# is_online :boolean default("0") +# video_name :string(255) +# video_desc :string(255) +# course_link :string(255) +# course_name :string(255) +# partner_id :integer +# customer_id :integer +# school_property_id :integer +# +# Indexes +# +# index_schools_on_customer_id (customer_id) +# index_schools_on_identifier (identifier) +# index_schools_on_partner_id (partner_id) +# index_schools_on_school_property_id (school_property_id) +# + class School < ApplicationRecord has_many :departments, dependent: :destroy diff --git a/app/models/trustie/course.rb b/app/models/trustie/course.rb index 6cf6411e1..1c951ad68 100644 --- a/app/models/trustie/course.rb +++ b/app/models/trustie/course.rb @@ -1,4 +1,87 @@ +# == Schema Information +# +# Table name: courses +# +# id :integer not null, primary key +# tea_id :integer +# name :string(255) +# state :integer +# code :string(255) +# time :integer +# extra :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# location :string(255) +# term :string(255) +# string :string(255) +# password :string(255) +# setup_time :string(255) +# endup_time :string(255) +# class_period :integer default("0") +# school_id :integer +# description :text(65535) +# status :integer default("1") +# attachmenttype :integer default("2") +# lft :integer +# rgt :integer +# is_public :integer default("1") +# inherit_members :integer default("1") +# open_student :integer default("0") +# outline :integer default("0") +# publish_resource :integer default("0") +# is_delete :integer default("0") +# end_time :integer +# end_term :string(255) +# is_excellent :integer default("0") +# excellent_option :integer default("0") +# is_copy :integer default("0") +# visits :integer default("0") +# syllabus_id :integer +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# invite_code_halt :integer default("0") +# os_allow :integer default("0") +# credit :float(24) +# is_end :boolean default("0") +# end_date :date +# choose_group_allow :boolean default("0") +# homepage_show :boolean default("0") +# course_list_id :integer +# members_count :integer default("0") +# homework_commons_count :integer default("0") +# show_unit :boolean default("0") +# teacher_list :string(255) default("老师") +# student_list :string(255) default("学生") +# is_hidden :boolean default("0") +# course_members_count :integer default("0") +# course_groups_count :integer default("0") +# authentication :boolean default("0") +# professional_certification :boolean default("0") +# graduation_topics_count :integer default("0") +# graduation_tasks_count :integer default("0") +# polls_count :integer default("0") +# exercises_count :integer default("0") +# start_date :date +# subject_id :integer default("0") +# excellent :boolean default("0") +# email_notify :boolean default("0") +# sticky :boolean default("0") +# sticky_time :datetime +# laboratory_id :integer +# mooc_course_id :integer +# +# Indexes +# +# index_courses_on_invite_code (invite_code) UNIQUE +# index_courses_on_laboratory_id (laboratory_id) +# index_courses_on_mooc_course_id (mooc_course_id) +# index_courses_on_school_id_and_is_delete (school_id,is_delete) +# index_courses_on_subject_id (subject_id) +# index_courses_on_tea_id (tea_id) +# + class Trustie::Course < Trustie::Database has_many :course_groups, class_name: "Trustie::CourseGroup" has_many :homework_commons, class_name: "Trustie::HomeworkCommon" -end \ No newline at end of file +end diff --git a/app/models/trustie/course_group.rb b/app/models/trustie/course_group.rb index d9fee73b3..539ddaa11 100644 --- a/app/models/trustie/course_group.rb +++ b/app/models/trustie/course_group.rb @@ -1,3 +1,25 @@ +# == Schema Information +# +# Table name: course_groups +# +# id :integer not null, primary key +# name :string(255) +# course_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# members_count :integer +# invite_code :string(255) +# position :integer default("0") +# course_members_count :integer default("0") +# invite_code_halt :boolean default("0") +# invite_code_set :integer default("0") +# +# Indexes +# +# index_course_groups_on_course_id (course_id) +# index_course_groups_on_invite_code (invite_code) UNIQUE +# + class Trustie::CourseGroup < Trustie::Database belongs_to :course, class_name: "Trustie::Course" -end \ No newline at end of file +end diff --git a/app/models/trustie/homework_common.rb b/app/models/trustie/homework_common.rb index 70dd31e6a..32af834ef 100644 --- a/app/models/trustie/homework_common.rb +++ b/app/models/trustie/homework_common.rb @@ -1,3 +1,54 @@ +# == Schema Information +# +# Table name: homework_commons +# +# id :integer not null, primary key +# name :string(255) +# user_id :integer +# description :text(65535) +# publish_time :datetime +# end_time :datetime +# homework_type :integer default("1") +# late_penalty :string(255) default("0") +# course_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# teacher_priority :integer default("1") +# anonymous_comment :boolean default("0") +# quotes :integer default("0") +# is_open :integer default("0") +# simi_time :datetime +# score_open :boolean default("0") +# anonymous_appeal :boolean default("0") +# homework_bank_id :integer +# is_update :boolean default("0") +# is_public :boolean default("0") +# reference_answer :text(65535) +# answer_public :boolean default("0") +# archive_time :datetime +# allow_late :boolean default("0") +# late_time :datetime +# work_public :boolean default("0") +# explanation :text(65535) +# unified_setting :boolean default("1") +# comment_public :boolean default("1") +# course_homework_category_id :integer +# work_efficiency :boolean default("0") +# eff_score :float(24) default("0") +# max_efficiency :float(24) default("0") +# course_second_category_id :integer default("0") +# calculation_time :datetime +# position :integer default("0") +# total_score :float(24) default("100") +# category_position :integer default("0") +# +# Indexes +# +# index_homework_commons_on_course_id_and_id (course_id,id) +# index_homework_commons_on_course_second_category_id (course_second_category_id) +# index_homework_commons_on_homework_bank_id (homework_bank_id) +# + class Trustie::HomeworkCommon < Trustie::Database belongs_to :course, class_name: "Trustie::Course" -end \ No newline at end of file +end diff --git a/app/models/user.rb b/app/models/user.rb index 20b3a8543..2bc2dc2c9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -39,13 +39,14 @@ # business :boolean default("0") # profile_completed :boolean default("0") # laboratory_id :integer -# platform :string(255) default("0") -# gitea_token :string(255) -# gitea_uid :integer # is_shixun_marker :boolean default("0") +# admin_visitable :boolean default("0") +# collaborator :boolean default("0") +# gitea_uid :integer # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") +# gitea_token :string(255) # # Indexes # @@ -53,8 +54,9 @@ # index_users_on_homepage_engineer (homepage_engineer) # index_users_on_homepage_teacher (homepage_teacher) # index_users_on_laboratory_id (laboratory_id) -# index_users_on_login (login) -# index_users_on_mail (mail) +# index_users_on_login (login) UNIQUE +# index_users_on_mail (mail) UNIQUE +# index_users_on_phone (phone) UNIQUE # index_users_on_type (type) # @@ -190,6 +192,10 @@ class User < Owner validate :validate_sensitive_string validate :validate_password_length + def name + login + end + # 删除自动登录的token,一旦退出下次会提示需要登录 def delete_autologin_token(value) Token.where(:user_id => id, :action => 'autologin', :value => value).delete_all diff --git a/app/models/user_action.rb b/app/models/user_action.rb index 3ad8010ea..179359695 100644 --- a/app/models/user_action.rb +++ b/app/models/user_action.rb @@ -12,7 +12,9 @@ # # Indexes # -# index_user_actions_on_ip (ip) +# index_user_actions_on_ip (ip) +# index_user_actions_on_user_id (user_id) +# index_user_actions_on_user_id_and_action_type (user_id,action_type) # class UserAction < ApplicationRecord diff --git a/app/models/user_agent.rb b/app/models/user_agent.rb index 49d7b35a1..ba519d6fb 100644 --- a/app/models/user_agent.rb +++ b/app/models/user_agent.rb @@ -10,10 +10,13 @@ # updated_at :datetime not null # register_status :integer default("0") # action_status :integer default("0") +# is_delete :boolean default("0") +# user_id :integer # # Indexes # -# index_user_agents_on_ip (ip) UNIQUE +# index_user_agents_on_ip (ip) +# index_user_agents_on_user_id (user_id) # class UserAgent < ApplicationRecord diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 20e2b5c4f..4afd89bd5 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -22,6 +22,9 @@ # school_id :integer # description :string(255) default("") # department_id :integer +# honor :text(65535) +# edu_background :integer +# edu_entry_year :integer # # Indexes # From 3a47c61010c99fa0a43d3775321c0c9df6f713f0 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 10:54:36 +0800 Subject: [PATCH 081/643] add: team nickname --- app/controllers/organizations/teams_controller.rb | 2 +- app/models/team.rb | 1 + app/views/organizations/teams/_detail.json.jbuilder | 1 + db/migrate/20210419023310_add_nickname_to_teams.rb | 5 +++++ 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20210419023310_add_nickname_to_teams.rb diff --git a/app/controllers/organizations/teams_controller.rb b/app/controllers/organizations/teams_controller.rb index 5bc01fe39..04b748c8a 100644 --- a/app/controllers/organizations/teams_controller.rb +++ b/app/controllers/organizations/teams_controller.rb @@ -60,7 +60,7 @@ class Organizations::TeamsController < Organizations::BaseController private def team_params - params.permit(:name, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types => []) + params.permit(:name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types => []) end def load_organization diff --git a/app/models/team.rb b/app/models/team.rb index 82a3e88c1..d17827da8 100644 --- a/app/models/team.rb +++ b/app/models/team.rb @@ -14,6 +14,7 @@ # gtid :integer # created_at :datetime not null # updated_at :datetime not null +# nickname :string(255) # # Indexes # diff --git a/app/views/organizations/teams/_detail.json.jbuilder b/app/views/organizations/teams/_detail.json.jbuilder index 4f3588cb9..cb0507b5a 100644 --- a/app/views/organizations/teams/_detail.json.jbuilder +++ b/app/views/organizations/teams/_detail.json.jbuilder @@ -1,5 +1,6 @@ json.id team.id json.name team.name +json.nickname team.nickname json.description team.description json.authorize team.authorize json.includes_all_project team.includes_all_project diff --git a/db/migrate/20210419023310_add_nickname_to_teams.rb b/db/migrate/20210419023310_add_nickname_to_teams.rb new file mode 100644 index 000000000..ed80f1935 --- /dev/null +++ b/db/migrate/20210419023310_add_nickname_to_teams.rb @@ -0,0 +1,5 @@ +class AddNicknameToTeams < ActiveRecord::Migration[5.2] + def change + add_column :teams, :nickname, :string + end +end From f0c4d1226b7666f621545405dcd18ad7eba7b02f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 11:26:30 +0800 Subject: [PATCH 082/643] fix: org not need create member --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index a25d540cc..b4fd7da32 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -158,7 +158,7 @@ class Project < ApplicationRecord #创建项目管理员 def check_project_members - unless members.present? && members.exists?(user_id: self.user_id) + unless members.present? && member?(user_id) member_params = { user_id: self.user_id, project_id: self.id From f75827bcf01f1311a5c955e73f5b44f7eef7d3d1 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 11:35:12 +0800 Subject: [PATCH 083/643] fix: org not need create member --- app/models/project.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index b4fd7da32..da1a8615b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -158,7 +158,8 @@ class Project < ApplicationRecord #创建项目管理员 def check_project_members - unless members.present? && member?(user_id) + return if owner.is_a?(Organization) + unless members.present? && members.exists?(user_id: self.user_id) member_params = { user_id: self.user_id, project_id: self.id From 5a9f29c25f42c7e2e6ec4b5ba7d81f0cefe9dba5 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 11:40:38 +0800 Subject: [PATCH 084/643] fix --- app/views/organizations/teams/_detail.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/organizations/teams/_detail.json.jbuilder b/app/views/organizations/teams/_detail.json.jbuilder index cb0507b5a..68572814f 100644 --- a/app/views/organizations/teams/_detail.json.jbuilder +++ b/app/views/organizations/teams/_detail.json.jbuilder @@ -1,6 +1,6 @@ json.id team.id json.name team.name -json.nickname team.nickname +json.nickname team.nickname.blank? ? team.name : team.nickname json.description team.description json.authorize team.authorize json.includes_all_project team.includes_all_project From a3c49b3d5f3ad46e2346b6520503ddefb7dfb759 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 12:07:12 +0800 Subject: [PATCH 085/643] add: org valid --- app/controllers/organizations/organizations_controller.rb | 1 + app/controllers/organizations/teams_controller.rb | 5 ++++- app/forms/organizations/create_form.rb | 8 ++++++++ app/forms/organizations/create_team_form.rb | 8 ++++++++ .../organizations/organizations/_detail.json.jbuilder | 2 +- 5 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 app/forms/organizations/create_form.rb create mode 100644 app/forms/organizations/create_team_form.rb diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index 73335cf11..09c12fd5a 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -25,6 +25,7 @@ class Organizations::OrganizationsController < Organizations::BaseController def create ActiveRecord::Base.transaction do + Organizations::CreateForm.new(organization_params).validate! @organization = Organizations::CreateService.call(current_user, organization_params) Util.write_file(@image, avatar_path(@organization)) if params[:image].present? end diff --git a/app/controllers/organizations/teams_controller.rb b/app/controllers/organizations/teams_controller.rb index 04b748c8a..a8d06ce46 100644 --- a/app/controllers/organizations/teams_controller.rb +++ b/app/controllers/organizations/teams_controller.rb @@ -33,7 +33,10 @@ class Organizations::TeamsController < Organizations::BaseController end def create - @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) + ActiveRecord::Base.transaction do + Organizations::CreateTeamForm.new(team_params).validate! + @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) + end rescue Exception => e uid_logger_error(e.message) tip_exception(e.message) diff --git a/app/forms/organizations/create_form.rb b/app/forms/organizations/create_form.rb new file mode 100644 index 000000000..00c1dd15e --- /dev/null +++ b/app/forms/organizations/create_form.rb @@ -0,0 +1,8 @@ +class Organizations::CreateForm < BaseForm + NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 + attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname + + validates :name, :nickname, :visibility, presence: true + validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + +end diff --git a/app/forms/organizations/create_team_form.rb b/app/forms/organizations/create_team_form.rb new file mode 100644 index 000000000..67b81c5f2 --- /dev/null +++ b/app/forms/organizations/create_team_form.rb @@ -0,0 +1,8 @@ +class Organizations::CreateTeamForm < BaseForm + NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 + attr_accessor :name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types + + validates :name, :nickname, :authorize, :includes_all_project, presence: true + validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + +end diff --git a/app/views/organizations/organizations/_detail.json.jbuilder b/app/views/organizations/organizations/_detail.json.jbuilder index 64feadca1..4a8b512b9 100644 --- a/app/views/organizations/organizations/_detail.json.jbuilder +++ b/app/views/organizations/organizations/_detail.json.jbuilder @@ -1,6 +1,6 @@ json.id organization.id json.name organization.login -json.nickname organization.nickname +json.nickname organization.nickname.blank? ? organization.name : organization.nickname json.description organization.description json.website organization.website json.location organization.location From 55e081ba2b1f8668dfb1d6eb554b3d8715ebd7a0 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 12:09:38 +0800 Subject: [PATCH 086/643] fix --- app/forms/organizations/create_team_form.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/forms/organizations/create_team_form.rb b/app/forms/organizations/create_team_form.rb index 67b81c5f2..898d69a1d 100644 --- a/app/forms/organizations/create_team_form.rb +++ b/app/forms/organizations/create_team_form.rb @@ -2,7 +2,7 @@ class Organizations::CreateTeamForm < BaseForm NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 attr_accessor :name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types - validates :name, :nickname, :authorize, :includes_all_project, presence: true + validates :name, :nickname, :authorize, presence: true validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } end From 2976742b293aff9745ca74af6bc197ac5665bf21 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 19 Apr 2021 12:14:11 +0800 Subject: [PATCH 087/643] fix: org team nickname change error --- app/services/organizations/teams/update_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/organizations/teams/update_service.rb b/app/services/organizations/teams/update_service.rb index 71c82c40b..b5b273d8a 100644 --- a/app/services/organizations/teams/update_service.rb +++ b/app/services/organizations/teams/update_service.rb @@ -27,7 +27,7 @@ class Organizations::Teams::UpdateService < ApplicationService if team.authorize == "owner" update_params = params.slice(:description) else - update_params = params.slice(:name, :description, :authorize, :includes_all_project, :can_create_org_project) + update_params = params.slice(:name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project) end update_params end From da98efe04f9447266aa48904054414aac977517c Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 20 Apr 2021 10:49:47 +0800 Subject: [PATCH 088/643] add: org project field --- app/views/organizations/team_projects/_detail.json.jbuilder | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/organizations/team_projects/_detail.json.jbuilder b/app/views/organizations/team_projects/_detail.json.jbuilder index 9af32d1df..dde707002 100644 --- a/app/views/organizations/team_projects/_detail.json.jbuilder +++ b/app/views/organizations/team_projects/_detail.json.jbuilder @@ -1,6 +1,7 @@ json.id team_project.id json.project do - json.owner_name team_project&.project&.owner&.login + json.owner_login team_project&.project&.owner&.login + json.owner_name team_project&.project&.owner&.real_name json.owner_image_url url_to_avatar(team_project&.project&.owner) json.name team_project&.project&.name json.identifier team_project&.project&.identifier From 84e48d25c1b5c0327330f8a2a7d4bb197c6e9713 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 20 Apr 2021 18:35:41 +0800 Subject: [PATCH 089/643] =?UTF-8?q?FIX=20render=20user=20bug=20with=20=20p?= =?UTF-8?q?ull=E2=80=98s=20commits=20and=20repo's=20commits=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/pull_requests/_commit.json.jbuilder | 4 ++-- app/views/repositories/commits.json.jbuilder | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/views/pull_requests/_commit.json.jbuilder b/app/views/pull_requests/_commit.json.jbuilder index 072e53c91..7a9232efe 100644 --- a/app/views/pull_requests/_commit.json.jbuilder +++ b/app/views/pull_requests/_commit.json.jbuilder @@ -1,10 +1,10 @@ json.author do - author = User.find_by(login: commit['Author']['Name']) + author = User.find_by(mail: commit['Author']['Email']) json.partial! 'repositories/commit_author', locals: { user: author, name: commit['Committer']['Name'] } end json.committer do - author = User.find_by(login: commit['Committer']['Name']) + author = User.find_by(mail: commit['Committer']['Email']) json.partial! 'repositories/commit_author', locals: { user: author, name: commit['Committer']['Name'] } end json.timestamp render_unix_time(commit['Committer']['When']) diff --git a/app/views/repositories/commits.json.jbuilder b/app/views/repositories/commits.json.jbuilder index 82cd17133..d123daf54 100644 --- a/app/views/repositories/commits.json.jbuilder +++ b/app/views/repositories/commits.json.jbuilder @@ -5,12 +5,15 @@ else json.total_count @hash_commit[:total_count] json.commits do json.array! @hash_commit[:body] do |commit| - json.commit1 commit commiter = commit['committer'] - if commiter.present? - commit_user_id = commiter['id'] - forge_user = User.simple_select.find_by(gitea_uid: commit_user_id) - end + + forge_user = + if commiter.present? + User.simple_select.find_by(mail: commiter['email']) + else + User.simple_select.find_by(mail: commit['commit']['committer']['email']) + end + json.sha commit['sha'] json.message commit['commit']['message'] json.timestamp render_unix_time(commit['commit']['author']['date']) From 45f05c9fc475721efe2769d622f42dea9b74fb20 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 20 Apr 2021 18:58:14 +0800 Subject: [PATCH 090/643] FIX render commmiter and author avatar bug --- app/models/user/avatar.rb | 11 ++++++++--- app/views/repositories/_commit_author.json.jbuilder | 2 +- app/views/repositories/commits.json.jbuilder | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/models/user/avatar.rb b/app/models/user/avatar.rb index 7a1a174c3..d6f88bb01 100644 --- a/app/models/user/avatar.rb +++ b/app/models/user/avatar.rb @@ -11,11 +11,16 @@ class User end def get_letter_avatar_url(size = :lg) - avatar_path(size).split('public/')&.last + avatar_path(self.username, size).split('public/')&.last end - def avatar_path(size) - LetterAvatar.generate self.username, avatar_size(size) + def self.get_letter_avatar_url(name, size = :lg) + return "" if name.blank? + avatar_path(Pinyin.t(name), size).split('public/')&.last + end + + def avatar_path(username, size) + LetterAvatar.generate username, avatar_size(size) end # 返回头像尺寸 diff --git a/app/views/repositories/_commit_author.json.jbuilder b/app/views/repositories/_commit_author.json.jbuilder index d57e7c534..fec311426 100644 --- a/app/views/repositories/_commit_author.json.jbuilder +++ b/app/views/repositories/_commit_author.json.jbuilder @@ -7,5 +7,5 @@ else json.id nil json.login name json.name name - json.image_url File.join("avatars/User","b") + json.image_url User.get_letter_avatar_url(name) end diff --git a/app/views/repositories/commits.json.jbuilder b/app/views/repositories/commits.json.jbuilder index d123daf54..750976e55 100644 --- a/app/views/repositories/commits.json.jbuilder +++ b/app/views/repositories/commits.json.jbuilder @@ -26,7 +26,7 @@ else json.login commit['commit']['author']['name'] json.type nil json.name commit['commit']['author']['name'] - json.image_url File.join("avatars/User","b") + json.image_url User.get_letter_avatar_url(commit['commit']['author']['name']) end end end From 002c7737469a8793ccc902f36044175f6744ca96 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 20 Apr 2021 19:06:31 +0800 Subject: [PATCH 091/643] FIX code bug --- app/models/user/avatar.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/user/avatar.rb b/app/models/user/avatar.rb index d6f88bb01..22f770cdd 100644 --- a/app/models/user/avatar.rb +++ b/app/models/user/avatar.rb @@ -14,9 +14,10 @@ class User avatar_path(self.username, size).split('public/')&.last end - def self.get_letter_avatar_url(name, size = :lg) + def self.get_letter_avatar_url(name) return "" if name.blank? - avatar_path(Pinyin.t(name), size).split('public/')&.last + avatar = LetterAvatar.generate Pinyin.t(name), 120 + avatar.split('public/')&.last end def avatar_path(username, size) From 6a3d297b30aec6b35cb3ff2edfff21188f1c3fbd Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 20 Apr 2021 19:07:48 +0800 Subject: [PATCH 092/643] FIX code bug --- app/views/repositories/_commit_author.json.jbuilder | 2 +- app/views/repositories/commits.json.jbuilder | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/repositories/_commit_author.json.jbuilder b/app/views/repositories/_commit_author.json.jbuilder index fec311426..1478cca0e 100644 --- a/app/views/repositories/_commit_author.json.jbuilder +++ b/app/views/repositories/_commit_author.json.jbuilder @@ -7,5 +7,5 @@ else json.id nil json.login name json.name name - json.image_url User.get_letter_avatar_url(name) + json.image_url User::Avatar.get_letter_avatar_url(name) end diff --git a/app/views/repositories/commits.json.jbuilder b/app/views/repositories/commits.json.jbuilder index 750976e55..16744858e 100644 --- a/app/views/repositories/commits.json.jbuilder +++ b/app/views/repositories/commits.json.jbuilder @@ -26,7 +26,7 @@ else json.login commit['commit']['author']['name'] json.type nil json.name commit['commit']['author']['name'] - json.image_url User.get_letter_avatar_url(commit['commit']['author']['name']) + json.image_url User::Avatar.get_letter_avatar_url(commit['commit']['author']['name']) end end end From 841778900c25dfc9d083fa8be03d16ef806e99e2 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 22 Apr 2021 16:35:54 +0800 Subject: [PATCH 093/643] FIX code review --- app/views/users/courses/index.json.jbuilder | 3 -- .../courses/shared/_course.json.jbuilder | 18 ----------- app/views/users/shixuns/index.json.jbuilder | 3 -- .../shixuns/shared/_shixun.json.jbuilder | 10 ------- app/views/users/videos/_video.json.jbuilder | 6 ---- app/views/users/videos/index.json.jbuilder | 2 -- app/views/users/videos/review.json.jbuilder | 7 ----- app/views/users/videos/update.json.jbuilder | 1 - .../weapps/code_sessions/create.json.jbuilder | 3 -- .../weapps/courses/basic_info.json.jbuilder | 8 ----- .../courses/course_activities.json.jbuilder | 12 -------- app/views/weapps/courses/edit.json.jbuilder | 2 -- .../shixun_homework_category.json.jbuilder | 3 -- app/views/weapps/courses/show.json.jbuilder | 4 --- .../weapps/courses/students.json.jbuilder | 7 ----- .../weapps/courses/teachers.json.jbuilder | 3 -- app/views/weapps/homes/show.json.jbuilder | 30 ------------------- .../weapps/registers/create.json.jbuilder | 4 --- app/views/weapps/searchs/index.json.jbuilder | 14 --------- .../weapps/sessions/create.json.jbuilder | 3 -- app/views/weapps/shared/_user.json.jbuilder | 15 ---------- .../weapps/unbind_accounts/show.json.jbuilder | 1 - 22 files changed, 159 deletions(-) delete mode 100644 app/views/users/courses/index.json.jbuilder delete mode 100644 app/views/users/courses/shared/_course.json.jbuilder delete mode 100644 app/views/users/shixuns/index.json.jbuilder delete mode 100644 app/views/users/shixuns/shared/_shixun.json.jbuilder delete mode 100644 app/views/users/videos/_video.json.jbuilder delete mode 100644 app/views/users/videos/index.json.jbuilder delete mode 100644 app/views/users/videos/review.json.jbuilder delete mode 100644 app/views/users/videos/update.json.jbuilder delete mode 100644 app/views/weapps/code_sessions/create.json.jbuilder delete mode 100644 app/views/weapps/courses/basic_info.json.jbuilder delete mode 100644 app/views/weapps/courses/course_activities.json.jbuilder delete mode 100644 app/views/weapps/courses/edit.json.jbuilder delete mode 100644 app/views/weapps/courses/shixun_homework_category.json.jbuilder delete mode 100644 app/views/weapps/courses/show.json.jbuilder delete mode 100644 app/views/weapps/courses/students.json.jbuilder delete mode 100644 app/views/weapps/courses/teachers.json.jbuilder delete mode 100644 app/views/weapps/homes/show.json.jbuilder delete mode 100644 app/views/weapps/registers/create.json.jbuilder delete mode 100644 app/views/weapps/searchs/index.json.jbuilder delete mode 100644 app/views/weapps/sessions/create.json.jbuilder delete mode 100644 app/views/weapps/shared/_user.json.jbuilder delete mode 100644 app/views/weapps/unbind_accounts/show.json.jbuilder diff --git a/app/views/users/courses/index.json.jbuilder b/app/views/users/courses/index.json.jbuilder deleted file mode 100644 index 614e06391..000000000 --- a/app/views/users/courses/index.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ - -json.count @count -json.courses @courses, partial: 'users/courses/shared/course', as: :course diff --git a/app/views/users/courses/shared/_course.json.jbuilder b/app/views/users/courses/shared/_course.json.jbuilder deleted file mode 100644 index a0c5ddc73..000000000 --- a/app/views/users/courses/shared/_course.json.jbuilder +++ /dev/null @@ -1,18 +0,0 @@ -json.id course.id -json.name course.name -# json.members_count course.members_count -json.members_count course.course_members_count -# json.homework_commons_count course.homework_commons_count -json.homework_commons_count get_tasks_count course -json.attachments_count course.attachments.count -json.visits course.visits -json.school course.school&.name - -json.first_category_url module_url(course.course_modules.where(hidden: 0).order(position: :desc).first, course) - -json.is_public course.is_public -json.can_visited observed_logged_user? || course.can_visited? - -json.teacher do - json.partial! 'users/shared/real_user', user: course.teacher -end \ No newline at end of file diff --git a/app/views/users/shixuns/index.json.jbuilder b/app/views/users/shixuns/index.json.jbuilder deleted file mode 100644 index a5321f1cd..000000000 --- a/app/views/users/shixuns/index.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ - -json.count @count -json.shixuns @shixuns, partial: 'users/shixuns/shared/shixun', as: :shixun, locals: { user: observed_user } diff --git a/app/views/users/shixuns/shared/_shixun.json.jbuilder b/app/views/users/shixuns/shared/_shixun.json.jbuilder deleted file mode 100644 index 663522e53..000000000 --- a/app/views/users/shixuns/shared/_shixun.json.jbuilder +++ /dev/null @@ -1,10 +0,0 @@ -json.id shixun.id -json.identifier shixun.identifier -json.tag shixun.first_tag_repertoire&.name -json.image_url url_to_avatar(shixun) -json.name shixun.name -json.status shixun.status -json.human_status shixun.human_status -json.challenges_count shixun.challenges_count -json.finished_challenges_count @finished_challenges_count_map&.fetch(shixun.id, 0) || shixun.finished_challenges_count(user) -json.is_jupyter shixun.is_jupyter \ No newline at end of file diff --git a/app/views/users/videos/_video.json.jbuilder b/app/views/users/videos/_video.json.jbuilder deleted file mode 100644 index 1e09ca4b9..000000000 --- a/app/views/users/videos/_video.json.jbuilder +++ /dev/null @@ -1,6 +0,0 @@ -json.extract! video, :id, :title, :cover_url, :file_url, :play_url, :vv, :user_id - -json.play_duration video.video_play_duration -json.published_at video.display_published_at -json.created_at video.display_created_at -json.updated_at video.display_updated_at \ No newline at end of file diff --git a/app/views/users/videos/index.json.jbuilder b/app/views/users/videos/index.json.jbuilder deleted file mode 100644 index f4a34aa00..000000000 --- a/app/views/users/videos/index.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.count @count -json.videos @videos, partial: 'video', as: :video \ No newline at end of file diff --git a/app/views/users/videos/review.json.jbuilder b/app/views/users/videos/review.json.jbuilder deleted file mode 100644 index 3e0fe8b93..000000000 --- a/app/views/users/videos/review.json.jbuilder +++ /dev/null @@ -1,7 +0,0 @@ -json.count @count -json.videos do - json.array! @videos.each do |video| - json.partial! 'video', video: video - json.file_url nil - end -end \ No newline at end of file diff --git a/app/views/users/videos/update.json.jbuilder b/app/views/users/videos/update.json.jbuilder deleted file mode 100644 index ed69a174c..000000000 --- a/app/views/users/videos/update.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'video', video: current_video \ No newline at end of file diff --git a/app/views/weapps/code_sessions/create.json.jbuilder b/app/views/weapps/code_sessions/create.json.jbuilder deleted file mode 100644 index 280086948..000000000 --- a/app/views/weapps/code_sessions/create.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.user do - json.partial! 'weapps/shared/user', locals: { user: current_user } -end \ No newline at end of file diff --git a/app/views/weapps/courses/basic_info.json.jbuilder b/app/views/weapps/courses/basic_info.json.jbuilder deleted file mode 100644 index 09639072d..000000000 --- a/app/views/weapps/courses/basic_info.json.jbuilder +++ /dev/null @@ -1,8 +0,0 @@ -json.course do - json.(@course, :id, :name) - json.code_halt @course.invite_code_halt == 1 - json.invite_code @course.invite_code_halt == 0 ? @course.generate_invite_code : "" - json.teacher_name @course.teacher.real_name - json.teacher_img url_to_avatar(@course.teacher) - json.teacher_school @course.school.try(:name) -end \ No newline at end of file diff --git a/app/views/weapps/courses/course_activities.json.jbuilder b/app/views/weapps/courses/course_activities.json.jbuilder deleted file mode 100644 index 498189cf8..000000000 --- a/app/views/weapps/courses/course_activities.json.jbuilder +++ /dev/null @@ -1,12 +0,0 @@ -json.activities @activities do |activity| - json.(activity, :course_act_id, :course_act_type) - json.author do - user = activity.user - json.name user.real_name - json.login user.login - json.img url_to_avatar(user) - end - json.created_at activity.created_at.strftime('%m-%d %H:%M:') - json.container_name activity.container_name - json.container_type activity.course_act_type == "HomeworkCommon" ? activity.course_act&.homework_type : "" -end \ No newline at end of file diff --git a/app/views/weapps/courses/edit.json.jbuilder b/app/views/weapps/courses/edit.json.jbuilder deleted file mode 100644 index 1b7d5aaa2..000000000 --- a/app/views/weapps/courses/edit.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.(@course, :id, :name, :credit, :end_date) -json.course_list_name @course.course_list&.name \ No newline at end of file diff --git a/app/views/weapps/courses/shixun_homework_category.json.jbuilder b/app/views/weapps/courses/shixun_homework_category.json.jbuilder deleted file mode 100644 index b38748597..000000000 --- a/app/views/weapps/courses/shixun_homework_category.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.categories @categories.each do |category| - json.(category, :id, :name) -end \ No newline at end of file diff --git a/app/views/weapps/courses/show.json.jbuilder b/app/views/weapps/courses/show.json.jbuilder deleted file mode 100644 index c22b24426..000000000 --- a/app/views/weapps/courses/show.json.jbuilder +++ /dev/null @@ -1,4 +0,0 @@ -json.(@course, :id, :name, :course_members_count, :credit, :invite_code_halt) -json.teachers_count @course.teachers.count -json.students_count @course.students.count -json.course_identity @current_user.course_identity(@course) \ No newline at end of file diff --git a/app/views/weapps/courses/students.json.jbuilder b/app/views/weapps/courses/students.json.jbuilder deleted file mode 100644 index 8c51393f0..000000000 --- a/app/views/weapps/courses/students.json.jbuilder +++ /dev/null @@ -1,7 +0,0 @@ -json.students student_list @students, @course.excellent, @user_course_identity -json.students_count @students_count -if @course_group - json.course_group do - json.(@course_group, :id, :name, :invite_code, :course_members_count) - end -end \ No newline at end of file diff --git a/app/views/weapps/courses/teachers.json.jbuilder b/app/views/weapps/courses/teachers.json.jbuilder deleted file mode 100644 index 684c12517..000000000 --- a/app/views/weapps/courses/teachers.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.teacher_list teacher_list(@teacher_list, @user_course_identity) -json.teacher_list_size @teacher_list_size -json.apply_size @applications_size \ No newline at end of file diff --git a/app/views/weapps/homes/show.json.jbuilder b/app/views/weapps/homes/show.json.jbuilder deleted file mode 100644 index f307d64fe..000000000 --- a/app/views/weapps/homes/show.json.jbuilder +++ /dev/null @@ -1,30 +0,0 @@ -json.carousels do - json.array! @carousels do |carousel| - json.extract! carousel, :id, :link, :position - - json.path carousel.link - json.image_url Util::FileManage.source_disk_file_url(carousel) - end -end - -if @advert.present? - json.advert do - json.extract! @advert, :id, :link - json.image_url Util::FileManage.source_disk_file_url(@advert) - end -else - json.advert nil -end - -json.course_count @course_count -json.courses @courses.each do |course| - json.(course, :id, :name, :visits, :course_members_count, :is_end, :invite_code_halt) - json.creator course.teacher.real_name - json.avatar_url url_to_avatar(course.teacher) - json.invite_code course.invite_code_halt == 0 ? course.generate_invite_code : "" - json.school course.school&.name - course_member = @category == "study" ? course.students.where(user_id: @user.id).first : course.teachers.where(user_id: @user.id).first - json.sticky course_member.sticky - json.course_identity current_user.course_identity(course) -end - diff --git a/app/views/weapps/registers/create.json.jbuilder b/app/views/weapps/registers/create.json.jbuilder deleted file mode 100644 index 0cfb5e30f..000000000 --- a/app/views/weapps/registers/create.json.jbuilder +++ /dev/null @@ -1,4 +0,0 @@ -json.status 0 -json.user do - json.partial! 'weapps/shared/user', locals: { user: @user } -end \ No newline at end of file diff --git a/app/views/weapps/searchs/index.json.jbuilder b/app/views/weapps/searchs/index.json.jbuilder deleted file mode 100644 index 11855fb77..000000000 --- a/app/views/weapps/searchs/index.json.jbuilder +++ /dev/null @@ -1,14 +0,0 @@ -json.count @results.total_count -json.results do - json.array! @results.with_highlights(multiple: true) do |obj, highlights| - json.merge! obj.to_searchable_json - json.type obj.class.name.downcase - - json.title highlights.delete(:name)&.join('...') || obj.searchable_title - json.cover url_to_avatar(obj) - - if obj.is_a?(Course) - json.author_avatar_url url_to_avatar(obj.teacher) - end - end -end \ No newline at end of file diff --git a/app/views/weapps/sessions/create.json.jbuilder b/app/views/weapps/sessions/create.json.jbuilder deleted file mode 100644 index 280086948..000000000 --- a/app/views/weapps/sessions/create.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.user do - json.partial! 'weapps/shared/user', locals: { user: current_user } -end \ No newline at end of file diff --git a/app/views/weapps/shared/_user.json.jbuilder b/app/views/weapps/shared/_user.json.jbuilder deleted file mode 100644 index 53212ec15..000000000 --- a/app/views/weapps/shared/_user.json.jbuilder +++ /dev/null @@ -1,15 +0,0 @@ -json.username user.full_name -json.real_name user.real_name -json.login user.login -json.user_id user.id -json.image_url url_to_avatar(user) -json.admin user.admin? -json.business user.business? -json.is_teacher user.user_extension&.teacher? -json.user_identity user.identity -json.identity user.user_extension&.identity -json.tidding_count 0 -json.user_phone_binded user.phone.present? -json.phone user.phone -json.profile_completed user.profile_completed? -json.professional_certification user.professional_certification \ No newline at end of file diff --git a/app/views/weapps/unbind_accounts/show.json.jbuilder b/app/views/weapps/unbind_accounts/show.json.jbuilder deleted file mode 100644 index c4223a021..000000000 --- a/app/views/weapps/unbind_accounts/show.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.user_account @user.phone.present? ? @user.phone : (@user.mail.present? ? @user.mail : @user.login) From 908cda56f39e15bceced9ab25017a54dfba9fb7b Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 22 Apr 2021 16:36:40 +0800 Subject: [PATCH 094/643] ADD users/hovercard api --- app/controllers/users_controller.rb | 7 +++++-- app/helpers/application_helper.rb | 6 ------ app/models/concerns/watchable.rb | 19 +++++++++++++++++++ app/models/user.rb | 4 ---- app/views/users/hovercard.json.jbuilder | 15 +++++++++++++++ config/routes.rb | 1 + 6 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 app/views/users/hovercard.json.jbuilder diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 14c296906..7f49ab614 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,8 +2,8 @@ class UsersController < ApplicationController include ApplicationHelper include Ci::DbConnectable - 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 :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard] + before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard] before_action :require_login, only: %i[me list sync_user_info] before_action :connect_to_ci_db, only: [:get_user_info] skip_before_action :check_sign, only: [:attachment_show] @@ -56,6 +56,9 @@ class UsersController < ApplicationController @watchers = paginate(watchers) end + def hovercard + end + def update @user = User.find params[:id] @user.update!(user_params) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b22954bb1..ccc45df0e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -35,12 +35,6 @@ module ApplicationHelper course.course_modules.find_by(module_type: "graduation").try(:id) end - # 是否关注 - # from_user_id为被关注的用户 - def follow?(from_user_id, user_id) - Watcher.where(watchable_type: 'Principal', watchable_id: from_user_id, user_id: user_id).exists? - end - # git用户 # git用户命名规则:login+"@educoder.net" def git_username(email) diff --git a/app/models/concerns/watchable.rb b/app/models/concerns/watchable.rb index 4c52cf99a..3ab43d95a 100644 --- a/app/models/concerns/watchable.rb +++ b/app/models/concerns/watchable.rb @@ -6,6 +6,7 @@ module Watchable has_many :watcher_users, through: :watchers, source: :user, validate: false scope :watched_by, -> (user_id) { includes(:watchers).where(watchers: { user_id: user_id }) } + scope :following, -> (user_id) { watched_by } end def watched?(watchable) @@ -21,6 +22,24 @@ module Watchable obj.destroy! if obj.present? end + # 我正在关注的、我追随的 + def following + User.following(self.id) + end + + def following_count + following.size + end + + # 关注我的、我的粉丝、我的追随者 + def followers + watcher_users + end + + def followers_count + followers.size + end + module ClassMethods end end diff --git a/app/models/user.rb b/app/models/user.rb index 2bc2dc2c9..e16e5ca02 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -137,10 +137,6 @@ class User < Owner has_many :attachments,foreign_key: :author_id, :dependent => :destroy - # 关注 - # has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注 - # has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户 - has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', dependent: :destroy # 认证 diff --git a/app/views/users/hovercard.json.jbuilder b/app/views/users/hovercard.json.jbuilder new file mode 100644 index 000000000..d74a14314 --- /dev/null +++ b/app/views/users/hovercard.json.jbuilder @@ -0,0 +1,15 @@ +json.id @user.id +json.login @user.login +json.name @user.full_name +json.image_url url_to_avatar(@user) +json.url "#{request.base_url }/users/#{@user.login}" +json.followers_count @user.followers_count +json.following_count @user.following_count +json.projects_count @user.projects_count +json.is_watch current_user&.watched?(@user) +json.organizations @user.organizations do |organization| + json.login organization.login + json.name organization.full_name + json.image_url url_to_avatar(organization) + json.url "#{request.base_url }/organize/#{organization.login}" +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 66c9d97af..bbcc29231 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -198,6 +198,7 @@ Rails.application.routes.draw do get :projects get :watch_users get :fan_users + get :hovercard end collection do post :following From d07543111a5722b887deb355e385fb59cb65449b Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 22 Apr 2021 16:42:50 +0800 Subject: [PATCH 095/643] FIX code bug --- app/models/concerns/watchable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/watchable.rb b/app/models/concerns/watchable.rb index 3ab43d95a..008d382f3 100644 --- a/app/models/concerns/watchable.rb +++ b/app/models/concerns/watchable.rb @@ -6,7 +6,7 @@ module Watchable has_many :watcher_users, through: :watchers, source: :user, validate: false scope :watched_by, -> (user_id) { includes(:watchers).where(watchers: { user_id: user_id }) } - scope :following, -> (user_id) { watched_by } + scope :following, -> (user_id) { watched_by(user_id) } end def watched?(watchable) From ddacf2a733bd90c0ab33c9be6a47363f15e011a4 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 22 Apr 2021 16:45:26 +0800 Subject: [PATCH 096/643] FIX get organzition's name bug --- app/views/users/hovercard.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/users/hovercard.json.jbuilder b/app/views/users/hovercard.json.jbuilder index d74a14314..973cc6fa4 100644 --- a/app/views/users/hovercard.json.jbuilder +++ b/app/views/users/hovercard.json.jbuilder @@ -9,7 +9,7 @@ json.projects_count @user.projects_count json.is_watch current_user&.watched?(@user) json.organizations @user.organizations do |organization| json.login organization.login - json.name organization.full_name + json.name organization.real_name json.image_url url_to_avatar(organization) json.url "#{request.base_url }/organize/#{organization.login}" end \ No newline at end of file From 37e17048974e42cf390d3fd03a5af9481c85cbe2 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 22 Apr 2021 18:10:20 +0800 Subject: [PATCH 097/643] ADD location column for user hovercard api --- app/views/users/hovercard.json.jbuilder | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/users/hovercard.json.jbuilder b/app/views/users/hovercard.json.jbuilder index 973cc6fa4..43977c9be 100644 --- a/app/views/users/hovercard.json.jbuilder +++ b/app/views/users/hovercard.json.jbuilder @@ -1,6 +1,7 @@ json.id @user.id json.login @user.login json.name @user.full_name +json.location @user.location json.image_url url_to_avatar(@user) json.url "#{request.base_url }/users/#{@user.login}" json.followers_count @user.followers_count From aa314c141cdce9ed0749e9b413049a5383bbbf5e Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 23 Apr 2021 14:40:26 +0800 Subject: [PATCH 098/643] ADD some url with in hovercoard api --- app/controllers/application_controller.rb | 7 ++++++- app/views/users/hovercard.json.jbuilder | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ee81765a5..6875b8155 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -28,7 +28,7 @@ class ApplicationController < ActionController::Base 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" - helper_method :current_user + helper_method :current_user, :base_url # 所有请求必须合法签名 def check_sign @@ -770,6 +770,11 @@ class ApplicationController < ActionController::Base @repository ||= load_project&.repository end + def base_url + request.base_url + end + + private def object_not_found uid_logger("Missing template or cant't find record, responding with 404") diff --git a/app/views/users/hovercard.json.jbuilder b/app/views/users/hovercard.json.jbuilder index 43977c9be..79f1793fe 100644 --- a/app/views/users/hovercard.json.jbuilder +++ b/app/views/users/hovercard.json.jbuilder @@ -5,12 +5,16 @@ json.location @user.location json.image_url url_to_avatar(@user) json.url "#{request.base_url }/users/#{@user.login}" json.followers_count @user.followers_count +json.followers_url "#{base_url}/users/#{@user.login}/fan_users" json.following_count @user.following_count +json.following_url "#{base_url}/users/#{@user.login}/watchers" +json.projects_count @user.projects_count +json.projects_url "#{base_url}/users/#{@user.login}" json.projects_count @user.projects_count json.is_watch current_user&.watched?(@user) json.organizations @user.organizations do |organization| json.login organization.login json.name organization.real_name json.image_url url_to_avatar(organization) - json.url "#{request.base_url }/organize/#{organization.login}" + json.url "#{base_url}/organize/#{organization.login}" end \ No newline at end of file From 55f7beb22db2ce0fae3c5df2e77ae8dfdec07ead Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 23 Apr 2021 17:08:04 +0800 Subject: [PATCH 099/643] FIX update CHANGELOG.md --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4345e60b8..42422e3bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Changelog +## [v3.0.2](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-04-23 + +* BUGFIXES + * Fix 解决部分用户头像不显示问题 + * Fix 解决代码库模块中最左侧目录中的文件定位加载不准确的问题 + * FIX 解决团队管理页面中项目链接错误问题 + * Fix 解决markdown格式文件显示问题 + * Fix 解决组织名下创建项目报错的问题 + * Fix 解决组织名下的项目,创建issue报错的问题 + * Fix 解决组织名下创建团队提示信息信息显示错误问题 + * Fix 解决点击组织图片时,链接加载错误问题 + * Fix 修复查询版本库信息安全漏洞 + * Fix 解决修复团队成员操作访问组织仓库报403错误的问题 + * Fix 解决owners团队成员对仓库添加成功失败的问题 + +* ENHANCEMENTS + * ADD 自动生产用户头像功能 + * ADD 创建组织支持中文名称 + * ADD 创建团建支持中文名称 + * ADD 组织名称统一显示中文名 + * ADD 团队名称统一显示中文名 + * ADD 用户头像悬浮时展示相关信息 + * ADD 项目详情页添加实践课程链接入口 + * ADD README文件页面添加添加目录导航功能 + * UPDATE 升级改版底部footer信息 + * UPDATE 升级用户操作版本库权限 + ## [v3.0.1](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-03-19 * BUGFIXES From c1d4df6e06e06b3c277aafb625099cefe1f6cedd Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 23 Apr 2021 17:21:17 +0800 Subject: [PATCH 100/643] FIX release show time bug --- app/views/version_releases/index.json.jbuilder | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/version_releases/index.json.jbuilder b/app/views/version_releases/index.json.jbuilder index b90830899..f1730ffa9 100644 --- a/app/views/version_releases/index.json.jbuilder +++ b/app/views/version_releases/index.json.jbuilder @@ -17,8 +17,8 @@ json.releases do json.tarball_url re["tarball_url"] json.zipball_url re["zipball_url"] json.draft re["draft"] ? "草稿" : (re["prerelease"] ? "预发行" : "稳定") - json.created_at format_time(re["created_at"].to_s.to_time) - json.published_at format_time(re["published_at"].to_s.to_time) + json.created_at format_time(version.created_at.to_s.to_time) + json.published_at format_time(version.created_at.to_s.to_time) json.user_name user.present? ? user.try(:show_real_name) : "" json.image_url user.present? ? url_to_avatar(user) : "" else @@ -33,8 +33,8 @@ json.releases do json.tarball_url re["tarball_url"] json.zipball_url re["zipball_url"] json.draft re["draft"] ? "草稿" : (re["prerelease"] ? "预发行" : "稳定") - json.created_at format_time(re["created_at"].to_s.to_time) - json.published_at format_time(re["published_at"].to_s.to_time) + json.created_at format_time(version.created_at.to_s.to_time) + json.published_at format_time(version.created_at.to_s.to_time) json.user_name user.present? ? user.try(:show_real_name) : "" json.image_url user.present? ? url_to_avatar(user) : "" end From ee7acaaa82d226d2ed8f45549c2ef78c8271642f Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 23 Apr 2021 17:32:45 +0800 Subject: [PATCH 101/643] FIX update README.md --- README.md | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 2a607e2ad..1bcd05cce 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Trustie (确实)是一个以大众化协同开发、开放式资源共享、 * Redis 5+ -* NodeJS > 13.0.0 +* imagemagick ### Steps @@ -65,7 +65,7 @@ default: &default **因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/Trustie/gitea-binary** -#### 配置gitea服务步骤 +**配置gitea服务步骤** 1. 部署gitea服务,并注册root账户 2. 修改forge平台的 config/configuration.yml中的gitea服务指向地址,如: @@ -80,60 +80,64 @@ gitea: #### 6. 安装redis环境 **请自行搜索各平台如何安装部署redis环境** +#### 7. 安装imagemagick插件 +- Mac OS X +```bash + brew install imagemagick ghostscript +``` -#### 7. 创建数据库 +- Linux +```bash +sudo apt-get install -y imagemagick +``` + +#### 8. 创建数据库 **开发环境为development, 生成环境为production** ```bash rails db:create RAILS_ENV=development ``` -#### 8. 导入数据表结构 +#### 9. 导入数据表结构 ```bash bundle exec rake sync_table_structure:import_csv ``` -#### 9. 执行migrate迁移文件 +#### 10. 执行migrate迁移文件 **开发环境为development, 生成环境为production** ```bash rails db:migrate RAILS_ENV=development ``` -#### 10. clone前端代码 +#### 11. clone前端代码 **将前端代码克隆到public/react目录下,目录结构应该是: public/react/build** ```bash git clone -b standalone https://git.trustie.net/jasder/build.git ``` -#### 11. 启动redis(此处已mac系统为例) +#### 12. 启动redis(此处已mac系统为例) ```bash redis-server& ``` -#### 12. 启动sidekiq +#### 13. 启动sidekiq **开发环境为development, 生成环境为production** ```bash bundle exec sidekiq -C config/sidekiq.yml -e production -d ``` -#### 13. 启动rails服务 +#### 14. 启动rails服务 ```bash rails s ``` -#### 14. 浏览器访问 -在浏览器中输入如下地址访问: -```bash -http://localhost:3000/ -``` - #### 15. 浏览器访问 在浏览器中输入如下地址访问: ```bash http://localhost:3000/ ``` -#### 15. 其他说明 +#### 16. 其他说明 通过页面注册都第一个用户为平台管理员用户 ## 页面展示 From 8c71a72fceb9ff1e30ff84e43e70ddf20c3ad054 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 23 Apr 2021 17:53:59 +0800 Subject: [PATCH 102/643] FIX code bug --- app/controllers/version_releases_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/version_releases_controller.rb b/app/controllers/version_releases_controller.rb index 1b56236a4..ac17c7d4b 100644 --- a/app/controllers/version_releases_controller.rb +++ b/app/controllers/version_releases_controller.rb @@ -8,7 +8,7 @@ class VersionReleasesController < ApplicationController version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call @version_releases = version_releases @user_permission = current_user.present? && (current_user == @user || current_user.admin?) - @forge_releases = @repository.version_releases.select(:id,:version_gid).includes(:attachments) + @forge_releases = @repository.version_releases.select(:id,:version_gid, :created_at).includes(:attachments) end def new From 1e081b5a3e23cb0ef66bf3d6958c18067274d487 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Sun, 25 Apr 2021 18:41:13 +0800 Subject: [PATCH 103/643] add: transfer project --- .../applied_transfer_projects_controller.rb | 26 +++++++++++ .../users/applied_messages_controller.rb | 18 ++++++++ .../applied_transfer_projects_controller.rb | 41 ++++++++++++++++++ app/controllers/users_controller.rb | 11 ++++- ...nd_transfer_project_applied_message_job.rb | 34 +++++++++++++++ app/models/applied_message.rb | 5 +++ app/models/applied_transfer_project.rb | 28 ++++++++++++ app/models/owner.rb | 2 + app/models/project.rb | 4 ++ app/models/user.rb | 4 +- .../projects/accept_transfer_service.rb | 43 +++++++++++++++++++ .../projects/apply_transfer_service.rb | 41 ++++++++++++++++++ .../projects/cancel_transfer_service.rb | 33 ++++++++++++++ .../projects/refuse_transfer_service.rb | 33 ++++++++++++++ .../organizations/_simple.json.jbuilder | 5 +++ .../_detail.json.jbuilder | 21 +++++++++ .../cancel.json.jbuilder | 1 + .../create.json.jbuilder | 1 + .../organizations.json.jbuilder | 4 ++ app/views/repositories/edit.json.jbuilder | 4 +- app/views/users/_user_simple.json.jbuilder | 1 + .../applied_messages/_detail.json.jbuilder | 25 +++++++++++ .../applied_messages/index.json.jbuilder | 4 ++ .../accept.json.jbuilder | 1 + .../index.json.jbuilder | 4 ++ .../refuse.json.jbuilder | 1 + config/routes.rb | 13 ++++++ ...032825_create_applied_transfer_projects.rb | 12 ++++++ 28 files changed, 416 insertions(+), 4 deletions(-) create mode 100644 app/controllers/projects/applied_transfer_projects_controller.rb create mode 100644 app/controllers/users/applied_messages_controller.rb create mode 100644 app/controllers/users/applied_transfer_projects_controller.rb create mode 100644 app/jobs/send_transfer_project_applied_message_job.rb create mode 100644 app/models/applied_transfer_project.rb create mode 100644 app/services/projects/accept_transfer_service.rb create mode 100644 app/services/projects/apply_transfer_service.rb create mode 100644 app/services/projects/cancel_transfer_service.rb create mode 100644 app/services/projects/refuse_transfer_service.rb create mode 100644 app/views/organizations/organizations/_simple.json.jbuilder create mode 100644 app/views/projects/applied_transfer_projects/_detail.json.jbuilder create mode 100644 app/views/projects/applied_transfer_projects/cancel.json.jbuilder create mode 100644 app/views/projects/applied_transfer_projects/create.json.jbuilder create mode 100644 app/views/projects/applied_transfer_projects/organizations.json.jbuilder create mode 100644 app/views/users/applied_messages/_detail.json.jbuilder create mode 100644 app/views/users/applied_messages/index.json.jbuilder create mode 100644 app/views/users/applied_transfer_projects/accept.json.jbuilder create mode 100644 app/views/users/applied_transfer_projects/index.json.jbuilder create mode 100644 app/views/users/applied_transfer_projects/refuse.json.jbuilder create mode 100644 db/migrate/20210425032825_create_applied_transfer_projects.rb diff --git a/app/controllers/projects/applied_transfer_projects_controller.rb b/app/controllers/projects/applied_transfer_projects_controller.rb new file mode 100644 index 000000000..887949f8d --- /dev/null +++ b/app/controllers/projects/applied_transfer_projects_controller.rb @@ -0,0 +1,26 @@ +class Projects::AppliedTransferProjectsController < Projects::BaseController + before_action :check_auth + + def organizations + @organizations = Organization.includes(:organization_extension).joins(team_users: :team).where(team_users: {user_id: current_user.id}, teams: {authorize: %w(admin owner)}) + end + + def create + @applied_transfer_project = Projects::ApplyTransferService.call(current_user, @project, params[:owner_id]) + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + def cancel + @applied_transfer_project = Projects::CancelTransferService.call(current_user, @project) + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def check_auth + return render_forbidden unless current_user.admin? ||@project.owner?(current_user) + end +end \ No newline at end of file diff --git a/app/controllers/users/applied_messages_controller.rb b/app/controllers/users/applied_messages_controller.rb new file mode 100644 index 000000000..e80cabf92 --- /dev/null +++ b/app/controllers/users/applied_messages_controller.rb @@ -0,0 +1,18 @@ +class Users::AppliedMessagesController < Users::BaseController + before_action :check_auth + after_action :view_messages, only: [:index] + + def index + @applied_messages = @_observed_user.applied_messages.order(viewed: :asc, created_at: :desc) + @applied_messages = paginate @applied_messages + end + + private + def check_auth + return render_forbidden unless observed_logged_user? + end + + def view_messages + @applied_messages.update_all(viewed: 'viewed') + end +end \ No newline at end of file diff --git a/app/controllers/users/applied_transfer_projects_controller.rb b/app/controllers/users/applied_transfer_projects_controller.rb new file mode 100644 index 000000000..74366bb55 --- /dev/null +++ b/app/controllers/users/applied_transfer_projects_controller.rb @@ -0,0 +1,41 @@ +class Users::AppliedTransferProjectsController < Users::BaseController + before_action :check_auth + before_action :find_applied_transfer_project, except: [:index] + before_action :find_project, except: [:index] + + def index + user_collection_sql = AppliedTransferProject.where(owner_id: @_observed_user.id).to_sql + org_collection_sql = AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @_observed_user.id}, teams: {authorize: %w(admin owner)} )).to_sql + @applied_transfer_projects = AppliedTransferProject.from("( #{ user_collection_sql } UNION #{ org_collection_sql } ) AS applied_transfer_projects") + @applied_transfer_projects = paginate @applied_transfer_projects + end + + # 接受迁移 + def accept + @applied_transfer_project = Projects::AcceptTransferService.call(current_user, @project) + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + # 拒绝迁移 + def refuse + @applied_transfer_project = Projects::RefuseTransferService.call(current_user, @project) + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def check_auth + return render_forbidden unless observed_logged_user? + end + + def find_applied_transfer_project + @applied_transfer_project = AppliedTransferProject.find_by_id params[:id] + end + + def find_project + @project = @applied_transfer_project.project + end +end \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 7f49ab614..c6ac626a3 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -27,11 +27,18 @@ class UsersController < ApplicationController def show #待办事项,现在未做 - @undo_events = 0 + if User.current.login == @user.login + @waiting_applied_messages = @user.applied_messages.waiting + @common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common + @undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + else + @undo_events = 0 + end #用户的组织数量 # @user_composes_count = @user.composes.size @user_composes_count = 0 - @user_org_count = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)).size + @user.organizations.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id}).size : @user.organizations.with_visibility("common").size + user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common") + @user_org_count = user_organizations.size 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 diff --git a/app/jobs/send_transfer_project_applied_message_job.rb b/app/jobs/send_transfer_project_applied_message_job.rb new file mode 100644 index 000000000..790d1fd5d --- /dev/null +++ b/app/jobs/send_transfer_project_applied_message_job.rb @@ -0,0 +1,34 @@ +class SendTransferProjectAppliedMessageJob < ApplicationJob + queue_as :default + + def perform(applied_transfer_project, applied_user, message_status) + project = applied_transfer_project.project + owner = applied_transfer_project.owner + return unless project.present? + return unless owner.present? + receivers = project.managers + owner.team_users.joins(:team).where(teams: {authorize: %w(owner admin)}) + receivers.each do |rec| + AppliedMessage.create!(user_id: rec.user_id, + applied: applied_transfer_project, + status: message_status, + name: build_name(project.name, owner.real_name, message_status), + applied_user_id: applied_user.id, + project_id: project.id) + end + end + + private + def build_name(repo_name, owner_name, message_status) + case message_status + when 'canceled' + return "取消转移【#{repo_name}】仓库" + when 'common' + return "正在将【#{repo_name}】仓库转移给【#{owner_name}】" + when 'successed' + return "【#{repo_name}】仓库成功转移给【#{owner_name}】" + when 'failure' + return "【#{repo_name}】仓库转移失败" + end + "" + end +end \ No newline at end of file diff --git a/app/models/applied_message.rb b/app/models/applied_message.rb index 8098e6e07..b3ebad34e 100644 --- a/app/models/applied_message.rb +++ b/app/models/applied_message.rb @@ -19,5 +19,10 @@ class AppliedMessage < ApplicationRecord belongs_to :user belongs_to :applied, polymorphic: true + belongs_to :project + belongs_to :applied_user, class_name: 'User' + + enum viewed: {waiting: 0, viewed: 1} + enum status: {canceled: -1, common: 0, successed: 1, failure: 2} # -1 已取消 0 正在操作 1 操作成功 2 操作失败 end diff --git a/app/models/applied_transfer_project.rb b/app/models/applied_transfer_project.rb new file mode 100644 index 000000000..d0e0e5c44 --- /dev/null +++ b/app/models/applied_transfer_project.rb @@ -0,0 +1,28 @@ +# == Schema Information +# +# Table name: applied_transfer_projects +# +# id :integer not null, primary key +# project_id :integer +# owner_id :integer +# user_id :integer +# status :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_applied_transfer_projects_on_owner_id (owner_id) +# index_applied_transfer_projects_on_project_id (project_id) +# index_applied_transfer_projects_on_user_id (user_id) +# + +class AppliedTransferProject < ApplicationRecord + belongs_to :project + belongs_to :user # 操作者 + belongs_to :owner # 接收个人或组织 + + has_many :applied_messages, as: :applied, dependent: :destroy + + enum status: {canceled: -1, common: 0, accepted: 1, refused: 2} # -1 已取消 0 待操作 1 已接收 2 已拒绝 +end diff --git a/app/models/owner.rb b/app/models/owner.rb index 1d537a1e0..b65ee0544 100644 --- a/app/models/owner.rb +++ b/app/models/owner.rb @@ -66,4 +66,6 @@ class Owner < ApplicationRecord has_many :projects, foreign_key: :user_id, dependent: :destroy has_many :repositories, foreign_key: :user_id, dependent: :destroy + has_many :applied_transfer_projects, dependent: :destroy + end diff --git a/app/models/project.rb b/app/models/project.rb index da1a8615b..0c30e13fa 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -112,6 +112,7 @@ class Project < ApplicationRecord has_one :project_detail, dependent: :destroy has_many :team_projects, dependent: :destroy has_many :project_units, dependent: :destroy + has_one :applied_transfer_project, dependent: :destroy after_save :check_project_members scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} @@ -295,4 +296,7 @@ class Project < ApplicationRecord update_column(:updated_on, time) end + def is_transfering + applied_transfer_project&.common? ? true : false + end end diff --git a/app/models/user.rb b/app/models/user.rb index e16e5ca02..e41e47d93 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -147,9 +147,11 @@ class User < Owner has_many :trail_auth_apply_actions, -> { where(container_type: 'TrialAuthorization') }, class_name: 'ApplyAction' # has_many :attendances - + has_many :applied_messages, dependent: :destroy + has_many :operate_applied_messages, class_name: 'AppliedMessage', dependent: :destroy # 项目 has_many :applied_projects, dependent: :destroy + has_many :operate_applied_transfer_projects, class_name: 'AppliedTransferProject', dependent: :destroy # 教学案例 # has_many :libraries, dependent: :destroy diff --git a/app/services/projects/accept_transfer_service.rb b/app/services/projects/accept_transfer_service.rb new file mode 100644 index 000000000..57cdfd54b --- /dev/null +++ b/app/services/projects/accept_transfer_service.rb @@ -0,0 +1,43 @@ +class Projects::AcceptTransferService < ApplicationService + attr_accessor :applied_transfer_project + attr_reader :user, :project + + def initialize(user, project) + @user = user + @project = project + @applied_transfer_project = project.applied_transfer_project + end + + def call + Rails.logger.info("###### Project accept_transfer_service begin ######") + ActiveRecord::Base.transaction do + validate! + update_apply + operate_project + send_apply_message + end + + Rails.logger.info("##### Project accept_transfer_service end ######") + + + return @applied_transfer_project + end + + private + def validate! + raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering + raise Error, '未拥有接受转移权限' unless @user.admin? || @project.is_admin?(@user) + end + + def update_apply + @applied_transfer_project.update!(status: 'accepted') + end + + def operate_project + @project = Projects::TransferService.call(@project, @applied_transfer_project.owner) + end + + def send_apply_message + SendTransferProjectAppliedMessageJob.perform_now(@applied_transfer_project, @user, 'successed') + end +end \ No newline at end of file diff --git a/app/services/projects/apply_transfer_service.rb b/app/services/projects/apply_transfer_service.rb new file mode 100644 index 000000000..1dd9f7f7a --- /dev/null +++ b/app/services/projects/apply_transfer_service.rb @@ -0,0 +1,41 @@ +class Projects::ApplyTransferService < ApplicationService + attr_accessor :owner, :applied_transfer_project + attr_reader :user, :project, :owner_id + + def initialize(user, project, owner_id) + @user = user + @project = project + @owner_id = owner_id + @owner = Owner.find_by_id(owner_id) + end + + def call + Rails.logger.info("###### Project apply_transfer_service begin ######") + validate! + create_apply + send_apply_message + Rails.logger.info("###### Project apply_transfer_service end ######") + + return @applied_transfer_project + end + + private + def validate! + raise Error, '该仓库正在迁移' if @project.is_transfering + raise Error, '新拥有者不存在' unless @owner.present? + raise Error, '未拥有转移权限' unless is_permit_owner + end + + def is_permit_owner + return true unless @owner.is_a?(Organization) + return @owner.is_owner?(@user) + end + + def create_apply + @applied_transfer_project = AppliedTransferProject.create!(user_id: user.id, project_id: project.id, owner_id: owner_id) + end + + def send_apply_message + SendTransferProjectAppliedMessageJob.perform_now(@applied_transfer_project, @user, 'common') + end +end \ No newline at end of file diff --git a/app/services/projects/cancel_transfer_service.rb b/app/services/projects/cancel_transfer_service.rb new file mode 100644 index 000000000..153b24ffb --- /dev/null +++ b/app/services/projects/cancel_transfer_service.rb @@ -0,0 +1,33 @@ +class Projects::CancelTransferService < ApplicationService + attr_accessor :applied_transfer_project + attr_reader :user, :project + + def initialize(user, project) + @user = user + @project = project + @applied_transfer_project = project.applied_transfer_project + end + + def call + Rails.logger.info("###### Project cancel_transfer_service begin ######") + validate! + update_apply + send_apply_message + Rails.logger.info("###### Project cancel_transfer_service end ######") + + return @applied_transfer_project + end + + private + def validate! + raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering + end + + def update_apply + @applied_transfer_project.update!(status: 'canceled') + end + + def send_apply_message + SendTransferProjectAppliedMessageJob.perform_now(@applied_transfer_project, @user, 'canceled') + end +end \ No newline at end of file diff --git a/app/services/projects/refuse_transfer_service.rb b/app/services/projects/refuse_transfer_service.rb new file mode 100644 index 000000000..88d252465 --- /dev/null +++ b/app/services/projects/refuse_transfer_service.rb @@ -0,0 +1,33 @@ +class Projects::RefuseTransferService < ApplicationService + attr_accessor :applied_transfer_project + attr_reader :user, :project + + def initialize(user, project) + @user = user + @project = project + @applied_transfer_project = project.applied_transfer_project + end + + def call + Rails.logger.info("###### Project refuse_transfer_service begin ######") + validate! + update_apply + send_apply_message + Rails.logger.info("###### Project refuse_transfer_service end ######") + + return @applied_transfer_project + end + + private + def validate! + raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering + end + + def update_apply + @applied_transfer_project.update!(status: 'refused') + end + + def send_apply_message + SendTransferProjectAppliedMessageJob.perform_now(@applied_transfer_project, @user, 'failure') + end +end \ No newline at end of file diff --git a/app/views/organizations/organizations/_simple.json.jbuilder b/app/views/organizations/organizations/_simple.json.jbuilder new file mode 100644 index 000000000..12792b125 --- /dev/null +++ b/app/views/organizations/organizations/_simple.json.jbuilder @@ -0,0 +1,5 @@ +json.id organization.id +json.name organization.login +json.nickname organization.nickname.blank? ? organization.name : organization.nickname +json.description organization.description +json.avatar_url url_to_avatar(organization) diff --git a/app/views/projects/applied_transfer_projects/_detail.json.jbuilder b/app/views/projects/applied_transfer_projects/_detail.json.jbuilder new file mode 100644 index 000000000..e583ed1d1 --- /dev/null +++ b/app/views/projects/applied_transfer_projects/_detail.json.jbuilder @@ -0,0 +1,21 @@ +project = object.project +json.project do + json.id project.id + json.identifier project.identifier + json.name project.name + json.description project.description + json.is_public project.is_public + json.owner do + json.partial! "/users/user_simple", locals: {user: project.owner} + end +end +json.user do + json.partial! "/users/user_simple", locals: {user: object.user} +end +json.owner do + json.partial! "/users/user_simple", locals: {user: object.owner} +end +json.id object.id +json.status object.status +json.created_at format_time(object.created_at) +json.time_ago time_from_now(object.created_at) diff --git a/app/views/projects/applied_transfer_projects/cancel.json.jbuilder b/app/views/projects/applied_transfer_projects/cancel.json.jbuilder new file mode 100644 index 000000000..59da42d4e --- /dev/null +++ b/app/views/projects/applied_transfer_projects/cancel.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/projects/applied_transfer_projects/detail", locals: {object: @applied_transfer_project} diff --git a/app/views/projects/applied_transfer_projects/create.json.jbuilder b/app/views/projects/applied_transfer_projects/create.json.jbuilder new file mode 100644 index 000000000..59da42d4e --- /dev/null +++ b/app/views/projects/applied_transfer_projects/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/projects/applied_transfer_projects/detail", locals: {object: @applied_transfer_project} diff --git a/app/views/projects/applied_transfer_projects/organizations.json.jbuilder b/app/views/projects/applied_transfer_projects/organizations.json.jbuilder new file mode 100644 index 000000000..772910f0b --- /dev/null +++ b/app/views/projects/applied_transfer_projects/organizations.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @organizations.size +json.organizations @organizations do |org| + json.partial! "/organizations/organizations/simple", locals: {organization: org} +end diff --git a/app/views/repositories/edit.json.jbuilder b/app/views/repositories/edit.json.jbuilder index 076ac3aa8..d268696cc 100644 --- a/app/views/repositories/edit.json.jbuilder +++ b/app/views/repositories/edit.json.jbuilder @@ -7,4 +7,6 @@ json.project_language_id @project.project_language_id json.private !@project.is_public json.website @project.website json.project_units @project.project_units.pluck(:unit_type) -json.lesson_url @project.lesson_url \ No newline at end of file +json.lesson_url @project.lesson_url +json.permission render_permission(current_user, @project) +json.is_transfering @project.is_transfering \ No newline at end of file diff --git a/app/views/users/_user_simple.json.jbuilder b/app/views/users/_user_simple.json.jbuilder index 3f9feebbe..cfd06a405 100644 --- a/app/views/users/_user_simple.json.jbuilder +++ b/app/views/users/_user_simple.json.jbuilder @@ -1,4 +1,5 @@ json.id user.id +json.type user.type json.name user.real_name json.login user.login json.image_url url_to_avatar(user) \ No newline at end of file diff --git a/app/views/users/applied_messages/_detail.json.jbuilder b/app/views/users/applied_messages/_detail.json.jbuilder new file mode 100644 index 000000000..0bbd49b01 --- /dev/null +++ b/app/views/users/applied_messages/_detail.json.jbuilder @@ -0,0 +1,25 @@ +project = object.project +json.project do + json.id project.id + json.identifier project.identifier + json.name project.name + json.description project.description + json.is_public project.is_public + json.owner do + json.partial! "/users/user_simple", locals: {user: project.owner} + end +end +json.user do + json.partial! "/users/user_simple", locals: {user: object.user} +end +json.applied do + json.partial! "/projects/applied_transfer_projects/detail", locals: {object: object.applied} +end +json.applied_user do + json.partial! "/users/user_simple", locals: {user: object.applied_user} +end +json.name object.name +json.viewed object.viewed +json.status object.status +json.created_at format_time(object.created_at) +json.time_ago time_from_now(object.created_at) diff --git a/app/views/users/applied_messages/index.json.jbuilder b/app/views/users/applied_messages/index.json.jbuilder new file mode 100644 index 000000000..75647566f --- /dev/null +++ b/app/views/users/applied_messages/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @applied_messages.total_count +json.applied_messages @applied_messages do |message| + json.partial! "/users/applied_messages/detail", locals: {object: message} +end diff --git a/app/views/users/applied_transfer_projects/accept.json.jbuilder b/app/views/users/applied_transfer_projects/accept.json.jbuilder new file mode 100644 index 000000000..59da42d4e --- /dev/null +++ b/app/views/users/applied_transfer_projects/accept.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/projects/applied_transfer_projects/detail", locals: {object: @applied_transfer_project} diff --git a/app/views/users/applied_transfer_projects/index.json.jbuilder b/app/views/users/applied_transfer_projects/index.json.jbuilder new file mode 100644 index 000000000..caf9d1ade --- /dev/null +++ b/app/views/users/applied_transfer_projects/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @applied_transfer_projects.total_count +json.applied_transfer_projects @applied_transfer_projects do |apply| + json.partial! "/projects/applied_transfer_projects/detail", locals: {object: apply} +end diff --git a/app/views/users/applied_transfer_projects/refuse.json.jbuilder b/app/views/users/applied_transfer_projects/refuse.json.jbuilder new file mode 100644 index 000000000..59da42d4e --- /dev/null +++ b/app/views/users/applied_transfer_projects/refuse.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/projects/applied_transfer_projects/detail", locals: {object: @applied_transfer_project} diff --git a/config/routes.rb b/config/routes.rb index bbcc29231..fa76ba467 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -257,6 +257,13 @@ Rails.application.routes.draw do end scope module: :users do + resources :applied_messages, only: [:index] + resources :applied_transfer_projects, only: [:index] do + member do + post :accept + post :refuse + end + end resources :organizations, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] @@ -532,6 +539,12 @@ Rails.application.routes.draw do scope module: :projects do resources :teams, only: [:index, :create, :destroy] resources :project_units, only: [:index, :create] + resources :applied_transfer_projects, only: [:create] do + collection do + get :organizations + post :cancel + end + end scope do get( '/blob/*id/diff', diff --git a/db/migrate/20210425032825_create_applied_transfer_projects.rb b/db/migrate/20210425032825_create_applied_transfer_projects.rb new file mode 100644 index 000000000..5c6774095 --- /dev/null +++ b/db/migrate/20210425032825_create_applied_transfer_projects.rb @@ -0,0 +1,12 @@ +class CreateAppliedTransferProjects < ActiveRecord::Migration[5.2] + def change + create_table :applied_transfer_projects do |t| + t.references :project + t.references :owner + t.references :user + t.integer :status, default: 0 + + t.timestamps + end + end +end From 8b7b1b7a4e603883af7f83f313a9ebb29204bcac Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 26 Apr 2021 10:07:22 +0800 Subject: [PATCH 104/643] add: api doc about projects --- .../applied_transfer_projects_controller.rb | 2 +- app/docs/slate/source/includes/_projects.md | 238 +++++++++ .../projects/apply_transfer_service.rb | 10 +- public/docs/api.html | 498 ++++++++++++++++++ 4 files changed, 742 insertions(+), 6 deletions(-) diff --git a/app/controllers/projects/applied_transfer_projects_controller.rb b/app/controllers/projects/applied_transfer_projects_controller.rb index 887949f8d..ad6c9b19c 100644 --- a/app/controllers/projects/applied_transfer_projects_controller.rb +++ b/app/controllers/projects/applied_transfer_projects_controller.rb @@ -6,7 +6,7 @@ class Projects::AppliedTransferProjectsController < Projects::BaseController end def create - @applied_transfer_project = Projects::ApplyTransferService.call(current_user, @project, params[:owner_id]) + @applied_transfer_project = Projects::ApplyTransferService.call(current_user, @project, params[:owner_name]) rescue Exception => e uid_logger_error(e.message) tip_exception(e.message) diff --git a/app/docs/slate/source/includes/_projects.md b/app/docs/slate/source/includes/_projects.md index 0a46d8cc7..85359d80e 100644 --- a/app/docs/slate/source/includes/_projects.md +++ b/app/docs/slate/source/includes/_projects.md @@ -526,3 +526,241 @@ await octokit.request('POST /api/jaser/jasder_test/forks.json') "identifier": "newadm" } ``` + +## 用户管理的组织列表 +用户管理的组织列表 + +> 示例: + +```shell +curl -X GET \ +http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizations.json | jq +``` + +```javascript +await octokit.request('GET /api/:owner/:repo/applied_transfer_projects/organizations') +``` + +### HTTP 请求 +`GET api/:owner/:repo/applied_transfer_projects/organizations` + +### 请求参数 +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +owner |是| |string |用户登录名 +repo |是| |string |项目标识identifier + +### 返回字段说明 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +name |string|组织标识 +nickname |string|组织名称 +description|string|组织描述 +avatar_url|string|组织头像 + + +> 返回的JSON示例: + +```json +{ + "total_count": 3, + "organizations": [ + { + "id": 9, + "name": "ceshi_org", + "nickname": "测试组织", + "description": "测试组织", + "avatar_url": "images/avatars/Organization/9?t=1612706073" + }, + { + "id": 51, + "name": "ceshi", + "nickname": "测试组织哈哈哈", + "description": "23212312", + "avatar_url": "images/avatars/Organization/51?t=1618800723" + }, + { + "id": 52, + "name": "ceshi1", + "nickname": "身份卡手动阀", + "description": "1231手动阀是的", + "avatar_url": "images/avatars/Organization/52?t=1618805056" + } + ] +} +``` + +## 迁移项目 +迁移项目,edit接口is_transfering为true表示正在迁移 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects.json +``` + +```javascript +await octokit.request('POST /api/:owner/:repo/applied_transfer_projects.json') +``` + +### HTTP 请求 +`POST /api/:owner/:repo/applied_transfer_projects.json` + +### 请求参数 +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|owner_name|是| |string |迁移对象标识 | + +### 返回字段说明 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |项目id | +|status |string |项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝| +|time_ago |string |项目迁移创建的时间 | +|project.id |int |迁移项目的id | +|project.identifier |string |迁移项目的标识 | +|project.name |string |迁移项目的名称 | +|project.description |string |迁移项目的描述 | +|project.is_public |bool |迁移项目是否公开 | +|project.owner.id |bool |迁移项目拥有者id | +|project.owner.type |string |迁移项目拥有者类型 | +|project.owner.name |string |迁移项目拥有者昵称 | +|project.owner.login |string |迁移项目拥有者标识 | +|project.owner.image_url |string |迁移项目拥有者头像 | +|user.id |int |迁移创建者的id | +|user.type |string |迁移创建者的类型 | +|user.name |string |迁移创建者的名称 | +|user.login |string |迁移创建者的标识 | +|user.image_url |string |迁移创建者头像 | +|owner.id |int |迁移接受者的id | +|owner.type |string |迁移接受者的类型 | +|owner.name |string |迁移接受者的名称 | +|owner.login |string |迁移接受者的标识 | +|owner.image_url |string |迁移接受者头像 | +> 返回的JSON示例: + +```json +{ + "project": { + "id": 86, + "identifier": "ceshi_repo1", + "name": "测试项目啊1", + "description": "二十多", + "is_public": true, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "yystopf", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + }, + "owner": { + "id": 9, + "type": "Organization", + "name": "测试组织", + "login": "ceshi_org", + "image_url": "images/avatars/Organization/9?t=1612706073" + }, + "id": 4, + "status": "common", + "created_at": "2021-04-26 09:54", + "time_ago": "1分钟前" +} +``` + +## 取消迁移项目 +迁移项目,edit接口is_transfering为true表示正在迁移 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/cancel.json +``` + +```javascript +await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.json') +``` + +### HTTP 请求 +`POST /api/:owner/:repo/applied_transfer_projects/cancel.json` + +### 请求参数 +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | + +### 返回字段说明 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |项目id | +|status |string |项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝| +|time_ago |string |项目迁移创建的时间 | +|project.id |int |迁移项目的id | +|project.identifier |string |迁移项目的标识 | +|project.name |string |迁移项目的名称 | +|project.description |string |迁移项目的描述 | +|project.is_public |bool |迁移项目是否公开 | +|project.owner.id |bool |迁移项目拥有者id | +|project.owner.type |string |迁移项目拥有者类型 | +|project.owner.name |string |迁移项目拥有者昵称 | +|project.owner.login |string |迁移项目拥有者标识 | +|project.owner.image_url |string |迁移项目拥有者头像 | +|user.id |int |迁移创建者的id | +|user.type |string |迁移创建者的类型 | +|user.name |string |迁移创建者的名称 | +|user.login |string |迁移创建者的标识 | +|user.image_url |string |迁移创建者头像 | +|owner.id |int |迁移接受者的id | +|owner.type |string |迁移接受者的类型 | +|owner.name |string |迁移接受者的名称 | +|owner.login |string |迁移接受者的标识 | +|owner.image_url |string |迁移接受者头像 | +> 返回的JSON示例: + +```json +{ + "project": { + "id": 86, + "identifier": "ceshi_repo1", + "name": "测试项目啊1", + "description": "二十多", + "is_public": true, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "yystopf", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + }, + "owner": { + "id": 9, + "type": "Organization", + "name": "测试组织", + "login": "ceshi_org", + "image_url": "images/avatars/Organization/9?t=1612706073" + }, + "id": 4, + "status": "common", + "created_at": "2021-04-26 09:54", + "time_ago": "1分钟前" +} +``` \ No newline at end of file diff --git a/app/services/projects/apply_transfer_service.rb b/app/services/projects/apply_transfer_service.rb index 1dd9f7f7a..ee4ec4265 100644 --- a/app/services/projects/apply_transfer_service.rb +++ b/app/services/projects/apply_transfer_service.rb @@ -1,12 +1,12 @@ class Projects::ApplyTransferService < ApplicationService attr_accessor :owner, :applied_transfer_project - attr_reader :user, :project, :owner_id + attr_reader :user, :project, :owner_name - def initialize(user, project, owner_id) + def initialize(user, project, owner_name) @user = user @project = project - @owner_id = owner_id - @owner = Owner.find_by_id(owner_id) + @owner_name = owner_name + @owner = Owner.find_by(login: owner_name) end def call @@ -32,7 +32,7 @@ class Projects::ApplyTransferService < ApplicationService end def create_apply - @applied_transfer_project = AppliedTransferProject.create!(user_id: user.id, project_id: project.id, owner_id: owner_id) + @applied_transfer_project = AppliedTransferProject.create!(user_id: user.id, project_id: project.id, owner_id: @owner.id) end def send_apply_message diff --git a/public/docs/api.html b/public/docs/api.html index 1b75a97a2..a2e4ef957 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -366,6 +366,15 @@
  • Fork项目
  • +
  • + 用户管理的组织列表 +
  • +
  • + 迁移项目 +
  • +
  • + 取消迁移项目 +
  • @@ -1590,6 +1599,495 @@ http://localhost:3000/api/projects/migrate.json "id": 3290, "identifier": "newadm" } +

    用户管理的组织列表

    +

    用户管理的组织列表

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizations.json  | jq
    +
    await octokit.request('GET /api/:owner/:repo/applied_transfer_projects/organizations')
    +

    HTTP 请求

    +

    GET api/:owner/:repo/applied_transfer_projects/organizations

    +

    请求参数

    +
  • + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    +

    返回字段说明

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    namestring组织标识
    nicknamestring组织名称
    + +

    description|string|组织描述 +avatar_url|string|组织头像

    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_count": 3,
    +    "organizations": [
    +        {
    +            "id": 9,
    +            "name": "ceshi_org",
    +            "nickname": "测试组织",
    +            "description": "测试组织",
    +            "avatar_url": "images/avatars/Organization/9?t=1612706073"
    +        },
    +        {
    +            "id": 51,
    +            "name": "ceshi",
    +            "nickname": "测试组织哈哈哈",
    +            "description": "23212312",
    +            "avatar_url": "images/avatars/Organization/51?t=1618800723"
    +        },
    +        {
    +            "id": 52,
    +            "name": "ceshi1",
    +            "nickname": "身份卡手动阀",
    +            "description": "1231手动阀是的",
    +            "avatar_url": "images/avatars/Organization/52?t=1618805056"
    +        }
    +    ]
    +}
    +

    迁移项目

    +

    迁移项目,edit接口is_transfering为true表示正在迁移

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects.json
    +
    await octokit.request('POST /api/:owner/:repo/applied_transfer_projects.json')
    +

    HTTP 请求

    +

    POST /api/:owner/:repo/applied_transfer_projects.json

    +

    请求参数

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    owner_namestring迁移对象标识
    +

    返回字段说明

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    idint项目id
    statusstring项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    time_agostring项目迁移创建的时间
    project.idint迁移项目的id
    project.identifierstring迁移项目的标识
    project.namestring迁移项目的名称
    project.descriptionstring迁移项目的描述
    project.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.typestring迁移项目拥有者类型
    project.owner.namestring迁移项目拥有者昵称
    project.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "project": {
    +        "id": 86,
    +        "identifier": "ceshi_repo1",
    +        "name": "测试项目啊1",
    +        "description": "二十多",
    +        "is_public": true,
    +        "owner": {
    +            "id": 52,
    +            "type": "Organization",
    +            "name": "身份卡手动阀",
    +            "login": "ceshi1",
    +            "image_url": "images/avatars/Organization/52?t=1618805056"
    +        }
    +    },
    +    "user": {
    +        "id": 6,
    +        "type": "User",
    +        "name": "yystopf",
    +        "login": "yystopf",
    +        "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
    +    },
    +    "owner": {
    +        "id": 9,
    +        "type": "Organization",
    +        "name": "测试组织",
    +        "login": "ceshi_org",
    +        "image_url": "images/avatars/Organization/9?t=1612706073"
    +    },
    +    "id": 4,
    +    "status": "common",
    +    "created_at": "2021-04-26 09:54",
    +    "time_ago": "1分钟前"
    +}
    +

    取消迁移项目

    +

    迁移项目,edit接口is_transfering为true表示正在迁移

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/cancel.json
    +
    await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.json')
    +

    HTTP 请求

    +

    POST /api/:owner/:repo/applied_transfer_projects/cancel.json

    +

    请求参数

    + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    +

    返回字段说明

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    idint项目id
    statusstring项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    time_agostring项目迁移创建的时间
    project.idint迁移项目的id
    project.identifierstring迁移项目的标识
    project.namestring迁移项目的名称
    project.descriptionstring迁移项目的描述
    project.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.typestring迁移项目拥有者类型
    project.owner.namestring迁移项目拥有者昵称
    project.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "project": {
    +        "id": 86,
    +        "identifier": "ceshi_repo1",
    +        "name": "测试项目啊1",
    +        "description": "二十多",
    +        "is_public": true,
    +        "owner": {
    +            "id": 52,
    +            "type": "Organization",
    +            "name": "身份卡手动阀",
    +            "login": "ceshi1",
    +            "image_url": "images/avatars/Organization/52?t=1618805056"
    +        }
    +    },
    +    "user": {
    +        "id": 6,
    +        "type": "User",
    +        "name": "yystopf",
    +        "login": "yystopf",
    +        "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
    +    },
    +    "owner": {
    +        "id": 9,
    +        "type": "Organization",
    +        "name": "测试组织",
    +        "login": "ceshi_org",
    +        "image_url": "images/avatars/Organization/9?t=1612706073"
    +    },
    +    "id": 4,
    +    "status": "common",
    +    "created_at": "2021-04-26 09:54",
    +    "time_ago": "1分钟前"
    +}
     

    Repositories

    仓库详情

    仓库详情

    From d532dc7cf55b9819853adc9aeb4937b2a6422fb6 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 26 Apr 2021 10:57:57 +0800 Subject: [PATCH 105/643] fix: some bug and users api doc --- app/docs/slate/source/includes/_projects.md | 8 +- app/docs/slate/source/includes/_users.md | 393 ++++++++ ...nd_transfer_project_applied_message_job.rb | 6 +- .../projects/apply_transfer_service.rb | 9 +- .../applied_messages/_detail.json.jbuilder | 29 +- public/docs/api.html | 850 +++++++++++++++++- 6 files changed, 1265 insertions(+), 30 deletions(-) diff --git a/app/docs/slate/source/includes/_projects.md b/app/docs/slate/source/includes/_projects.md index 85359d80e..87a37c45b 100644 --- a/app/docs/slate/source/includes/_projects.md +++ b/app/docs/slate/source/includes/_projects.md @@ -555,7 +555,7 @@ repo |是| |string |项目标识identifier --------- | ----------- | ----------- name |string|组织标识 nickname |string|组织名称 -description|string|组织描述 +description|string|组织描述 avatar_url|string|组织头像 @@ -703,9 +703,9 @@ await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.j ### 返回字段说明 参数 | 类型 | 字段说明 --------- | ----------- | ----------- -|id |int |项目id | -|status |string |项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝| -|time_ago |string |项目迁移创建的时间 | +|id |int |迁移id | +|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝| +|time_ago |string |迁移创建的时间 | |project.id |int |迁移项目的id | |project.identifier |string |迁移项目的标识 | |project.name |string |迁移项目的名称 | diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 62a6391e1..1d1afc028 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,3 +1,9 @@ + # Users ## 获取当前登陆用户信息 @@ -40,3 +46,390 @@ await octokit.request('GET /api/users/me.json') + +## 待办事项-用户通知信息 +待办事项-用户通知信息 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json +``` + +```javascript +await octokit.request('GET /api/users/:login/applied_messages.json') +``` + +### HTTP 请求 +`GET /api/users/:login/applied_messages.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|login |string |用户标识 | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|applied |object |通知主体 | +|applied.id |int |通知主体的迁移id | +|applied.status |string |通知主体的迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝| +|applied.time_ago |string |通知主体的迁移创建的时间 | +|applied.project.id |int |通知主体的迁移项目的id | +|applied.project.identifier |string |通知主体的迁移项目的标识 | +|applied.project.name |string |通知主体的迁移项目的名称 | +|applied.project.description |string |通知主体的迁移项目的描述 | +|applied.project.is_public |bool |通知主体的迁移项目是否公开 | +|applied.project.owner.id |bool |通知主体的迁移项目拥有者id | +|applied.project.owner.type |string |通知主体的迁移项目拥有者类型 | +|applied.project.owner.name |string |通知主体的迁移项目拥有者昵称 | +|applied.project.owner.login |string |通知主体的迁移项目拥有者标识 | +|applied.project.owner.image_url |string |通知主体的迁移项目拥有者头像 | +|applied.user.id |int |通知主体的迁移创建者的id | +|applied.user.type |string |通知主体的迁移创建者的类型 | +|applied.user.name |string |通知主体的迁移创建者的名称 | +|applied.user.login |string |通知主体的迁移创建者的标识 | +|applied.user.image_url |string |通知主体的迁移创建者头像 | +|applied.owner.id |int |通知主体的迁移接受者的id | +|applied.owner.type |string |通知主体的迁移接受者的类型 | +|applied.owner.name |string |通知主体的迁移接受者的名称 | +|applied.owner.login |string |通知主体的迁移接受者的标识 | +|applied.owner.image_url |string |通知主体的迁移接受者头像 | +|applied_type |string |通知类型 | +|name |string | 通知内容 | +|viewed |string|是否已读,waiting:未读,viewed:已读| +|status |string|通知状态, canceled:已取消,common: 正常,successed:成功,failure:失败| +|time_ago |string|通知时间| + + +> 返回的JSON示例: + +```json +{ + "total_count": 5, + "applied_messages": [ + { + "applied": { + "project": { + "id": 86, + "identifier": "ceshi_repo1", + "name": "测试项目啊1", + "description": "二十多", + "is_public": true, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "yystopf", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + }, + "owner": { + "id": 9, + "type": "Organization", + "name": "测试组织", + "login": "ceshi_org", + "image_url": "images/avatars/Organization/9?t=1612706073" + }, + "id": 4, + "status": "common", + "created_at": "2021-04-26 09:54", + "time_ago": "35分钟前" + }, + "applied_user": { + "id": 6, + "type": "User", + "name": "yystopf", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + }, + "applied_type": "AppliedTransferProject", + "name": "正在将【测试项目啊1】仓库转移给【测试组织】", + "viewed": "viewed", + "status": "common", + "created_at": "2021-04-26 09:54", + "time_ago": "35分钟前" + }, + ... + ] +} +``` + +## 待办事项-接受仓库 +待办事项-接受仓库 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json +``` + +```javascript +await octokit.request('GET /api/users/:login/applied_transfer_projects.json') +``` + +### HTTP 请求 +`GET /api/users/:login/applied_transfer_projects.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|login |string |用户标识 | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |迁移id | +|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝| +|time_ago |string |迁移创建的时间 | +|project.id |int |迁移项目的id | +|project.identifier |string |迁移项目的标识 | +|project.name |string |迁移项目的名称 | +|project.description |string |迁移项目的描述 | +|project.is_public |bool |迁移项目是否公开 | +|project.owner.id |bool |迁移项目拥有者id | +|project.owner.type |string |迁移项目拥有者类型 | +|project.owner.name |string |迁移项目拥有者昵称 | +|project.owner.login |string |迁移项目拥有者标识 | +|project.owner.image_url |string |迁移项目拥有者头像 | +|user.id |int |迁移创建者的id | +|user.type |string |迁移创建者的类型 | +|user.name |string |迁移创建者的名称 | +|user.login |string |迁移创建者的标识 | +|user.image_url |string |迁移创建者头像 | +|owner.id |int |迁移接受者的id | +|owner.type |string |迁移接受者的类型 | +|owner.name |string |迁移接受者的名称 | +|owner.login |string |迁移接受者的标识 | +|owner.image_url |string |迁移接受者头像 | + + +> 返回的JSON示例: + +```json +{ + "total_count": 4, + "applied_transfer_projects": [ + { + "project": { + "id": 86, + "identifier": "ceshi_repo1", + "name": "测试项目啊1", + "description": "二十多", + "is_public": true, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "yystopf", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + }, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + }, + "id": 1, + "status": "canceled", + "created_at": "2021-04-25 18:06", + "time_ago": "16小时前" + }, + ... + ] +} +``` + +## 用户接受迁移 +用户接受迁移 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json +``` + +```javascript +await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json') +``` + +### HTTP 请求 +`GET /api/users/:login/applied_transfer_projects/:id/accept.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|login |string |用户标识 | +|id |int |迁移id | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |迁移id | +|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝| +|time_ago |string |迁移创建的时间 | +|project.id |int |迁移项目的id | +|project.identifier |string |迁移项目的标识 | +|project.name |string |迁移项目的名称 | +|project.description |string |迁移项目的描述 | +|project.is_public |bool |迁移项目是否公开 | +|project.owner.id |bool |迁移项目拥有者id | +|project.owner.type |string |迁移项目拥有者类型 | +|project.owner.name |string |迁移项目拥有者昵称 | +|project.owner.login |string |迁移项目拥有者标识 | +|project.owner.image_url |string |迁移项目拥有者头像 | +|user.id |int |迁移创建者的id | +|user.type |string |迁移创建者的类型 | +|user.name |string |迁移创建者的名称 | +|user.login |string |迁移创建者的标识 | +|user.image_url |string |迁移创建者头像 | +|owner.id |int |迁移接受者的id | +|owner.type |string |迁移接受者的类型 | +|owner.name |string |迁移接受者的名称 | +|owner.login |string |迁移接受者的标识 | +|owner.image_url |string |迁移接受者头像 | + + +> 返回的JSON示例: + +```json +{ + "project": { + "id": 86, + "identifier": "ceshi_repo1", + "name": "测试项目啊1", + "description": "二十多", + "is_public": true, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "yystopf", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + }, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + }, + "id": 1, + "status": "canceled", + "created_at": "2021-04-25 18:06", + "time_ago": "16小时前" +} +``` + +## 用户拒绝迁移 +用户拒绝迁移 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json +``` + +```javascript +await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json') +``` + +### HTTP 请求 +`GET /api/users/:login/applied_transfer_projects/:id/refuse.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|login |string |用户标识 | +|id |int |迁移id | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |迁移id | +|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝| +|time_ago |string |迁移创建的时间 | +|project.id |int |迁移项目的id | +|project.identifier |string |迁移项目的标识 | +|project.name |string |迁移项目的名称 | +|project.description |string |迁移项目的描述 | +|project.is_public |bool |迁移项目是否公开 | +|project.owner.id |bool |迁移项目拥有者id | +|project.owner.type |string |迁移项目拥有者类型 | +|project.owner.name |string |迁移项目拥有者昵称 | +|project.owner.login |string |迁移项目拥有者标识 | +|project.owner.image_url |string |迁移项目拥有者头像 | +|user.id |int |迁移创建者的id | +|user.type |string |迁移创建者的类型 | +|user.name |string |迁移创建者的名称 | +|user.login |string |迁移创建者的标识 | +|user.image_url |string |迁移创建者头像 | +|owner.id |int |迁移接受者的id | +|owner.type |string |迁移接受者的类型 | +|owner.name |string |迁移接受者的名称 | +|owner.login |string |迁移接受者的标识 | +|owner.image_url |string |迁移接受者头像 | + + +> 返回的JSON示例: + +```json +{ + "project": { + "id": 86, + "identifier": "ceshi_repo1", + "name": "测试项目啊1", + "description": "二十多", + "is_public": true, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "yystopf", + "login": "yystopf", + "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + }, + "owner": { + "id": 52, + "type": "Organization", + "name": "身份卡手动阀", + "login": "ceshi1", + "image_url": "images/avatars/Organization/52?t=1618805056" + }, + "id": 1, + "status": "canceled", + "created_at": "2021-04-25 18:06", + "time_ago": "16小时前" +} +``` \ No newline at end of file diff --git a/app/jobs/send_transfer_project_applied_message_job.rb b/app/jobs/send_transfer_project_applied_message_job.rb index 790d1fd5d..ef05f266d 100644 --- a/app/jobs/send_transfer_project_applied_message_job.rb +++ b/app/jobs/send_transfer_project_applied_message_job.rb @@ -6,7 +6,11 @@ class SendTransferProjectAppliedMessageJob < ApplicationJob owner = applied_transfer_project.owner return unless project.present? return unless owner.present? - receivers = project.managers + owner.team_users.joins(:team).where(teams: {authorize: %w(owner admin)}) + if owner.is_a?(Organization) + receivers = project.managers + owner.team_users.joins(:team).where(teams: {authorize: %w(owner admin)}) + else + receivers = project.managers + end receivers.each do |rec| AppliedMessage.create!(user_id: rec.user_id, applied: applied_transfer_project, diff --git a/app/services/projects/apply_transfer_service.rb b/app/services/projects/apply_transfer_service.rb index ee4ec4265..7f33cc101 100644 --- a/app/services/projects/apply_transfer_service.rb +++ b/app/services/projects/apply_transfer_service.rb @@ -1,12 +1,12 @@ class Projects::ApplyTransferService < ApplicationService attr_accessor :owner, :applied_transfer_project - attr_reader :user, :project, :owner_name + attr_reader :user, :project, :params - def initialize(user, project, owner_name) + def initialize(user, project, params) @user = user @project = project - @owner_name = owner_name - @owner = Owner.find_by(login: owner_name) + @params = params + @owner = Owner.find_by(login: params[:owner_name]) end def call @@ -21,6 +21,7 @@ class Projects::ApplyTransferService < ApplicationService private def validate! + raise Error, '仓库标识不正确' if @project.identifier != params[:identifier] raise Error, '该仓库正在迁移' if @project.is_transfering raise Error, '新拥有者不存在' unless @owner.present? raise Error, '未拥有转移权限' unless is_permit_owner diff --git a/app/views/users/applied_messages/_detail.json.jbuilder b/app/views/users/applied_messages/_detail.json.jbuilder index 0bbd49b01..cca202c10 100644 --- a/app/views/users/applied_messages/_detail.json.jbuilder +++ b/app/views/users/applied_messages/_detail.json.jbuilder @@ -1,23 +1,24 @@ -project = object.project -json.project do - json.id project.id - json.identifier project.identifier - json.name project.name - json.description project.description - json.is_public project.is_public - json.owner do - json.partial! "/users/user_simple", locals: {user: project.owner} - end -end -json.user do - json.partial! "/users/user_simple", locals: {user: object.user} -end +# project = object.project +# json.project do +# json.id project.id +# json.identifier project.identifier +# json.name project.name +# json.description project.description +# json.is_public project.is_public +# json.owner do +# json.partial! "/users/user_simple", locals: {user: project.owner} +# end +# end +# json.user do +# json.partial! "/users/user_simple", locals: {user: object.user} +# end json.applied do json.partial! "/projects/applied_transfer_projects/detail", locals: {object: object.applied} end json.applied_user do json.partial! "/users/user_simple", locals: {user: object.applied_user} end +json.applied_type object.applied_type json.name object.name json.viewed object.viewed json.status object.status diff --git a/public/docs/api.html b/public/docs/api.html index a2e4ef957..f970ea84d 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -331,6 +331,18 @@
  • 获取当前登陆用户信息
  • +
  • + 待办事项-用户通知信息 +
  • +
  • + 待办事项-接受仓库 +
  • +
  • + 用户接受迁移 +
  • +
  • + 用户拒绝迁移 +
  • @@ -572,6 +584,12 @@ http://localhost:3000/api/ignores.json +

    Users

    获取当前登陆用户信息

    获取当前登陆用户信息

    @@ -631,7 +649,818 @@ Success — a happy kitten is an authenticated kitten! -

    Projects

    获取项目列表

    +

    待办事项-用户通知信息

    +

    待办事项-用户通知信息

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
    +
    await octokit.request('GET /api/users/:login/applied_messages.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/applied_messages.json

    +

    请求字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    loginstring用户标识
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    appliedobject通知主体
    applied.idint通知主体的迁移id
    applied.statusstring通知主体的迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    applied.time_agostring通知主体的迁移创建的时间
    applied.project.idint通知主体的迁移项目的id
    applied.project.identifierstring通知主体的迁移项目的标识
    applied.project.namestring通知主体的迁移项目的名称
    applied.project.descriptionstring通知主体的迁移项目的描述
    applied.project.is_publicbool通知主体的迁移项目是否公开
    applied.project.owner.idbool通知主体的迁移项目拥有者id
    applied.project.owner.typestring通知主体的迁移项目拥有者类型
    applied.project.owner.namestring通知主体的迁移项目拥有者昵称
    applied.project.owner.loginstring通知主体的迁移项目拥有者标识
    applied.project.owner.image_urlstring通知主体的迁移项目拥有者头像
    applied.user.idint通知主体的迁移创建者的id
    applied.user.typestring通知主体的迁移创建者的类型
    applied.user.namestring通知主体的迁移创建者的名称
    applied.user.loginstring通知主体的迁移创建者的标识
    applied.user.image_urlstring通知主体的迁移创建者头像
    applied.owner.idint通知主体的迁移接受者的id
    applied.owner.typestring通知主体的迁移接受者的类型
    applied.owner.namestring通知主体的迁移接受者的名称
    applied.owner.loginstring通知主体的迁移接受者的标识
    applied.owner.image_urlstring通知主体的迁移接受者头像
    applied_typestring通知类型
    namestring通知内容
    viewedstring是否已读,waiting:未读,viewed:已读
    statusstring通知状态, canceled:已取消,common: 正常,successed:成功,failure:失败
    time_agostring通知时间
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_count": 5,
    +    "applied_messages": [
    +        {
    +            "applied": {
    +                "project": {
    +                    "id": 86,
    +                    "identifier": "ceshi_repo1",
    +                    "name": "测试项目啊1",
    +                    "description": "二十多",
    +                    "is_public": true,
    +                    "owner": {
    +                        "id": 52,
    +                        "type": "Organization",
    +                        "name": "身份卡手动阀",
    +                        "login": "ceshi1",
    +                        "image_url": "images/avatars/Organization/52?t=1618805056"
    +                    }
    +                },
    +                "user": {
    +                    "id": 6,
    +                    "type": "User",
    +                    "name": "yystopf",
    +                    "login": "yystopf",
    +                    "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
    +                },
    +                "owner": {
    +                    "id": 9,
    +                    "type": "Organization",
    +                    "name": "测试组织",
    +                    "login": "ceshi_org",
    +                    "image_url": "images/avatars/Organization/9?t=1612706073"
    +                },
    +                "id": 4,
    +                "status": "common",
    +                "created_at": "2021-04-26 09:54",
    +                "time_ago": "35分钟前"
    +            },
    +            "applied_user": {
    +                "id": 6,
    +                "type": "User",
    +                "name": "yystopf",
    +                "login": "yystopf",
    +                "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
    +            },
    +            "applied_type": "AppliedTransferProject",
    +            "name": "正在将【测试项目啊1】仓库转移给【测试组织】",
    +            "viewed": "viewed",
    +            "status": "common",
    +            "created_at": "2021-04-26 09:54",
    +            "time_ago": "35分钟前"
    +        },
    +        ...
    +    ]
    +}
    +

    待办事项-接受仓库

    +

    待办事项-接受仓库

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
    +
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/applied_transfer_projects.json

    +

    请求字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    loginstring用户标识
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    idint迁移id
    statusstring迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    time_agostring迁移创建的时间
    project.idint迁移项目的id
    project.identifierstring迁移项目的标识
    project.namestring迁移项目的名称
    project.descriptionstring迁移项目的描述
    project.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.typestring迁移项目拥有者类型
    project.owner.namestring迁移项目拥有者昵称
    project.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_count": 4,
    +    "applied_transfer_projects": [
    +        {
    +            "project": {
    +                "id": 86,
    +                "identifier": "ceshi_repo1",
    +                "name": "测试项目啊1",
    +                "description": "二十多",
    +                "is_public": true,
    +                "owner": {
    +                    "id": 52,
    +                    "type": "Organization",
    +                    "name": "身份卡手动阀",
    +                    "login": "ceshi1",
    +                    "image_url": "images/avatars/Organization/52?t=1618805056"
    +                }
    +            },
    +            "user": {
    +                "id": 6,
    +                "type": "User",
    +                "name": "yystopf",
    +                "login": "yystopf",
    +                "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
    +            },
    +            "owner": {
    +                "id": 52,
    +                "type": "Organization",
    +                "name": "身份卡手动阀",
    +                "login": "ceshi1",
    +                "image_url": "images/avatars/Organization/52?t=1618805056"
    +            },
    +            "id": 1,
    +            "status": "canceled",
    +            "created_at": "2021-04-25 18:06",
    +            "time_ago": "16小时前"
    +        },
    +        ...
    +    ]
    +}
    +

    用户接受迁移

    +

    用户接受迁移

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
    +
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    loginstring用户标识
    idint迁移id
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    idint迁移id
    statusstring迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    time_agostring迁移创建的时间
    project.idint迁移项目的id
    project.identifierstring迁移项目的标识
    project.namestring迁移项目的名称
    project.descriptionstring迁移项目的描述
    project.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.typestring迁移项目拥有者类型
    project.owner.namestring迁移项目拥有者昵称
    project.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "project": {
    +        "id": 86,
    +        "identifier": "ceshi_repo1",
    +        "name": "测试项目啊1",
    +        "description": "二十多",
    +        "is_public": true,
    +        "owner": {
    +            "id": 52,
    +            "type": "Organization",
    +            "name": "身份卡手动阀",
    +            "login": "ceshi1",
    +            "image_url": "images/avatars/Organization/52?t=1618805056"
    +        }
    +    },
    +    "user": {
    +        "id": 6,
    +        "type": "User",
    +        "name": "yystopf",
    +        "login": "yystopf",
    +        "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
    +    },
    +    "owner": {
    +        "id": 52,
    +        "type": "Organization",
    +        "name": "身份卡手动阀",
    +        "login": "ceshi1",
    +        "image_url": "images/avatars/Organization/52?t=1618805056"
    +    },
    +    "id": 1,
    +    "status": "canceled",
    +    "created_at": "2021-04-25 18:06",
    +    "time_ago": "16小时前"
    +}
    +

    用户拒绝迁移

    +

    用户拒绝迁移

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
    +
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    loginstring用户标识
    idint迁移id
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    idint迁移id
    statusstring迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    time_agostring迁移创建的时间
    project.idint迁移项目的id
    project.identifierstring迁移项目的标识
    project.namestring迁移项目的名称
    project.descriptionstring迁移项目的描述
    project.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.typestring迁移项目拥有者类型
    project.owner.namestring迁移项目拥有者昵称
    project.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "project": {
    +        "id": 86,
    +        "identifier": "ceshi_repo1",
    +        "name": "测试项目啊1",
    +        "description": "二十多",
    +        "is_public": true,
    +        "owner": {
    +            "id": 52,
    +            "type": "Organization",
    +            "name": "身份卡手动阀",
    +            "login": "ceshi1",
    +            "image_url": "images/avatars/Organization/52?t=1618805056"
    +        }
    +    },
    +    "user": {
    +        "id": 6,
    +        "type": "User",
    +        "name": "yystopf",
    +        "login": "yystopf",
    +        "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
    +    },
    +    "owner": {
    +        "id": 52,
    +        "type": "Organization",
    +        "name": "身份卡手动阀",
    +        "login": "ceshi1",
    +        "image_url": "images/avatars/Organization/52?t=1618805056"
    +    },
    +    "id": 1,
    +    "status": "canceled",
    +    "created_at": "2021-04-25 18:06",
    +    "time_ago": "16小时前"
    +}
    +

    Projects

    获取项目列表

    获取项目列表,也可以更加相关条件过滤搜素

    @@ -1653,11 +2482,18 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat string 组织名称 + +description +string +组织描述 + + +avatar_url +string|组织头像 + + -

    description|string|组织描述 -avatar_url|string|组织头像

    -

    返回的JSON示例:

    @@ -1937,17 +2773,17 @@ avatar_url|string|组织头像

    id int -项目id +迁移id status string -项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝 +迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝 time_ago string -项目迁移创建的时间 +迁移创建的时间 project.id From 96238c2e13e6932e188c6fa98622615de60558af Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 26 Apr 2021 11:04:10 +0800 Subject: [PATCH 106/643] fix --- .../projects/applied_transfer_projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/applied_transfer_projects_controller.rb b/app/controllers/projects/applied_transfer_projects_controller.rb index ad6c9b19c..e62033f21 100644 --- a/app/controllers/projects/applied_transfer_projects_controller.rb +++ b/app/controllers/projects/applied_transfer_projects_controller.rb @@ -6,7 +6,7 @@ class Projects::AppliedTransferProjectsController < Projects::BaseController end def create - @applied_transfer_project = Projects::ApplyTransferService.call(current_user, @project, params[:owner_name]) + @applied_transfer_project = Projects::ApplyTransferService.call(current_user, @project, params) rescue Exception => e uid_logger_error(e.message) tip_exception(e.message) From 1d81548eb62284526cbf69bed632e53fa7ffb210 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 26 Apr 2021 11:32:59 +0800 Subject: [PATCH 107/643] fix --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 0c30e13fa..170bae06a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -112,7 +112,7 @@ class Project < ApplicationRecord has_one :project_detail, dependent: :destroy has_many :team_projects, dependent: :destroy has_many :project_units, dependent: :destroy - has_one :applied_transfer_project, dependent: :destroy + has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy after_save :check_project_members scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} From 28c8761f323a405fba82311e68789b8d45d4676d Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 26 Apr 2021 15:11:08 +0800 Subject: [PATCH 108/643] fix --- app/controllers/users/applied_transfer_projects_controller.rb | 4 ++-- app/services/projects/accept_transfer_service.rb | 2 +- app/services/projects/refuse_transfer_service.rb | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/controllers/users/applied_transfer_projects_controller.rb b/app/controllers/users/applied_transfer_projects_controller.rb index 74366bb55..3889f2eb6 100644 --- a/app/controllers/users/applied_transfer_projects_controller.rb +++ b/app/controllers/users/applied_transfer_projects_controller.rb @@ -4,10 +4,10 @@ class Users::AppliedTransferProjectsController < Users::BaseController before_action :find_project, except: [:index] def index - user_collection_sql = AppliedTransferProject.where(owner_id: @_observed_user.id).to_sql + user_collection_sql = AppliedTransferProject.joins(project: [members: :roles]).where(members: {user_id: @_observed_user.id}, roles: {name: 'Manager'}).to_sql org_collection_sql = AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @_observed_user.id}, teams: {authorize: %w(admin owner)} )).to_sql @applied_transfer_projects = AppliedTransferProject.from("( #{ user_collection_sql } UNION #{ org_collection_sql } ) AS applied_transfer_projects") - @applied_transfer_projects = paginate @applied_transfer_projects + @applied_transfer_projects = paginate @applied_transfer_projects.order("created_at desc") end # 接受迁移 diff --git a/app/services/projects/accept_transfer_service.rb b/app/services/projects/accept_transfer_service.rb index 57cdfd54b..284499002 100644 --- a/app/services/projects/accept_transfer_service.rb +++ b/app/services/projects/accept_transfer_service.rb @@ -26,7 +26,7 @@ class Projects::AcceptTransferService < ApplicationService private def validate! raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering - raise Error, '未拥有接受转移权限' unless @user.admin? || @project.is_admin?(@user) + raise Error, '未拥有接受转移权限' unless @user.admin? || @project.manager?(@user) end def update_apply diff --git a/app/services/projects/refuse_transfer_service.rb b/app/services/projects/refuse_transfer_service.rb index 88d252465..b8199e65e 100644 --- a/app/services/projects/refuse_transfer_service.rb +++ b/app/services/projects/refuse_transfer_service.rb @@ -21,6 +21,7 @@ class Projects::RefuseTransferService < ApplicationService private def validate! raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering + raise Error, '未拥有拒绝转移权限' unless @user.admin? || @project.manager?(@user) end def update_apply From 220ca966696c50aada0dc986bd69ff5f580f7234 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 26 Apr 2021 15:17:51 +0800 Subject: [PATCH 109/643] fix --- app/controllers/users/applied_transfer_projects_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/users/applied_transfer_projects_controller.rb b/app/controllers/users/applied_transfer_projects_controller.rb index 3889f2eb6..74366bb55 100644 --- a/app/controllers/users/applied_transfer_projects_controller.rb +++ b/app/controllers/users/applied_transfer_projects_controller.rb @@ -4,10 +4,10 @@ class Users::AppliedTransferProjectsController < Users::BaseController before_action :find_project, except: [:index] def index - user_collection_sql = AppliedTransferProject.joins(project: [members: :roles]).where(members: {user_id: @_observed_user.id}, roles: {name: 'Manager'}).to_sql + user_collection_sql = AppliedTransferProject.where(owner_id: @_observed_user.id).to_sql org_collection_sql = AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @_observed_user.id}, teams: {authorize: %w(admin owner)} )).to_sql @applied_transfer_projects = AppliedTransferProject.from("( #{ user_collection_sql } UNION #{ org_collection_sql } ) AS applied_transfer_projects") - @applied_transfer_projects = paginate @applied_transfer_projects.order("created_at desc") + @applied_transfer_projects = paginate @applied_transfer_projects end # 接受迁移 From 13768f97787236840b5cd81da3d14a678d1b2898 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 26 Apr 2021 15:28:49 +0800 Subject: [PATCH 110/643] add: same repo condition --- app/services/projects/apply_transfer_service.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/projects/apply_transfer_service.rb b/app/services/projects/apply_transfer_service.rb index 7f33cc101..e8839167d 100644 --- a/app/services/projects/apply_transfer_service.rb +++ b/app/services/projects/apply_transfer_service.rb @@ -22,6 +22,7 @@ class Projects::ApplyTransferService < ApplicationService private def validate! raise Error, '仓库标识不正确' if @project.identifier != params[:identifier] + raise Error, '新拥有者已经存在同名仓库!' if Project.where(user_id: @owner.id, identifier: params[:identifier]).present? raise Error, '该仓库正在迁移' if @project.is_transfering raise Error, '新拥有者不存在' unless @owner.present? raise Error, '未拥有转移权限' unless is_permit_owner From 95a355b87c85efa633931fa2c75ede2a661a1e65 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 26 Apr 2021 16:45:26 +0800 Subject: [PATCH 111/643] FIX admin projects api bug --- app/views/admins/projects/shared/_list.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admins/projects/shared/_list.html.erb b/app/views/admins/projects/shared/_list.html.erb index bd6300283..fe8d96e9d 100644 --- a/app/views/admins/projects/shared/_list.html.erb +++ b/app/views/admins/projects/shared/_list.html.erb @@ -23,7 +23,7 @@ <%= list_index_no((params[:page] || 1).to_i, index) %> <%= project.id %> - <%= link_to(project.name, "/projects/#{project.id}", target: '_blank') %> + <%= link_to(project.name, "/projects/#{project&.owner&.login}/#{project.identifier}", target: '_blank') %> <%= project.is_public ? '√' : '' %> <%= project.issues.size %> @@ -33,7 +33,7 @@ <%= project.versions.size %> <%= project.members.size %> - <%= project.owner ? link_to(project.owner&.real_name, "/users/#{project.owner&.login}", target: '_blank') : "" %> + <%= link_to_project(project) %> <%= project.created_on&.strftime('%Y-%m-%d %H:%M') %> From 1a22491e36af66c80b6dfe7502ca1ad20834433f Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 26 Apr 2021 16:45:58 +0800 Subject: [PATCH 112/643] ADD admin role to org api --- app/controllers/organizations/base_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/organizations/base_controller.rb b/app/controllers/organizations/base_controller.rb index e6163bf8c..e18ab9aef 100644 --- a/app/controllers/organizations/base_controller.rb +++ b/app/controllers/organizations/base_controller.rb @@ -17,6 +17,7 @@ class Organizations::BaseController < ApplicationController end def org_privacy_condition + return false if current_user.admin? @organization.organization_extension.privacy? && @organization.organization_users.where(user_id: current_user.id).blank? end From 0d828ead1f5e52915c64f330a7f733095bc0a15a Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 26 Apr 2021 16:50:50 +0800 Subject: [PATCH 113/643] fix:some bug --- .../users/applied_transfer_projects_controller.rb | 2 +- .../send_transfer_project_applied_message_job.rb | 13 +++++++++++-- app/services/projects/accept_transfer_service.rb | 12 +++++++++--- app/services/projects/refuse_transfer_service.rb | 10 ++++++++-- app/services/projects/transfer_service.rb | 1 + 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/app/controllers/users/applied_transfer_projects_controller.rb b/app/controllers/users/applied_transfer_projects_controller.rb index 74366bb55..b1777f526 100644 --- a/app/controllers/users/applied_transfer_projects_controller.rb +++ b/app/controllers/users/applied_transfer_projects_controller.rb @@ -7,7 +7,7 @@ class Users::AppliedTransferProjectsController < Users::BaseController user_collection_sql = AppliedTransferProject.where(owner_id: @_observed_user.id).to_sql org_collection_sql = AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @_observed_user.id}, teams: {authorize: %w(admin owner)} )).to_sql @applied_transfer_projects = AppliedTransferProject.from("( #{ user_collection_sql } UNION #{ org_collection_sql } ) AS applied_transfer_projects") - @applied_transfer_projects = paginate @applied_transfer_projects + @applied_transfer_projects = paginate @applied_transfer_projects.order("created_at desc") end # 接受迁移 diff --git a/app/jobs/send_transfer_project_applied_message_job.rb b/app/jobs/send_transfer_project_applied_message_job.rb index ef05f266d..5f0c24c65 100644 --- a/app/jobs/send_transfer_project_applied_message_job.rb +++ b/app/jobs/send_transfer_project_applied_message_job.rb @@ -3,7 +3,7 @@ class SendTransferProjectAppliedMessageJob < ApplicationJob def perform(applied_transfer_project, applied_user, message_status) project = applied_transfer_project.project - owner = applied_transfer_project.owner + owner = project.owner return unless project.present? return unless owner.present? if owner.is_a?(Organization) @@ -12,13 +12,22 @@ class SendTransferProjectAppliedMessageJob < ApplicationJob receivers = project.managers end receivers.each do |rec| + next if applied_user.id == rec.user_id # 自己不要给自己发通知 AppliedMessage.create!(user_id: rec.user_id, applied: applied_transfer_project, status: message_status, - name: build_name(project.name, owner.real_name, message_status), + name: build_name(project.name, applied_transfer_project&.owner&.real_name, message_status), applied_user_id: applied_user.id, project_id: project.id) end + if message_status == 'successed' # 如果转移成功,给转移发起者发通知已转移成功 + AppliedMessage.find_or_create_by!(user_id: applied_transfer_project.user_id, + applied: applied_transfer_project, + status: message_status, + name: build_name(project.name, applied_transfer_project&.owner&.real_name, message_status), + applied_user_id: applied_user.id, + project_id: project.id) + end end private diff --git a/app/services/projects/accept_transfer_service.rb b/app/services/projects/accept_transfer_service.rb index 284499002..c99885ca0 100644 --- a/app/services/projects/accept_transfer_service.rb +++ b/app/services/projects/accept_transfer_service.rb @@ -1,11 +1,12 @@ class Projects::AcceptTransferService < ApplicationService - attr_accessor :applied_transfer_project + attr_accessor :applied_transfer_project, :owner attr_reader :user, :project def initialize(user, project) @user = user @project = project @applied_transfer_project = project.applied_transfer_project + @owner = @applied_transfer_project.owner end def call @@ -26,7 +27,12 @@ class Projects::AcceptTransferService < ApplicationService private def validate! raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering - raise Error, '未拥有接受转移权限' unless @user.admin? || @project.manager?(@user) + raise Error, '未拥有接受转移权限' unless is_permit_operator + end + + def is_permit_operator + return true if @user == @owner + return @owner.is_a?(Organization) && @owner.is_admin?(@user) end def update_apply @@ -34,7 +40,7 @@ class Projects::AcceptTransferService < ApplicationService end def operate_project - @project = Projects::TransferService.call(@project, @applied_transfer_project.owner) + @project = Projects::TransferService.call(@project, @owner) end def send_apply_message diff --git a/app/services/projects/refuse_transfer_service.rb b/app/services/projects/refuse_transfer_service.rb index b8199e65e..1b81b5741 100644 --- a/app/services/projects/refuse_transfer_service.rb +++ b/app/services/projects/refuse_transfer_service.rb @@ -1,11 +1,12 @@ class Projects::RefuseTransferService < ApplicationService - attr_accessor :applied_transfer_project + attr_accessor :applied_transfer_project, :owner attr_reader :user, :project def initialize(user, project) @user = user @project = project @applied_transfer_project = project.applied_transfer_project + @owner = @applied_transfer_project.owner end def call @@ -21,7 +22,12 @@ class Projects::RefuseTransferService < ApplicationService private def validate! raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering - raise Error, '未拥有拒绝转移权限' unless @user.admin? || @project.manager?(@user) + raise Error, '未拥有拒绝转移权限' unless is_permit_operator + end + + def is_permit_operator + return true if @user == @owner + return @owner.is_a?(Organization) && @owner.is_admin?(@user) end def update_apply diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index b32b24817..4582a2103 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -23,6 +23,7 @@ class Projects::TransferService < ApplicationService private def update_owner + project.members.find_by(user_id: owner.id).destroy! if owner.is_a?(User) project.update!(user_id: new_owner.id) end From 5bd33c033cd708ef47b7c816e77a7f5297c493fa Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 26 Apr 2021 16:52:48 +0800 Subject: [PATCH 114/643] FIX bug --- app/helpers/admins/projects_helper.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 app/helpers/admins/projects_helper.rb diff --git a/app/helpers/admins/projects_helper.rb b/app/helpers/admins/projects_helper.rb new file mode 100644 index 000000000..c6d94c4ca --- /dev/null +++ b/app/helpers/admins/projects_helper.rb @@ -0,0 +1,14 @@ +module Admins::ProjectsHelper + + def link_to_project(project) + owner = project.owner + + if owner.is_a?(User) + link_to(project.owner&.real_name, "/users/#{project&.owner&.login}", target: '_blank') + elsif owner.is_a?(Organization) + link_to(project.owner&.real_name, "/organize/#{project&.owner&.login}", target: '_blank') + else + "" + end + end +end \ No newline at end of file From 01360de423159d32f2c005feace855a30a771dbd Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 27 Apr 2021 13:56:12 +0800 Subject: [PATCH 115/643] fix: acceptor must exist --- app/services/projects/apply_transfer_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/projects/apply_transfer_service.rb b/app/services/projects/apply_transfer_service.rb index e8839167d..28097bed5 100644 --- a/app/services/projects/apply_transfer_service.rb +++ b/app/services/projects/apply_transfer_service.rb @@ -22,9 +22,9 @@ class Projects::ApplyTransferService < ApplicationService private def validate! raise Error, '仓库标识不正确' if @project.identifier != params[:identifier] - raise Error, '新拥有者已经存在同名仓库!' if Project.where(user_id: @owner.id, identifier: params[:identifier]).present? raise Error, '该仓库正在迁移' if @project.is_transfering raise Error, '新拥有者不存在' unless @owner.present? + raise Error, '新拥有者已经存在同名仓库!' if Project.where(user_id: @owner.id, identifier: params[:identifier]).present? raise Error, '未拥有转移权限' unless is_permit_owner end From b68c9945e54f34f3bcf45a474d2131555749a337 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 27 Apr 2021 14:40:18 +0800 Subject: [PATCH 116/643] add: project edit transfer --- app/views/repositories/edit.json.jbuilder | 5 ++++- app/views/users/_user_simple.json.jbuilder | 14 +++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/views/repositories/edit.json.jbuilder b/app/views/repositories/edit.json.jbuilder index d268696cc..7a11411f4 100644 --- a/app/views/repositories/edit.json.jbuilder +++ b/app/views/repositories/edit.json.jbuilder @@ -9,4 +9,7 @@ json.website @project.website json.project_units @project.project_units.pluck(:unit_type) json.lesson_url @project.lesson_url json.permission render_permission(current_user, @project) -json.is_transfering @project.is_transfering \ No newline at end of file +json.is_transfering @project.is_transfering +json.transfer do + json.partial! "/users/user_simple", locals: {user: @project&.applied_transfer_project&.owner} +end \ No newline at end of file diff --git a/app/views/users/_user_simple.json.jbuilder b/app/views/users/_user_simple.json.jbuilder index cfd06a405..5da161509 100644 --- a/app/views/users/_user_simple.json.jbuilder +++ b/app/views/users/_user_simple.json.jbuilder @@ -1,5 +1,9 @@ -json.id user.id -json.type user.type -json.name user.real_name -json.login user.login -json.image_url url_to_avatar(user) \ No newline at end of file +if user.present? + json.id user.id + json.type user.type + json.name user.real_name + json.login user.login + json.image_url url_to_avatar(user) +else + json.nil! +end \ No newline at end of file From 120a33bc8ab5ae09c79fb589c6eecb3a50269513 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 27 Apr 2021 15:43:37 +0800 Subject: [PATCH 117/643] add: undo count --- app/controllers/users_controller.rb | 2 ++ app/jobs/send_transfer_project_applied_message_job.rb | 6 +++--- app/views/users/show.json.jbuilder | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c6ac626a3..395a5a6d9 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -32,6 +32,8 @@ class UsersController < ApplicationController @common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common @undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size else + @waiting_applied_messages = AppliedMessage.none + @common_applied_transfer_projects = AppliedTransferProject.none @undo_events = 0 end #用户的组织数量 diff --git a/app/jobs/send_transfer_project_applied_message_job.rb b/app/jobs/send_transfer_project_applied_message_job.rb index 5f0c24c65..92ea306d1 100644 --- a/app/jobs/send_transfer_project_applied_message_job.rb +++ b/app/jobs/send_transfer_project_applied_message_job.rb @@ -16,7 +16,7 @@ class SendTransferProjectAppliedMessageJob < ApplicationJob AppliedMessage.create!(user_id: rec.user_id, applied: applied_transfer_project, status: message_status, - name: build_name(project.name, applied_transfer_project&.owner&.real_name, message_status), + name: build_name(project.name, applied_transfer_project&.owner&.real_name, message_status, applied_user&.real_name), applied_user_id: applied_user.id, project_id: project.id) end @@ -31,7 +31,7 @@ class SendTransferProjectAppliedMessageJob < ApplicationJob end private - def build_name(repo_name, owner_name, message_status) + def build_name(repo_name, owner_name, message_status, applied_name="") case message_status when 'canceled' return "取消转移【#{repo_name}】仓库" @@ -40,7 +40,7 @@ class SendTransferProjectAppliedMessageJob < ApplicationJob when 'successed' return "【#{repo_name}】仓库成功转移给【#{owner_name}】" when 'failure' - return "【#{repo_name}】仓库转移失败" + return "拒绝转移【#{repo_name}】仓库" end "" end diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index 54f85c5c2..e80ac7494 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -10,6 +10,8 @@ json.user_identity @user.identity json.is_watch current_user&.watched?(@user) json.watched_count @user.fan_count #粉丝 json.watching_count @user.follow_count #关注数 +json.undo_messages @waiting_applied_messages.size +json.undo_transfer_projects @common_applied_transfer_projects.size json.undo_events @undo_events json.user_composes_count @user_composes_count json.user_org_count @user_org_count From 65d51e857804d1bf2bbdea7adc6297aed45fecec Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 28 Apr 2021 15:15:45 +0800 Subject: [PATCH 118/643] add: project operate add organization team users --- app/controllers/pull_requests_controller.rb | 2 +- app/helpers/tag_chosen_helper.rb | 15 ++++++--------- app/models/concerns/project_operable.rb | 6 ++++++ app/models/user.rb | 3 +++ app/views/pull_requests/_merge_item.json.jbuilder | 10 +++++----- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index c59a196b5..48735e787 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -215,7 +215,7 @@ class PullRequestsController < ApplicationController 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_members = @project.all_collaborators @project_priories = IssuePriority&.select(:id,:name, :position).as_json end diff --git a/app/helpers/tag_chosen_helper.rb b/app/helpers/tag_chosen_helper.rb index afd51170d..1e7879d18 100644 --- a/app/helpers/tag_chosen_helper.rb +++ b/app/helpers/tag_chosen_helper.rb @@ -124,14 +124,13 @@ module TagChosenHelper end def render_cache_collaborators(project) - cache_key = "all_collaborators/#{project.members.maximum('created_on')}" - + cache_key = "all_collaborators/#{project.all_collaborators.maximum('created_on')}" Rails.cache.fetch(cache_key) do - project.members.includes(:user).collect do |event| + project.all_collaborators.order(created_on: :desc).collect do |user| { - id: event.user&.id, - name: event.user&.show_real_name, - avatar_url: url_to_avatar(event.user), + id: user&.id, + name: user&.show_real_name, + avatar_url: url_to_avatar(user), is_chosen: '0' } end @@ -171,10 +170,8 @@ module TagChosenHelper # depended_issues_id = @depended_issues_id end - project_members = project.members_user_infos project_members_info = [] #指派给 - project_members.includes(user: :user_extension).each do |member| - user = member&.user + project.all_collaborators.includes(:user_extension).each do |user| if user real_name = user.try(:show_real_name) user_id = user.id diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index e151613d5..5937126d3 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -92,4 +92,10 @@ module ProjectOperable def has_menu_permission(unit_type) self.project_units.where(unit_type: unit_type).exists? end + + def all_collaborators + member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager Developer Reporter)}).to_sql + team_user_sql = User.joins(teams: :team_projects).where(team_projects: {project_id: self.id}).to_sql + return User.from("( #{ member_sql } UNION #{ team_user_sql } ) AS users").distinct + end end diff --git a/app/models/user.rb b/app/models/user.rb index e41e47d93..256cc7b41 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -152,6 +152,9 @@ class User < Owner # 项目 has_many :applied_projects, dependent: :destroy has_many :operate_applied_transfer_projects, class_name: 'AppliedTransferProject', dependent: :destroy + has_many :members, dependent: :destroy + has_many :team_users, dependent: :destroy + has_many :teams, through: :team_users # 教学案例 # has_many :libraries, dependent: :destroy diff --git a/app/views/pull_requests/_merge_item.json.jbuilder b/app/views/pull_requests/_merge_item.json.jbuilder index 8475c468d..0db17e265 100644 --- a/app/views/pull_requests/_merge_item.json.jbuilder +++ b/app/views/pull_requests/_merge_item.json.jbuilder @@ -5,10 +5,10 @@ json.issue_priories @project_priories json.project_author @project.owner.try(:show_real_name) json.project_name @project.try(:name) json.members do - json.array! @project_members.to_a.each do |member| - json.id member.user_id - json.login member.user.try(:login) - json.name member.user.try(:show_real_name) - json.avatar_url url_to_avatar(member.user) + json.array! @project_members.to_a.each do |user| + json.id user.id + json.login user.try(:login) + json.name user.try(:show_real_name) + json.avatar_url url_to_avatar(user) end end \ No newline at end of file From ea42b0d6edc01ed6daad025b1a4256a37c812ca3 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 28 Apr 2021 20:10:21 +0800 Subject: [PATCH 119/643] fix: pull_request can not select reporter and compare userinfo lose --- app/controllers/pull_requests_controller.rb | 2 +- app/models/concerns/project_operable.rb | 6 ++++++ app/views/compare/show.json.jbuilder | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 48735e787..d0221b768 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -215,7 +215,7 @@ class PullRequestsController < ApplicationController 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.all_collaborators + @project_members = @project.all_managers @project_priories = IssuePriority&.select(:id,:name, :position).as_json end diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index 5937126d3..5f8f929e7 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -98,4 +98,10 @@ module ProjectOperable team_user_sql = User.joins(teams: :team_projects).where(team_projects: {project_id: self.id}).to_sql return User.from("( #{ member_sql } UNION #{ team_user_sql } ) AS users").distinct end + + def all_managers + member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager)}).to_sql + team_user_sql = User.joins(teams: :team_projects).where(teams: {authorize: %w(owner admin)},team_projects: {project_id: self.id}).to_sql + return User.from("( #{ member_sql} UNION #{ team_user_sql } ) AS users").distinct + end end diff --git a/app/views/compare/show.json.jbuilder b/app/views/compare/show.json.jbuilder index 8257cc7fa..8b75fa3dd 100644 --- a/app/views/compare/show.json.jbuilder +++ b/app/views/compare/show.json.jbuilder @@ -4,7 +4,7 @@ json.commits do json.array! @compare_result['Commits'] do |commit| json.author do # TODO: 获取头像地址待优化 - forge_user = User.includes(:user_extension).select(:id, :login).find_by(login: commit['Author']['Name']) + forge_user = User.includes(:user_extension).find_by(login: commit['Author']['Name']) json.login commit['Author']['Name'] json.name commit['Author']['Name'] json.image_url forge_user.nil? ? '' : url_to_avatar(forge_user) @@ -12,7 +12,7 @@ json.commits do json.committer do # TODO: 获取头像地址待优化 - forge_user = User.includes(:user_extension).select(:id, :login).find_by(login: commit['Committer']['Name']) + forge_user = User.includes(:user_extension).find_by(login: commit['Committer']['Name']) json.login commit['Committer']['Name'] json.name commit['Committer']['Name'] json.image_url forge_user.nil? ? '' : url_to_avatar(forge_user) From c14c92ac11f1b0e188fbcd5b025d157ae1e7c4d5 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 29 Apr 2021 10:23:16 +0800 Subject: [PATCH 120/643] fix: pull_request permit develop create pr --- app/controllers/pull_requests_controller.rb | 4 ++-- app/models/concerns/project_operable.rb | 6 ++++++ app/models/project_unit.rb | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index d0221b768..3d18e5032 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -140,7 +140,7 @@ class PullRequestsController < ApplicationController end def pr_merge - return render_forbidden("你没有权限操作.") unless current_user.project_manager?(@project) + return render_forbidden("你没有权限操作.") unless @project.develper?(current_user) if params[:do].blank? normal_status(-1, "请选择合并方式") @@ -215,7 +215,7 @@ class PullRequestsController < ApplicationController 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.all_managers + @project_members = @project.all_developers @project_priories = IssuePriority&.select(:id,:name, :position).as_json end diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index 5f8f929e7..a4646f9ee 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -99,6 +99,12 @@ module ProjectOperable return User.from("( #{ member_sql } UNION #{ team_user_sql } ) AS users").distinct end + def all_developers + member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager Developer)}).to_sql + team_user_sql = User.joins(teams: :team_projects).where(teams: {authorize: %w(owner admin write)}, team_projects: {project_id: self.id}).to_sql + return User.from("( #{ member_sql } UNION #{ team_user_sql } ) AS users").distinct + end + def all_managers member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager)}).to_sql team_user_sql = User.joins(teams: :team_projects).where(teams: {authorize: %w(owner admin)},team_projects: {project_id: self.id}).to_sql diff --git a/app/models/project_unit.rb b/app/models/project_unit.rb index 0f4275345..1cb74fc4a 100644 --- a/app/models/project_unit.rb +++ b/app/models/project_unit.rb @@ -27,6 +27,8 @@ class ProjectUnit < ApplicationRecord end def self.update_by_unit_types!(project, types) + # 默认code类型自动创建 + types << "code" project.project_units.where.not(unit_type: types).each(&:destroy!) types.each do |type| project.project_units.find_or_create_by!(unit_type: type) From b673747475c1750372ab426e76218af00d7409b9 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 29 Apr 2021 16:26:39 +0800 Subject: [PATCH 121/643] fix: personal projects --- app/queries/projects/list_my_query.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/queries/projects/list_my_query.rb b/app/queries/projects/list_my_query.rb index 8ad0d0b0a..5bda56120 100644 --- a/app/queries/projects/list_my_query.rb +++ b/app/queries/projects/list_my_query.rb @@ -18,7 +18,9 @@ class Projects::ListMyQuery < ApplicationQuery end if params[:category].blank? - projects = projects.members_projects(user.id) + normal_projects = projects.members_projects(user.id).to_sql + org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: user.id}).to_sql + projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct elsif params[:category].to_s == "join" normal_projects = projects.where.not(user_id: user.id).members_projects(user.id).to_sql org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: user.id}).to_sql From fffe57a211d0d853dd72b3eb527ca67ce785456c Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 29 Apr 2021 17:36:36 +0800 Subject: [PATCH 122/643] fix: mirror project permission error --- app/controllers/users_controller.rb | 1 + app/models/concerns/project_operable.rb | 8 ++++++++ app/models/organization.rb | 7 +++++++ app/services/projects/migrate_service.rb | 2 ++ app/services/projects/transfer_service.rb | 5 ++--- app/services/repositories/create_service.rb | 11 +---------- lib/tasks/sync_org_project_permission.rake | 8 ++++++++ 7 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 lib/tasks/sync_org_project_permission.rake diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 395a5a6d9..6d95e350a 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -41,6 +41,7 @@ class UsersController < ApplicationController @user_composes_count = 0 user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common") @user_org_count = user_organizations.size + normal_projects = @user.projects 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 diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index a4646f9ee..739ddf27c 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -11,6 +11,14 @@ module ProjectOperable has_many :team_projects, dependent: :destroy end + def set_owner_permission(creator) + return unless owner.is_a?(Organization) + owner.build_permit_team_projects!(id) + # 避免自己创建的项目,却无法拥有访问权,因为该用户所在团队暂未获得项目访问权 + return if creator.nil? || owner.is_owner?(creator.id) + add_member!(creator.id, "Manager") + end + def add_member!(user_id, role_name='Developer') member = members.create!(user_id: user_id) set_developer_role(member, role_name) diff --git a/app/models/organization.rb b/app/models/organization.rb index fbf3def79..1d7c24b8e 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -114,6 +114,13 @@ class Organization < Owner owner_team_users.pluck(:user_id).include?(user_id) && owner_team_users.size == 1 end + # 为包含组织所有项目的团队创建项目访问权限 + def build_permit_team_projects!(project_id) + teams.where(includes_all_project: true).each do |team| + TeamProject.build(id, team.id, project_id) + end + end + def real_name name = lastname + firstname name = name.blank? ? (nickname.blank? ? login : nickname) : name diff --git a/app/services/projects/migrate_service.rb b/app/services/projects/migrate_service.rb index d1e14088f..1eba03788 100644 --- a/app/services/projects/migrate_service.rb +++ b/app/services/projects/migrate_service.rb @@ -1,5 +1,6 @@ class Projects::MigrateService < ApplicationService attr_reader :user, :params + attr_accessor :project def initialize(user, params) @user = user @@ -11,6 +12,7 @@ class Projects::MigrateService < ApplicationService if @project.save! ProjectUnit.init_types(@project.id) Project.update_mirror_projects_count! + @project.set_owner_permission(user) Repositories::MigrateService.new(user, @project, repository_params).call else # diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 4582a2103..a2da34f09 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -33,9 +33,8 @@ class Projects::TransferService < ApplicationService def update_visit_teams if new_owner.is_a?(Organization) - new_owner.teams.where(includes_all_project: true).each do |team| - TeamProject.build(new_owner.id, team.id, project.id) - end + # 为包含组织所有项目的团队创建项目访问权限 + new_owner.build_permit_team_projects(project.id) else project.team_projects.each(&:destroy!) end diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb index 18e726440..c341429fe 100644 --- a/app/services/repositories/create_service.rb +++ b/app/services/repositories/create_service.rb @@ -15,6 +15,7 @@ class Repositories::CreateService < ApplicationService create_gitea_repository sync_project sync_repository + set_owner_permission(user) # if project.project_type == "common" # chain_params = { # type: "create", @@ -44,19 +45,9 @@ class Repositories::CreateService < ApplicationService @gitea_repository = Gitea::Repository::CreateService.new(user.gitea_token, gitea_repository_params).call elsif project.owner.is_a?(Organization) @gitea_repository = Gitea::Organization::Repository::CreateService.call(user.gitea_token, project.owner.login, gitea_repository_params) - project.owner.teams.each do |team| - next unless team.includes_all_project - TeamProject.build(project.user_id, team.id, project.id) - end - create_manager_member end end - def create_manager_member - return if project.owner.is_owner?(user.id) - project.add_member!(user.id, "Manager") - end - def sync_project if gitea_repository project.update_columns( diff --git a/lib/tasks/sync_org_project_permission.rake b/lib/tasks/sync_org_project_permission.rake new file mode 100644 index 000000000..5828d1c8a --- /dev/null +++ b/lib/tasks/sync_org_project_permission.rake @@ -0,0 +1,8 @@ +namespace :sync_org_project_permission do + desc "sync organization project team permissions" + task mirror: :environment do + Project.mirror.includes(:team_projects,:owner).where(team_projects: {id: nil}, users: {type: 'Organization'}).find_each do |project| + project.set_owner_permission(nil) + end + end +end \ No newline at end of file From 1a7b323120acd143bf79e301125ab56af7cc23e0 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 29 Apr 2021 17:43:36 +0800 Subject: [PATCH 123/643] fix: user info projects count --- app/controllers/users_controller.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6d95e350a..3c62b1145 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -41,8 +41,10 @@ class UsersController < ApplicationController @user_composes_count = 0 user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common") @user_org_count = user_organizations.size - normal_projects = @user.projects - user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? @user.projects : @user.projects.visible + normal_projects = Project.members_projects(@user.id).to_sql + org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql + projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct + user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : 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 From 1277e717ffd56453c76eb9a18c15457a7824a077 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 29 Apr 2021 18:35:57 +0800 Subject: [PATCH 124/643] =?UTF-8?q?ADD=20github=20gitlab=E9=95=9C=E5=83=8F?= =?UTF-8?q?=E5=8A=A0=E9=80=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/concerns/.keep | 0 app/controllers/concerns/acceleratorable.rb | 28 ++++ app/controllers/projects_controller.rb | 20 ++- app/helpers/projects_helper.rb | 5 +- app/models/project.rb | 145 ++++++++--------- app/models/repository.rb | 2 + .../gitea/accelerator/migrate_service.rb | 146 ++++++++++++++++++ app/services/projects/migrate_service.rb | 3 +- app/services/repositories/migrate_service.rb | 4 +- app/views/repositories/detail.json.jbuilder | 2 +- config/configuration.yml.example | 12 +- ...016_add_accelerator_url_to_repositories.rb | 5 + ...19_add_source_clone_url_to_repositories.rb | 5 + 13 files changed, 295 insertions(+), 82 deletions(-) delete mode 100644 app/controllers/concerns/.keep create mode 100644 app/controllers/concerns/acceleratorable.rb create mode 100644 app/services/gitea/accelerator/migrate_service.rb create mode 100644 db/migrate/20210429095016_add_accelerator_url_to_repositories.rb create mode 100644 db/migrate/20210429100619_add_source_clone_url_to_repositories.rb diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/controllers/concerns/acceleratorable.rb b/app/controllers/concerns/acceleratorable.rb new file mode 100644 index 000000000..9a11e46c2 --- /dev/null +++ b/app/controllers/concerns/acceleratorable.rb @@ -0,0 +1,28 @@ +module Acceleratorable + extend ActiveSupport::Concern + + def enable_accelerator?(clone_addr) + clone_addr.include?(github_domain) || clone_addr.include?(gitlab_domain) + end + + def accelerator_url(repo_name) + [accelerator_domain, accelerator_username, "#{repo_name}.git"].join('/') + end + + def github_domain + 'github.com' + end + + def gitlab_domain + 'gitlab.com' + end + + def accelerator_domain + Gitea.gitea_config[:accelerator]["domain"] + end + + def accelerator_username + Gitea.gitea_config[:accelerator]["access_key_id"] + end + +end \ No newline at end of file diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index ca66b4361..e6abf98a4 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -2,6 +2,8 @@ class ProjectsController < ApplicationController include ApplicationHelper include OperateProjectAbilityAble include ProjectsHelper + include Acceleratorable + before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about menu_list] before_action :load_project, except: %i[index group_type_list migrate create recommend] before_action :authorizate_user_can_edit_project!, only: %i[update] @@ -53,7 +55,23 @@ class ProjectsController < ApplicationController def migrate Projects::MigrateForm.new(mirror_params).validate! - @project = Projects::MigrateService.new(current_user, mirror_params).call + + @project = + if enable_accelerator?(mirror_params[:clone_addr]) + source_clone_url = mirror_params[:clone_addr] + uid_logger("########## 已动加速器 ##########") + result = Gitea::Accelerator::MigrateService.call(mirror_params) + if result[:status] == :success + Rails.logger.info "########## 加速镜像成功 ########## " + Projects::MigrateService.call(current_user, + mirror_params.merge(source_clone_url: source_clone_url, + clone_addr: accelerator_url(mirror_params[:repository_name]))) + else + Projects::MigrateService.call(current_user, mirror_params) + end + else + Projects::MigrateService.call(current_user, mirror_params) + end rescue Exception => e uid_logger_error(e.message) tip_exception(e.message) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index aec4b38d7..c220701a1 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -34,15 +34,14 @@ module ProjectsHelper end def json_response(project, user) - # repo = project.repository - repo = Repository.includes(:mirror).select(:id, :mirror_url).find_by(project: project) + repo = Repository.includes(:mirror).select(:id, :mirror_url, :source_clone_url).find_by(project: project) tmp_json = {} unless project.common? tmp_json = tmp_json.merge({ mirror_status: repo.mirror_status, mirror_num: repo.mirror_num, - mirror_url: repo.mirror_url, + mirror_url: repo.source_clone_url || repo.mirror_url, first_sync: repo.first_sync? }) end diff --git a/app/models/project.rb b/app/models/project.rb index 170bae06a..b48680830 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,75 +1,76 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(4294967295) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# license_id :integer -# ignore_id :integer -# default_branch :string(255) default("master") -# website :string(255) -# lesson_url :string(255) -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(4294967295) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# license_id :integer +# ignore_id :integer +# default_branch :string(255) default("master") +# website :string(255) +# lesson_url :string(255) +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + class Project < ApplicationRecord include Matchable diff --git a/app/models/repository.rb b/app/models/repository.rb index 978bc3c57..f4556cea1 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -22,6 +22,8 @@ # version_releases_count :integer default("0") # fork_url :string(255) # is_mirror :boolean default("0") +# accelerator_url :string(255) default("") +# source_clone_url :string(255) default("") # # Indexes # diff --git a/app/services/gitea/accelerator/migrate_service.rb b/app/services/gitea/accelerator/migrate_service.rb new file mode 100644 index 000000000..afe35f139 --- /dev/null +++ b/app/services/gitea/accelerator/migrate_service.rb @@ -0,0 +1,146 @@ +class Gitea::Accelerator::MigrateService < ApplicationService + attr_reader :params + + # params description: + # { + # auth_username string + # clone_addr* string #clone地址 + # description string + # issues boolean + # labels boolean + # milestones boolean + # mirror boolean + # private boolean + # pull_requests boolean + # releases boolean + # repo_name* string #仓库名称 + # uid* integer($int64) #gitea用户id或组织id + # wiki boolean + # } + # EX: + # params = { + # clone_addr: 'xxx.com', + # repo_name: 'repo_name', + # uid: 2, + # private: false + # } + + def initialize(params) + @params = params + end + + def call + return error('[gitea:] accelerator config missing') if check_accelerator! + response = post(url, request_params) + + render_status(response) + end + + private + + def request_params + { + uid: access_uid, + clone_addr: params[:clone_addr], + repo_name: params[:repository_name], + auth_username: params[:auth_username], + auth_password: params[:auth_password], + mirror: ActiveModel::Type::Boolean.new.cast(params[:is_mirror]) + } + end + + def url + "/repos/migrate".freeze + end + + def post(url, params) + puts "[gitea] request params: #{params}" + puts "[gitea] access_username: #{access_username}" + puts "[gitea] access_password: #{access_password}" + conn.post do |req| + req.url full_url(url) + req.body = params.to_json + end + end + + def conn + @client ||= begin + Faraday.new(url: domain) do |req| + req.request :url_encoded + req.headers['Content-Type'] = 'application/json' + req.response :logger # 显示日志 + req.adapter Faraday.default_adapter + req.basic_auth(access_username, access_password) + end + end + @client + end + + def base_url + accelerator["base_url"] + end + + def domain + accelerator["domain"] + end + + def api_url + [domain, base_url].join('') + end + + def full_url(api_rest, action='post') + url = [api_url, api_rest].join('').freeze + url = action === 'get' ? url : URI.escape(url) + puts "[gitea] request url: #{url}" + url + end + + def access_username + accelerator["access_key_id"] + end + + def access_password + accelerator["access_key_secret"] + end + + def access_uid + accelerator["access_admin_uid"] + end + + def accelerator + Gitea.gitea_config[:accelerator] + end + + def render_status(response) + puts "[gitea] response status: #{response.status}" + puts "[gitea] response body: #{response.body}" + case response.status + when 201 + success + when 403 + error('APIForbiddenError') + when 422 + error('APIValidationError') + end + end + + def error(message) + { + status: :error, + message: message, + data: nil + } + end + + def success(data=nil) + { + status: :success, + message: nil, + data: data + } + end + + def check_accelerator! + accelerator.blank? || access_username.blank? || access_password.blank? || domain.blank? + end +end \ No newline at end of file diff --git a/app/services/projects/migrate_service.rb b/app/services/projects/migrate_service.rb index d1e14088f..c5c2cf753 100644 --- a/app/services/projects/migrate_service.rb +++ b/app/services/projects/migrate_service.rb @@ -48,7 +48,8 @@ class Projects::MigrateService < ApplicationService user_id: params[:user_id], login: params[:auth_username], password: params[:auth_password], - is_mirror: params[:is_mirror] + is_mirror: params[:is_mirror], + source_clone_url: params[:source_clone_url] } end diff --git a/app/services/repositories/migrate_service.rb b/app/services/repositories/migrate_service.rb index 156777cc3..b737b2ef5 100644 --- a/app/services/repositories/migrate_service.rb +++ b/app/services/repositories/migrate_service.rb @@ -21,7 +21,9 @@ class Repositories::MigrateService < ApplicationService private def repository_params - params.merge(project_id: project.id, identifier: params[:identifier]) + params.merge(project_id: project.id, + identifier: params[:identifier], + source_clone_url: params[:source_clone_url]) end def gitea_repository_params diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index fc1dc830b..644a472ab 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -21,7 +21,7 @@ json.versions_count @project.versions_count #里程碑数量 json.version_releases_count @project.releases_size(@user.try(:id), "all") json.version_releasesed_count @project.releases_size(@user.try(:id), "released") #已发行的版本 json.permission render_permission(@user, @project) -json.mirror_url @project&.repository.mirror_url +json.mirror_url @project&.repository.source_clone_url json.mirror @project&.repository.mirror_url.present? json.type @project.numerical_for_project_type json.open_devops @project.open_devops? diff --git a/config/configuration.yml.example b/config/configuration.yml.example index 823d8547e..b45c9532c 100644 --- a/config/configuration.yml.example +++ b/config/configuration.yml.example @@ -45,10 +45,16 @@ default: &default signature_key: 'test12345678' gitea: - access_key_id: 'root' - access_key_secret: '_Trustie_10010' - domain: 'https://testgitea.trustie.net' + access_key_id: '' + access_key_secret: '' + domain: 'https://testgit.trustie.net' base_url: '/api/v1' + accelerator: + access_key_id: '' + access_key_secret: '' + access_admin_uid: 1 + domain: 'https://testgit.trustie.net' + base_url: '/api/v1' production: diff --git a/db/migrate/20210429095016_add_accelerator_url_to_repositories.rb b/db/migrate/20210429095016_add_accelerator_url_to_repositories.rb new file mode 100644 index 000000000..0c33ef7b5 --- /dev/null +++ b/db/migrate/20210429095016_add_accelerator_url_to_repositories.rb @@ -0,0 +1,5 @@ +class AddAcceleratorUrlToRepositories < ActiveRecord::Migration[5.2] + def change + add_column :repositories, :accelerator_url, :string, default: "" + end +end diff --git a/db/migrate/20210429100619_add_source_clone_url_to_repositories.rb b/db/migrate/20210429100619_add_source_clone_url_to_repositories.rb new file mode 100644 index 000000000..a7f213037 --- /dev/null +++ b/db/migrate/20210429100619_add_source_clone_url_to_repositories.rb @@ -0,0 +1,5 @@ +class AddSourceCloneUrlToRepositories < ActiveRecord::Migration[5.2] + def change + add_column :repositories, :source_clone_url, :string, default: "" + end +end From 0133ec24cabdfedba9c07c6d31352aa67bec330d Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 29 Apr 2021 18:48:54 +0800 Subject: [PATCH 125/643] FIX pr merge bug --- app/controllers/pull_requests_controller.rb | 2 +- app/models/concerns/project_operable.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 3d18e5032..518ad91d9 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -140,7 +140,7 @@ class PullRequestsController < ApplicationController end def pr_merge - return render_forbidden("你没有权限操作.") unless @project.develper?(current_user) + return render_forbidden("你没有权限操作.") unless @project.operator?(current_user) if params[:do].blank? normal_status(-1, "请选择合并方式") diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index a4646f9ee..c877b7858 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -84,6 +84,10 @@ module ProjectOperable end end + def operator?(user) + user.admin? || !reporter?(user) + end + def set_developer_role(member, role_name) role = Role.find_by(name: role_name) member.member_roles.create!(role: role) From e87413f8a0909e9dd58233234ead802631ba7343 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 29 Apr 2021 19:12:48 +0800 Subject: [PATCH 126/643] FIX migrate repo api bug --- app/services/gitea/accelerator/migrate_service.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/services/gitea/accelerator/migrate_service.rb b/app/services/gitea/accelerator/migrate_service.rb index afe35f139..015a09b16 100644 --- a/app/services/gitea/accelerator/migrate_service.rb +++ b/app/services/gitea/accelerator/migrate_service.rb @@ -121,6 +121,8 @@ class Gitea::Accelerator::MigrateService < ApplicationService error('APIForbiddenError') when 422 error('APIValidationError') + else + error("MigrateError") end end From c56f0ca7fc6d59a65aeadac0ae24e9a5defcf00b Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 29 Apr 2021 23:17:55 +0800 Subject: [PATCH 127/643] =?UTF-8?q?FIX=20=E8=A7=A3=E5=86=B3=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E8=AF=B7=E6=B1=82=E7=9A=84=E6=9D=83=E9=99=90=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/organization.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/organization.rb b/app/models/organization.rb index fbf3def79..b4ebc59a2 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -108,6 +108,10 @@ class Organization < Owner team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read write admin owner)}).present? end + def is_only_read?(user_id) + team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read)}).present? + end + # 是不是所有者团队的最后一个成员 def is_owner_team_last_one?(user_id) owner_team_users = team_users.joins(:team).where(teams: {authorize: %w(owner)}) From b2e338732d9215a82c6c14ce28771880751cb992 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 29 Apr 2021 23:23:16 +0800 Subject: [PATCH 128/643] =?UTF-8?q?FIX=20=E8=A7=A3=E5=86=B3=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E8=AF=B7=E6=B1=82=E7=9A=84=E6=9D=83=E9=99=90=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/concerns/project_operable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index c877b7858..54bc94a6b 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -78,7 +78,7 @@ module ProjectOperable if owner.is_a?(User) reporters.exists?(user_id: user.id) elsif owner.is_a?(Organization) - reporters.exists?(user_id: user.id) || owner.is_read?(user.id) + reporters.exists?(user_id: user.id) || owner.is_only_read?(user.id) else false end From a9c0d18a5ff8bf4ff0dff899ff28bd65b996df50 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 30 Apr 2021 15:36:14 +0800 Subject: [PATCH 129/643] add: gitea response process --- app/controllers/pull_requests_controller.rb | 4 ++-- app/services/gitea/client_service.rb | 19 +++++++++++++++++++ .../gitea/pull_request/merge_service.rb | 2 +- app/services/pull_requests/merge_service.rb | 6 +++--- config/gitea_response.yml | 7 +++++++ 5 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 config/gitea_response.yml diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 518ad91d9..0dbcdc942 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -149,12 +149,12 @@ class PullRequestsController < ApplicationController begin result = PullRequests::MergeService.call(@owner, @repository, @pull_request, current_user, params) - if result && @pull_request.merge! + if result.status == 200 && @pull_request.merge! @pull_request.project_trend_status! @issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id) normal_status(1, "合并成功") else - normal_status(-1, "合并失败") + normal_status(-1, result.message) end rescue => e normal_status(-1, e.message) diff --git a/app/services/gitea/client_service.rb b/app/services/gitea/client_service.rb index 1c13bc424..0ef041997 100644 --- a/app/services/gitea/client_service.rb +++ b/app/services/gitea/client_service.rb @@ -176,6 +176,25 @@ class Gitea::ClientService < ApplicationService [status, message, body] end + def render_gitea_response(response) + status = response.status + body = response&.body + + log_error(status, body) + message = nil + begin + translate = YAML.load(File.read('config/gitea_response.yml')) + + self.class.to_s.underscore.split("/").map{|i| translate=translate[i]} + message = body.nil? ? translate[status]['default'] : JSON.parse(body)['message'] + message = translate[status][message].nil? ? message : translate[status][message] + + return [status, message] + rescue + return [status, message] + end + end + def get_body_by_status(status, body) body, message = case status diff --git a/app/services/gitea/pull_request/merge_service.rb b/app/services/gitea/pull_request/merge_service.rb index c33c8781d..bdf2b23be 100644 --- a/app/services/gitea/pull_request/merge_service.rb +++ b/app/services/gitea/pull_request/merge_service.rb @@ -20,7 +20,7 @@ class Gitea::PullRequest::MergeService < Gitea::ClientService def call response = post(url, request_params) - render_200_no_body(response) + render_gitea_response(response) end private diff --git a/app/services/pull_requests/merge_service.rb b/app/services/pull_requests/merge_service.rb index a20ee3aa9..d5fc102ec 100644 --- a/app/services/pull_requests/merge_service.rb +++ b/app/services/pull_requests/merge_service.rb @@ -1,6 +1,6 @@ class PullRequests::MergeService < ApplicationService attr_reader :owner, :repo, :pull, :current_user, :params - + attr_accessor :status, :message # eq: # PullRequests::MergeService.call(owner, repo, pull, current_user, params) def initialize(owner, repo, pull, current_user, params) @@ -15,6 +15,7 @@ class PullRequests::MergeService < ApplicationService ActiveRecord::Base.transaction do gitea_pull_merge! end + self end private @@ -22,8 +23,7 @@ class PullRequests::MergeService < ApplicationService def gitea_pull_merge! result = Gitea::PullRequest::MergeService.call(@current_user.gitea_token, @owner.login, @repo.identifier, @pull.gpid, gitea_merge_pull_params) - - result[:status] === 200 ? true : false + @status, @message = result end def gitea_merge_pull_params diff --git a/config/gitea_response.yml b/config/gitea_response.yml new file mode 100644 index 000000000..1ff636ac0 --- /dev/null +++ b/config/gitea_response.yml @@ -0,0 +1,7 @@ +gitea: + pull_request: + merge_service: + 405: + default: "此合并请求有变更与目标分支冲突。" + 'User not allowed to merge PR': "用户没有合并请求的权限" + 403: From 3ca629d47d1adf9de2976df05c5e251a032b6964 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 30 Apr 2021 16:45:09 +0800 Subject: [PATCH 130/643] fix:create repo error --- app/services/repositories/create_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb index c341429fe..f0c584e18 100644 --- a/app/services/repositories/create_service.rb +++ b/app/services/repositories/create_service.rb @@ -15,7 +15,7 @@ class Repositories::CreateService < ApplicationService create_gitea_repository sync_project sync_repository - set_owner_permission(user) + @project.set_owner_permission(user) # if project.project_type == "common" # chain_params = { # type: "create", From 1c111e83b3157f466c350230049b759987a43694 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 6 May 2021 14:48:44 +0800 Subject: [PATCH 131/643] fix: project controbutor nil --- app/views/repositories/detail.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 644a472ab..75b474ee0 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -80,7 +80,7 @@ json.contributors do total_count = @result[:contributor].size json.list @result[:contributor].each do |contributor| user = User.find_by(gitea_uid: contributor["id"]) - if contributor["login"] == "root" + if contributor["login"] == "root" || user.nil? total_count -= 1 next end From 604c2595d35f125501a55495acf1ea52cfb8dadc Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 6 May 2021 15:10:02 +0800 Subject: [PATCH 132/643] add: projects create validate length --- app/forms/projects/create_form.rb | 6 +++++- config/locales/forms/projects_create_form.zh-CN.yml | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 config/locales/forms/projects_create_form.zh-CN.yml diff --git a/app/forms/projects/create_form.rb b/app/forms/projects/create_form.rb index 2838996b6..0b57f215b 100644 --- a/app/forms/projects/create_form.rb +++ b/app/forms/projects/create_form.rb @@ -2,11 +2,15 @@ class Projects::CreateForm < BaseForm REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, :project_language_id, :ignore_id, :license_id, :private, :owner - + validates :user_id, :name, :description,:repository_name, :project_category_id, :project_language_id, presence: true validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + validates :name, length: { maximum: 50 } + validates :repository_name, length: { maximum: 100 } + validates :description, length: { maximum: 200 } + validate :check_ignore, :check_license, :check_owner, :check_max_repo_creation validate do check_project_category(project_category_id) diff --git a/config/locales/forms/projects_create_form.zh-CN.yml b/config/locales/forms/projects_create_form.zh-CN.yml new file mode 100644 index 000000000..e36a0520a --- /dev/null +++ b/config/locales/forms/projects_create_form.zh-CN.yml @@ -0,0 +1,7 @@ +'zh-CN': + activemodel: + attributes: + projects/create_form: + name: 项目名称 + repository_name: 仓库名称 + description: 项目简介 \ No newline at end of file From d867823f01dc715b4985c9e17c53b53da6d823db Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 6 May 2021 17:04:08 +0800 Subject: [PATCH 133/643] add: organization validate --- .../organizations/organizations_controller.rb | 1 + app/forms/organizations/create_form.rb | 3 +++ config/locales/forms/organizations_create_form.zh-CN.yml | 9 +++++++++ 3 files changed, 13 insertions(+) create mode 100644 config/locales/forms/organizations_create_form.zh-CN.yml diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index 09c12fd5a..c8f4f4aa0 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -36,6 +36,7 @@ class Organizations::OrganizationsController < Organizations::BaseController def update ActiveRecord::Base.transaction do + Organizations::CreateForm.new(organization_params).validate! login = @organization.login @organization.login = organization_params[:name] if organization_params[:name].present? @organization.nickname = organization_params[:nickname] if organization_params[:nickname].present? diff --git a/app/forms/organizations/create_form.rb b/app/forms/organizations/create_form.rb index 00c1dd15e..d92a99040 100644 --- a/app/forms/organizations/create_form.rb +++ b/app/forms/organizations/create_form.rb @@ -3,6 +3,9 @@ class Organizations::CreateForm < BaseForm attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname validates :name, :nickname, :visibility, presence: true + validates :name, :nickname, length: { maximum: 100 } + validates :location, length: { maximum: 50 } + validates :description, length: { maximum: 200 } validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } end diff --git a/config/locales/forms/organizations_create_form.zh-CN.yml b/config/locales/forms/organizations_create_form.zh-CN.yml new file mode 100644 index 000000000..ab43b0941 --- /dev/null +++ b/config/locales/forms/organizations_create_form.zh-CN.yml @@ -0,0 +1,9 @@ +'zh-CN': + activemodel: + attributes: + organizations/create_form: + name: 组织账号 + nickname: 组织名称 + location: 组织所在地区 + description: 组织简介 + visibility: 组织可见性 \ No newline at end of file From 411c10e8f3c42db704ba616c4674ee61a7a1d4fb Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 6 May 2021 17:37:30 +0800 Subject: [PATCH 134/643] add: project update valid and user login valid --- app/controllers/accounts_controller.rb | 4 ++++ app/controllers/projects_controller.rb | 2 +- app/forms/projects/update_form.rb | 9 ++++++++- app/forms/users/login_form.rb | 8 ++++++++ config/locales/forms/projects_update_form.zh-CN.yml | 8 ++++++++ config/locales/forms/users_login_form.zh-CN.yml | 6 ++++++ 6 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 app/forms/users/login_form.rb create mode 100644 config/locales/forms/projects_update_form.zh-CN.yml create mode 100644 config/locales/forms/users_login_form.zh-CN.yml diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 8e82a814a..09dfdbdb7 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -169,6 +169,7 @@ class AccountsController < ApplicationController # 用户登录 def login + Users::LoginForm.new(account_params).validate! @user = User.try_to_login(params[:login], params[:password]) return normal_status(-2, "错误的账号或密码") if @user.blank? @@ -345,4 +346,7 @@ class AccountsController < ApplicationController params.require(:user).permit(:login, :email, :phone) end + def account_params + params.require(:account).permit(:login, :password) + end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e6abf98a4..2cc8380a9 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -106,7 +106,7 @@ class ProjectsController < ApplicationController def update ActiveRecord::Base.transaction do - # Projects::CreateForm.new(project_params).validate! + Projects::UpdateForm.new(project_params).validate! private = params[:private] || false new_project_params = project_params.except(:private).merge(is_public: !private) diff --git a/app/forms/projects/update_form.rb b/app/forms/projects/update_form.rb index 4696beaa3..65810a820 100644 --- a/app/forms/projects/update_form.rb +++ b/app/forms/projects/update_form.rb @@ -1,4 +1,11 @@ class Projects::UpdateForm < BaseForm - attr_reader :name, :description, :repository_name, :project_category_id + attr_accessor :name, :description, :project_category_id, :project_language_id, :private + validates :name, :description, :project_category_id, :project_language_id, presence: true + validates :name, length: { maximum: 50 } + validates :description, length: { maximum: 200 } + validate do + check_project_category(project_category_id) + check_project_language(project_language_id) + end end diff --git a/app/forms/users/login_form.rb b/app/forms/users/login_form.rb new file mode 100644 index 000000000..2634a36cc --- /dev/null +++ b/app/forms/users/login_form.rb @@ -0,0 +1,8 @@ +class Users::LoginForm + include ActiveModel::Model + + attr_accessor :password, :login + + validates :login, presence: true + validates :password, presence: true, length: { minimum: 8, maximum: 16 }, format: { with: CustomRegexp::PASSWORD, message: "8~16位,支持字母数字和符号" } +end \ No newline at end of file diff --git a/config/locales/forms/projects_update_form.zh-CN.yml b/config/locales/forms/projects_update_form.zh-CN.yml new file mode 100644 index 000000000..74804f6af --- /dev/null +++ b/config/locales/forms/projects_update_form.zh-CN.yml @@ -0,0 +1,8 @@ +'zh-CN': + activemodel: + attributes: + projects/update_form: + name: 项目名称 + description: 项目简介 + project_category_id: 项目类别 + project_language_id: 项目语言 \ No newline at end of file diff --git a/config/locales/forms/users_login_form.zh-CN.yml b/config/locales/forms/users_login_form.zh-CN.yml new file mode 100644 index 000000000..8b94db42b --- /dev/null +++ b/config/locales/forms/users_login_form.zh-CN.yml @@ -0,0 +1,6 @@ +'zh-CN': + activemodel: + attributes: + users/login_form: + login: 用户名 + password: 密码 \ No newline at end of file From fc5876fc32b5136e3bad04c7a6dfb05b6ac4fba4 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 6 May 2021 18:22:30 +0800 Subject: [PATCH 135/643] add: team valid --- app/controllers/organizations/teams_controller.rb | 1 + app/forms/organizations/create_team_form.rb | 4 +++- app/models/team.rb | 3 ++- app/services/organizations/teams/create_service.rb | 6 +++++- .../locales/forms/organizations_create_team_form.zh-CN.yml | 7 +++++++ 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 config/locales/forms/organizations_create_team_form.zh-CN.yml diff --git a/app/controllers/organizations/teams_controller.rb b/app/controllers/organizations/teams_controller.rb index a8d06ce46..c599ac420 100644 --- a/app/controllers/organizations/teams_controller.rb +++ b/app/controllers/organizations/teams_controller.rb @@ -43,6 +43,7 @@ class Organizations::TeamsController < Organizations::BaseController end def update + Organizations::CreateTeamForm.new(team_params).validate! @team = Organizations::Teams::UpdateService.call(current_user, @team, team_params) rescue Exception => e uid_logger_error(e.message) diff --git a/app/forms/organizations/create_team_form.rb b/app/forms/organizations/create_team_form.rb index 898d69a1d..6d816b0ed 100644 --- a/app/forms/organizations/create_team_form.rb +++ b/app/forms/organizations/create_team_form.rb @@ -2,7 +2,9 @@ class Organizations::CreateTeamForm < BaseForm NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 attr_accessor :name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types - validates :name, :nickname, :authorize, presence: true + validates :name, :nickname, presence: true + validates :name, :nickname, length: { maximum: 100 } + validates :description, length: { maximum: 200 } validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } end diff --git a/app/models/team.rb b/app/models/team.rb index d17827da8..c25963905 100644 --- a/app/models/team.rb +++ b/app/models/team.rb @@ -33,9 +33,10 @@ class Team < ApplicationRecord enum authorize: {common: 0, read: 1, write: 2, admin: 3, owner: 4} - def self.build(organization_id, name, description, authorize, includes_all_project, can_create_org_project) + def self.build(organization_id, name, nickname, description, authorize, includes_all_project, can_create_org_project) self.create!(organization_id: organization_id, name: name, + nickname: nickname, description: description, authorize: authorize, includes_all_project: includes_all_project, diff --git a/app/services/organizations/teams/create_service.rb b/app/services/organizations/teams/create_service.rb index 81ad78772..c3fc5f599 100644 --- a/app/services/organizations/teams/create_service.rb +++ b/app/services/organizations/teams/create_service.rb @@ -28,6 +28,10 @@ class Organizations::Teams::CreateService < ApplicationService params[:name] end + def nickname + params[:nickname] + end + def description params[:description] end @@ -45,7 +49,7 @@ class Organizations::Teams::CreateService < ApplicationService end def create_team - @team = Team.build(org.id, name, description, authorize, + @team = Team.build(org.id, name, nickname, description, authorize, includes_all_project, can_create_org_project) end diff --git a/config/locales/forms/organizations_create_team_form.zh-CN.yml b/config/locales/forms/organizations_create_team_form.zh-CN.yml new file mode 100644 index 000000000..ebf40dde0 --- /dev/null +++ b/config/locales/forms/organizations_create_team_form.zh-CN.yml @@ -0,0 +1,7 @@ +'zh-CN': + activemodel: + attributes: + organizations/create_team_form: + name: 团队标识 + nickname: 团队名称 + description: 团队描述 \ No newline at end of file From 1021731d2bb745bff01a17905e49868feed0d42b Mon Sep 17 00:00:00 2001 From: guotao Date: Fri, 7 May 2021 10:45:31 +0800 Subject: [PATCH 136/643] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BC=96=E5=8F=B7?= =?UTF-8?q?=EF=BC=9A45283=20=E6=98=93=E4=BF=AE=E6=A0=87=E9=A2=98=E8=BF=87?= =?UTF-8?q?=E9=95=BF=E5=AF=BC=E8=87=B4=E6=8E=92=E7=89=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/issues_controller.rb | 78 +++++++++---------- app/forms/issues/create_form.rb | 11 +++ app/forms/issues/update_form.rb | 10 +++ .../forms/create_issuse_form.zh-CN.yml | 7 ++ 4 files changed, 66 insertions(+), 40 deletions(-) create mode 100644 app/forms/issues/create_form.rb create mode 100644 app/forms/issues/update_form.rb create mode 100644 config/locales/forms/create_issuse_form.zh-CN.yml diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index a3b5fe923..b44a04072 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -101,51 +101,46 @@ class IssuesController < ApplicationController end def create - if params[:subject].blank? - normal_status(-1, "标题不能为空") - elsif params[:subject].to_s.size > 255 - normal_status(-1, "标题不能超过255个字符") - else - issue_params = issue_send_params(params) - - @issue = Issue.new(issue_params) - if @issue.save! - 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 = @issue - attachment.author_id = current_user.id - attachment.description = "" - attachment.save - end + issue_params = issue_send_params(params) + Issues::CreateForm.new(issue_params).validate! + @issue = Issue.new(issue_params) + if @issue.save! + 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 = @issue + attachment.author_id = current_user.id + attachment.description = "" + attachment.save end end - if params[:issue_tag_ids].present? - params[:issue_tag_ids].each do |tag| - IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag) - end + end + if params[:issue_tag_ids].present? + params[:issue_tag_ids].each do |tag| + IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag) end - if params[:assigned_to_id].present? - Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id, - container_id: @issue.id, container_type: 'Issue', - parent_container_id: @project.id, parent_container_type: "Project", - tiding_type: 'issue', status: 0) - 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") - render json: {status: 0, message: "创建成", id: @issue.id} - else - normal_status(-1, "创建失败") + end + if params[:assigned_to_id].present? + Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id, + container_id: @issue.id, container_type: 'Issue', + parent_container_id: @project.id, parent_container_type: "Project", + 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") + render json: {status: 0, message: "创建成", id: @issue.id} + else + normal_status(-1, "创建失败") + end + rescue Exception => exception + puts exception.message + normal_status(-1, exception.message) end def edit @@ -199,7 +194,7 @@ class IssuesController < ApplicationController normal_status(-1, "不允许修改为关闭状态") else issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id) - + Issues::UpdateForm.new(issue_params).validate! if @issue.update_attributes(issue_params) if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时 @issue.issue_times.update_all(end_time: Time.now) @@ -225,6 +220,9 @@ class IssuesController < ApplicationController normal_status(-1, "更新失败") end end + rescue Exception => exception + puts exception.message + normal_status(-1, exception.message) end def show diff --git a/app/forms/issues/create_form.rb b/app/forms/issues/create_form.rb new file mode 100644 index 000000000..a8e514c36 --- /dev/null +++ b/app/forms/issues/create_form.rb @@ -0,0 +1,11 @@ +class Issues::CreateForm + include ActiveModel::Model + + attr_accessor :subject,:description,:is_private,:assigned_to_id,:tracker_id,:status_id,:priority_id,:fixed_version_id,:start_date,:due_date,:estimated_hours,:done_ratio,:issue_type,:token,:issue_tags_value,:closed_on,:branch_name,:issue_classify,:author_id,:project_id + + validates :subject, presence: { message: "不能为空" } + + validates :subject, length: { maximum: 80, too_long: "不能超过80个字符" } + + +end diff --git a/app/forms/issues/update_form.rb b/app/forms/issues/update_form.rb new file mode 100644 index 000000000..1c83779c4 --- /dev/null +++ b/app/forms/issues/update_form.rb @@ -0,0 +1,10 @@ +class Issues::UpdateForm + include ActiveModel::Model + + attr_accessor :subject,:description,:is_private,:assigned_to_id,:tracker_id,:status_id,:priority_id,:fixed_version_id,:start_date,:due_date,:estimated_hours,:done_ratio,:issue_type,:token,:issue_tags_value,:closed_on,:branch_name,:issue_classify,:author_id,:project_id + + validates :subject, presence: { message: "不能为空" } + + validates :subject, length: { maximum: 80, too_long: "不能超过80个字符" } + +end \ No newline at end of file diff --git a/config/locales/forms/create_issuse_form.zh-CN.yml b/config/locales/forms/create_issuse_form.zh-CN.yml new file mode 100644 index 000000000..643c68667 --- /dev/null +++ b/config/locales/forms/create_issuse_form.zh-CN.yml @@ -0,0 +1,7 @@ +'zh-CN': + activemodel: + attributes: + issues/create_form: + subject: 标题 + issues/update_form: + subject: 标题 \ No newline at end of file From c67686bdf50f335addf1c222d72b03ae679178df Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 7 May 2021 11:10:03 +0800 Subject: [PATCH 137/643] FIX code review --- app/controllers/projects_controller.rb | 2 +- config/routes.rb | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e6abf98a4..ed63ab1d1 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -167,7 +167,7 @@ class ProjectsController < ApplicationController end def recommend - @projects = Project.recommend.includes(:repository, :project_category, :owner).limit(5) + @projects = Project.recommend.includes(:repository, :project_category, :owner).order(id: :desc).limit(5) end def about diff --git a/config/routes.rb b/config/routes.rb index fa76ba467..2901e0f56 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -392,7 +392,6 @@ Rails.application.routes.draw do get :files get :detail get :archive - get :top_counts get :entries match :sub_entries, :via => [:get, :put] get :commits From b162b3357a979fbd7ecc6f8a18afce32a7509ce8 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 7 May 2021 14:06:40 +0800 Subject: [PATCH 138/643] FIX get mirror url bug --- app/helpers/projects_helper.rb | 2 +- app/models/repository.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index c220701a1..226096c24 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -41,7 +41,7 @@ module ProjectsHelper tmp_json = tmp_json.merge({ mirror_status: repo.mirror_status, mirror_num: repo.mirror_num, - mirror_url: repo.source_clone_url || repo.mirror_url, + mirror_url: repo.remote_mirror_url, first_sync: repo.first_sync? }) end diff --git a/app/models/repository.rb b/app/models/repository.rb index f4556cea1..0daa4b916 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -78,4 +78,9 @@ class Repository < ApplicationRecord end end + def remote_mirror_url + source_clone_url.blank? ? mirror_url : source_clone_url + end + + end From c96dacbf88788b31f0b19499c791eb134f32c48a Mon Sep 17 00:00:00 2001 From: guotao Date: Fri, 7 May 2021 16:26:56 +0800 Subject: [PATCH 139/643] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BC=96=E5=8F=B7?= =?UTF-8?q?=EF=BC=9A45283=20=E6=98=93=E4=BF=AE=E6=A0=87=E9=A2=98=E8=BF=87?= =?UTF-8?q?=E9=95=BF=E5=AF=BC=E8=87=B4=E6=8E=92=E7=89=88=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20=E5=8E=BB=E6=8E=89=E5=A4=9A=E4=BD=99=E7=9A=84=E5=B1=9E?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/issues_controller.rb | 4 ++-- app/forms/issues/create_form.rb | 2 +- app/forms/issues/update_form.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index b44a04072..3584d6bf5 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -102,7 +102,7 @@ class IssuesController < ApplicationController def create issue_params = issue_send_params(params) - Issues::CreateForm.new(issue_params).validate! + Issues::CreateForm.new({subject:issue_params[:subject]}).validate! @issue = Issue.new(issue_params) if @issue.save! if params[:attachment_ids].present? @@ -194,7 +194,7 @@ class IssuesController < ApplicationController normal_status(-1, "不允许修改为关闭状态") else issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id) - Issues::UpdateForm.new(issue_params).validate! + Issues::UpdateForm.new({subject:issue_params[:subject]}).validate! if @issue.update_attributes(issue_params) if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时 @issue.issue_times.update_all(end_time: Time.now) diff --git a/app/forms/issues/create_form.rb b/app/forms/issues/create_form.rb index a8e514c36..7dde8ecda 100644 --- a/app/forms/issues/create_form.rb +++ b/app/forms/issues/create_form.rb @@ -1,7 +1,7 @@ class Issues::CreateForm include ActiveModel::Model - attr_accessor :subject,:description,:is_private,:assigned_to_id,:tracker_id,:status_id,:priority_id,:fixed_version_id,:start_date,:due_date,:estimated_hours,:done_ratio,:issue_type,:token,:issue_tags_value,:closed_on,:branch_name,:issue_classify,:author_id,:project_id + attr_accessor :subject validates :subject, presence: { message: "不能为空" } diff --git a/app/forms/issues/update_form.rb b/app/forms/issues/update_form.rb index 1c83779c4..7447c8cc0 100644 --- a/app/forms/issues/update_form.rb +++ b/app/forms/issues/update_form.rb @@ -1,7 +1,7 @@ class Issues::UpdateForm include ActiveModel::Model - attr_accessor :subject,:description,:is_private,:assigned_to_id,:tracker_id,:status_id,:priority_id,:fixed_version_id,:start_date,:due_date,:estimated_hours,:done_ratio,:issue_type,:token,:issue_tags_value,:closed_on,:branch_name,:issue_classify,:author_id,:project_id + attr_accessor :subject validates :subject, presence: { message: "不能为空" } From e490ddb1f51fc94e7f3d39c5361442fd6fc52154 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 7 May 2021 17:27:37 +0800 Subject: [PATCH 140/643] add: sync mirror project remove pulls module --- app/models/project_unit.rb | 7 +++++-- app/services/projects/migrate_service.rb | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/models/project_unit.rb b/app/models/project_unit.rb index 1cb74fc4a..a07f62b4e 100644 --- a/app/models/project_unit.rb +++ b/app/models/project_unit.rb @@ -20,13 +20,16 @@ class ProjectUnit < ApplicationRecord validates :unit_type, uniqueness: { scope: :project_id} - def self.init_types(project_id) - ProjectUnit::unit_types.each do |_, v| + def self.init_types(project_id, project_type='common') + unit_types = project_type == 'sync_mirror' ? ProjectUnit::unit_types.except("pulls") : ProjectUnit::unit_types + unit_types.each do |_, v| self.create!(project_id: project_id, unit_type: v) end end def self.update_by_unit_types!(project, types) + # 同步镜像项目不能有合并请求模块 + types.delete("pulls") if project.sync_mirror? # 默认code类型自动创建 types << "code" project.project_units.where.not(unit_type: types).each(&:destroy!) diff --git a/app/services/projects/migrate_service.rb b/app/services/projects/migrate_service.rb index 85648eda9..7df08f9eb 100644 --- a/app/services/projects/migrate_service.rb +++ b/app/services/projects/migrate_service.rb @@ -10,7 +10,7 @@ class Projects::MigrateService < ApplicationService def call @project = Project.new(project_params) if @project.save! - ProjectUnit.init_types(@project.id) + ProjectUnit.init_types(@project.id, project.project_type) Project.update_mirror_projects_count! @project.set_owner_permission(user) Repositories::MigrateService.new(user, @project, repository_params).call From 5c9702b308a4e19d32c85eb8560d3e24570132ae Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Sat, 8 May 2021 15:07:41 +0800 Subject: [PATCH 141/643] fix: build owner team need nickname --- app/services/organizations/create_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/organizations/create_service.rb b/app/services/organizations/create_service.rb index 96bb3f46a..a430ed6f4 100644 --- a/app/services/organizations/create_service.rb +++ b/app/services/organizations/create_service.rb @@ -54,7 +54,7 @@ class Organizations::CreateService < ApplicationService end def create_owner_info - @owner_team = Team.build(organization.id, "Owners", "", 4, true, true) + @owner_team = Team.build(organization.id, "Owners", "Owner团队", "", 4, true, true) TeamUnit.unit_types.keys.each do |u_type| TeamUnit.build(organization.id, owner_team.id, u_type) end From d768e81afdcb592e8092b67cf038cd3ecda03e40 Mon Sep 17 00:00:00 2001 From: jasder Date: Sat, 8 May 2021 16:48:56 +0800 Subject: [PATCH 142/643] Update CHANGELOG.md --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42422e3bd..401655072 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08 + +* BUGFIXES + * Fix 解决易修标题过长导致的排版问题(45469) + * Fix 解决合并请求详情页面排版错误的问题(45457) + * FIX 解决转移仓库界面专有名词描述错误的问题(45455) + * Fix 解决markdown格式文件自动生成数字排序的问题(45454) + * Fix 解决镜像项目源地址不显示的问题(45403) + * Fix 解决镜像项目导航显示错误问题(45398) + * Fix 解决其他相关bug + +* ENHANCEMENTS + * UPDATE 用户注册时,账号和密码正则匹配调整(45336) (45318) (45290) + * ADD 创建组织各属性添加规则匹配功能(45313) (45289) + * ADD 创建团建各属性添加规则匹配功能(45334) (45325) (45287) + * ADD 仓库转移功能(45017) (45015) + ## [v3.0.2](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-04-23 * BUGFIXES From 23704dbae394219501cf852ca4474b93a8ed7bac Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 10 May 2021 14:38:39 +0800 Subject: [PATCH 143/643] FIX get mirror url bug with get detail repo api --- app/services/repositories/migrate_service.rb | 4 +--- app/views/repositories/detail.json.jbuilder | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/services/repositories/migrate_service.rb b/app/services/repositories/migrate_service.rb index b737b2ef5..374115bf0 100644 --- a/app/services/repositories/migrate_service.rb +++ b/app/services/repositories/migrate_service.rb @@ -21,9 +21,7 @@ class Repositories::MigrateService < ApplicationService private def repository_params - params.merge(project_id: project.id, - identifier: params[:identifier], - source_clone_url: params[:source_clone_url]) + params.merge(project_id: project.id) end def gitea_repository_params diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 75b474ee0..39f2563a4 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -21,7 +21,7 @@ json.versions_count @project.versions_count #里程碑数量 json.version_releases_count @project.releases_size(@user.try(:id), "all") json.version_releasesed_count @project.releases_size(@user.try(:id), "released") #已发行的版本 json.permission render_permission(@user, @project) -json.mirror_url @project&.repository.source_clone_url +json.mirror_url @project&.repository.remote_mirror_url json.mirror @project&.repository.mirror_url.present? json.type @project.numerical_for_project_type json.open_devops @project.open_devops? From 2cca2c756eaccb2635977ee593c93a94f1275062 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 13 May 2021 14:52:07 +0800 Subject: [PATCH 144/643] ADD recommend organizations api --- .../organizations/organizations_controller.rb | 9 ++++++++- app/models/organization.rb | 1 + .../organizations/organizations/recommend.json.jbuilder | 6 ++++++ config/routes.rb | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 app/views/organizations/organizations/recommend.json.jbuilder diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index c8f4f4aa0..042d9a9fe 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -1,5 +1,5 @@ class Organizations::OrganizationsController < Organizations::BaseController - before_action :require_login, except: [:index, :show] + before_action :require_login, except: [:index, :show, :recommend] before_action :convert_image!, only: [:create, :update] before_action :load_organization, only: [:show, :update, :destroy] before_action :check_user_can_edit_org, only: [:update, :destroy] @@ -62,6 +62,13 @@ class Organizations::OrganizationsController < Organizations::BaseController tip_exception(e.message) end + def recommend + recommend = %W(xuos Huawei_Technology openatom_foundation pkecosystem TensorLayer) + + @organizations = Organization.with_visibility(%w(common) + .where(nickname: recommend).select(:id, :nickname) + end + private def convert_image! return unless params[:image].present? diff --git a/app/models/organization.rb b/app/models/organization.rb index f12c8b0a6..444938e72 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -47,6 +47,7 @@ # watchers_count :integer default("0") # devops_step :integer default("0") # gitea_token :string(255) +# platform :string(255) # # Indexes # diff --git a/app/views/organizations/organizations/recommend.json.jbuilder b/app/views/organizations/organizations/recommend.json.jbuilder new file mode 100644 index 000000000..262cc23dd --- /dev/null +++ b/app/views/organizations/organizations/recommend.json.jbuilder @@ -0,0 +1,6 @@ +json.organizations @organizations do |organization| + json.id organization.id + json.name organization.login + json.nickname organization.nickname.blank? ? organization.name : organization.nickname + json.avatar_url url_to_avatar(organization) +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 2901e0f56..63c7520ae 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -130,6 +130,7 @@ Rails.application.routes.draw do get :search end end + get :recommend, on: :collection end end From c2d7d8289e2ba3c296317bb075b86776d5b86b27 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 13 May 2021 14:53:46 +0800 Subject: [PATCH 145/643] FIX dismiss num for recommend projects api --- app/controllers/projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 500c584cd..3ddbeb401 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -167,7 +167,7 @@ class ProjectsController < ApplicationController end def recommend - @projects = Project.recommend.includes(:repository, :project_category, :owner).order(id: :desc).limit(5) + @projects = Project.recommend.includes(:repository, :project_category, :owner).order(id: :desc) end def about From fe9201d9f689c43466c398de0f6c4db501e56d35 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 13 May 2021 14:56:58 +0800 Subject: [PATCH 146/643] FIX code bug --- app/controllers/organizations/organizations_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index 042d9a9fe..bce34a5a5 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -65,7 +65,7 @@ class Organizations::OrganizationsController < Organizations::BaseController def recommend recommend = %W(xuos Huawei_Technology openatom_foundation pkecosystem TensorLayer) - @organizations = Organization.with_visibility(%w(common) + @organizations = Organization.with_visibility(%w(common)) .where(nickname: recommend).select(:id, :nickname) end From e304dd0c9899a98e3eddfd0c0e42cf45a6ad76d4 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 13 May 2021 15:02:28 +0800 Subject: [PATCH 147/643] FIX query recommend organization bug --- app/controllers/organizations/organizations_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index bce34a5a5..a2318f0a7 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -66,7 +66,7 @@ class Organizations::OrganizationsController < Organizations::BaseController recommend = %W(xuos Huawei_Technology openatom_foundation pkecosystem TensorLayer) @organizations = Organization.with_visibility(%w(common)) - .where(nickname: recommend).select(:id, :nickname) + .where(login: recommend).select(:id, :nickname) end private From b1abac201f5cb8e13c9347d4aeff5362a99c55a5 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 13 May 2021 15:06:41 +0800 Subject: [PATCH 148/643] FIX query columns bug with query recommend organization api --- app/controllers/organizations/organizations_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index a2318f0a7..29cb15a6a 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -66,7 +66,7 @@ class Organizations::OrganizationsController < Organizations::BaseController recommend = %W(xuos Huawei_Technology openatom_foundation pkecosystem TensorLayer) @organizations = Organization.with_visibility(%w(common)) - .where(login: recommend).select(:id, :nickname) + .where(login: recommend).select(:id, :login, :firstname, :lastname, :nickname) end private From dac07bcae095a8103b3ac1ad211993387671d652 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 14 May 2021 16:23:19 +0800 Subject: [PATCH 149/643] =?UTF-8?q?ADD=20=E9=A1=B5=E9=9D=A2=E7=BD=AE?= =?UTF-8?q?=E9=A1=B6=E5=8A=9F=E8=83=BD=E3=80=81=E5=B8=AE=E5=8A=A9=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=BF=AB=E9=80=9F=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/javascripts/admins/faqs.js | 2 + app/assets/javascripts/helps/faqs.js | 2 + app/assets/stylesheets/admins/faqs.scss | 3 + app/assets/stylesheets/helps/faqs.scss | 3 + app/controllers/admins/faqs_controller.rb | 58 +++++++++++++++++++ app/controllers/helps/faqs_controller.rb | 8 +++ app/helpers/admins/faqs_helper.rb | 2 + app/helpers/helps/faqs_helper.rb | 2 + app/models/ci/user.rb | 1 + app/models/faq.rb | 20 +++++++ app/models/user.rb | 1 + app/views/admins/faqs/_form_modal.html.erb | 24 ++++++++ app/views/admins/faqs/_list.html.erb | 33 +++++++++++ app/views/admins/faqs/edit.js.erb | 2 + app/views/admins/faqs/index.html.erb | 17 ++++++ app/views/admins/faqs/index.js.erb | 1 + app/views/admins/faqs/new.js.erb | 2 + .../shared/_laboratory_item.html.erb | 1 - app/views/admins/shared/_sidebar.html.erb | 1 + config/routes.rb | 5 ++ db/migrate/20210514024444_create_faqs.rb | 10 ++++ 21 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/admins/faqs.js create mode 100644 app/assets/javascripts/helps/faqs.js create mode 100644 app/assets/stylesheets/admins/faqs.scss create mode 100644 app/assets/stylesheets/helps/faqs.scss create mode 100644 app/controllers/admins/faqs_controller.rb create mode 100644 app/controllers/helps/faqs_controller.rb create mode 100644 app/helpers/admins/faqs_helper.rb create mode 100644 app/helpers/helps/faqs_helper.rb create mode 100644 app/models/faq.rb create mode 100644 app/views/admins/faqs/_form_modal.html.erb create mode 100644 app/views/admins/faqs/_list.html.erb create mode 100644 app/views/admins/faqs/edit.js.erb create mode 100644 app/views/admins/faqs/index.html.erb create mode 100644 app/views/admins/faqs/index.js.erb create mode 100644 app/views/admins/faqs/new.js.erb create mode 100644 db/migrate/20210514024444_create_faqs.rb diff --git a/app/assets/javascripts/admins/faqs.js b/app/assets/javascripts/admins/faqs.js new file mode 100644 index 000000000..dee720fac --- /dev/null +++ b/app/assets/javascripts/admins/faqs.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/helps/faqs.js b/app/assets/javascripts/helps/faqs.js new file mode 100644 index 000000000..dee720fac --- /dev/null +++ b/app/assets/javascripts/helps/faqs.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/admins/faqs.scss b/app/assets/stylesheets/admins/faqs.scss new file mode 100644 index 000000000..8d1a08d30 --- /dev/null +++ b/app/assets/stylesheets/admins/faqs.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the admins/faqs controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/helps/faqs.scss b/app/assets/stylesheets/helps/faqs.scss new file mode 100644 index 000000000..4d3d2bc49 --- /dev/null +++ b/app/assets/stylesheets/helps/faqs.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the helps/faqs controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/admins/faqs_controller.rb b/app/controllers/admins/faqs_controller.rb new file mode 100644 index 000000000..08dc69a79 --- /dev/null +++ b/app/controllers/admins/faqs_controller.rb @@ -0,0 +1,58 @@ +class Admins::FaqsController < Admins::BaseController + before_action :find_faq, only: [:edit,:update, :destroy] + + def index + sort_by = params[:sort_by] ||= 'created_at' + sort_direction = params[:sort_direction] ||= 'desc' + + keyword = params[:keyword].to_s.strip + collection = Faq.search_question(keyword).order("#{sort_by} #{sort_direction}") + @faqs = paginate collection + end + + def new + @faq = Faq.new + end + + def edit + end + + def update + begin + @faq.update!(faq_params) + flash[:success] = '修改成功' + rescue Exception + flash[:danger] = @faq.errors.full_messages.to_sentence + end + + redirect_to admins_faqs_path + end + + def destroy + @faq.destroy + + redirect_to admins_faqs_path + flash[:success] = "删除成功" + end + + def create + @faq = Faq.new(faq_params) + begin + @faq.save! + flash[:success] = '创建成功' + rescue Exception + flash[:danger] = @faq.errors.full_messages.to_sentence + end + redirect_to admins_faqs_path + end + + private + def find_faq + @faq = Faq.find params[:id] + end + + def faq_params + params.require(:faq).permit(:question, :url) + end + +end diff --git a/app/controllers/helps/faqs_controller.rb b/app/controllers/helps/faqs_controller.rb new file mode 100644 index 000000000..133748ed5 --- /dev/null +++ b/app/controllers/helps/faqs_controller.rb @@ -0,0 +1,8 @@ +class Helps::FaqsController < ApplicationController + skip_before_action :check_sign, :user_setup + + def index + faqs = Faq.select_without_id + render json: faqs.as_json(:except => [:id]) + end +end diff --git a/app/helpers/admins/faqs_helper.rb b/app/helpers/admins/faqs_helper.rb new file mode 100644 index 000000000..0316d44fd --- /dev/null +++ b/app/helpers/admins/faqs_helper.rb @@ -0,0 +1,2 @@ +module Admins::FaqsHelper +end diff --git a/app/helpers/helps/faqs_helper.rb b/app/helpers/helps/faqs_helper.rb new file mode 100644 index 000000000..68b8279f7 --- /dev/null +++ b/app/helpers/helps/faqs_helper.rb @@ -0,0 +1,2 @@ +module Helps::FaqsHelper +end diff --git a/app/models/ci/user.rb b/app/models/ci/user.rb index fc82596c4..e4a4d0623 100644 --- a/app/models/ci/user.rb +++ b/app/models/ci/user.rb @@ -47,6 +47,7 @@ # watchers_count :integer default("0") # devops_step :integer default("0") # gitea_token :string(255) +# platform :string(255) # # Indexes # diff --git a/app/models/faq.rb b/app/models/faq.rb new file mode 100644 index 000000000..5965de036 --- /dev/null +++ b/app/models/faq.rb @@ -0,0 +1,20 @@ +# == Schema Information +# +# Table name: faqs +# +# id :integer not null, primary key +# question :string(255) +# url :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# + +class Faq < ApplicationRecord + + validates :question, presence: true,length: { maximum: 100, too_long: "最多%{count}个字符" } + validates :url, format: { with: CustomRegexp::URL, multiline: true, message: "格式不正确" } + + scope :select_without_id, -> { select(:question, :url) } + scope :search_question, ->(keyword) { where("question LIKE ?", "%#{keyword}%") unless keyword.blank?} + +end diff --git a/app/models/user.rb b/app/models/user.rb index 256cc7b41..2f67410c0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -47,6 +47,7 @@ # watchers_count :integer default("0") # devops_step :integer default("0") # gitea_token :string(255) +# platform :string(255) # # Indexes # diff --git a/app/views/admins/faqs/_form_modal.html.erb b/app/views/admins/faqs/_form_modal.html.erb new file mode 100644 index 000000000..45ceb901c --- /dev/null +++ b/app/views/admins/faqs/_form_modal.html.erb @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/app/views/admins/faqs/_list.html.erb b/app/views/admins/faqs/_list.html.erb new file mode 100644 index 000000000..81e658edd --- /dev/null +++ b/app/views/admins/faqs/_list.html.erb @@ -0,0 +1,33 @@ + + + + + + + + + + + + + <% if faqs.present? %> + <% faqs.each_with_index do |faq, index| %> + + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
    序号标题url<%= sort_tag('创建于', name: 'created_at', path: admins_faqs_path) %><%= sort_tag('更新于', name: 'updated_at', path: admins_faqs_path) %>操作
    <%= list_index_no((params[:page] || 1).to_i, index) %><%= faq.question%><%= link_to faq.url, target: '_blank' %><%= display_text(faq.created_at&.strftime('%Y-%m-%d %H:%M')) %><%= display_text(faq.updated_at&.strftime('%Y-%m-%d %H:%M')) %> + <%= link_to "编辑", edit_admins_faq_path(faq), remote: true, class: "action" %> + <%= link_to "删除", admins_faqs_path(faq.id), method: :delete, data:{confirm: "确认删除的吗?"}, class: "delete-project-action" %> +
    + +<%= render partial: 'admins/shared/paginate', locals: { objects: faqs } %> diff --git a/app/views/admins/faqs/edit.js.erb b/app/views/admins/faqs/edit.js.erb new file mode 100644 index 000000000..fc121b18e --- /dev/null +++ b/app/views/admins/faqs/edit.js.erb @@ -0,0 +1,2 @@ +$("#faq-modals").html("<%= j render(partial: 'admins/faqs/form_modal', locals: {type: 'update'}) %>") +$(".faq-change-modal").modal('show'); \ No newline at end of file diff --git a/app/views/admins/faqs/index.html.erb b/app/views/admins/faqs/index.html.erb new file mode 100644 index 000000000..3b327249b --- /dev/null +++ b/app/views/admins/faqs/index.html.erb @@ -0,0 +1,17 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('FAQ', admins_faqs_path) %> +<% end %> + +
    + <%= form_tag(admins_faqs_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> + <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '输入标题搜素') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> + <% end %> + <%= link_to "新增", new_admins_faq_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> +
    + +
    + <%= render partial: 'admins/faqs/list', locals: { faqs: @faqs } %> +
    +
    +
    \ No newline at end of file diff --git a/app/views/admins/faqs/index.js.erb b/app/views/admins/faqs/index.js.erb new file mode 100644 index 000000000..ebb1900e5 --- /dev/null +++ b/app/views/admins/faqs/index.js.erb @@ -0,0 +1 @@ +$('.faqs-list-container').html("<%= j( render partial: 'admins/faqs/list', locals: { faqs: @faqs } ) %>"); \ No newline at end of file diff --git a/app/views/admins/faqs/new.js.erb b/app/views/admins/faqs/new.js.erb new file mode 100644 index 000000000..edeb83a81 --- /dev/null +++ b/app/views/admins/faqs/new.js.erb @@ -0,0 +1,2 @@ +$("#faq-modals").html("<%= j render(partial: 'admins/faqs/form_modal', locals: {type: 'create'}) %>") +$(".faq-change-modal").modal('show'); \ No newline at end of file diff --git a/app/views/admins/laboratories/shared/_laboratory_item.html.erb b/app/views/admins/laboratories/shared/_laboratory_item.html.erb index 8fdf9c727..a121528e3 100644 --- a/app/views/admins/laboratories/shared/_laboratory_item.html.erb +++ b/app/views/admins/laboratories/shared/_laboratory_item.html.erb @@ -10,7 +10,6 @@ <% if school && school.identifier.present? %> - <%= link_to school.identifier.to_s, statistics_college_path(school.identifier), target: '_blank' %> <% else %> -- <% end %> diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb index de56a5477..ad53c661a 100644 --- a/app/views/admins/shared/_sidebar.html.erb +++ b/app/views/admins/shared/_sidebar.html.erb @@ -38,6 +38,7 @@
  • <%= sidebar_item(admins_cooperatives_path, '合作伙伴', icon: 'handshake-o', controller: 'admins-cooperatives') %>
  • <%= sidebar_item(edit_admins_agreement_path, '服务协议', icon: 'file-text-o', controller: 'admins-agreements') %>
  • <%= sidebar_item(edit_admins_help_center_path, '帮助中心', icon: 'question-circle-o', controller: 'admins-help_centers') %>
  • +
  • <%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %>
  • <% end %>
  • diff --git a/config/routes.rb b/config/routes.rb index 63c7520ae..a8c97effc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -604,6 +604,10 @@ Rails.application.routes.draw do end end # Project Area END + + scope module: :helps do + resources :faqs, only: [:index] + end end namespace :admins do @@ -780,6 +784,7 @@ Rails.application.routes.draw do post :drag, on: :collection post :replace_image_url, on: :member end + resources :faqs resources :laboratories, only: [:index, :create, :destroy, :update] do member do get :shixuns_for_select diff --git a/db/migrate/20210514024444_create_faqs.rb b/db/migrate/20210514024444_create_faqs.rb new file mode 100644 index 000000000..d63a64fa2 --- /dev/null +++ b/db/migrate/20210514024444_create_faqs.rb @@ -0,0 +1,10 @@ +class CreateFaqs < ActiveRecord::Migration[5.2] + def change + create_table :faqs do |t| + t.string :question + t.string :url + + t.timestamps + end + end +end From 8ee0acae85e8d40c5652fd3791848c26ee268b5a Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 14 May 2021 16:39:32 +0800 Subject: [PATCH 150/643] set default desc sort for faqs api --- app/controllers/admins/faqs_controller.rb | 2 +- app/controllers/helps/faqs_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/admins/faqs_controller.rb b/app/controllers/admins/faqs_controller.rb index 08dc69a79..fc00f847c 100644 --- a/app/controllers/admins/faqs_controller.rb +++ b/app/controllers/admins/faqs_controller.rb @@ -2,7 +2,7 @@ class Admins::FaqsController < Admins::BaseController before_action :find_faq, only: [:edit,:update, :destroy] def index - sort_by = params[:sort_by] ||= 'created_at' + sort_by = params[:sort_by] ||= 'updated_at' sort_direction = params[:sort_direction] ||= 'desc' keyword = params[:keyword].to_s.strip diff --git a/app/controllers/helps/faqs_controller.rb b/app/controllers/helps/faqs_controller.rb index 133748ed5..a18f49270 100644 --- a/app/controllers/helps/faqs_controller.rb +++ b/app/controllers/helps/faqs_controller.rb @@ -2,7 +2,7 @@ class Helps::FaqsController < ApplicationController skip_before_action :check_sign, :user_setup def index - faqs = Faq.select_without_id + faqs = Faq.select_without_id.order(updated_at: :desc) render json: faqs.as_json(:except => [:id]) end end From 27d9d806cee1a6d04e7d61b0bef0a96335255c15 Mon Sep 17 00:00:00 2001 From: jasder Date: Sat, 15 May 2021 10:19:25 +0800 Subject: [PATCH 151/643] FIX update project bug --- app/controllers/projects_controller.rb | 34 +++++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3ddbeb401..7612003f2 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -106,19 +106,29 @@ class ProjectsController < ApplicationController def update ActiveRecord::Base.transaction do - Projects::UpdateForm.new(project_params).validate! - private = params[:private] || false + # TODO: + # 临时特殊处理修改website、lesson_url操作方法 + if project_params.has_key?("website") + @project.update(project_params) + else + validate_params = project_params.slice(:name, :description, + :project_category_id, :project_language_id, :private) + + Projects::UpdateForm.new(validate_params).validate! + + private = params[:private] || false - new_project_params = project_params.except(:private).merge(is_public: !private) - @project.update_attributes!(new_project_params) - gitea_params = { - private: private, - default_branch: @project.default_branch, - website: @project.website - } - if [true, false].include? private - Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params) - @project.repository.update_column(:hidden, private) + new_project_params = project_params.except(:private).merge(is_public: !private) + @project.update_attributes!(new_project_params) + gitea_params = { + private: private, + default_branch: @project.default_branch, + website: @project.website + } + if [true, false].include? private + Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params) + @project.repository.update_column(:hidden, private) + end end end rescue Exception => e From 2f9d583fac696703b9d67402c56694cd7ea3d053 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 17 May 2021 16:57:46 +0800 Subject: [PATCH 152/643] FIX add nickname lastname query conditions for list users api --- app/models/user.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 2f67410c0..03989cbab 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -168,7 +168,8 @@ class User < Owner # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } scope :like, lambda { |keywords| - where("LOWER(concat(lastname, firstname, login, mail)) LIKE ?", "%#{keywords.split(" ").join('|')}%") unless keywords.blank? + sql = "CONCAT(lastname, firstname) LIKE :keyword OR login LIKE :keyword OR mail LIKE :keyword OR nickname LIKE :keyword" + where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? } scope :simple_select, -> {select(:id, :login, :lastname,:firstname, :nickname, :gitea_uid, :type)} From c627ea6c1938ec126a35a43b8debe5e813b698d0 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 17 May 2021 17:14:55 +0800 Subject: [PATCH 153/643] FIX migration project accelerator's bug --- app/controllers/concerns/acceleratorable.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/controllers/concerns/acceleratorable.rb b/app/controllers/concerns/acceleratorable.rb index 9a11e46c2..5243ac538 100644 --- a/app/controllers/concerns/acceleratorable.rb +++ b/app/controllers/concerns/acceleratorable.rb @@ -2,7 +2,7 @@ module Acceleratorable extend ActiveSupport::Concern def enable_accelerator?(clone_addr) - clone_addr.include?(github_domain) || clone_addr.include?(gitlab_domain) + is_foreign_url?(clone_addr) && config_accelerator? end def accelerator_url(repo_name) @@ -25,4 +25,12 @@ module Acceleratorable Gitea.gitea_config[:accelerator]["access_key_id"] end + def config_accelerator? + Gitea.gitea_config[:accelerator].present? + end + + def is_foreign_url?(clone_addr) + clone_addr.include?(github_domain) || clone_addr.include?(gitlab_domain) + end + end \ No newline at end of file From 8a47761afbdeac4da414fdf17de5a3e6e0d65c92 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 21 May 2021 11:39:50 +0800 Subject: [PATCH 154/643] ADD mergeable column for get pull api --- app/controllers/pull_requests_controller.rb | 3 ++- .../gitea/pull_request/get_service.rb | 21 +++++++++---------- app/views/pull_requests/show.json.jbuilder | 2 ++ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 0dbcdc942..139ea9526 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -136,7 +136,8 @@ class PullRequestsController < ApplicationController def show @issue_user = @issue.user @issue_assign_to = @issue.get_assign_user - + @gitea_pull = Gitea::PullRequest::GetService.call(@owner.login, + @repository.identifier, @pull_request.gpid, current_user&.gitea_token) end def pr_merge diff --git a/app/services/gitea/pull_request/get_service.rb b/app/services/gitea/pull_request/get_service.rb index 6a7ec30f4..601c669e1 100644 --- a/app/services/gitea/pull_request/get_service.rb +++ b/app/services/gitea/pull_request/get_service.rb @@ -1,15 +1,14 @@ # Get a pull request class Gitea::PullRequest::GetService < Gitea::ClientService - attr_reader :user, :repo, :pull_request_id + attr_reader :owner, :repo, :number, :token - # user: 用户 - # repo: 仓库名称/标识 - # pull_request_id: pull request主键id - def initialize(user, repo, pull_request_id) - super({token: user.gitea_token}) - @user = user + #eq: + # Gitea::PullRequest::GetService.call(user.login, repository.identifier, pull.gpid, user.gitea_token) + def initialize(owner, repo, number, token=nil) + @owner = owner @repo = repo - @pull_request_id = pull_request_id + @number = number + @token = token end def call @@ -19,11 +18,11 @@ class Gitea::PullRequest::GetService < Gitea::ClientService private def params - Hash.new.merge(token: user.gitea_token) + Hash.new.merge(token: token) end def url - "/repos/#{user.login}/#{repo}/pulls/#{pull_request_id}".freeze + "/repos/#{owner}/#{repo}/pulls/#{number}".freeze end def render_result(response) @@ -31,7 +30,7 @@ class Gitea::PullRequest::GetService < Gitea::ClientService when 200 JSON.parse(response.body) else - nil + {} end end end diff --git a/app/views/pull_requests/show.json.jbuilder b/app/views/pull_requests/show.json.jbuilder index c3f781f73..9c2681861 100644 --- a/app/views/pull_requests/show.json.jbuilder +++ b/app/views/pull_requests/show.json.jbuilder @@ -12,6 +12,8 @@ json.pull_request do json.pull_request_staus @pull_request.status == 1 ? "merged" : (@pull_request.status == 2 ? "closed" : "open") json.fork_project_user @pull_request&.fork_project&.owner.try(:login) json.create_user @pull_request&.user&.login + json.mergeable @gitea_pull["mergeable"] + json.state @gitea_pull["state"] end json.issue do From 00f5a7f9165ede29520f7e53aff1d56319440cbf Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 21 May 2021 16:42:53 +0800 Subject: [PATCH 155/643] =?UTF-8?q?ADD=20issue=20pull=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/issues/list_query_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/issues/list_query_service.rb b/app/services/issues/list_query_service.rb index dbb502ab6..1718db97d 100644 --- a/app/services/issues/list_query_service.rb +++ b/app/services/issues/list_query_service.rb @@ -28,7 +28,7 @@ class Issues::ListQueryService < ApplicationService end if search_name.present? - issues = issues.where("subject like ?", "%#{search_name}%") + issues = issues.where("subject LIKE ? OR description LIKE ? ", "%#{search_name}%", "%#{search_name}%") end if start_time&.present? || end_time&.present? From ffa74e92a3d7976621465c295f166658fad3caad Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 21 May 2021 18:29:14 +0800 Subject: [PATCH 156/643] =?UTF-8?q?FIX=20=E4=B8=B4=E6=97=B6=E5=A4=84?= =?UTF-8?q?=E7=90=86=E8=8E=B7=E5=8F=96readme=E6=96=87=E4=BB=B6=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/repositories_controller.rb | 5 +++++ app/views/repositories/entries.json.jbuilder | 1 + 2 files changed, 6 insertions(+) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 10b352ae6..414711832 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -53,6 +53,11 @@ class RepositoriesController < ApplicationController @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}/" + + # TODO + # 临时处理readme文件问题 + admin = User.where(admin: true).last + @readme = Gitea::Repository::Readme::GetService.call(@owner.login, @project.identifier, @ref, admin&.gitea_token) end end diff --git a/app/views/repositories/entries.json.jbuilder b/app/views/repositories/entries.json.jbuilder index 6964c1c54..f0b069dc7 100644 --- a/app/views/repositories/entries.json.jbuilder +++ b/app/views/repositories/entries.json.jbuilder @@ -59,4 +59,5 @@ if @project.forge? end end end + json.readme @readme end From 5b2d6a8063eda3c108a7717cc11dd1aa4f0c3fc5 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 21 May 2021 18:34:33 +0800 Subject: [PATCH 157/643] =?UTF-8?q?FIX=20[bug]=E4=B8=B4=E6=97=B6=E5=A4=84?= =?UTF-8?q?=E7=90=86=E8=8E=B7=E5=8F=96readme=E6=96=87=E4=BB=B6=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/repositories_controller.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 414711832..8019e905d 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -57,7 +57,13 @@ class RepositoriesController < ApplicationController # TODO # 临时处理readme文件问题 admin = User.where(admin: true).last - @readme = Gitea::Repository::Readme::GetService.call(@owner.login, @project.identifier, @ref, admin&.gitea_token) + result = Gitea::Repository::Readme::GetService.call(@owner.login, @project.identifier, @ref, admin&.gitea_token) + @readme = + if result[:status] == :success + result[:body] + else + {} + end end end From 1c8d0686ee0c56631d83e69a14aadc7d52ff7ec8 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 21 May 2021 18:41:29 +0800 Subject: [PATCH 158/643] =?UTF-8?q?FIX=20[base64=E8=A7=A3=E7=A0=81?= =?UTF-8?q?=E6=93=8D=E4=BD=9C]=E4=B8=B4=E6=97=B6=E5=A4=84=E7=90=86?= =?UTF-8?q?=E8=8E=B7=E5=8F=96readme=E6=96=87=E4=BB=B6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/repositories/entries.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/repositories/entries.json.jbuilder b/app/views/repositories/entries.json.jbuilder index f0b069dc7..e62930a95 100644 --- a/app/views/repositories/entries.json.jbuilder +++ b/app/views/repositories/entries.json.jbuilder @@ -59,5 +59,5 @@ if @project.forge? end end end - json.readme @readme + json.readme @readme[:readme].merge(content: readme_render_decode64_content(@result[:readme]["content"], nil)) end From a8e53d4e5cdf4ed1e1255f9c55ef040f23f3a934 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 21 May 2021 18:51:46 +0800 Subject: [PATCH 159/643] =?UTF-8?q?FIX=20[code=20bug]=E4=B8=B4=E6=97=B6?= =?UTF-8?q?=E5=A4=84=E7=90=86=E8=8E=B7=E5=8F=96readme=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/repositories_controller.rb | 2 +- app/views/repositories/entries.json.jbuilder | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 8019e905d..cf4c2132e 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -56,7 +56,7 @@ class RepositoriesController < ApplicationController # TODO # 临时处理readme文件问题 - admin = User.where(admin: true).last + admin = User.find_by_login "jasder" result = Gitea::Repository::Readme::GetService.call(@owner.login, @project.identifier, @ref, admin&.gitea_token) @readme = if result[:status] == :success diff --git a/app/views/repositories/entries.json.jbuilder b/app/views/repositories/entries.json.jbuilder index e62930a95..a12c088b0 100644 --- a/app/views/repositories/entries.json.jbuilder +++ b/app/views/repositories/entries.json.jbuilder @@ -59,5 +59,6 @@ if @project.forge? end end end - json.readme @readme[:readme].merge(content: readme_render_decode64_content(@result[:readme]["content"], nil)) + + json.readme @readme.merge(content: readme_render_decode64_content(@readme["content"], nil)) end From e0eae66ab4193c83ef0be3e75e7667d389e688a5 Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 21 May 2021 19:26:17 +0800 Subject: [PATCH 160/643] =?UTF-8?q?FIX=20[=E7=94=A8=E6=88=B7=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=96=B9=E5=BC=8F]=E4=B8=B4=E6=97=B6=E5=A4=84?= =?UTF-8?q?=E7=90=86=E8=8E=B7=E5=8F=96readme=E6=96=87=E4=BB=B6=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/repositories_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index cf4c2132e..6594d06e9 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -56,7 +56,8 @@ class RepositoriesController < ApplicationController # TODO # 临时处理readme文件问题 - admin = User.find_by_login "jasder" + admin = current_user.blank? ? User.where(admin: true).last : current_user + result = Gitea::Repository::Readme::GetService.call(@owner.login, @project.identifier, @ref, admin&.gitea_token) @readme = if result[:status] == :success From 554925eacdacb0ac6b674dc8220e5d9e13cab8e6 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 24 May 2021 10:13:14 +0800 Subject: [PATCH 161/643] FIX update CHANGELOG.md --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 401655072..d24953c43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [v3.0.4](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-24 + +* BUGFIXES + * Fix 在线修改文件,页面文件显不及时的问题(46049) + * Fix Fork项目,接口多次调用问题(45052) + * FIX 页面置顶功能区域排版问题(45825) + * Fix 其他样式显示问题 + +* ENHANCEMENTS + * ADD 合并请求页面显示有冲突文件状态(46016) + * ADD 创建组织各属性添加规则匹配功能(45707) + * ADD 微信分享功能(45707) + ## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08 * BUGFIXES From e716dba249e0b626f21549c226ffb265a4792744 Mon Sep 17 00:00:00 2001 From: jasder Date: Mon, 24 May 2021 17:05:06 +0800 Subject: [PATCH 162/643] FIX query project members api bug --- app/models/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 03989cbab..b778c80f9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -168,7 +168,7 @@ class User < Owner # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } scope :like, lambda { |keywords| - sql = "CONCAT(lastname, firstname) LIKE :keyword OR login LIKE :keyword OR mail LIKE :keyword OR nickname LIKE :keyword" + sql = "CONCAT(lastname, firstname) LIKE :search OR login LIKE :search OR mail LIKE :search OR nickname LIKE :search" where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? } From 77076c60a60de262241ada6770c9eb83e88ef679 Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 26 May 2021 17:37:13 +0800 Subject: [PATCH 163/643] =?UTF-8?q?ADD=20issue=E3=80=81pull=E3=80=81milest?= =?UTF-8?q?one=E9=92=A9=E5=AD=90,=E8=87=AA=E5=8A=A8=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E7=9A=84=E6=9B=B4=E6=96=B0=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/issue.rb | 2 +- app/models/pull_request.rb | 2 +- app/models/version.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/issue.rb b/app/models/issue.rb index 934e1d314..69de1eae2 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -50,7 +50,7 @@ class Issue < ApplicationRecord #issue_type 1为普通,2为悬赏 - belongs_to :project, :counter_cache => true + belongs_to :project, counter_cache: true, touch: true belongs_to :tracker,optional: true has_many :project_trends, as: :trend, dependent: :destroy has_one :pull_request diff --git a/app/models/pull_request.rb b/app/models/pull_request.rb index cf057c3f2..62d6c3cc6 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -31,7 +31,7 @@ class PullRequest < ApplicationRecord belongs_to :issue belongs_to :user - belongs_to :project, :counter_cache => true + belongs_to :project, counter_cache: true, touch: true # belongs_to :fork_project, foreign_key: :fork_project_id has_many :pull_request_assigns, foreign_key: :pull_request_id has_many :pull_request_tags, foreign_key: :pull_request_id diff --git a/app/models/version.rb b/app/models/version.rb index bee22cd5c..650d5a656 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -24,7 +24,7 @@ # class Version < ApplicationRecord - belongs_to :project, counter_cache: true + belongs_to :project, counter_cache: true, touch: true has_many :issues, class_name: "Issue", foreign_key: "fixed_version_id" belongs_to :user, optional: true From cacc807978a71f849abbd5c5888a0e51f72151a9 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 27 May 2021 10:30:34 +0800 Subject: [PATCH 164/643] add: user headmap --- app/controllers/users/headmaps_controller.rb | 26 ++++ app/docs/slate/source/includes/_users.md | 124 ++++++++++++++- app/services/gitea/user/headmap_service.rb | 23 +++ app/views/users/headmaps/index.json.jbuilder | 5 + config/routes.rb | 1 + public/docs/api.html | 152 +++++++++++++++++-- 6 files changed, 321 insertions(+), 10 deletions(-) create mode 100644 app/controllers/users/headmaps_controller.rb create mode 100644 app/services/gitea/user/headmap_service.rb create mode 100644 app/views/users/headmaps/index.json.jbuilder diff --git a/app/controllers/users/headmaps_controller.rb b/app/controllers/users/headmaps_controller.rb new file mode 100644 index 000000000..81bd5771c --- /dev/null +++ b/app/controllers/users/headmaps_controller.rb @@ -0,0 +1,26 @@ +class Users::HeadmapsController < Users::BaseController + def index + result = Gitea::User::HeadmapService.call(observed_user.login, start_stamp, end_stamp) + @headmaps = result[2] + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def start_stamp + if params[:year].present? + Date.new(params[:year], 1).to_time.to_i + else + Date.today.to_time.to_i - 365*24*60*60 + end + end + + def end_stamp + if params[:year].present? + Date.new(params[:year], 1).to_time.to_i + 365*24*60*60 + else + Date.today.to_time.to_i + end + end +end \ No newline at end of file diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 1d1afc028..982543fdc 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -47,6 +47,128 @@ await octokit.request('GET /api/users/me.json') Success Data. +## 获取用户贡献度 +获取用户贡献度 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json +``` + +```javascript +await octokit.request('GET /api/users/:login/headmaps.json') +``` + +### HTTP 请求 +`GET api/users/:login/headmaps.json` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_contributions |int |所选时间内的总贡献度 | +|headmaps.date |string|时间| +|headmaps.contributions |int|贡献度| + + +> 返回的JSON示例: + +```json +{ + "total_contributions": 139, + "headmaps": [ + { + "date": 1612627200, + "contributions": 1 + }, + { + "date": 1613836800, + "contributions": 13 + }, + { + "date": 1614182400, + "contributions": 5 + }, + { + "date": 1614528000, + "contributions": 2 + }, + { + "date": 1614787200, + "contributions": 1 + }, + { + "date": 1615737600, + "contributions": 9 + }, + { + "date": 1616342400, + "contributions": 14 + }, + { + "date": 1616515200, + "contributions": 1 + }, + { + "date": 1617033600, + "contributions": 11 + }, + { + "date": 1617638400, + "contributions": 1 + }, + { + "date": 1618156800, + "contributions": 1 + }, + { + "date": 1618243200, + "contributions": 2 + }, + { + "date": 1618761600, + "contributions": 3 + }, + { + "date": 1619107200, + "contributions": 37 + }, + { + "date": 1619280000, + "contributions": 2 + }, + { + "date": 1619366400, + "contributions": 6 + }, + { + "date": 1619539200, + "contributions": 1 + }, + { + "date": 1619625600, + "contributions": 18 + }, + { + "date": 1619712000, + "contributions": 9 + }, + { + "date": 1620057600, + "contributions": 1 + }, + { + "date": 1620230400, + "contributions": 1 + } + ] +} +``` + + + ## 待办事项-用户通知信息 待办事项-用户通知信息 diff --git a/app/services/gitea/user/headmap_service.rb b/app/services/gitea/user/headmap_service.rb new file mode 100644 index 000000000..611a8b9d0 --- /dev/null +++ b/app/services/gitea/user/headmap_service.rb @@ -0,0 +1,23 @@ +class Gitea::User::HeadmapService < Gitea::ClientService + attr_reader :start_time, :end_time, :username + + def initialize(username, start_time, end_time) + @username = username + @start_time = start_time + @end_time = end_time + end + + def call + response = get(url, params) + render_response(response) + end + + private + def params + Hash.new.merge(start: start_time, end: end_time) + end + + def url + "/users/#{username}/heatmap".freeze + end +end \ No newline at end of file diff --git a/app/views/users/headmaps/index.json.jbuilder b/app/views/users/headmaps/index.json.jbuilder new file mode 100644 index 000000000..7011b2559 --- /dev/null +++ b/app/views/users/headmaps/index.json.jbuilder @@ -0,0 +1,5 @@ +json.total_contributions @headmaps.collect{|map| map["contributions"]}.reduce(0, :+) +json.headmaps @headmaps.each do |map| + json.date map["timestamp"] + json.contributions map["contributions"] +end diff --git a/config/routes.rb b/config/routes.rb index a8c97effc..ae121bb08 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -265,6 +265,7 @@ Rails.application.routes.draw do post :refuse end end + resources :headmaps, only: [:index] resources :organizations, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] diff --git a/public/docs/api.html b/public/docs/api.html index f970ea84d..9f52b9066 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -331,6 +331,9 @@
  • 获取当前登陆用户信息
  • +
  • + 获取用户贡献度 +
  • 待办事项-用户通知信息
  • @@ -587,7 +590,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -649,6 +652,137 @@ Success — a happy kitten is an authenticated kitten! +

    获取用户贡献度

    +

    获取用户贡献度

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
    +
    await octokit.request('GET /api/users/:login/headmaps.json')
    +

    HTTP 请求

    +

    GET api/users/:login/headmaps.json

    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_contributionsint所选时间内的总贡献度
    headmaps.datestring时间
    headmaps.contributionsint贡献度
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_contributions": 139,
    +    "headmaps": [
    +        {
    +            "date": 1612627200,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1613836800,
    +            "contributions": 13
    +        },
    +        {
    +            "date": 1614182400,
    +            "contributions": 5
    +        },
    +        {
    +            "date": 1614528000,
    +            "contributions": 2
    +        },
    +        {
    +            "date": 1614787200,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1615737600,
    +            "contributions": 9
    +        },
    +        {
    +            "date": 1616342400,
    +            "contributions": 14
    +        },
    +        {
    +            "date": 1616515200,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1617033600,
    +            "contributions": 11
    +        },
    +        {
    +            "date": 1617638400,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1618156800,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1618243200,
    +            "contributions": 2
    +        },
    +        {
    +            "date": 1618761600,
    +            "contributions": 3
    +        },
    +        {
    +            "date": 1619107200,
    +            "contributions": 37
    +        },
    +        {
    +            "date": 1619280000,
    +            "contributions": 2
    +        },
    +        {
    +            "date": 1619366400,
    +            "contributions": 6
    +        },
    +        {
    +            "date": 1619539200,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1619625600,
    +            "contributions": 18
    +        },
    +        {
    +            "date": 1619712000,
    +            "contributions": 9
    +        },
    +        {
    +            "date": 1620057600,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1620230400,
    +            "contributions": 1
    +        }
    +    ]
    +}
    +
    +

    待办事项-用户通知信息

    待办事项-用户通知信息

    @@ -657,7 +791,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    请求字段说明:

    @@ -673,7 +807,7 @@ Success — a happy kitten is an authenticated kitten!
    用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -894,7 +1028,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    请求字段说明:

    参数
    @@ -910,7 +1044,7 @@ Success — a happy kitten is an authenticated kitten!
    用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1086,7 +1220,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    请求字段说明:

    参数
    @@ -1107,7 +1241,7 @@ Success — a happy kitten is an authenticated kitten!
    迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1277,7 +1411,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    请求字段说明:

    参数
    @@ -1298,7 +1432,7 @@ Success — a happy kitten is an authenticated kitten!
    迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    From c2449d59afe3583db7dad88ee9be6f62a499df88 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 27 May 2021 14:23:59 +0800 Subject: [PATCH 165/643] add: user pinned projects --- .../users/is_pinned_projects_controller.rb | 27 ++ app/docs/slate/source/includes/_users.md | 131 ++++++++- app/models/pinned_project.rb | 22 ++ app/models/project.rb | 148 +++++----- app/models/user.rb | 10 + .../projects/_project_detail.json.jbuilder | 3 + app/views/repositories/edit.json.jbuilder | 3 +- .../is_pinned_projects/index.json.jbuilder | 4 + config/routes.rb | 5 + .../20210527024043_create_pinned_projects.rb | 11 + public/docs/api.html | 266 ++++++++++++++++-- spec/models/pinned_project_spec.rb | 5 + 12 files changed, 544 insertions(+), 91 deletions(-) create mode 100644 app/controllers/users/is_pinned_projects_controller.rb create mode 100644 app/models/pinned_project.rb create mode 100644 app/views/users/is_pinned_projects/index.json.jbuilder create mode 100644 db/migrate/20210527024043_create_pinned_projects.rb create mode 100644 spec/models/pinned_project_spec.rb diff --git a/app/controllers/users/is_pinned_projects_controller.rb b/app/controllers/users/is_pinned_projects_controller.rb new file mode 100644 index 000000000..22ce29263 --- /dev/null +++ b/app/controllers/users/is_pinned_projects_controller.rb @@ -0,0 +1,27 @@ +class Users::IsPinnedProjectsController < Users::BaseController + before_action :private_user_resources!, only: [:pin] + def index + @is_pinned_projects = observed_user.is_pinned_projects.includes(:project_category, :project_language, :repository).order(position: :desc) + @is_pinned_projects = kaminari_paginate(@is_pinned_projects) + end + + def pin + observed_user.is_pinned_project_ids = is_pinned_project_ids + render_ok + rescue ActiveRecord::RecordNotFound => e + render_not_found + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def is_pinned_project_ids + if params[:is_pinned_project_ids].present? + return params[:is_pinned_project_ids].select{|id| observed_user.full_member_projects.pluck(:id).include?(id.to_i) } + end + if params[:is_pinned_project_id].present? + return observed_user.is_pinned_project_ids.include?(params[:is_pinned_project_id].to_i) ? observed_user.is_pinned_project_ids : observed_user.is_pinned_project_ids.push(params[:is_pinned_project_id].to_i) + end + end +end \ No newline at end of file diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 982543fdc..b2c3ebccb 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -47,6 +47,135 @@ await octokit.request('GET /api/users/me.json') Success Data. +## 获取用户星标项目 +获取用户星标项目 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/is_pinned_projects.json +``` + +```javascript +await octokit.request('GET /api/users/:login/is_pinned_projects.json') +``` + +### HTTP 请求 +`GET api/users/:login/is_pinned_projects.json` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_count |int |星标项目数量 | +|identifier |string |项目标识 | +|name |string |项目名称 | +|description |string |项目描述 | +|visits |int |项目访问数量| +|praises_count |int |项目点赞数量| +|watchers_count |int |项目关注数量| +|issues_count |int |项目issue数量| +|pull_requests_count |int |项目合并请求数量| +|forked_count |int |项目复刻数量| +|is_public |bool |项目是否公开| +|mirror_url |string |镜像地址| +|type |int |项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目| +|time_ago |string |上次更新时间| +|open_devops |int |是否开启devops| +|forked_from_project_id |int |fork项目id| +|platform |string |项目平台| +|author.name |string |项目拥有者名称| +|author.type |string |项目拥有者类型| +|author.login |string |项目拥有者用户名| +|author.image_url |string |项目拥有者头像| +|category.name |string |项目分类名称| +|language.name |string |项目语言名称| + + +> 返回的JSON示例: + +```json +{ + "total_count": 1, + "projects": [ + { + "id": 89, + "repo_id": 89, + "identifier": "monkey", + "name": "boke", + "description": "dkkd", + "visits": 4, + "praises_count": 0, + "watchers_count": 0, + "issues_count": 0, + "pull_requests_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": "https://github.com/viletyy/monkey.git", + "type": 1, + "last_update_time": 1619685144, + "time_ago": "27天前", + "forked_from_project_id": null, + "open_devops": false, + "platform": "forge", + "author": { + "name": "测试组织", + "type": "Organization", + "login": "ceshi_org", + "image_url": "images/avatars/Organization/9?t=1612706073" + }, + "category": { + "id": 3, + "name": "深度学习" + }, + "language": { + "id": 2, + "name": "C" + } + } + ] +} +``` + + +## 用户添加星标项目 +用户添加星标项目 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/users/yystopf/is_pinned_projects/pin.json +``` + +```javascript +await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json') +``` + +### HTTP 请求 +`POST /api/users/:login/is_pinned_projects/pin.json` + +### 请求字段说明: +#### 同时设定多个星标项目 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|is_pinned_project_ids |array |设定为星标项目的id | + +#### 只设定一个星标项目 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|is_pinned_project_id |integer |设定为星标项目的id | + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` + + ## 获取用户贡献度 获取用户贡献度 diff --git a/app/models/pinned_project.rb b/app/models/pinned_project.rb new file mode 100644 index 000000000..8e47c9ea4 --- /dev/null +++ b/app/models/pinned_project.rb @@ -0,0 +1,22 @@ +# == Schema Information +# +# Table name: pinned_projects +# +# id :integer not null, primary key +# user_id :integer +# project_id :integer +# position :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_pinned_projects_on_project_id (project_id) +# index_pinned_projects_on_user_id (user_id) +# + +class PinnedProject < ApplicationRecord + + belongs_to :user + belongs_to :project +end diff --git a/app/models/project.rb b/app/models/project.rb index b48680830..9299abcdb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,76 +1,76 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(4294967295) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# license_id :integer -# ignore_id :integer -# default_branch :string(255) default("master") -# website :string(255) -# lesson_url :string(255) -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# - +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(4294967295) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# license_id :integer +# ignore_id :integer +# default_branch :string(255) default("master") +# website :string(255) +# lesson_url :string(255) +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + class Project < ApplicationRecord include Matchable @@ -114,6 +114,8 @@ class Project < ApplicationRecord has_many :team_projects, dependent: :destroy has_many :project_units, dependent: :destroy has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy + has_many :pinned_projects, dependent: :destroy + has_many :has_pinned_users, through: :pinned_projects, source: :user after_save :check_project_members scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} diff --git a/app/models/user.rb b/app/models/user.rb index b778c80f9..bac795dd5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -164,6 +164,9 @@ class User < Owner has_many :organization_users, dependent: :destroy has_many :organizations, through: :organization_users + has_many :pinned_projects, dependent: :destroy + has_many :is_pinned_projects, through: :pinned_projects, source: :project + accepts_nested_attributes_for :is_pinned_projects # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } @@ -195,6 +198,13 @@ class User < Owner validate :validate_sensitive_string validate :validate_password_length + # 用户参与的所有项目 + def full_member_projects + normal_projects = Project.members_projects(self.id).to_sql + org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: self.id}).to_sql + return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct + end + def name login end diff --git a/app/views/projects/_project_detail.json.jbuilder b/app/views/projects/_project_detail.json.jbuilder index d0b62aaa3..2e256fcb4 100644 --- a/app/views/projects/_project_detail.json.jbuilder +++ b/app/views/projects/_project_detail.json.jbuilder @@ -5,6 +5,9 @@ json.name project.name json.description Nokogiri::HTML(project.description).text json.visits project.visits json.praises_count project.praises_count.to_i +json.watchers_count project.watchers_count.to_i +json.issues_count project.issues_count.to_i +json.pull_requests_count project.pull_requests_count.to_i json.forked_count project.forked_count.to_i json.is_public project.is_public json.mirror_url project.repository&.mirror_url diff --git a/app/views/repositories/edit.json.jbuilder b/app/views/repositories/edit.json.jbuilder index 7a11411f4..e0b601f6d 100644 --- a/app/views/repositories/edit.json.jbuilder +++ b/app/views/repositories/edit.json.jbuilder @@ -12,4 +12,5 @@ json.permission render_permission(current_user, @project) json.is_transfering @project.is_transfering json.transfer do json.partial! "/users/user_simple", locals: {user: @project&.applied_transfer_project&.owner} -end \ No newline at end of file +end +json.is_pinned @project.has_pinned_users.include?(current_user) \ No newline at end of file diff --git a/app/views/users/is_pinned_projects/index.json.jbuilder b/app/views/users/is_pinned_projects/index.json.jbuilder new file mode 100644 index 000000000..facc158b9 --- /dev/null +++ b/app/views/users/is_pinned_projects/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @is_pinned_projects.total_count +json.projects @is_pinned_projects.each do |project| + json.partial! "projects/project_detail", project: project +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index ae121bb08..d61acaf8e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -266,6 +266,11 @@ Rails.application.routes.draw do end end resources :headmaps, only: [:index] + resources :is_pinned_projects, only: [:index] do + collection do + post :pin + end + end resources :organizations, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] diff --git a/db/migrate/20210527024043_create_pinned_projects.rb b/db/migrate/20210527024043_create_pinned_projects.rb new file mode 100644 index 000000000..50345cebc --- /dev/null +++ b/db/migrate/20210527024043_create_pinned_projects.rb @@ -0,0 +1,11 @@ +class CreatePinnedProjects < ActiveRecord::Migration[5.2] + def change + create_table :pinned_projects do |t| + t.references :user + t.references :project + t.integer :position, default: 0 + + t.timestamps + end + end +end diff --git a/public/docs/api.html b/public/docs/api.html index 9f52b9066..9bd9bb6ea 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -331,6 +331,12 @@
  • 获取当前登陆用户信息
  • +
  • + 获取用户星标项目 +
  • +
  • + 用户添加星标项目 +
  • 获取用户贡献度
  • @@ -590,7 +596,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -652,7 +658,235 @@ Success — a happy kitten is an authenticated kitten! -

    获取用户贡献度

    +

    获取用户星标项目

    +

    获取用户星标项目

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/is_pinned_projects.json
    +
    await octokit.request('GET /api/users/:login/is_pinned_projects.json')
    +

    HTTP 请求

    +

    GET api/users/:login/is_pinned_projects.json

    +

    返回字段说明:

    +
    参数
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_countint星标项目数量
    identifierstring项目标识
    namestring项目名称
    descriptionstring项目描述
    visitsint项目访问数量
    praises_countint项目点赞数量
    watchers_countint项目关注数量
    issues_countint项目issue数量
    pull_requests_countint项目合并请求数量
    forked_countint项目复刻数量
    is_publicbool项目是否公开
    mirror_urlstring镜像地址
    typeint项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目
    time_agostring上次更新时间
    open_devopsint是否开启devops
    forked_from_project_idintfork项目id
    platformstring项目平台
    author.namestring项目拥有者名称
    author.typestring项目拥有者类型
    author.loginstring项目拥有者用户名
    author.image_urlstring项目拥有者头像
    category.namestring项目分类名称
    language.namestring项目语言名称
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_count": 1,
    +    "projects": [
    +        {
    +            "id": 89,
    +            "repo_id": 89,
    +            "identifier": "monkey",
    +            "name": "boke",
    +            "description": "dkkd",
    +            "visits": 4,
    +            "praises_count": 0,
    +            "watchers_count": 0,
    +            "issues_count": 0,
    +            "pull_requests_count": 0,
    +            "forked_count": 0,
    +            "is_public": true,
    +            "mirror_url": "https://github.com/viletyy/monkey.git",
    +            "type": 1,
    +            "last_update_time": 1619685144,
    +            "time_ago": "27天前",
    +            "forked_from_project_id": null,
    +            "open_devops": false,
    +            "platform": "forge",
    +            "author": {
    +                "name": "测试组织",
    +                "type": "Organization",
    +                "login": "ceshi_org",
    +                "image_url": "images/avatars/Organization/9?t=1612706073"
    +            },
    +            "category": {
    +                "id": 3,
    +                "name": "深度学习"
    +            },
    +            "language": {
    +                "id": 2,
    +                "name": "C"
    +            }
    +        }
    +    ]
    +}
    +
    + +

    用户添加星标项目

    +

    用户添加星标项目

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/users/yystopf/is_pinned_projects/pin.json
    +
    await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json')
    +

    HTTP 请求

    +

    POST /api/users/:login/is_pinned_projects/pin.json

    +

    请求字段说明:

    同时设定多个星标项目

    + + + + + + + + + + + + +
    参数类型字段说明
    is_pinned_project_idsarray设定为星标项目的id
    +

    只设定一个星标项目

    + + + + + + + + + + + + +
    参数类型字段说明
    is_pinned_project_idinteger设定为星标项目的id
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "status": 0,
    +    "message": "success"
    +}
    +

    获取用户贡献度

    获取用户贡献度

    @@ -660,9 +894,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
     
    await octokit.request('GET /api/users/:login/headmaps.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/headmaps.json

    -

    返回字段说明:

    +

    返回字段说明:

    @@ -791,9 +1025,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -807,7 +1041,7 @@ Success — a happy kitten is an authenticated kitten!
    参数用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1028,9 +1262,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1044,7 +1278,7 @@ Success — a happy kitten is an authenticated kitten!
    参数用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1220,9 +1454,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1241,7 +1475,7 @@ Success — a happy kitten is an authenticated kitten!
    参数迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1411,9 +1645,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1432,7 +1666,7 @@ Success — a happy kitten is an authenticated kitten!
    参数迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    diff --git a/spec/models/pinned_project_spec.rb b/spec/models/pinned_project_spec.rb new file mode 100644 index 000000000..cda43562e --- /dev/null +++ b/spec/models/pinned_project_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe PinnedProject, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From ff1c80d1deed89146c583bc28d2f684195fc35f4 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 27 May 2021 16:40:15 +0800 Subject: [PATCH 166/643] add: user project trends --- .../users/is_pinned_projects_controller.rb | 3 ++- .../users/project_trends_controller.rb | 11 ++++++++++ .../users/statistics_controller.rb | 2 ++ .../issues/_simple_issue_item.json.jbuilder | 3 +++ .../project_trends/_detail.json.jbuilder | 17 ++++++++++++++++ app/views/project_trends/index.json.jbuilder | 20 ++----------------- .../users/project_trends/index.json.jbuilder | 4 ++++ config/routes.rb | 1 + 8 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 app/controllers/users/project_trends_controller.rb create mode 100644 app/controllers/users/statistics_controller.rb create mode 100644 app/views/project_trends/_detail.json.jbuilder create mode 100644 app/views/users/project_trends/index.json.jbuilder diff --git a/app/controllers/users/is_pinned_projects_controller.rb b/app/controllers/users/is_pinned_projects_controller.rb index 22ce29263..4f3f4e37e 100644 --- a/app/controllers/users/is_pinned_projects_controller.rb +++ b/app/controllers/users/is_pinned_projects_controller.rb @@ -18,9 +18,10 @@ class Users::IsPinnedProjectsController < Users::BaseController private def is_pinned_project_ids if params[:is_pinned_project_ids].present? - return params[:is_pinned_project_ids].select{|id| observed_user.full_member_projects.pluck(:id).include?(id.to_i) } + return params[:is_pinned_project_ids].select{|id| observed_user.full_member_projects.visible.pluck(:id).include?(id.to_i) } end if params[:is_pinned_project_id].present? + return observed_user.is_pinned_project_ids unless observed_user.full_member_projects.visible.pluck(:id).include?(params[:is_pinned_project_id].to_i) return observed_user.is_pinned_project_ids.include?(params[:is_pinned_project_id].to_i) ? observed_user.is_pinned_project_ids : observed_user.is_pinned_project_ids.push(params[:is_pinned_project_id].to_i) end end diff --git a/app/controllers/users/project_trends_controller.rb b/app/controllers/users/project_trends_controller.rb new file mode 100644 index 000000000..9edd56f18 --- /dev/null +++ b/app/controllers/users/project_trends_controller.rb @@ -0,0 +1,11 @@ +class Users::ProjectTrendsController < Users::BaseController + + def index + if params[:date].present? + @project_trends = observed_user.project_trends.where("DATE(created_at) = ?", params[:date]) + else + @project_trends = observed_user.project_trends + end + @project_trends = kaminari_paginate(@project_trends.includes(:trend, :project).order(created_at: :desc)) + end +end \ No newline at end of file diff --git a/app/controllers/users/statistics_controller.rb b/app/controllers/users/statistics_controller.rb new file mode 100644 index 000000000..82a3ef012 --- /dev/null +++ b/app/controllers/users/statistics_controller.rb @@ -0,0 +1,2 @@ +class Users::StatisticController < Users::BaseController +end \ No newline at end of file diff --git a/app/views/issues/_simple_issue_item.json.jbuilder b/app/views/issues/_simple_issue_item.json.jbuilder index f711253a4..3f9c22e9e 100644 --- a/app/views/issues/_simple_issue_item.json.jbuilder +++ b/app/views/issues/_simple_issue_item.json.jbuilder @@ -1,4 +1,7 @@ json.name issue.try(:subject) +json.issue_type issue.try(:issue_type) +json.status_id issue.try(:status_id) +json.priority_id issue.try(:priority_id) json.created_at format_time(issue.try(:created_on)) json.updated_at format_time(issue.try(:updated_on)) json.assign_user_name issue&.get_assign_user.try(:show_real_name) diff --git a/app/views/project_trends/_detail.json.jbuilder b/app/views/project_trends/_detail.json.jbuilder new file mode 100644 index 000000000..7ffa9f152 --- /dev/null +++ b/app/views/project_trends/_detail.json.jbuilder @@ -0,0 +1,17 @@ +json.id trend.id +json.trend_type trend.trend_type +json.action_type l("trend.#{trend.action_type}") + l("trend.#{trend.trend_type}") +json.trend_id trend.trend_id +json.user_name trend.user.try(:show_real_name) +json.user_login trend.user.login +json.user_avatar url_to_avatar(trend.user) +json.action_time time_from_now(trend.created_at) + +if trend.trend_type == "Issue" + json.partial! "issues/simple_issue_item", locals: {issue: trend.trend} +elsif trend.trend_type == "VersionRelease" + json.partial! "version_releases/simple_version_release", locals: {version: trend.trend} +else + json.name trend.trend.title + json.created_at format_time(trend.trend.created_at) +end diff --git a/app/views/project_trends/index.json.jbuilder b/app/views/project_trends/index.json.jbuilder index 159a3bdb8..6dca7bdb5 100644 --- a/app/views/project_trends/index.json.jbuilder +++ b/app/views/project_trends/index.json.jbuilder @@ -9,25 +9,9 @@ json.limit @limit json.project_trends_size @project_trends_size json.project_trends do json.array! @project_trends.to_a.each do |trend| - json.id trend.id - json.trend_type trend.trend_type - json.action_type l("trend.#{trend.action_type}") + l("trend.#{trend.trend_type}") - json.trend_id trend.trend_id - json.user_name trend.user.try(:show_real_name) - json.user_login trend.user.login - json.user_avatar url_to_avatar(trend.user) - - if trend.trend_type == "Issue" - json.partial! "issues/simple_issue_item", locals: {issue: trend.trend} - elsif trend.trend_type == "VersionRelease" - json.partial! "version_releases/simple_version_release", locals: {version: trend.trend} - else - json.name trend.trend.title - json.created_at format_time(trend.trend.created_at) - end - + #后续需要天际pullrequest 和 版本的内容 - + json.partial! "detail", trend: trend end end diff --git a/app/views/users/project_trends/index.json.jbuilder b/app/views/users/project_trends/index.json.jbuilder new file mode 100644 index 000000000..d1aab1390 --- /dev/null +++ b/app/views/users/project_trends/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @project_trends.total_count +json.project_trends @project_trends.each do |trend| + json.partial! "project_trends/detail", trend: trend +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index d61acaf8e..2363b89df 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -271,6 +271,7 @@ Rails.application.routes.draw do post :pin end end + resources :project_trends, only: [:index] resources :organizations, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] From 1df95eab4dfce6883fc12e4ca12a55cf96f87933 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 15:36:05 +0800 Subject: [PATCH 167/643] add: user statistics --- .../users/statistics_controller.rb | 190 +++++++++++++++++- app/models/concerns/project_operable.rb | 1 + app/models/project.rb | 1 - app/models/user.rb | 4 +- .../projects/_project_detail.json.jbuilder | 1 + app/views/users/headmaps/index.json.jbuilder | 2 +- .../users/statistics/develop.json.jbuilder | 19 ++ app/views/users/statistics/role.json.jbuilder | 19 ++ config/routes.rb | 8 + 9 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 app/views/users/statistics/develop.json.jbuilder create mode 100644 app/views/users/statistics/role.json.jbuilder diff --git a/app/controllers/users/statistics_controller.rb b/app/controllers/users/statistics_controller.rb index 82a3ef012..7ab9a4bf4 100644 --- a/app/controllers/users/statistics_controller.rb +++ b/app/controllers/users/statistics_controller.rb @@ -1,2 +1,190 @@ -class Users::StatisticController < Users::BaseController +class Users::StatisticsController < Users::BaseController + before_action :preload_develop_data, only: [:develop] + + # 近期活动统计 + def activity + date_range = (1.week.ago.to_date..Date.today).to_a + commit_request = Gitea::User::HeadmapService.call(observed_user.login, 1.week.ago.to_date.to_time.to_i, Date.today.to_time.to_i) + commit_data = commit_request[2] + @date_data = [] + @issue_data = [] + @pull_request_data = [] + @commit_data = [] + date_range.each do |date| + @date_data << date.strftime("%Y.%m.%d") + @issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size + @pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size + date_commit_data = commit_data.select{|item| item["timestamp"] == date.to_time.to_i} + @commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i) + end + render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commtis_count: @commit_data} + end + + # 开发能力 + def develop + if params[:start_time].present? && params[:end_time].present? + # 影响力 + @influence = (60.0 + @follow_count / (@follow_count + 10.0) * 40.0).to_i + @platform_influence = (60.0 + @platform_follow_count / (@platform_follow_count + 10.0) * 40.0).to_i + # 贡献度 + @contribution = (60.0 + @pullrequest_count / (@pullrequest_count + 10.0) * 40.0).to_i + @platform_contribution = (60.0 + @platform_pullrequest_count / (@platform_pullrequest_count + 10.0) * 40.0).to_i + # 活跃度 + @activity = (60.0 + @issues_count / (@issues_count + 10.0) * 40.0).to_i + @platform_activity = (60.0 + @platform_issues_count / (@platform_issues_count + 10.0) * 40.0).to_i + # 项目经验 + @experience = 10 * @project_count + 5 * @fork_count + @project_watchers_count + @project_praises_count + @experience = (60.0 + @experience / (@experience + 100.0) * 40.0).to_i + @platform_experience = 10 * @platform_project_count + 5 * @platform_fork_count + @platform_project_watchers_count + @platform_project_praises_count + @platform_experience = (60.0 + @platform_experience / (@platform_experience + 100.0) * 40.0).to_i + # 语言能力 + @language = (60.0 + @project_languages_count.length / (@project_languages_count.length + 5.0) * 40.0).to_i + @platform_language = (60.0 + @platform_project_languages_count.length / (@platform_project_languages_count.length + 5.0) * 40.0).to_i + # 语言百分比 + @languages_percent = Hash.new + for key in @project_languages_count.keys do + @languages_percent[key] = (@project_languages_count[key].to_f / @project_languages_count.values.sum).round(2) + end + @platform_languages_percent = Hash.new + for key in @platform_project_languages_count.keys do + @platform_languages_percent[key] = (@platform_project_languages_count[key].to_f / @platform_project_languages_count.values.sum).round(2) + end + # 各门语言分数 + @each_language_score = Hash.new + for key in @project_languages_count.keys do + @each_language_score[key] = (60.0 + @project_languages_count[key] / (@project_languages_count[key] + 5.0) * 40.0).to_i + end + @platform_each_language_score = Hash.new + for key in @platform_project_languages_count.keys do + @platform_each_language_score[key] = (60.0 + @platform_project_languages_count[key] / (@platform_project_languages_count[key] + 5.0) * 40.0).to_i + end + else + # 影响力 + @influence = (60.0 + @follow_count / (@follow_count + 20.0) * 40.0).to_i + @platform_influence = (60.0 + @platform_follow_count / (@platform_follow_count + 20.0) * 40.0).to_i + + # 贡献度 + @contribution = (60.0 + @pullrequest_count / (@pullrequest_count + 20.0) * 40.0).to_i + @platform_contribution = (60.0 + @platform_pullrequest_count / (@platform_pullrequest_count + 20.0) * 40.0).to_i + + # 活跃度 + @activity = (60.0 + @issues_count / (@issues_count + 80.0) * 40.0).to_i + @platform_activity = (60.0 + @platform_issues_count / (@platform_issues_count + 80.0) * 40.0).to_i + + # 项目经验 + @experience = 10 * @project_count + 5 * @fork_count + @project_watchers_count + @project_praises_count + @experience = (60.0 + @experience / (@experience + 100.0) * 40.0).to_i + @platform_experience = 10 * @platform_project_count + 5 * @platform_fork_count + @platform_project_watchers_count + @platform_project_praises_count + @platform_experience = (60.0 + @platform_experience / (@platform_experience + 100.0) * 40.0).to_i + # 语言能力 + @language = (60.0 + @project_languages_count.length / (@project_languages_count.length + 5.0) * 40.0).to_i + @platform_language = (60.0 + @platform_project_languages_count.length / (@platform_project_languages_count.length + 5.0) * 40.0).to_i + + # 语言百分比 + @languages_percent = Hash.new + for key in @project_languages_count.keys do + @languages_percent[key] = (@project_languages_count[key].to_f / @project_languages_count.values.sum).round(2) + end + @platform_languages_percent = Hash.new + for key in @platform_project_languages_count.keys do + @platform_languages_percent[key] = (@platform_project_languages_count[key].to_f / @platform_project_languages_count.values.sum).round(2) + end + # 各门语言分数 + @each_language_score = Hash.new + for key in @project_languages_count.keys do + @each_language_score[key] = (60.0 + @project_languages_count[key] / (@project_languages_count[key] + 5.0) * 40.0).to_i + end + @platform_each_language_score = Hash.new + for key in @platform_project_languages_count.keys do + @platform_each_language_score[key] = (60.0 + @platform_project_languages_count[key] / (@platform_project_languages_count[key] + 5.0) * 40.0).to_i + end + end + + end + + # 角色定位 + def role + full_member_projects = observed_user.full_member_projects + owner_projects = filter_member_projects_by_role("Owner") + manager_projects = filter_member_projects_by_role("Manager").where.not(id: owner_projects.ids) + developer_projects = filter_member_projects_by_role("Developer").where.not(id: owner_projects.ids + manager_projects.ids) + reporter_projects = filter_member_projects_by_role("Reporter").where.not(id: owner_projects.ids + manager_projects.ids + developer_projects.ids) + + @full_member_projects_count = full_member_projects.size + @owner_projects_count = owner_projects.size + @manager_projects_count = manager_projects.size + @developer_projects_count = developer_projects.size + @reporter_projects_count = reporter_projects.size + + end + + # 专业定位 + def major + # 参与项目 + join_normal_projects_sql = Project.members_projects(observed_user.id).to_sql + join_org_projects_sql = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: observed_user.id}).to_sql + # 关注项目 + star_projects_sql = Project.joins(:watchers).where(watchers: {watchable_type: "Project", user_id: observed_user.id}).to_sql + # fork项目 + fork_projects_sql = Project.where(id: observed_user.fork_users.select(:id, :fork_project_id).pluck(:fork_project_id)).to_sql + major_projects = Project.from("( #{ join_normal_projects_sql} UNION #{ join_org_projects_sql } UNION #{ star_projects_sql } UNION #{fork_projects_sql}) AS projects").distinct + categories = ProjectCategory.joins(:projects).merge(Project.where(id: time_filter(major_projects, 'created_on'))).distinct.pluck(:name) + render :json => {categories: categories} + end + + private + def time_filter(collection, time_field) + if params[:start_time].present? && params[:end_time].present? + return collection.where("#{time_field} > ? AND #{time_field} < ?", Time.at(params[:start_time].to_i).beginning_of_day, Time.at(params[:end_time].to_i).end_of_day) + else + return collection + end + rescue + return collection + end + + def filter_member_projects_by_role(role) + case role + when 'Owner' + normal_projects_sql = Project.joins(members: :roles).where(user_id: observed_user.id).where(members: {user_id: observed_user.id}, roles: {name: 'Manager'}).to_sql + org_projects_sql = Project.joins(:owner, teams: :team_users).where(users: {type: 'Organization'}, teams: {authorize: "owner"}, team_users: {user_id: observed_user.id}).to_sql + when "Manager" + normal_projects_sql = Project.joins(members: :roles).where.not(user_id: observed_user.id).where(members: {user_id: observed_user.id}, roles: {name: 'Manager'}).to_sql + org_projects_sql = Project.joins(:owner, teams: :team_users).where(users: {type: 'Organization'}, teams: {authorize: "admin"}, team_users: {user_id: observed_user.id}).to_sql + when "Developer" + normal_projects_sql = Project.joins(members: :roles).where.not(user_id: observed_user.id).where(members: {user_id: observed_user.id}, roles: {name: 'Developer'}).to_sql + org_projects_sql = Project.joins(:owner, teams: :team_users).where(users: {type: 'Organization'}, teams: {authorize: "write"}, team_users: {user_id: observed_user.id}).to_sql + when "Reporter" + normal_projects_sql = Project.joins(members: :roles).where.not(user_id: observed_user.id).where(members: {user_id: observed_user.id}, roles: {name: 'Reporter'}).to_sql + org_projects_sql = Project.joins(:owner, teams: :team_users).where(users: {type: 'Organization'}, teams: {authorize: "read"}, team_users: {user_id: observed_user.id}).to_sql + end + return time_filter(Project.from("( #{normal_projects_sql} UNION #{org_projects_sql} ) AS projects").distinct, 'created_on') + end + + def preload_develop_data + # 用户被follow数量 + @follow_count = time_filter(Watcher.where(watchable: observed_user), 'created_at').count + @platform_follow_count = time_filter(Watcher.where(watchable_type: 'User'), 'created_at').count + # 用户pr数量 + @pullrequest_count = time_filter(PullRequest.where(user_id: observed_user.id), 'created_at').count + @platform_pullrequest_count = time_filter(PullRequest, 'created_at').count + # 用户issue数量 + @issues_count = time_filter(Issue.where(author_id: observed_user.id), 'created_on').count + @platform_issues_count = time_filter(Issue, 'created_on').count + # 用户总项目数 @fork_count + @project_watchers_count + @project_praises_count + @project_count = filter_member_projects_by_role("Owner").count + @platform_project_count = time_filter(Project, 'created_on').count + # 用户项目被fork数量 + @fork_count = filter_member_projects_by_role("Owner").sum("forked_count") + @platform_fork_count = time_filter(Project, 'created_on').sum("forked_count") + # 用户项目关注数 + @project_watchers_count = filter_member_projects_by_role("Owner").sum("watchers_count") + @platform_project_watchers_count = time_filter(Project, 'created_on').sum("watchers_count") + # 用户项目点赞数 + @project_praises_count = filter_member_projects_by_role("Owner").sum("praises_count") + @platform_project_praises_count = time_filter(Project, 'created_on').sum("praises_count") + # 用户不同语言项目数量 + @project_languages_count = filter_member_projects_by_role("Owner").joins(:project_language).group("project_languages.name").count + @platform_project_languages_count = time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count + end end \ No newline at end of file diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index b8adf5c8a..e016ca1dc 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -9,6 +9,7 @@ module ProjectOperable has_many :reporters, -> { joins(:roles).where(roles: { name: 'Reporter' }) }, class_name: 'Member' has_many :writable_members, -> { joins(:roles).where.not(roles: {name: 'Reporter'}) }, class_name: 'Member' has_many :team_projects, dependent: :destroy + has_many :teams, through: :team_projects, source: :team end def set_owner_permission(creator) diff --git a/app/models/project.rb b/app/models/project.rb index 9299abcdb..8141a56bf 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -111,7 +111,6 @@ class Project < ApplicationRecord has_many :praise_treads, as: :praise_tread_object, dependent: :destroy has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position" has_one :project_detail, dependent: :destroy - has_many :team_projects, dependent: :destroy has_many :project_units, dependent: :destroy has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy has_many :pinned_projects, dependent: :destroy diff --git a/app/models/user.rb b/app/models/user.rb index bac795dd5..56043f5f6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -167,6 +167,8 @@ class User < Owner has_many :pinned_projects, dependent: :destroy has_many :is_pinned_projects, through: :pinned_projects, source: :project accepts_nested_attributes_for :is_pinned_projects + has_many :issues, dependent: :destroy, foreign_key: :author_id + has_many :pull_requests, dependent: :destroy # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } @@ -201,7 +203,7 @@ class User < Owner # 用户参与的所有项目 def full_member_projects normal_projects = Project.members_projects(self.id).to_sql - org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: self.id}).to_sql + org_projects = Project.joins(teams: :team_users).where(team_users: {user_id: self.id}).to_sql return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct end diff --git a/app/views/projects/_project_detail.json.jbuilder b/app/views/projects/_project_detail.json.jbuilder index 2e256fcb4..da5d67473 100644 --- a/app/views/projects/_project_detail.json.jbuilder +++ b/app/views/projects/_project_detail.json.jbuilder @@ -17,6 +17,7 @@ json.time_ago time_from_now(project.updated_on) json.forked_from_project_id project.forked_from_project_id json.open_devops project.open_devops? json.platform project.platform +json.is_pinned @project.has_pinned_users.include?(current_user) json.author do if project.educoder? project_educoder = project.project_educoder diff --git a/app/views/users/headmaps/index.json.jbuilder b/app/views/users/headmaps/index.json.jbuilder index 7011b2559..0e6a540b5 100644 --- a/app/views/users/headmaps/index.json.jbuilder +++ b/app/views/users/headmaps/index.json.jbuilder @@ -1,5 +1,5 @@ json.total_contributions @headmaps.collect{|map| map["contributions"]}.reduce(0, :+) json.headmaps @headmaps.each do |map| - json.date map["timestamp"] + json.date Time.at(map["timestamp"].to_i).strftime("%Y-%m-%d") json.contributions map["contributions"] end diff --git a/app/views/users/statistics/develop.json.jbuilder b/app/views/users/statistics/develop.json.jbuilder new file mode 100644 index 000000000..9d530fbbe --- /dev/null +++ b/app/views/users/statistics/develop.json.jbuilder @@ -0,0 +1,19 @@ +json.platform do + json.influence @platform_influence + json.contribution @platform_contribution + json.activity @platform_activity + json.experience @platform_experience + json.language @platform_language + json.languages_percent @platform_languages_percent + json.each_language_score @platform_each_language_score +end + +json.user do + json.influence @influence + json.contribution @contribution + json.activity @activity + json.experience @experience + json.language @language + json.languages_percent @languages_percent + json.each_language_score @each_language_score +end \ No newline at end of file diff --git a/app/views/users/statistics/role.json.jbuilder b/app/views/users/statistics/role.json.jbuilder new file mode 100644 index 000000000..5ca290586 --- /dev/null +++ b/app/views/users/statistics/role.json.jbuilder @@ -0,0 +1,19 @@ +json.total_projects_count @full_member_projects_count +json.role do + json.owner do + json.count @owner_projects_count + json.percent (@owner_projects_count.to_f/@full_member_projects_count).round(2) + end + json.manager do + json.count @manager_projects_count + json.percent (@manager_projects_count.to_f/@full_member_projects_count).round(2) + end + json.developer do + json.count @developer_projects_count + json.percent (@developer_projects_count.to_f/@full_member_projects_count).round(2) + end + json.reporter do + json.count @reporter_projects_count + json.percent (@reporter_projects_count.to_f/@full_member_projects_count).round(2) + end +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 2363b89df..cfadf4941 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -271,6 +271,14 @@ Rails.application.routes.draw do post :pin end end + resources :statistics, only: [:index] do + collection do + get :activity + get :develop + get :role + get :major + end + end resources :project_trends, only: [:index] resources :organizations, only: [:index] # resources :projects, only: [:index] From 61b19c17459d13cbdc8c33f68ad621e98524fde3 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 16:04:52 +0800 Subject: [PATCH 168/643] uupdate: api docs --- .../users/statistics_controller.rb | 2 +- app/docs/slate/source/includes/_users.md | 609 +++++++++++++- public/docs/api.html | 795 +++++++++++++++++- 3 files changed, 1346 insertions(+), 60 deletions(-) diff --git a/app/controllers/users/statistics_controller.rb b/app/controllers/users/statistics_controller.rb index 7ab9a4bf4..d508176e2 100644 --- a/app/controllers/users/statistics_controller.rb +++ b/app/controllers/users/statistics_controller.rb @@ -17,7 +17,7 @@ class Users::StatisticsController < Users::BaseController date_commit_data = commit_data.select{|item| item["timestamp"] == date.to_time.to_i} @commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i) end - render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commtis_count: @commit_data} + render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data} end # 开发能力 diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index b2c3ebccb..d7e8ed488 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -176,6 +176,82 @@ await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json') ``` +## 用户近期活动统计 +用户近期活动统计, 默认显示近一周的数据 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/statistics/activity.json +``` + +```javascript +await octokit.request('GET /api/users/:login/statistics/activity.json') +``` + +### HTTP 请求 +`GET /api/users/:login/statistics/activity.json` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|dates |array |时间 | +|issues_count |array |易修数量| +|pull_requests_count |array |合并请求数量| +|commtis_count |array |贡献数量| + + +> 返回的JSON示例: + +```json +{ + "dates": [ + "2021.05.21", + "2021.05.22", + "2021.05.23", + "2021.05.24", + "2021.05.25", + "2021.05.26", + "2021.05.27", + "2021.05.28" + ], + "issues_count": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "pull_requests_count": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "commits_count": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] +} +``` + + + ## 获取用户贡献度 获取用户贡献度 @@ -192,6 +268,12 @@ await octokit.request('GET /api/users/:login/headmaps.json') ### HTTP 请求 `GET api/users/:login/headmaps.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|year |string |年份 | + ### 返回字段说明: 参数 | 类型 | 字段说明 --------- | ----------- | ----------- @@ -207,87 +289,87 @@ await octokit.request('GET /api/users/:login/headmaps.json') "total_contributions": 139, "headmaps": [ { - "date": 1612627200, + "date": "2021-02-07", "contributions": 1 }, { - "date": 1613836800, + "date": "2021-02-21", "contributions": 13 }, { - "date": 1614182400, + "date": "2021-02-25", "contributions": 5 }, { - "date": 1614528000, + "date": "2021-03-01", "contributions": 2 }, { - "date": 1614787200, + "date": "2021-03-04", "contributions": 1 }, { - "date": 1615737600, + "date": "2021-03-15", "contributions": 9 }, { - "date": 1616342400, + "date": "2021-03-22", "contributions": 14 }, { - "date": 1616515200, + "date": "2021-03-24", "contributions": 1 }, { - "date": 1617033600, + "date": "2021-03-30", "contributions": 11 }, { - "date": 1617638400, + "date": "2021-04-06", "contributions": 1 }, { - "date": 1618156800, + "date": "2021-04-12", "contributions": 1 }, { - "date": 1618243200, + "date": "2021-04-13", "contributions": 2 }, { - "date": 1618761600, + "date": "2021-04-19", "contributions": 3 }, { - "date": 1619107200, + "date": "2021-04-23", "contributions": 37 }, { - "date": 1619280000, + "date": "2021-04-25", "contributions": 2 }, { - "date": 1619366400, + "date": "2021-04-26", "contributions": 6 }, { - "date": 1619539200, + "date": "2021-04-28", "contributions": 1 }, { - "date": 1619625600, + "date": "2021-04-29", "contributions": 18 }, { - "date": 1619712000, + "date": "2021-04-30", "contributions": 9 }, { - "date": 1620057600, + "date": "2021-05-04", "contributions": 1 }, { - "date": 1620230400, + "date": "2021-05-06", "contributions": 1 } ] @@ -297,6 +379,489 @@ await octokit.request('GET /api/users/:login/headmaps.json') Success Data. +## 获取用户动态 +获取用户动态 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/project_trends.json +``` + +```javascript +await octokit.request('GET /api/users/:login/project_trends.json') +``` + +### HTTP 请求 +`GET api/users/:login/project_trends.json` + + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|date |string |日期,格式: 2021-05-28 | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_count |int |所选时间内的总动态数 | +|project_trends.trend_type |string|动态类型,Issue:易修,VersionRelease:版本发布,PullRequest:合并请求| +|project_trends.action_type |string|操作类型| +|project_trends.trend_id |integer|动态id| +|project_trends.user_name |string|用户名称| +|project_trends.user_login |string|用户用户名| +|project_trends.user_avatar |string|用户头像| +|project_trends.action_time |string|操作时间| +|project_trends.name |string|动态标题| + +> 返回的JSON示例: + +```json +{ + "total_count": 16, + "project_trends": [ + { + "id": 27, + "trend_type": "Issue", + "action_type": "创建了工单", + "trend_id": 18, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "21天前", + "name": "31213123123", + "issue_type": "1", + "status_id": 2, + "priority_id": 4, + "created_at": "2021-05-07 15:39", + "updated_at": "2021-05-27 15:42", + "assign_user_name": "yystopf", + "assign_user_login": "yystopf", + "issue_journal_size": 1, + "issue_journals": [] + }, + { + "id": 8, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 8, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "24天前", + "name": "heihei1", + "tag_name": "v1.0", + "target_commitish": "master", + "tarball_url": "http://localhost:10080/forgeceshiorg1/ceshi1/archive/v1.0.tar.gz", + "zipball_url": "http://localhost:10080/forgeceshiorg1/ceshi1/archive/v1.0.zip", + "url": "http://localhost:10080/api/v1/repos/forgeceshiorg1/ceshi1/releases/84", + "version_gid": "84", + "created_at": "2021-05-04 12:04" + }, + { + "id": 25, + "trend_type": "PullRequest", + "action_type": "关闭了合并请求", + "trend_id": 14, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "13", + "created_at": "2021-04-30 15:39" + }, + { + "id": 24, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 13, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "211212", + "created_at": "2021-04-30 15:37" + }, + { + "id": 23, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 12, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "奇偶哦iu", + "created_at": "2021-04-30 10:19" + }, + { + "id": 22, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 11, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "2112123", + "created_at": "2021-04-29 18:46" + }, + { + "id": 21, + "trend_type": "PullRequest", + "action_type": "关闭了合并请求", + "trend_id": 10, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "23123", + "created_at": "2021-04-29 18:45" + }, + { + "id": 20, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 9, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "33", + "created_at": "2021-04-29 18:37" + }, + { + "id": 19, + "trend_type": "PullRequest", + "action_type": "关闭了合并请求", + "trend_id": 8, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "gggg", + "created_at": "2021-04-29 17:51" + }, + { + "id": 16, + "trend_type": "Issue", + "action_type": "创建了工单", + "trend_id": 8, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "1个月前", + "name": "hjhkj", + "issue_type": "1", + "status_id": 1, + "priority_id": 2, + "created_at": "2021-04-19 10:52", + "updated_at": "2021-04-19 10:52", + "assign_user_name": null, + "assign_user_login": null, + "issue_journal_size": 0, + "issue_journals": [] + }, + { + "id": 7, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 7, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "1个月前", + "name": "v3.0.1", + "tag_name": "v3.0.1", + "target_commitish": "master", + "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.1.tar.gz", + "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.1.zip", + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/78", + "version_gid": "78", + "created_at": "2021-03-30 15:51" + }, + { + "id": 6, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 6, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "1个月前", + "name": "v3.0.0", + "tag_name": "v3.0.0", + "target_commitish": "master", + "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.0.tar.gz", + "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.0.zip", + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/77", + "version_gid": "77", + "created_at": "2021-03-30 15:33" + }, + { + "id": 5, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 5, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "1个月前", + "name": "v1.0.0", + "tag_name": "v1.0.0", + "target_commitish": "master", + "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v1.0.0.tar.gz", + "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v1.0.0.zip", + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/76", + "version_gid": "76", + "created_at": "2021-03-30 15:27" + }, + { + "id": 2, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 2, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "2个月前", + "name": "vvvv", + "tag_name": "v1.1", + "target_commitish": "dev", + "tarball_url": "http://localhost:10080/yystopf/virus_blog/archive/v1.1.tar.gz", + "zipball_url": "http://localhost:10080/yystopf/virus_blog/archive/v1.1.zip", + "url": "http://localhost:10080/api/v1/repos/yystopf/virus_blog/releases/6", + "version_gid": "6", + "created_at": "2021-03-15 14:18" + }, + { + "id": 2, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 2, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "3个月前", + "name": "444", + "created_at": "2021-02-25 17:31" + } + ] +} +``` + + +## 用户开发能力 +用户开发能力, 默认为所有时间下的开发能力 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/statistics/develop.json +``` + +```javascript +await octokit.request('GET /api/users/:login/statistics/develop.json') +``` + +### HTTP 请求 +`GET /api/users/:login/statistics/develop.json` + + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|start_time |integer |时间戳,开始时间,格式:1621526400| +|end_time |integer |时间戳,结束时间,格式:1622131200| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|influence |int |影响力 | +|contribution |int |贡献度| +|activity |int |活跃度| +|experience |int |项目经验| +|language |int |语言能力| +|languages_percent |float |语言百分比| +|each_language_score |int |各门语言分数| + + +> 返回的JSON示例: + +```json +{ + "platform": { + "influence": 61, + "contribution": 75, + "activity": 66, + "experience": 95, + "language": 87, + "languages_percent": { + "CSS": 0.03, + "C#": 0.13, + "Ruby": 0.04, + "Go": 0.05, + "C": 0.19, + "Java": 0.34, + "Python": 0.09, + "C+": 0.01, + "C++": 0.11, + "Scala": 0.01, + "HTML": 0.01 + }, + "each_language_score": { + "CSS": 71, + "C#": 86, + "Ruby": 75, + "Go": 77, + "C": 90, + "Java": 93, + "Python": 83, + "C+": 66, + "C++": 85, + "Scala": 66, + "HTML": 66 + } + }, + "user": { + "influence": 60, + "contribution": 72, + "activity": 65, + "experience": 88, + "language": 84, + "languages_percent": { + "C": 0.25, + "C#": 0.33, + "C++": 0.13, + "CSS": 0.08, + "Go": 0.04, + "HTML": 0.04, + "Java": 0.04, + "Ruby": 0.08 + }, + "each_language_score": { + "C": 81, + "C#": 84, + "C++": 75, + "CSS": 71, + "Go": 66, + "HTML": 66, + "Java": 66, + "Ruby": 71 + } + } +} +``` + + +## 用户角色定位 +用户角色定位,默认显示所有时间下的角色定位数据 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/statistics/role.json +``` + +```javascript +await octokit.request('GET /api/users/:login/statistics/role.json') +``` + +### HTTP 请求 +`GET /api/users/:login/statistics/role.json` + + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|start_time |integer |时间戳,开始时间,格式:1621526400| +|end_time |integer |时间戳,结束时间,格式:1622131200| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_projects_count |int |用户所有的项目数量 | +|role.object.count |int |用户该语言下的项目数量| +|role.object.percent |float |用户该语言下的项目占比| + +> 返回的JSON示例: + +```json +{ + "total_projects_count": 27, + "role": { + "owner": { + "count": 24, + "percent": 0.89 + }, + "manager": { + "count": 1, + "percent": 0.04 + }, + "developer": { + "count": 2, + "percent": 0.07 + }, + "reporter": { + "count": 0, + "percent": 0.0 + } + } +} +``` + + +## 用户专业定位 +用户专业定位,默认显示所有时间下的专业定位数据 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/statistics/major.json +``` + +```javascript +await octokit.request('GET /api/users/:login/statistics/major.json') +``` + +### HTTP 请求 +`GET /api/users/:login/statistics/major.json` + + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|start_time |integer |时间戳,开始时间,格式:1621526400| +|end_time |integer |时间戳,结束时间,格式:1622131200| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|categories |int |用户项目分类 | + +> 返回的JSON示例: + +```json +{ + "categories": [ + "大数据", + "机器学习", + "深度学习", + "人工智能", + "智慧医疗", + "云计算" + ] +} +``` + ## 待办事项-用户通知信息 待办事项-用户通知信息 diff --git a/public/docs/api.html b/public/docs/api.html index 9bd9bb6ea..616803e4e 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -337,9 +337,24 @@
  • 用户添加星标项目
  • +
  • + 用户近期活动统计 +
  • 获取用户贡献度
  • +
  • + 获取用户动态 +
  • +
  • + 用户开发能力 +
  • +
  • + 用户角色定位 +
  • +
  • + 用户专业定位 +
  • 待办事项-用户通知信息
  • @@ -596,7 +611,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -886,7 +901,96 @@ Success — a happy kitten is an authenticated kitten! "status": 0, "message": "success" } -

    获取用户贡献度

    +

    用户近期活动统计

    +

    用户近期活动统计, 默认显示近一周的数据

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/activity.json
    +
    await octokit.request('GET /api/users/:login/statistics/activity.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/statistics/activity.json

    +

    返回字段说明:

    +
    参数
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    datesarray时间
    issues_countarray易修数量
    pull_requests_countarray合并请求数量
    commtis_countarray贡献数量
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "dates": [
    +        "2021.05.21",
    +        "2021.05.22",
    +        "2021.05.23",
    +        "2021.05.24",
    +        "2021.05.25",
    +        "2021.05.26",
    +        "2021.05.27",
    +        "2021.05.28"
    +    ],
    +    "issues_count": [
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0
    +    ],
    +    "pull_requests_count": [
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0
    +    ],
    +    "commits_count": [
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0
    +    ]
    +}
    +
    + +

    获取用户贡献度

    获取用户贡献度

    @@ -894,9 +998,23 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
     
    await octokit.request('GET /api/users/:login/headmaps.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/headmaps.json

    -

    返回字段说明:

    +

    请求字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    yearstring年份
    +

    返回字段说明:

    @@ -928,87 +1046,87 @@ Success — a happy kitten is an authenticated kitten! "total_contributions": 139, "headmaps": [ { - "date": 1612627200, + "date": "2021-02-07", "contributions": 1 }, { - "date": 1613836800, + "date": "2021-02-21", "contributions": 13 }, { - "date": 1614182400, + "date": "2021-02-25", "contributions": 5 }, { - "date": 1614528000, + "date": "2021-03-01", "contributions": 2 }, { - "date": 1614787200, + "date": "2021-03-04", "contributions": 1 }, { - "date": 1615737600, + "date": "2021-03-15", "contributions": 9 }, { - "date": 1616342400, + "date": "2021-03-22", "contributions": 14 }, { - "date": 1616515200, + "date": "2021-03-24", "contributions": 1 }, { - "date": 1617033600, + "date": "2021-03-30", "contributions": 11 }, { - "date": 1617638400, + "date": "2021-04-06", "contributions": 1 }, { - "date": 1618156800, + "date": "2021-04-12", "contributions": 1 }, { - "date": 1618243200, + "date": "2021-04-13", "contributions": 2 }, { - "date": 1618761600, + "date": "2021-04-19", "contributions": 3 }, { - "date": 1619107200, + "date": "2021-04-23", "contributions": 37 }, { - "date": 1619280000, + "date": "2021-04-25", "contributions": 2 }, { - "date": 1619366400, + "date": "2021-04-26", "contributions": 6 }, { - "date": 1619539200, + "date": "2021-04-28", "contributions": 1 }, { - "date": 1619625600, + "date": "2021-04-29", "contributions": 18 }, { - "date": 1619712000, + "date": "2021-04-30", "contributions": 9 }, { - "date": 1620057600, + "date": "2021-05-04", "contributions": 1 }, { - "date": 1620230400, + "date": "2021-05-06", "contributions": 1 } ] @@ -1017,6 +1135,609 @@ Success — a happy kitten is an authenticated kitten! +

    获取用户动态

    +

    获取用户动态

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/project_trends.json
    +
    await octokit.request('GET /api/users/:login/project_trends.json')
    +

    HTTP 请求

    +

    GET api/users/:login/project_trends.json

    +

    请求字段说明:

    +
    参数
    + + + + + + + + + + + +
    参数类型字段说明
    datestring日期,格式: 2021-05-28
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_countint所选时间内的总动态数
    project_trends.trend_typestring动态类型,Issue:易修,VersionRelease:版本发布,PullRequest:合并请求
    project_trends.action_typestring操作类型
    project_trends.trend_idinteger动态id
    project_trends.user_namestring用户名称
    project_trends.user_loginstring用户用户名
    project_trends.user_avatarstring用户头像
    project_trends.action_timestring操作时间
    project_trends.namestring动态标题
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_count": 16,
    +    "project_trends": [
    +        {
    +            "id": 27,
    +            "trend_type": "Issue",
    +            "action_type": "创建了工单",
    +            "trend_id": 18,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "21天前",
    +            "name": "31213123123",
    +            "issue_type": "1",
    +            "status_id": 2,
    +            "priority_id": 4,
    +            "created_at": "2021-05-07 15:39",
    +            "updated_at": "2021-05-27 15:42",
    +            "assign_user_name": "yystopf",
    +            "assign_user_login": "yystopf",
    +            "issue_journal_size": 1,
    +            "issue_journals": []
    +        },
    +        {
    +            "id": 8,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 8,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "24天前",
    +            "name": "heihei1",
    +            "tag_name": "v1.0",
    +            "target_commitish": "master",
    +            "tarball_url": "http://localhost:10080/forgeceshiorg1/ceshi1/archive/v1.0.tar.gz",
    +            "zipball_url": "http://localhost:10080/forgeceshiorg1/ceshi1/archive/v1.0.zip",
    +            "url": "http://localhost:10080/api/v1/repos/forgeceshiorg1/ceshi1/releases/84",
    +            "version_gid": "84",
    +            "created_at": "2021-05-04 12:04"
    +        },
    +        {
    +            "id": 25,
    +            "trend_type": "PullRequest",
    +            "action_type": "关闭了合并请求",
    +            "trend_id": 14,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "13",
    +            "created_at": "2021-04-30 15:39"
    +        },
    +        {
    +            "id": 24,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 13,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "211212",
    +            "created_at": "2021-04-30 15:37"
    +        },
    +        {
    +            "id": 23,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 12,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "奇偶哦iu",
    +            "created_at": "2021-04-30 10:19"
    +        },
    +        {
    +            "id": 22,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 11,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "2112123",
    +            "created_at": "2021-04-29 18:46"
    +        },
    +        {
    +            "id": 21,
    +            "trend_type": "PullRequest",
    +            "action_type": "关闭了合并请求",
    +            "trend_id": 10,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "23123",
    +            "created_at": "2021-04-29 18:45"
    +        },
    +        {
    +            "id": 20,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 9,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "33",
    +            "created_at": "2021-04-29 18:37"
    +        },
    +        {
    +            "id": 19,
    +            "trend_type": "PullRequest",
    +            "action_type": "关闭了合并请求",
    +            "trend_id": 8,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "gggg",
    +            "created_at": "2021-04-29 17:51"
    +        },
    +        {
    +            "id": 16,
    +            "trend_type": "Issue",
    +            "action_type": "创建了工单",
    +            "trend_id": 8,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "1个月前",
    +            "name": "hjhkj",
    +            "issue_type": "1",
    +            "status_id": 1,
    +            "priority_id": 2,
    +            "created_at": "2021-04-19 10:52",
    +            "updated_at": "2021-04-19 10:52",
    +            "assign_user_name": null,
    +            "assign_user_login": null,
    +            "issue_journal_size": 0,
    +            "issue_journals": []
    +        },
    +        {
    +            "id": 7,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 7,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "1个月前",
    +            "name": "v3.0.1",
    +            "tag_name": "v3.0.1",
    +            "target_commitish": "master",
    +            "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.1.tar.gz",
    +            "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.1.zip",
    +            "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/78",
    +            "version_gid": "78",
    +            "created_at": "2021-03-30 15:51"
    +        },
    +        {
    +            "id": 6,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 6,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "1个月前",
    +            "name": "v3.0.0",
    +            "tag_name": "v3.0.0",
    +            "target_commitish": "master",
    +            "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.0.tar.gz",
    +            "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.0.zip",
    +            "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/77",
    +            "version_gid": "77",
    +            "created_at": "2021-03-30 15:33"
    +        },
    +        {
    +            "id": 5,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 5,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "1个月前",
    +            "name": "v1.0.0",
    +            "tag_name": "v1.0.0",
    +            "target_commitish": "master",
    +            "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v1.0.0.tar.gz",
    +            "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v1.0.0.zip",
    +            "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/76",
    +            "version_gid": "76",
    +            "created_at": "2021-03-30 15:27"
    +        },
    +        {
    +            "id": 2,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 2,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "2个月前",
    +            "name": "vvvv",
    +            "tag_name": "v1.1",
    +            "target_commitish": "dev",
    +            "tarball_url": "http://localhost:10080/yystopf/virus_blog/archive/v1.1.tar.gz",
    +            "zipball_url": "http://localhost:10080/yystopf/virus_blog/archive/v1.1.zip",
    +            "url": "http://localhost:10080/api/v1/repos/yystopf/virus_blog/releases/6",
    +            "version_gid": "6",
    +            "created_at": "2021-03-15 14:18"
    +        },
    +        {
    +            "id": 2,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 2,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "3个月前",
    +            "name": "444",
    +            "created_at": "2021-02-25 17:31"
    +        }
    +    ]
    +}
    +
    + +

    用户开发能力

    +

    用户开发能力, 默认为所有时间下的开发能力

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/develop.json
    +
    await octokit.request('GET /api/users/:login/statistics/develop.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/statistics/develop.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    start_timeinteger时间戳,开始时间,格式:1621526400
    end_timeinteger时间戳,结束时间,格式:1622131200
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    influenceint影响力
    contributionint贡献度
    activityint活跃度
    experienceint项目经验
    languageint语言能力
    languages_percentfloat语言百分比
    each_language_scoreint各门语言分数
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "platform": {
    +        "influence": 61,
    +        "contribution": 75,
    +        "activity": 66,
    +        "experience": 95,
    +        "language": 87,
    +        "languages_percent": {
    +            "CSS": 0.03,
    +            "C#": 0.13,
    +            "Ruby": 0.04,
    +            "Go": 0.05,
    +            "C": 0.19,
    +            "Java": 0.34,
    +            "Python": 0.09,
    +            "C+": 0.01,
    +            "C++": 0.11,
    +            "Scala": 0.01,
    +            "HTML": 0.01
    +        },
    +        "each_language_score": {
    +            "CSS": 71,
    +            "C#": 86,
    +            "Ruby": 75,
    +            "Go": 77,
    +            "C": 90,
    +            "Java": 93,
    +            "Python": 83,
    +            "C+": 66,
    +            "C++": 85,
    +            "Scala": 66,
    +            "HTML": 66
    +        }
    +    },
    +    "user": {
    +        "influence": 60,
    +        "contribution": 72,
    +        "activity": 65,
    +        "experience": 88,
    +        "language": 84,
    +        "languages_percent": {
    +            "C": 0.25,
    +            "C#": 0.33,
    +            "C++": 0.13,
    +            "CSS": 0.08,
    +            "Go": 0.04,
    +            "HTML": 0.04,
    +            "Java": 0.04,
    +            "Ruby": 0.08
    +        },
    +        "each_language_score": {
    +            "C": 81,
    +            "C#": 84,
    +            "C++": 75,
    +            "CSS": 71,
    +            "Go": 66,
    +            "HTML": 66,
    +            "Java": 66,
    +            "Ruby": 71
    +        }
    +    }
    +}
    +
    + +

    用户角色定位

    +

    用户角色定位,默认显示所有时间下的角色定位数据

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/role.json
    +
    await octokit.request('GET /api/users/:login/statistics/role.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/statistics/role.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    start_timeinteger时间戳,开始时间,格式:1621526400
    end_timeinteger时间戳,结束时间,格式:1622131200
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_projects_countint用户所有的项目数量
    role.object.countint用户该语言下的项目数量
    role.object.percentfloat用户该语言下的项目占比
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_projects_count": 27,
    +    "role": {
    +        "owner": {
    +            "count": 24,
    +            "percent": 0.89
    +        },
    +        "manager": {
    +            "count": 1,
    +            "percent": 0.04
    +        },
    +        "developer": {
    +            "count": 2,
    +            "percent": 0.07
    +        },
    +        "reporter": {
    +            "count": 0,
    +            "percent": 0.0
    +        }
    +    }
    +}
    +
    + +

    用户专业定位

    +

    用户专业定位,默认显示所有时间下的专业定位数据

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/major.json
    +
    await octokit.request('GET /api/users/:login/statistics/major.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/statistics/major.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    start_timeinteger时间戳,开始时间,格式:1621526400
    end_timeinteger时间戳,结束时间,格式:1622131200
    +

    返回字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    categoriesint用户项目分类
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "categories": [
    +        "大数据",
    +        "机器学习",
    +        "深度学习",
    +        "人工智能",
    +        "智慧医疗",
    +        "云计算"
    +    ]
    +}
    +
    +

    待办事项-用户通知信息

    待办事项-用户通知信息

    @@ -1025,9 +1746,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    -

    请求字段说明:

    +

    请求字段说明:

    @@ -1041,7 +1762,7 @@ Success — a happy kitten is an authenticated kitten!
    参数用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1262,9 +1983,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1278,7 +1999,7 @@ Success — a happy kitten is an authenticated kitten!
    参数用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1454,9 +2175,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1475,7 +2196,7 @@ Success — a happy kitten is an authenticated kitten!
    参数迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1645,9 +2366,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1666,7 +2387,7 @@ Success — a happy kitten is an authenticated kitten!
    参数迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    From 5431349d4640347047f1cb864edbcc712ac236c4 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 16:08:49 +0800 Subject: [PATCH 169/643] fix --- app/views/projects/_project_detail.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/_project_detail.json.jbuilder b/app/views/projects/_project_detail.json.jbuilder index da5d67473..c9e03fa22 100644 --- a/app/views/projects/_project_detail.json.jbuilder +++ b/app/views/projects/_project_detail.json.jbuilder @@ -17,7 +17,7 @@ json.time_ago time_from_now(project.updated_on) json.forked_from_project_id project.forked_from_project_id json.open_devops project.open_devops? json.platform project.platform -json.is_pinned @project.has_pinned_users.include?(current_user) +json.is_pinned project.has_pinned_users.include?(current_user) json.author do if project.educoder? project_educoder = project.project_educoder From 9a2b067bc185263e1cc81db4de40e3c30a5113eb Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 16:53:37 +0800 Subject: [PATCH 170/643] add: user created time --- app/views/users/show.json.jbuilder | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index e80ac7494..c529cf79f 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -17,4 +17,5 @@ json.user_composes_count @user_composes_count json.user_org_count @user_org_count json.common_projects_count @projects_common_count json.mirror_projects_count @projects_mirrior_count -json.sync_mirror_projects_count @projects_sync_mirrior_count \ No newline at end of file +json.sync_mirror_projects_count @projects_sync_mirrior_count +json.created_time format_time(@user.created_on) \ No newline at end of file From a0f0b5e3f1ac205a936fd479943d00cce79d727f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 18:00:53 +0800 Subject: [PATCH 171/643] fix: psimple issue field --- app/views/issues/_simple_issue_item.json.jbuilder | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/issues/_simple_issue_item.json.jbuilder b/app/views/issues/_simple_issue_item.json.jbuilder index 3f9c22e9e..d21c9fcae 100644 --- a/app/views/issues/_simple_issue_item.json.jbuilder +++ b/app/views/issues/_simple_issue_item.json.jbuilder @@ -1,7 +1,10 @@ json.name issue.try(:subject) -json.issue_type issue.try(:issue_type) +json.issue_type issue.issue_type == "1" ? "普通" : "悬赏" json.status_id issue.try(:status_id) +json.issue_status issue.issue_status.try(:name) +json.priority issue.priority.try(:name) json.priority_id issue.try(:priority_id) +json.version issue.version.try(:name) json.created_at format_time(issue.try(:created_on)) json.updated_at format_time(issue.try(:updated_on)) json.assign_user_name issue&.get_assign_user.try(:show_real_name) From 0b450c0c5f1f92c8b622084e8afd31816b33fd58 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 31 May 2021 18:39:49 +0800 Subject: [PATCH 172/643] add: update user_info --- app/controllers/users_controller.rb | 15 ++- app/docs/slate/source/includes/_users.md | 53 +++++++- app/models/user.rb | 2 +- app/models/user_extension.rb | 6 +- app/views/users/show.json.jbuilder | 7 +- ...531100250_add_fields_to_user_extensions.rb | 8 ++ public/docs/api.html | 124 ++++++++++++++---- 7 files changed, 180 insertions(+), 35 deletions(-) create mode 100644 db/migrate/20210531100250_add_fields_to_user_extensions.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3c62b1145..4cbb2cbdf 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -72,9 +72,13 @@ class UsersController < ApplicationController end def update - @user = User.find params[:id] - @user.update!(user_params) - render_ok + return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id]) + @user.attributes = user_params + if @user.save + render_ok + else + render_error(@user.errors.full_messages.join(", ")) + end end def me @@ -274,11 +278,12 @@ class UsersController < ApplicationController end def user_params - params.require(:user).permit(:nickname, :lastname, :show_realname,:login,:mail, + params.require(:user).permit(:nickname, user_extension_attributes: [ :gender, :location, :location_city, :occupation, :technical_title, - :school_id, :department_id,:identity, :student_id, :description] + :school_id, :department_id, :province, :city, + :custom_department, :identity, :student_id, :description] ) end diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index d7e8ed488..573e171eb 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -47,6 +47,57 @@ await octokit.request('GET /api/users/me.json') Success Data. +## 更改用户信息 +更改用户信息 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/users/yystopf.json +``` + +```javascript +await octokit.request('PATCH/PUT /api/users/:login.json') +``` + +### HTTP 请求 +`PATCH/PUT /api/users/:login.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|user.nickname |string |用户昵称 | +|user.user_extension_attributes.gender |int |性别, 0男 1女 | +|user.user_extension_attributes.province |string |省份 | +|user.user_extension_attributes.city |string |城市 | +|user.user_extension_attributes.description |string |个性签名 | +|user.user_extension_attributes.custom_department|string |单位名称 | + +> 请求的JSON示例: + +```json +{ + "user": { + "nickname": "xxx", + "user_extension_attributes": { + "gender": 0, + "province": "湖南", + "city": "长沙", + "description": "个性签名", + "custom_department": "湖南智擎科技有限公司", + } + } +} +``` + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` ## 获取用户星标项目 获取用户星标项目 diff --git a/app/models/user.rb b/app/models/user.rb index 56043f5f6..e190e82ea 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -181,7 +181,7 @@ class User < Owner attr_accessor :password, :password_confirmation - delegate :gender, :department_id, :school_id, :location, :location_city, :technical_title, to: :user_extension, allow_nil: true + delegate :description, :gender, :department_id, :school_id, :location, :location_city, :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true before_save :update_hashed_password after_create do diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 4afd89bd5..56eed12bd 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -22,9 +22,9 @@ # school_id :integer # description :string(255) default("") # department_id :integer -# honor :text(65535) -# edu_background :integer -# edu_entry_year :integer +# province :string(255) +# city :string(255) +# custom_department :string(255) # # Indexes # diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index c529cf79f..560c207d6 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -18,4 +18,9 @@ json.user_org_count @user_org_count json.common_projects_count @projects_common_count json.mirror_projects_count @projects_mirrior_count json.sync_mirror_projects_count @projects_sync_mirrior_count -json.created_time format_time(@user.created_on) \ No newline at end of file +json.created_time format_time(@user.created_on) +json.email @user.mail +json.province @user.province +json.city @user.city +json.custom_department @user.custom_department +json.description @user.description \ No newline at end of file diff --git a/db/migrate/20210531100250_add_fields_to_user_extensions.rb b/db/migrate/20210531100250_add_fields_to_user_extensions.rb new file mode 100644 index 000000000..880438405 --- /dev/null +++ b/db/migrate/20210531100250_add_fields_to_user_extensions.rb @@ -0,0 +1,8 @@ +class AddFieldsToUserExtensions < ActiveRecord::Migration[5.2] + def change + add_column :user_extensions, :province, :string # 省份 + add_column :user_extensions, :city, :string # 城市 + add_column :user_extensions, :custom_department, :string #自己填写的单位名称 + remove_column :users, :description + end +end diff --git a/public/docs/api.html b/public/docs/api.html index 616803e4e..e713ea1d0 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -331,6 +331,9 @@
  • 获取当前登陆用户信息
  • +
  • + 更改用户信息 +
  • 获取用户星标项目
  • @@ -611,7 +614,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -673,7 +676,80 @@ Success — a happy kitten is an authenticated kitten! -

    获取用户星标项目

    +

    更改用户信息

    +

    更改用户信息

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/users/yystopf.json
    +
    await octokit.request('PATCH/PUT /api/users/:login.json')
    +

    HTTP 请求

    +

    PATCH/PUT /api/users/:login.json

    +

    请求字段说明:

    +
    参数
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    user.nicknamestring用户昵称
    user.user_extension_attributes.genderint性别, 0男 1女
    user.user_extension_attributes.provincestring省份
    user.user_extension_attributes.citystring城市
    user.user_extension_attributes.descriptionstring个性签名
    user.user_extension_attributes.custom_departmentstring单位名称
    + +
    +

    请求的JSON示例:

    +
    +
    {
    +    "user": {
    +        "nickname": "xxx",
    +        "user_extension_attributes": {
    +            "gender": 0,
    +            "province": "湖南",
    +            "city": "长沙",
    +            "description": "个性签名",
    +            "custom_department": "湖南智擎科技有限公司",
    +        }
    +    }
    +}
    +
    +
    +

    返回的JSON示例:

    +
    +
    {
    +    "status": 0,
    +    "message": "success"
    +}
    +

    获取用户星标项目

    获取用户星标项目

    @@ -681,7 +757,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/is_pinned_projects.json
     
    await octokit.request('GET /api/users/:login/is_pinned_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/is_pinned_projects.json

    返回字段说明:

    @@ -863,9 +939,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/is_pinned_projects/pin.json
     
    await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST /api/users/:login/is_pinned_projects/pin.json

    -

    请求字段说明:

    同时设定多个星标项目

    +

    请求字段说明:

    同时设定多个星标项目

    @@ -909,7 +985,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/activity.json
     
    await octokit.request('GET /api/users/:login/statistics/activity.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/activity.json

    返回字段说明:

    参数
    @@ -998,9 +1074,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
     
    await octokit.request('GET /api/users/:login/headmaps.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/headmaps.json

    -

    请求字段说明:

    +

    请求字段说明:

    @@ -1143,9 +1219,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/project_trends.json
     
    await octokit.request('GET /api/users/:login/project_trends.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/project_trends.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1460,9 +1536,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/develop.json
     
    await octokit.request('GET /api/users/:login/statistics/develop.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/develop.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1603,9 +1679,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/role.json
     
    await octokit.request('GET /api/users/:login/statistics/role.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/role.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1685,9 +1761,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/major.json
     
    await octokit.request('GET /api/users/:login/statistics/major.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/major.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1746,9 +1822,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1983,9 +2059,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2175,9 +2251,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2366,9 +2442,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    From 4a1b857655676b8bf8c4bddf6fb661559619f4f6 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 31 May 2021 18:46:39 +0800 Subject: [PATCH 173/643] fix --- db/migrate/20210531100250_add_fields_to_user_extensions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20210531100250_add_fields_to_user_extensions.rb b/db/migrate/20210531100250_add_fields_to_user_extensions.rb index 880438405..890cd35ae 100644 --- a/db/migrate/20210531100250_add_fields_to_user_extensions.rb +++ b/db/migrate/20210531100250_add_fields_to_user_extensions.rb @@ -3,6 +3,6 @@ class AddFieldsToUserExtensions < ActiveRecord::Migration[5.2] add_column :user_extensions, :province, :string # 省份 add_column :user_extensions, :city, :string # 城市 add_column :user_extensions, :custom_department, :string #自己填写的单位名称 - remove_column :users, :description + # remove_column :users, :description end end From 2ad963cdf1bb3eacee78afcfcc1483a458d5bd5f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 1 Jun 2021 10:07:01 +0800 Subject: [PATCH 174/643] add: update user image --- app/controllers/application_controller.rb | 19 +++++++++++++++++++ .../organizations/organizations_controller.rb | 19 ------------------- app/controllers/users_controller.rb | 6 ++++-- app/docs/slate/source/includes/_users.md | 3 ++- app/queries/projects/list_my_query.rb | 2 +- public/docs/api.html | 7 ++++++- 6 files changed, 32 insertions(+), 24 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6875b8155..8536147ca 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -773,7 +773,26 @@ class ApplicationController < ActionController::Base def base_url request.base_url end + + def convert_image! + @image = params[:image] || user_params[:image] + return unless @image.present? + max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M + if @image.class == ActionDispatch::Http::UploadedFile + render_error('请上传文件') if @image.size.zero? + render_error('文件大小超过限制') if @image.size > max_size.to_i + else + image = @image.to_s.strip + return render_error('请上传正确的图片') if image.blank? + @image = Util.convert_base64_image(image, max_size: max_size.to_i) + end + rescue Base64ImageConverter::Error => ex + render_error(ex.message) + end + def avatar_path(object) + ApplicationController.helpers.disk_filename(object.class, object.id) + end private def object_not_found diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index 29cb15a6a..7be9390d7 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -70,25 +70,6 @@ class Organizations::OrganizationsController < Organizations::BaseController end private - def convert_image! - return unless params[:image].present? - max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M - if params[:image].class == ActionDispatch::Http::UploadedFile - @image = params[:image] - render_error('请上传文件') if @image.size.zero? - render_error('文件大小超过限制') if @image.size > max_size.to_i - else - image = params[:image].to_s.strip - return render_error('请上传正确的图片') if image.blank? - @image = Util.convert_base64_image(image, max_size: max_size.to_i) - end - rescue Base64ImageConverter::Error => ex - render_error(ex.message) - end - - def avatar_path(organization) - ApplicationController.helpers.disk_filename(organization.class, organization.id) - end def organization_params params.permit(:name, :description, :website, :location, diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4cbb2cbdf..6c28271db 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -6,6 +6,7 @@ class UsersController < ApplicationController before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard] before_action :require_login, only: %i[me list sync_user_info] before_action :connect_to_ci_db, only: [:get_user_info] + before_action :convert_image!, only: [:update] skip_before_action :check_sign, only: [:attachment_show] def connect_to_ci_db(options={}) @@ -73,7 +74,8 @@ class UsersController < ApplicationController def update return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id]) - @user.attributes = user_params + Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? + @user.attributes = user_params.except(:image) if @user.save render_ok else @@ -278,7 +280,7 @@ class UsersController < ApplicationController end def user_params - params.require(:user).permit(:nickname, + params.require(:user).permit(:nickname, :image, user_extension_attributes: [ :gender, :location, :location_city, :occupation, :technical_title, diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 573e171eb..b72ee0c12 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -67,6 +67,7 @@ await octokit.request('PATCH/PUT /api/users/:login.json') 参数 | 类型 | 字段说明 --------- | ----------- | ----------- |user.nickname |string |用户昵称 | +|user.image |string/file |用户头像 | |user.user_extension_attributes.gender |int |性别, 0男 1女 | |user.user_extension_attributes.province |string |省份 | |user.user_extension_attributes.city |string |城市 | diff --git a/app/queries/projects/list_my_query.rb b/app/queries/projects/list_my_query.rb index 5bda56120..5c508c961 100644 --- a/app/queries/projects/list_my_query.rb +++ b/app/queries/projects/list_my_query.rb @@ -53,7 +53,7 @@ class Projects::ListMyQuery < ApplicationQuery q = projects.ransack(name_or_identifier_cont: params[:search]) - scope = q.result.includes(:project_category, :project_language,:owner, :repository) + scope = q.result.includes(:project_category, :project_language,:owner, :repository, :has_pinned_users) sort = params[:sort_by] || "updated_on" sort_direction = params[:sort_direction] || "desc" diff --git a/public/docs/api.html b/public/docs/api.html index e713ea1d0..71753c32b 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -614,7 +614,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -700,6 +700,11 @@ Success — a happy kitten is an authenticated kitten!
    + + + + + From df6da37b95255236f8ece69f2df6a62bf023010f Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 2 Jun 2021 15:29:00 +0800 Subject: [PATCH 175/643] fix: some bug --- app/views/project_trends/_detail.json.jbuilder | 4 ++-- app/views/users/_watch_user_detail.json.jbuilder | 2 +- app/views/users/watch_users.json.jbuilder | 2 +- config/locales/zh-CN.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/views/project_trends/_detail.json.jbuilder b/app/views/project_trends/_detail.json.jbuilder index 7ffa9f152..75bcf2237 100644 --- a/app/views/project_trends/_detail.json.jbuilder +++ b/app/views/project_trends/_detail.json.jbuilder @@ -12,6 +12,6 @@ if trend.trend_type == "Issue" elsif trend.trend_type == "VersionRelease" json.partial! "version_releases/simple_version_release", locals: {version: trend.trend} else - json.name trend.trend.title - json.created_at format_time(trend.trend.created_at) + json.name trend.trend&.title + json.created_at format_time(trend.trend&.created_at) end diff --git a/app/views/users/_watch_user_detail.json.jbuilder b/app/views/users/_watch_user_detail.json.jbuilder index 80a711626..8c4881bcc 100644 --- a/app/views/users/_watch_user_detail.json.jbuilder +++ b/app/views/users/_watch_user_detail.json.jbuilder @@ -3,7 +3,7 @@ json.format_time target.created_at.strftime("%Y-%m-%d") json.name user.try(:show_real_name) json.login user.try(:login) json.image_url url_to_avatar(user) -json.is_current_user current_user.try(:id) == target.user_id +json.is_current_user current_user.try(:id) == user.id json.is_watch current_user&.watched?(user) diff --git a/app/views/users/watch_users.json.jbuilder b/app/views/users/watch_users.json.jbuilder index b265e2e0a..ed2697f0c 100644 --- a/app/views/users/watch_users.json.jbuilder +++ b/app/views/users/watch_users.json.jbuilder @@ -1,7 +1,7 @@ json.count @watchers_count json.users do json.array! @watchers do |watcher| - json.partial! "/users/watch_user_detail", locals: {target: watcher, user: watcher.watchable} + json.partial! "/users/watch_user_detail", target: watcher, user: watcher.watchable end # json.partial! "/users/watch_user_detail", collection: @watchers, as: :target end \ No newline at end of file diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index c040f9bd1..db1030163 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -15,7 +15,7 @@ zh-CN: 'refused': '已拒绝' 'agreed': '已同意' trend: - Issue: 工单 + Issue: 易修(Issue) PullRequest: 合并请求 VersionRelease: 版本发布 create: 创建了 From 96a8da5d26d557b74c56c73fad578ee0d7de1020 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 2 Jun 2021 16:40:40 +0800 Subject: [PATCH 176/643] add: pinned projects order by position --- .../users/is_pinned_projects_controller.rb | 19 +++- app/docs/slate/source/includes/_users.md | 44 ++++++++- .../is_pinned_projects/index.json.jbuilder | 4 +- config/routes.rb | 2 +- public/docs/api.html | 91 ++++++++++++++----- 5 files changed, 134 insertions(+), 26 deletions(-) diff --git a/app/controllers/users/is_pinned_projects_controller.rb b/app/controllers/users/is_pinned_projects_controller.rb index 4f3f4e37e..1ddadd277 100644 --- a/app/controllers/users/is_pinned_projects_controller.rb +++ b/app/controllers/users/is_pinned_projects_controller.rb @@ -1,7 +1,7 @@ class Users::IsPinnedProjectsController < Users::BaseController before_action :private_user_resources!, only: [:pin] def index - @is_pinned_projects = observed_user.is_pinned_projects.includes(:project_category, :project_language, :repository).order(position: :desc) + @is_pinned_projects = observed_user.pinned_projects.order(position: :desc, created_at: :asc).includes(project: [:project_category, :project_language, :repository]).order(position: :desc) @is_pinned_projects = kaminari_paginate(@is_pinned_projects) end @@ -15,6 +15,19 @@ class Users::IsPinnedProjectsController < Users::BaseController tip_exception(e.message) end + def update + @pinned_project = PinnedProject.find_by_id(params[:id]) + @pinned_project.attributes = pinned_project_params + if @pinned_project.save + render_ok + else + render_error + end + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + private def is_pinned_project_ids if params[:is_pinned_project_ids].present? @@ -25,4 +38,8 @@ class Users::IsPinnedProjectsController < Users::BaseController return observed_user.is_pinned_project_ids.include?(params[:is_pinned_project_id].to_i) ? observed_user.is_pinned_project_ids : observed_user.is_pinned_project_ids.push(params[:is_pinned_project_id].to_i) end end + + def pinned_project_params + params.require(:pinned_project).permit(:position) + end end \ No newline at end of file diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index b72ee0c12..5771f757f 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -53,7 +53,7 @@ await octokit.request('GET /api/users/me.json') > 示例: ```shell -curl -X POST http://localhost:3000/api/users/yystopf.json +curl -X PATCH/PUT http://localhost:3000/api/users/yystopf.json ``` ```javascript @@ -141,6 +141,7 @@ await octokit.request('GET /api/users/:login/is_pinned_projects.json') |author.image_url |string |项目拥有者头像| |category.name |string |项目分类名称| |language.name |string |项目语言名称| +|position |int |项目排序| > 返回的JSON示例: @@ -228,6 +229,45 @@ await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json') ``` +## 星标项目展示排序 +星标项目展示排序 + +> 示例: + +```shell +curl -X PATCH http://localhost:3000/api/users/yystopf/is_pinned_projects/11.json +``` + +```javascript +await octokit.request('PATCH/PUT /api/users/:login/is_pinned_projects/:id.json') +``` + +### HTTP 请求 +`PATCH/PUT /api/users/:login/is_pinned_projects/:id.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|pinned_projects.position |int |排序,数字越大排名越前 | + +> 请求的JSON示例: + +```json +{ + "pinned_project": { + "position": 1 + } +} +``` + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` ## 用户近期活动统计 用户近期活动统计, 默认显示近一周的数据 diff --git a/app/views/users/is_pinned_projects/index.json.jbuilder b/app/views/users/is_pinned_projects/index.json.jbuilder index facc158b9..a96ecf986 100644 --- a/app/views/users/is_pinned_projects/index.json.jbuilder +++ b/app/views/users/is_pinned_projects/index.json.jbuilder @@ -1,4 +1,6 @@ json.total_count @is_pinned_projects.total_count json.projects @is_pinned_projects.each do |project| - json.partial! "projects/project_detail", project: project + json.partial! "projects/project_detail", project: project&.project + json.id project.id + json.position project.position end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index cfadf4941..1160a4072 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -266,7 +266,7 @@ Rails.application.routes.draw do end end resources :headmaps, only: [:index] - resources :is_pinned_projects, only: [:index] do + resources :is_pinned_projects, only: [:index, :update] do collection do post :pin end diff --git a/public/docs/api.html b/public/docs/api.html index 71753c32b..c8fa29fa2 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -340,6 +340,9 @@
  • 用户添加星标项目
  • +
  • + 星标项目展示排序 +
  • 用户近期活动统计
  • @@ -614,7 +617,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -682,7 +685,7 @@ Success — a happy kitten is an authenticated kitten!

    示例:

    -
    curl -X POST http://localhost:3000/api/users/yystopf.json
    +
    curl -X PATCH/PUT http://localhost:3000/api/users/yystopf.json
     
    await octokit.request('PATCH/PUT /api/users/:login.json')
     

    HTTP 请求

    PATCH/PUT /api/users/:login.json

    @@ -887,6 +890,11 @@ Success — a happy kitten is an authenticated kitten!
    + + + + +
    参数用户昵称
    user.imagestring/file用户头像
    user.user_extension_attributes.gender int 性别, 0男 1女string 项目语言名称
    positionint项目排序
    @@ -975,6 +983,47 @@ Success — a happy kitten is an authenticated kitten! +
    +

    返回的JSON示例:

    +
    +
    {
    +    "status": 0,
    +    "message": "success"
    +}
    +

    星标项目展示排序

    +

    星标项目展示排序

    + +
    +

    示例:

    +
    +
    curl -X PATCH http://localhost:3000/api/users/yystopf/is_pinned_projects/11.json
    +
    await octokit.request('PATCH/PUT /api/users/:login/is_pinned_projects/:id.json')
    +

    HTTP 请求

    +

    PATCH/PUT /api/users/:login/is_pinned_projects/:id.json

    +

    请求字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    pinned_projects.positionint排序,数字越大排名越前
    + +
    +

    请求的JSON示例:

    +
    +
    {
    +    "pinned_project": {
    +        "position": 1
    +    }
    +}
    +

    返回的JSON示例:

    @@ -990,7 +1039,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/activity.json
     
    await octokit.request('GET /api/users/:login/statistics/activity.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/activity.json

    返回字段说明:

    @@ -1079,9 +1128,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
     
    await octokit.request('GET /api/users/:login/headmaps.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/headmaps.json

    -

    请求字段说明:

    +

    请求字段说明:

    @@ -1224,9 +1273,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/project_trends.json
     
    await octokit.request('GET /api/users/:login/project_trends.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/project_trends.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1541,9 +1590,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/develop.json
     
    await octokit.request('GET /api/users/:login/statistics/develop.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/develop.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1684,9 +1733,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/role.json
     
    await octokit.request('GET /api/users/:login/statistics/role.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/role.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1766,9 +1815,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/major.json
     
    await octokit.request('GET /api/users/:login/statistics/major.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/major.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1827,9 +1876,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2064,9 +2113,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2256,9 +2305,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2447,9 +2496,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    From c727ccf3e603903339cdd1317d3c11ad75c72095 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 2 Jun 2021 17:29:11 +0800 Subject: [PATCH 177/643] add: pinned projects project_id --- app/views/users/is_pinned_projects/index.json.jbuilder | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/users/is_pinned_projects/index.json.jbuilder b/app/views/users/is_pinned_projects/index.json.jbuilder index a96ecf986..7790607d6 100644 --- a/app/views/users/is_pinned_projects/index.json.jbuilder +++ b/app/views/users/is_pinned_projects/index.json.jbuilder @@ -3,4 +3,5 @@ json.projects @is_pinned_projects.each do |project| json.partial! "projects/project_detail", project: project&.project json.id project.id json.position project.position + json.project_id project.project_id end \ No newline at end of file From a0ca4d3acb5fc08f51635e19990937cd3cfe69d2 Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 2 Jun 2021 17:35:06 +0800 Subject: [PATCH 178/643] =?UTF-8?q?FIX=20=E6=96=B0=E5=BB=BA=E6=98=93?= =?UTF-8?q?=E4=BF=AEapi=E4=B8=AD=20=E6=9B=B4=E6=96=B0=E7=9B=B8=E5=85=B3cac?= =?UTF-8?q?he=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/tag_chosen_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/helpers/tag_chosen_helper.rb b/app/helpers/tag_chosen_helper.rb index 1e7879d18..348062c77 100644 --- a/app/helpers/tag_chosen_helper.rb +++ b/app/helpers/tag_chosen_helper.rb @@ -94,7 +94,7 @@ module TagChosenHelper def render_issue_tags(project) # project.issue_tags.last&.cache_key - cache_key = "all_issue_tags/#{project.issue_tags.maximum('updated_at')}" + cache_key = "project-#{project.id}/all_issue_tags/size-#{project.issue_tags.size}/#{project.issue_tags.maximum('updated_at')}" Rails.cache.fetch(cache_key) do project.issue_tags.select(:id, :name, :color).collect do |event| @@ -109,7 +109,7 @@ module TagChosenHelper end def render_cache_milestones(project) - cache_key = "all_milestones/#{project.versions.maximum('updated_on')}" + cache_key = "project-#{project.id}/all_milestones/size-#{project.version}/#{project.versions.maximum('updated_on')}" Rails.cache.fetch(cache_key) do project.versions.select(:id, :name, :status).collect do |event| @@ -124,7 +124,7 @@ module TagChosenHelper end def render_cache_collaborators(project) - cache_key = "all_collaborators/#{project.all_collaborators.maximum('created_on')}" + cache_key = "project-#{project.id}/all_collaborators/size-#{project.all_collaborators.size}/#{project.all_collaborators.maximum('updated_on')}" Rails.cache.fetch(cache_key) do project.all_collaborators.order(created_on: :desc).collect do |user| { From e4a40fb382d4242a0fe559e0e6f9065e3ea03651 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 3 Jun 2021 09:48:58 +0800 Subject: [PATCH 179/643] fix: org transfer bug --- app/services/projects/transfer_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index a2da34f09..0b4f1d998 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -34,7 +34,7 @@ class Projects::TransferService < ApplicationService def update_visit_teams if new_owner.is_a?(Organization) # 为包含组织所有项目的团队创建项目访问权限 - new_owner.build_permit_team_projects(project.id) + new_owner.build_permit_team_projects!(project.id) else project.team_projects.each(&:destroy!) end From 496867cac7208f2fa3fa87bf356aec80aa479941 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 3 Jun 2021 10:19:33 +0800 Subject: [PATCH 180/643] add: update user more info --- app/controllers/users_controller.rb | 3 ++- app/docs/slate/source/includes/_users.md | 12 ++++++--- app/models/user.rb | 4 ++- app/models/user_extension.rb | 3 +++ app/views/users/show.json.jbuilder | 8 +++--- ...7_add_show_condition_to_user_extensions.rb | 7 +++++ public/docs/api.html | 26 ++++++++++++++++--- 7 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 db/migrate/20210603020327_add_show_condition_to_user_extensions.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6c28271db..3f7cd4170 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -285,7 +285,8 @@ class UsersController < ApplicationController :gender, :location, :location_city, :occupation, :technical_title, :school_id, :department_id, :province, :city, - :custom_department, :identity, :student_id, :description] + :custom_department, :identity, :student_id, :description, + :show_email, :show_location, :show_department] ) end diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 5771f757f..72bf724a5 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -66,13 +66,17 @@ await octokit.request('PATCH/PUT /api/users/:login.json') ### 请求字段说明: 参数 | 类型 | 字段说明 --------- | ----------- | ----------- -|user.nickname |string |用户昵称 | -|user.image |string/file |用户头像 | +|user.nickname |string |用户昵称 | +|user.image |base64/file |用户头像 | |user.user_extension_attributes.gender |int |性别, 0男 1女 | |user.user_extension_attributes.province |string |省份 | |user.user_extension_attributes.city |string |城市 | -|user.user_extension_attributes.description |string |个性签名 | +|user.user_extension_attributes.description |string |简介 | |user.user_extension_attributes.custom_department|string |单位名称 | +|user.user_extension_attributes.technical_title |string |职业 | +|user.user_extension_attributes.show_email |bool |是否展示邮箱 | +|user.user_extension_attributes.show_location |bool |是否展示位置 | +|user.user_extension_attributes.show_department |bool |是否展示公司 | > 请求的JSON示例: diff --git a/app/models/user.rb b/app/models/user.rb index e190e82ea..09880b8cd 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -181,7 +181,9 @@ class User < Owner attr_accessor :password, :password_confirmation - delegate :description, :gender, :department_id, :school_id, :location, :location_city, :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true + delegate :description, :gender, :department_id, :school_id, :location, :location_city, + :show_email, :show_location, :show_department, + :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true before_save :update_hashed_password after_create do diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 56eed12bd..47b27c08b 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -25,6 +25,9 @@ # province :string(255) # city :string(255) # custom_department :string(255) +# show_email :boolean default("0") +# show_location :boolean default("0") +# show_department :boolean default("0") # # Indexes # diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index 560c207d6..06fab129f 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -19,8 +19,8 @@ json.common_projects_count @projects_common_count json.mirror_projects_count @projects_mirrior_count json.sync_mirror_projects_count @projects_sync_mirrior_count json.created_time format_time(@user.created_on) -json.email @user.mail -json.province @user.province -json.city @user.city -json.custom_department @user.custom_department +json.email @user.show_email ? @user.mail : nil +json.province @user.show_location ? @user.province : nil +json.city @user.show_location ? @user.city : nil +json.custom_department @user.show_department ? @user.custom_department : nil json.description @user.description \ No newline at end of file diff --git a/db/migrate/20210603020327_add_show_condition_to_user_extensions.rb b/db/migrate/20210603020327_add_show_condition_to_user_extensions.rb new file mode 100644 index 000000000..e64da0b71 --- /dev/null +++ b/db/migrate/20210603020327_add_show_condition_to_user_extensions.rb @@ -0,0 +1,7 @@ +class AddShowConditionToUserExtensions < ActiveRecord::Migration[5.2] + def change + add_column :user_extensions, :show_email, :boolean, default: false + add_column :user_extensions, :show_location, :boolean, default: false + add_column :user_extensions, :show_department, :boolean, default: false + end +end diff --git a/public/docs/api.html b/public/docs/api.html index c8fa29fa2..0cf007cf1 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -617,7 +617,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -704,7 +704,7 @@ Success — a happy kitten is an authenticated kitten!
    - + @@ -725,13 +725,33 @@ Success — a happy kitten is an authenticated kitten! - + + + + + + + + + + + + + + + + + + + + +
    参数
    user.imagestring/filebase64/file 用户头像
    user.user_extension_attributes.description string个性签名简介
    user.user_extension_attributes.custom_department string 单位名称
    user.user_extension_attributes.technical_titlestring职业
    user.user_extension_attributes.show_emailbool是否展示邮箱
    user.user_extension_attributes.show_locationbool是否展示位置
    user.user_extension_attributes.show_departmentbool是否展示公司
    From 422fd35f1eb1b5b5b941fe8141555df267f2d5b6 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 27 May 2021 10:30:34 +0800 Subject: [PATCH 181/643] add: user headmap --- app/controllers/users/headmaps_controller.rb | 26 ++++ app/docs/slate/source/includes/_users.md | 124 ++++++++++++++- app/services/gitea/user/headmap_service.rb | 23 +++ app/views/users/headmaps/index.json.jbuilder | 5 + config/routes.rb | 1 + public/docs/api.html | 152 +++++++++++++++++-- 6 files changed, 321 insertions(+), 10 deletions(-) create mode 100644 app/controllers/users/headmaps_controller.rb create mode 100644 app/services/gitea/user/headmap_service.rb create mode 100644 app/views/users/headmaps/index.json.jbuilder diff --git a/app/controllers/users/headmaps_controller.rb b/app/controllers/users/headmaps_controller.rb new file mode 100644 index 000000000..81bd5771c --- /dev/null +++ b/app/controllers/users/headmaps_controller.rb @@ -0,0 +1,26 @@ +class Users::HeadmapsController < Users::BaseController + def index + result = Gitea::User::HeadmapService.call(observed_user.login, start_stamp, end_stamp) + @headmaps = result[2] + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def start_stamp + if params[:year].present? + Date.new(params[:year], 1).to_time.to_i + else + Date.today.to_time.to_i - 365*24*60*60 + end + end + + def end_stamp + if params[:year].present? + Date.new(params[:year], 1).to_time.to_i + 365*24*60*60 + else + Date.today.to_time.to_i + end + end +end \ No newline at end of file diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 1d1afc028..982543fdc 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -47,6 +47,128 @@ await octokit.request('GET /api/users/me.json') Success Data. +## 获取用户贡献度 +获取用户贡献度 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json +``` + +```javascript +await octokit.request('GET /api/users/:login/headmaps.json') +``` + +### HTTP 请求 +`GET api/users/:login/headmaps.json` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_contributions |int |所选时间内的总贡献度 | +|headmaps.date |string|时间| +|headmaps.contributions |int|贡献度| + + +> 返回的JSON示例: + +```json +{ + "total_contributions": 139, + "headmaps": [ + { + "date": 1612627200, + "contributions": 1 + }, + { + "date": 1613836800, + "contributions": 13 + }, + { + "date": 1614182400, + "contributions": 5 + }, + { + "date": 1614528000, + "contributions": 2 + }, + { + "date": 1614787200, + "contributions": 1 + }, + { + "date": 1615737600, + "contributions": 9 + }, + { + "date": 1616342400, + "contributions": 14 + }, + { + "date": 1616515200, + "contributions": 1 + }, + { + "date": 1617033600, + "contributions": 11 + }, + { + "date": 1617638400, + "contributions": 1 + }, + { + "date": 1618156800, + "contributions": 1 + }, + { + "date": 1618243200, + "contributions": 2 + }, + { + "date": 1618761600, + "contributions": 3 + }, + { + "date": 1619107200, + "contributions": 37 + }, + { + "date": 1619280000, + "contributions": 2 + }, + { + "date": 1619366400, + "contributions": 6 + }, + { + "date": 1619539200, + "contributions": 1 + }, + { + "date": 1619625600, + "contributions": 18 + }, + { + "date": 1619712000, + "contributions": 9 + }, + { + "date": 1620057600, + "contributions": 1 + }, + { + "date": 1620230400, + "contributions": 1 + } + ] +} +``` + + + ## 待办事项-用户通知信息 待办事项-用户通知信息 diff --git a/app/services/gitea/user/headmap_service.rb b/app/services/gitea/user/headmap_service.rb new file mode 100644 index 000000000..611a8b9d0 --- /dev/null +++ b/app/services/gitea/user/headmap_service.rb @@ -0,0 +1,23 @@ +class Gitea::User::HeadmapService < Gitea::ClientService + attr_reader :start_time, :end_time, :username + + def initialize(username, start_time, end_time) + @username = username + @start_time = start_time + @end_time = end_time + end + + def call + response = get(url, params) + render_response(response) + end + + private + def params + Hash.new.merge(start: start_time, end: end_time) + end + + def url + "/users/#{username}/heatmap".freeze + end +end \ No newline at end of file diff --git a/app/views/users/headmaps/index.json.jbuilder b/app/views/users/headmaps/index.json.jbuilder new file mode 100644 index 000000000..7011b2559 --- /dev/null +++ b/app/views/users/headmaps/index.json.jbuilder @@ -0,0 +1,5 @@ +json.total_contributions @headmaps.collect{|map| map["contributions"]}.reduce(0, :+) +json.headmaps @headmaps.each do |map| + json.date map["timestamp"] + json.contributions map["contributions"] +end diff --git a/config/routes.rb b/config/routes.rb index a8c97effc..ae121bb08 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -265,6 +265,7 @@ Rails.application.routes.draw do post :refuse end end + resources :headmaps, only: [:index] resources :organizations, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] diff --git a/public/docs/api.html b/public/docs/api.html index f970ea84d..9f52b9066 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -331,6 +331,9 @@
  • 获取当前登陆用户信息
  • +
  • + 获取用户贡献度 +
  • 待办事项-用户通知信息
  • @@ -587,7 +590,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -649,6 +652,137 @@ Success — a happy kitten is an authenticated kitten! +

    获取用户贡献度

    +

    获取用户贡献度

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
    +
    await octokit.request('GET /api/users/:login/headmaps.json')
    +

    HTTP 请求

    +

    GET api/users/:login/headmaps.json

    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_contributionsint所选时间内的总贡献度
    headmaps.datestring时间
    headmaps.contributionsint贡献度
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_contributions": 139,
    +    "headmaps": [
    +        {
    +            "date": 1612627200,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1613836800,
    +            "contributions": 13
    +        },
    +        {
    +            "date": 1614182400,
    +            "contributions": 5
    +        },
    +        {
    +            "date": 1614528000,
    +            "contributions": 2
    +        },
    +        {
    +            "date": 1614787200,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1615737600,
    +            "contributions": 9
    +        },
    +        {
    +            "date": 1616342400,
    +            "contributions": 14
    +        },
    +        {
    +            "date": 1616515200,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1617033600,
    +            "contributions": 11
    +        },
    +        {
    +            "date": 1617638400,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1618156800,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1618243200,
    +            "contributions": 2
    +        },
    +        {
    +            "date": 1618761600,
    +            "contributions": 3
    +        },
    +        {
    +            "date": 1619107200,
    +            "contributions": 37
    +        },
    +        {
    +            "date": 1619280000,
    +            "contributions": 2
    +        },
    +        {
    +            "date": 1619366400,
    +            "contributions": 6
    +        },
    +        {
    +            "date": 1619539200,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1619625600,
    +            "contributions": 18
    +        },
    +        {
    +            "date": 1619712000,
    +            "contributions": 9
    +        },
    +        {
    +            "date": 1620057600,
    +            "contributions": 1
    +        },
    +        {
    +            "date": 1620230400,
    +            "contributions": 1
    +        }
    +    ]
    +}
    +
    +

    待办事项-用户通知信息

    待办事项-用户通知信息

    @@ -657,7 +791,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    请求字段说明:

    @@ -673,7 +807,7 @@ Success — a happy kitten is an authenticated kitten!
    用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -894,7 +1028,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    请求字段说明:

    参数
    @@ -910,7 +1044,7 @@ Success — a happy kitten is an authenticated kitten!
    用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1086,7 +1220,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    请求字段说明:

    参数
    @@ -1107,7 +1241,7 @@ Success — a happy kitten is an authenticated kitten!
    迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1277,7 +1411,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    请求字段说明:

    参数
    @@ -1298,7 +1432,7 @@ Success — a happy kitten is an authenticated kitten!
    迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    From ea79772bd27b099f080376e8a34d661e0d690e88 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 27 May 2021 14:23:59 +0800 Subject: [PATCH 182/643] add: user pinned projects --- .../users/is_pinned_projects_controller.rb | 27 ++ app/docs/slate/source/includes/_users.md | 131 ++++++++- app/models/pinned_project.rb | 22 ++ app/models/project.rb | 148 +++++----- app/models/user.rb | 10 + .../projects/_project_detail.json.jbuilder | 3 + app/views/repositories/edit.json.jbuilder | 3 +- .../is_pinned_projects/index.json.jbuilder | 4 + config/routes.rb | 5 + .../20210527024043_create_pinned_projects.rb | 11 + public/docs/api.html | 266 ++++++++++++++++-- spec/models/pinned_project_spec.rb | 5 + 12 files changed, 544 insertions(+), 91 deletions(-) create mode 100644 app/controllers/users/is_pinned_projects_controller.rb create mode 100644 app/models/pinned_project.rb create mode 100644 app/views/users/is_pinned_projects/index.json.jbuilder create mode 100644 db/migrate/20210527024043_create_pinned_projects.rb create mode 100644 spec/models/pinned_project_spec.rb diff --git a/app/controllers/users/is_pinned_projects_controller.rb b/app/controllers/users/is_pinned_projects_controller.rb new file mode 100644 index 000000000..22ce29263 --- /dev/null +++ b/app/controllers/users/is_pinned_projects_controller.rb @@ -0,0 +1,27 @@ +class Users::IsPinnedProjectsController < Users::BaseController + before_action :private_user_resources!, only: [:pin] + def index + @is_pinned_projects = observed_user.is_pinned_projects.includes(:project_category, :project_language, :repository).order(position: :desc) + @is_pinned_projects = kaminari_paginate(@is_pinned_projects) + end + + def pin + observed_user.is_pinned_project_ids = is_pinned_project_ids + render_ok + rescue ActiveRecord::RecordNotFound => e + render_not_found + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def is_pinned_project_ids + if params[:is_pinned_project_ids].present? + return params[:is_pinned_project_ids].select{|id| observed_user.full_member_projects.pluck(:id).include?(id.to_i) } + end + if params[:is_pinned_project_id].present? + return observed_user.is_pinned_project_ids.include?(params[:is_pinned_project_id].to_i) ? observed_user.is_pinned_project_ids : observed_user.is_pinned_project_ids.push(params[:is_pinned_project_id].to_i) + end + end +end \ No newline at end of file diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 982543fdc..b2c3ebccb 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -47,6 +47,135 @@ await octokit.request('GET /api/users/me.json') Success Data. +## 获取用户星标项目 +获取用户星标项目 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/is_pinned_projects.json +``` + +```javascript +await octokit.request('GET /api/users/:login/is_pinned_projects.json') +``` + +### HTTP 请求 +`GET api/users/:login/is_pinned_projects.json` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_count |int |星标项目数量 | +|identifier |string |项目标识 | +|name |string |项目名称 | +|description |string |项目描述 | +|visits |int |项目访问数量| +|praises_count |int |项目点赞数量| +|watchers_count |int |项目关注数量| +|issues_count |int |项目issue数量| +|pull_requests_count |int |项目合并请求数量| +|forked_count |int |项目复刻数量| +|is_public |bool |项目是否公开| +|mirror_url |string |镜像地址| +|type |int |项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目| +|time_ago |string |上次更新时间| +|open_devops |int |是否开启devops| +|forked_from_project_id |int |fork项目id| +|platform |string |项目平台| +|author.name |string |项目拥有者名称| +|author.type |string |项目拥有者类型| +|author.login |string |项目拥有者用户名| +|author.image_url |string |项目拥有者头像| +|category.name |string |项目分类名称| +|language.name |string |项目语言名称| + + +> 返回的JSON示例: + +```json +{ + "total_count": 1, + "projects": [ + { + "id": 89, + "repo_id": 89, + "identifier": "monkey", + "name": "boke", + "description": "dkkd", + "visits": 4, + "praises_count": 0, + "watchers_count": 0, + "issues_count": 0, + "pull_requests_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": "https://github.com/viletyy/monkey.git", + "type": 1, + "last_update_time": 1619685144, + "time_ago": "27天前", + "forked_from_project_id": null, + "open_devops": false, + "platform": "forge", + "author": { + "name": "测试组织", + "type": "Organization", + "login": "ceshi_org", + "image_url": "images/avatars/Organization/9?t=1612706073" + }, + "category": { + "id": 3, + "name": "深度学习" + }, + "language": { + "id": 2, + "name": "C" + } + } + ] +} +``` + + +## 用户添加星标项目 +用户添加星标项目 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/users/yystopf/is_pinned_projects/pin.json +``` + +```javascript +await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json') +``` + +### HTTP 请求 +`POST /api/users/:login/is_pinned_projects/pin.json` + +### 请求字段说明: +#### 同时设定多个星标项目 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|is_pinned_project_ids |array |设定为星标项目的id | + +#### 只设定一个星标项目 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|is_pinned_project_id |integer |设定为星标项目的id | + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` + + ## 获取用户贡献度 获取用户贡献度 diff --git a/app/models/pinned_project.rb b/app/models/pinned_project.rb new file mode 100644 index 000000000..8e47c9ea4 --- /dev/null +++ b/app/models/pinned_project.rb @@ -0,0 +1,22 @@ +# == Schema Information +# +# Table name: pinned_projects +# +# id :integer not null, primary key +# user_id :integer +# project_id :integer +# position :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_pinned_projects_on_project_id (project_id) +# index_pinned_projects_on_user_id (user_id) +# + +class PinnedProject < ApplicationRecord + + belongs_to :user + belongs_to :project +end diff --git a/app/models/project.rb b/app/models/project.rb index b48680830..9299abcdb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,76 +1,76 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(4294967295) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# license_id :integer -# ignore_id :integer -# default_branch :string(255) default("master") -# website :string(255) -# lesson_url :string(255) -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# - +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(4294967295) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# license_id :integer +# ignore_id :integer +# default_branch :string(255) default("master") +# website :string(255) +# lesson_url :string(255) +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + class Project < ApplicationRecord include Matchable @@ -114,6 +114,8 @@ class Project < ApplicationRecord has_many :team_projects, dependent: :destroy has_many :project_units, dependent: :destroy has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy + has_many :pinned_projects, dependent: :destroy + has_many :has_pinned_users, through: :pinned_projects, source: :user after_save :check_project_members scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} diff --git a/app/models/user.rb b/app/models/user.rb index b778c80f9..bac795dd5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -164,6 +164,9 @@ class User < Owner has_many :organization_users, dependent: :destroy has_many :organizations, through: :organization_users + has_many :pinned_projects, dependent: :destroy + has_many :is_pinned_projects, through: :pinned_projects, source: :project + accepts_nested_attributes_for :is_pinned_projects # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } @@ -195,6 +198,13 @@ class User < Owner validate :validate_sensitive_string validate :validate_password_length + # 用户参与的所有项目 + def full_member_projects + normal_projects = Project.members_projects(self.id).to_sql + org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: self.id}).to_sql + return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct + end + def name login end diff --git a/app/views/projects/_project_detail.json.jbuilder b/app/views/projects/_project_detail.json.jbuilder index d0b62aaa3..2e256fcb4 100644 --- a/app/views/projects/_project_detail.json.jbuilder +++ b/app/views/projects/_project_detail.json.jbuilder @@ -5,6 +5,9 @@ json.name project.name json.description Nokogiri::HTML(project.description).text json.visits project.visits json.praises_count project.praises_count.to_i +json.watchers_count project.watchers_count.to_i +json.issues_count project.issues_count.to_i +json.pull_requests_count project.pull_requests_count.to_i json.forked_count project.forked_count.to_i json.is_public project.is_public json.mirror_url project.repository&.mirror_url diff --git a/app/views/repositories/edit.json.jbuilder b/app/views/repositories/edit.json.jbuilder index 7a11411f4..e0b601f6d 100644 --- a/app/views/repositories/edit.json.jbuilder +++ b/app/views/repositories/edit.json.jbuilder @@ -12,4 +12,5 @@ json.permission render_permission(current_user, @project) json.is_transfering @project.is_transfering json.transfer do json.partial! "/users/user_simple", locals: {user: @project&.applied_transfer_project&.owner} -end \ No newline at end of file +end +json.is_pinned @project.has_pinned_users.include?(current_user) \ No newline at end of file diff --git a/app/views/users/is_pinned_projects/index.json.jbuilder b/app/views/users/is_pinned_projects/index.json.jbuilder new file mode 100644 index 000000000..facc158b9 --- /dev/null +++ b/app/views/users/is_pinned_projects/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @is_pinned_projects.total_count +json.projects @is_pinned_projects.each do |project| + json.partial! "projects/project_detail", project: project +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index ae121bb08..d61acaf8e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -266,6 +266,11 @@ Rails.application.routes.draw do end end resources :headmaps, only: [:index] + resources :is_pinned_projects, only: [:index] do + collection do + post :pin + end + end resources :organizations, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] diff --git a/db/migrate/20210527024043_create_pinned_projects.rb b/db/migrate/20210527024043_create_pinned_projects.rb new file mode 100644 index 000000000..50345cebc --- /dev/null +++ b/db/migrate/20210527024043_create_pinned_projects.rb @@ -0,0 +1,11 @@ +class CreatePinnedProjects < ActiveRecord::Migration[5.2] + def change + create_table :pinned_projects do |t| + t.references :user + t.references :project + t.integer :position, default: 0 + + t.timestamps + end + end +end diff --git a/public/docs/api.html b/public/docs/api.html index 9f52b9066..9bd9bb6ea 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -331,6 +331,12 @@
  • 获取当前登陆用户信息
  • +
  • + 获取用户星标项目 +
  • +
  • + 用户添加星标项目 +
  • 获取用户贡献度
  • @@ -590,7 +596,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -652,7 +658,235 @@ Success — a happy kitten is an authenticated kitten! -

    获取用户贡献度

    +

    获取用户星标项目

    +

    获取用户星标项目

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/is_pinned_projects.json
    +
    await octokit.request('GET /api/users/:login/is_pinned_projects.json')
    +

    HTTP 请求

    +

    GET api/users/:login/is_pinned_projects.json

    +

    返回字段说明:

    +
    参数
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_countint星标项目数量
    identifierstring项目标识
    namestring项目名称
    descriptionstring项目描述
    visitsint项目访问数量
    praises_countint项目点赞数量
    watchers_countint项目关注数量
    issues_countint项目issue数量
    pull_requests_countint项目合并请求数量
    forked_countint项目复刻数量
    is_publicbool项目是否公开
    mirror_urlstring镜像地址
    typeint项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目
    time_agostring上次更新时间
    open_devopsint是否开启devops
    forked_from_project_idintfork项目id
    platformstring项目平台
    author.namestring项目拥有者名称
    author.typestring项目拥有者类型
    author.loginstring项目拥有者用户名
    author.image_urlstring项目拥有者头像
    category.namestring项目分类名称
    language.namestring项目语言名称
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_count": 1,
    +    "projects": [
    +        {
    +            "id": 89,
    +            "repo_id": 89,
    +            "identifier": "monkey",
    +            "name": "boke",
    +            "description": "dkkd",
    +            "visits": 4,
    +            "praises_count": 0,
    +            "watchers_count": 0,
    +            "issues_count": 0,
    +            "pull_requests_count": 0,
    +            "forked_count": 0,
    +            "is_public": true,
    +            "mirror_url": "https://github.com/viletyy/monkey.git",
    +            "type": 1,
    +            "last_update_time": 1619685144,
    +            "time_ago": "27天前",
    +            "forked_from_project_id": null,
    +            "open_devops": false,
    +            "platform": "forge",
    +            "author": {
    +                "name": "测试组织",
    +                "type": "Organization",
    +                "login": "ceshi_org",
    +                "image_url": "images/avatars/Organization/9?t=1612706073"
    +            },
    +            "category": {
    +                "id": 3,
    +                "name": "深度学习"
    +            },
    +            "language": {
    +                "id": 2,
    +                "name": "C"
    +            }
    +        }
    +    ]
    +}
    +
    + +

    用户添加星标项目

    +

    用户添加星标项目

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/users/yystopf/is_pinned_projects/pin.json
    +
    await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json')
    +

    HTTP 请求

    +

    POST /api/users/:login/is_pinned_projects/pin.json

    +

    请求字段说明:

    同时设定多个星标项目

    + + + + + + + + + + + + +
    参数类型字段说明
    is_pinned_project_idsarray设定为星标项目的id
    +

    只设定一个星标项目

    + + + + + + + + + + + + +
    参数类型字段说明
    is_pinned_project_idinteger设定为星标项目的id
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "status": 0,
    +    "message": "success"
    +}
    +

    获取用户贡献度

    获取用户贡献度

    @@ -660,9 +894,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
     
    await octokit.request('GET /api/users/:login/headmaps.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/headmaps.json

    -

    返回字段说明:

    +

    返回字段说明:

    @@ -791,9 +1025,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -807,7 +1041,7 @@ Success — a happy kitten is an authenticated kitten!
    参数用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1028,9 +1262,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1044,7 +1278,7 @@ Success — a happy kitten is an authenticated kitten!
    参数用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1220,9 +1454,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1241,7 +1475,7 @@ Success — a happy kitten is an authenticated kitten!
    参数迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1411,9 +1645,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1432,7 +1666,7 @@ Success — a happy kitten is an authenticated kitten!
    参数迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    diff --git a/spec/models/pinned_project_spec.rb b/spec/models/pinned_project_spec.rb new file mode 100644 index 000000000..cda43562e --- /dev/null +++ b/spec/models/pinned_project_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe PinnedProject, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From ca8fa20c2c0b28e1a0e5ad1d8b5c6585073c833d Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 27 May 2021 16:40:15 +0800 Subject: [PATCH 183/643] add: user project trends --- .../users/is_pinned_projects_controller.rb | 3 ++- .../users/project_trends_controller.rb | 11 ++++++++++ .../users/statistics_controller.rb | 2 ++ .../issues/_simple_issue_item.json.jbuilder | 3 +++ .../project_trends/_detail.json.jbuilder | 17 ++++++++++++++++ app/views/project_trends/index.json.jbuilder | 20 ++----------------- .../users/project_trends/index.json.jbuilder | 4 ++++ config/routes.rb | 1 + 8 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 app/controllers/users/project_trends_controller.rb create mode 100644 app/controllers/users/statistics_controller.rb create mode 100644 app/views/project_trends/_detail.json.jbuilder create mode 100644 app/views/users/project_trends/index.json.jbuilder diff --git a/app/controllers/users/is_pinned_projects_controller.rb b/app/controllers/users/is_pinned_projects_controller.rb index 22ce29263..4f3f4e37e 100644 --- a/app/controllers/users/is_pinned_projects_controller.rb +++ b/app/controllers/users/is_pinned_projects_controller.rb @@ -18,9 +18,10 @@ class Users::IsPinnedProjectsController < Users::BaseController private def is_pinned_project_ids if params[:is_pinned_project_ids].present? - return params[:is_pinned_project_ids].select{|id| observed_user.full_member_projects.pluck(:id).include?(id.to_i) } + return params[:is_pinned_project_ids].select{|id| observed_user.full_member_projects.visible.pluck(:id).include?(id.to_i) } end if params[:is_pinned_project_id].present? + return observed_user.is_pinned_project_ids unless observed_user.full_member_projects.visible.pluck(:id).include?(params[:is_pinned_project_id].to_i) return observed_user.is_pinned_project_ids.include?(params[:is_pinned_project_id].to_i) ? observed_user.is_pinned_project_ids : observed_user.is_pinned_project_ids.push(params[:is_pinned_project_id].to_i) end end diff --git a/app/controllers/users/project_trends_controller.rb b/app/controllers/users/project_trends_controller.rb new file mode 100644 index 000000000..9edd56f18 --- /dev/null +++ b/app/controllers/users/project_trends_controller.rb @@ -0,0 +1,11 @@ +class Users::ProjectTrendsController < Users::BaseController + + def index + if params[:date].present? + @project_trends = observed_user.project_trends.where("DATE(created_at) = ?", params[:date]) + else + @project_trends = observed_user.project_trends + end + @project_trends = kaminari_paginate(@project_trends.includes(:trend, :project).order(created_at: :desc)) + end +end \ No newline at end of file diff --git a/app/controllers/users/statistics_controller.rb b/app/controllers/users/statistics_controller.rb new file mode 100644 index 000000000..82a3ef012 --- /dev/null +++ b/app/controllers/users/statistics_controller.rb @@ -0,0 +1,2 @@ +class Users::StatisticController < Users::BaseController +end \ No newline at end of file diff --git a/app/views/issues/_simple_issue_item.json.jbuilder b/app/views/issues/_simple_issue_item.json.jbuilder index f711253a4..3f9c22e9e 100644 --- a/app/views/issues/_simple_issue_item.json.jbuilder +++ b/app/views/issues/_simple_issue_item.json.jbuilder @@ -1,4 +1,7 @@ json.name issue.try(:subject) +json.issue_type issue.try(:issue_type) +json.status_id issue.try(:status_id) +json.priority_id issue.try(:priority_id) json.created_at format_time(issue.try(:created_on)) json.updated_at format_time(issue.try(:updated_on)) json.assign_user_name issue&.get_assign_user.try(:show_real_name) diff --git a/app/views/project_trends/_detail.json.jbuilder b/app/views/project_trends/_detail.json.jbuilder new file mode 100644 index 000000000..7ffa9f152 --- /dev/null +++ b/app/views/project_trends/_detail.json.jbuilder @@ -0,0 +1,17 @@ +json.id trend.id +json.trend_type trend.trend_type +json.action_type l("trend.#{trend.action_type}") + l("trend.#{trend.trend_type}") +json.trend_id trend.trend_id +json.user_name trend.user.try(:show_real_name) +json.user_login trend.user.login +json.user_avatar url_to_avatar(trend.user) +json.action_time time_from_now(trend.created_at) + +if trend.trend_type == "Issue" + json.partial! "issues/simple_issue_item", locals: {issue: trend.trend} +elsif trend.trend_type == "VersionRelease" + json.partial! "version_releases/simple_version_release", locals: {version: trend.trend} +else + json.name trend.trend.title + json.created_at format_time(trend.trend.created_at) +end diff --git a/app/views/project_trends/index.json.jbuilder b/app/views/project_trends/index.json.jbuilder index 159a3bdb8..6dca7bdb5 100644 --- a/app/views/project_trends/index.json.jbuilder +++ b/app/views/project_trends/index.json.jbuilder @@ -9,25 +9,9 @@ json.limit @limit json.project_trends_size @project_trends_size json.project_trends do json.array! @project_trends.to_a.each do |trend| - json.id trend.id - json.trend_type trend.trend_type - json.action_type l("trend.#{trend.action_type}") + l("trend.#{trend.trend_type}") - json.trend_id trend.trend_id - json.user_name trend.user.try(:show_real_name) - json.user_login trend.user.login - json.user_avatar url_to_avatar(trend.user) - - if trend.trend_type == "Issue" - json.partial! "issues/simple_issue_item", locals: {issue: trend.trend} - elsif trend.trend_type == "VersionRelease" - json.partial! "version_releases/simple_version_release", locals: {version: trend.trend} - else - json.name trend.trend.title - json.created_at format_time(trend.trend.created_at) - end - + #后续需要天际pullrequest 和 版本的内容 - + json.partial! "detail", trend: trend end end diff --git a/app/views/users/project_trends/index.json.jbuilder b/app/views/users/project_trends/index.json.jbuilder new file mode 100644 index 000000000..d1aab1390 --- /dev/null +++ b/app/views/users/project_trends/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @project_trends.total_count +json.project_trends @project_trends.each do |trend| + json.partial! "project_trends/detail", trend: trend +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index d61acaf8e..2363b89df 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -271,6 +271,7 @@ Rails.application.routes.draw do post :pin end end + resources :project_trends, only: [:index] resources :organizations, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] From 2410f5bbc095511c464673409dc643f0769efbf9 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 15:36:05 +0800 Subject: [PATCH 184/643] add: user statistics --- .../users/statistics_controller.rb | 190 +++++++++++++++++- app/models/concerns/project_operable.rb | 1 + app/models/project.rb | 1 - app/models/user.rb | 4 +- .../projects/_project_detail.json.jbuilder | 1 + app/views/users/headmaps/index.json.jbuilder | 2 +- .../users/statistics/develop.json.jbuilder | 19 ++ app/views/users/statistics/role.json.jbuilder | 19 ++ config/routes.rb | 8 + 9 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 app/views/users/statistics/develop.json.jbuilder create mode 100644 app/views/users/statistics/role.json.jbuilder diff --git a/app/controllers/users/statistics_controller.rb b/app/controllers/users/statistics_controller.rb index 82a3ef012..7ab9a4bf4 100644 --- a/app/controllers/users/statistics_controller.rb +++ b/app/controllers/users/statistics_controller.rb @@ -1,2 +1,190 @@ -class Users::StatisticController < Users::BaseController +class Users::StatisticsController < Users::BaseController + before_action :preload_develop_data, only: [:develop] + + # 近期活动统计 + def activity + date_range = (1.week.ago.to_date..Date.today).to_a + commit_request = Gitea::User::HeadmapService.call(observed_user.login, 1.week.ago.to_date.to_time.to_i, Date.today.to_time.to_i) + commit_data = commit_request[2] + @date_data = [] + @issue_data = [] + @pull_request_data = [] + @commit_data = [] + date_range.each do |date| + @date_data << date.strftime("%Y.%m.%d") + @issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size + @pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size + date_commit_data = commit_data.select{|item| item["timestamp"] == date.to_time.to_i} + @commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i) + end + render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commtis_count: @commit_data} + end + + # 开发能力 + def develop + if params[:start_time].present? && params[:end_time].present? + # 影响力 + @influence = (60.0 + @follow_count / (@follow_count + 10.0) * 40.0).to_i + @platform_influence = (60.0 + @platform_follow_count / (@platform_follow_count + 10.0) * 40.0).to_i + # 贡献度 + @contribution = (60.0 + @pullrequest_count / (@pullrequest_count + 10.0) * 40.0).to_i + @platform_contribution = (60.0 + @platform_pullrequest_count / (@platform_pullrequest_count + 10.0) * 40.0).to_i + # 活跃度 + @activity = (60.0 + @issues_count / (@issues_count + 10.0) * 40.0).to_i + @platform_activity = (60.0 + @platform_issues_count / (@platform_issues_count + 10.0) * 40.0).to_i + # 项目经验 + @experience = 10 * @project_count + 5 * @fork_count + @project_watchers_count + @project_praises_count + @experience = (60.0 + @experience / (@experience + 100.0) * 40.0).to_i + @platform_experience = 10 * @platform_project_count + 5 * @platform_fork_count + @platform_project_watchers_count + @platform_project_praises_count + @platform_experience = (60.0 + @platform_experience / (@platform_experience + 100.0) * 40.0).to_i + # 语言能力 + @language = (60.0 + @project_languages_count.length / (@project_languages_count.length + 5.0) * 40.0).to_i + @platform_language = (60.0 + @platform_project_languages_count.length / (@platform_project_languages_count.length + 5.0) * 40.0).to_i + # 语言百分比 + @languages_percent = Hash.new + for key in @project_languages_count.keys do + @languages_percent[key] = (@project_languages_count[key].to_f / @project_languages_count.values.sum).round(2) + end + @platform_languages_percent = Hash.new + for key in @platform_project_languages_count.keys do + @platform_languages_percent[key] = (@platform_project_languages_count[key].to_f / @platform_project_languages_count.values.sum).round(2) + end + # 各门语言分数 + @each_language_score = Hash.new + for key in @project_languages_count.keys do + @each_language_score[key] = (60.0 + @project_languages_count[key] / (@project_languages_count[key] + 5.0) * 40.0).to_i + end + @platform_each_language_score = Hash.new + for key in @platform_project_languages_count.keys do + @platform_each_language_score[key] = (60.0 + @platform_project_languages_count[key] / (@platform_project_languages_count[key] + 5.0) * 40.0).to_i + end + else + # 影响力 + @influence = (60.0 + @follow_count / (@follow_count + 20.0) * 40.0).to_i + @platform_influence = (60.0 + @platform_follow_count / (@platform_follow_count + 20.0) * 40.0).to_i + + # 贡献度 + @contribution = (60.0 + @pullrequest_count / (@pullrequest_count + 20.0) * 40.0).to_i + @platform_contribution = (60.0 + @platform_pullrequest_count / (@platform_pullrequest_count + 20.0) * 40.0).to_i + + # 活跃度 + @activity = (60.0 + @issues_count / (@issues_count + 80.0) * 40.0).to_i + @platform_activity = (60.0 + @platform_issues_count / (@platform_issues_count + 80.0) * 40.0).to_i + + # 项目经验 + @experience = 10 * @project_count + 5 * @fork_count + @project_watchers_count + @project_praises_count + @experience = (60.0 + @experience / (@experience + 100.0) * 40.0).to_i + @platform_experience = 10 * @platform_project_count + 5 * @platform_fork_count + @platform_project_watchers_count + @platform_project_praises_count + @platform_experience = (60.0 + @platform_experience / (@platform_experience + 100.0) * 40.0).to_i + # 语言能力 + @language = (60.0 + @project_languages_count.length / (@project_languages_count.length + 5.0) * 40.0).to_i + @platform_language = (60.0 + @platform_project_languages_count.length / (@platform_project_languages_count.length + 5.0) * 40.0).to_i + + # 语言百分比 + @languages_percent = Hash.new + for key in @project_languages_count.keys do + @languages_percent[key] = (@project_languages_count[key].to_f / @project_languages_count.values.sum).round(2) + end + @platform_languages_percent = Hash.new + for key in @platform_project_languages_count.keys do + @platform_languages_percent[key] = (@platform_project_languages_count[key].to_f / @platform_project_languages_count.values.sum).round(2) + end + # 各门语言分数 + @each_language_score = Hash.new + for key in @project_languages_count.keys do + @each_language_score[key] = (60.0 + @project_languages_count[key] / (@project_languages_count[key] + 5.0) * 40.0).to_i + end + @platform_each_language_score = Hash.new + for key in @platform_project_languages_count.keys do + @platform_each_language_score[key] = (60.0 + @platform_project_languages_count[key] / (@platform_project_languages_count[key] + 5.0) * 40.0).to_i + end + end + + end + + # 角色定位 + def role + full_member_projects = observed_user.full_member_projects + owner_projects = filter_member_projects_by_role("Owner") + manager_projects = filter_member_projects_by_role("Manager").where.not(id: owner_projects.ids) + developer_projects = filter_member_projects_by_role("Developer").where.not(id: owner_projects.ids + manager_projects.ids) + reporter_projects = filter_member_projects_by_role("Reporter").where.not(id: owner_projects.ids + manager_projects.ids + developer_projects.ids) + + @full_member_projects_count = full_member_projects.size + @owner_projects_count = owner_projects.size + @manager_projects_count = manager_projects.size + @developer_projects_count = developer_projects.size + @reporter_projects_count = reporter_projects.size + + end + + # 专业定位 + def major + # 参与项目 + join_normal_projects_sql = Project.members_projects(observed_user.id).to_sql + join_org_projects_sql = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: observed_user.id}).to_sql + # 关注项目 + star_projects_sql = Project.joins(:watchers).where(watchers: {watchable_type: "Project", user_id: observed_user.id}).to_sql + # fork项目 + fork_projects_sql = Project.where(id: observed_user.fork_users.select(:id, :fork_project_id).pluck(:fork_project_id)).to_sql + major_projects = Project.from("( #{ join_normal_projects_sql} UNION #{ join_org_projects_sql } UNION #{ star_projects_sql } UNION #{fork_projects_sql}) AS projects").distinct + categories = ProjectCategory.joins(:projects).merge(Project.where(id: time_filter(major_projects, 'created_on'))).distinct.pluck(:name) + render :json => {categories: categories} + end + + private + def time_filter(collection, time_field) + if params[:start_time].present? && params[:end_time].present? + return collection.where("#{time_field} > ? AND #{time_field} < ?", Time.at(params[:start_time].to_i).beginning_of_day, Time.at(params[:end_time].to_i).end_of_day) + else + return collection + end + rescue + return collection + end + + def filter_member_projects_by_role(role) + case role + when 'Owner' + normal_projects_sql = Project.joins(members: :roles).where(user_id: observed_user.id).where(members: {user_id: observed_user.id}, roles: {name: 'Manager'}).to_sql + org_projects_sql = Project.joins(:owner, teams: :team_users).where(users: {type: 'Organization'}, teams: {authorize: "owner"}, team_users: {user_id: observed_user.id}).to_sql + when "Manager" + normal_projects_sql = Project.joins(members: :roles).where.not(user_id: observed_user.id).where(members: {user_id: observed_user.id}, roles: {name: 'Manager'}).to_sql + org_projects_sql = Project.joins(:owner, teams: :team_users).where(users: {type: 'Organization'}, teams: {authorize: "admin"}, team_users: {user_id: observed_user.id}).to_sql + when "Developer" + normal_projects_sql = Project.joins(members: :roles).where.not(user_id: observed_user.id).where(members: {user_id: observed_user.id}, roles: {name: 'Developer'}).to_sql + org_projects_sql = Project.joins(:owner, teams: :team_users).where(users: {type: 'Organization'}, teams: {authorize: "write"}, team_users: {user_id: observed_user.id}).to_sql + when "Reporter" + normal_projects_sql = Project.joins(members: :roles).where.not(user_id: observed_user.id).where(members: {user_id: observed_user.id}, roles: {name: 'Reporter'}).to_sql + org_projects_sql = Project.joins(:owner, teams: :team_users).where(users: {type: 'Organization'}, teams: {authorize: "read"}, team_users: {user_id: observed_user.id}).to_sql + end + return time_filter(Project.from("( #{normal_projects_sql} UNION #{org_projects_sql} ) AS projects").distinct, 'created_on') + end + + def preload_develop_data + # 用户被follow数量 + @follow_count = time_filter(Watcher.where(watchable: observed_user), 'created_at').count + @platform_follow_count = time_filter(Watcher.where(watchable_type: 'User'), 'created_at').count + # 用户pr数量 + @pullrequest_count = time_filter(PullRequest.where(user_id: observed_user.id), 'created_at').count + @platform_pullrequest_count = time_filter(PullRequest, 'created_at').count + # 用户issue数量 + @issues_count = time_filter(Issue.where(author_id: observed_user.id), 'created_on').count + @platform_issues_count = time_filter(Issue, 'created_on').count + # 用户总项目数 @fork_count + @project_watchers_count + @project_praises_count + @project_count = filter_member_projects_by_role("Owner").count + @platform_project_count = time_filter(Project, 'created_on').count + # 用户项目被fork数量 + @fork_count = filter_member_projects_by_role("Owner").sum("forked_count") + @platform_fork_count = time_filter(Project, 'created_on').sum("forked_count") + # 用户项目关注数 + @project_watchers_count = filter_member_projects_by_role("Owner").sum("watchers_count") + @platform_project_watchers_count = time_filter(Project, 'created_on').sum("watchers_count") + # 用户项目点赞数 + @project_praises_count = filter_member_projects_by_role("Owner").sum("praises_count") + @platform_project_praises_count = time_filter(Project, 'created_on').sum("praises_count") + # 用户不同语言项目数量 + @project_languages_count = filter_member_projects_by_role("Owner").joins(:project_language).group("project_languages.name").count + @platform_project_languages_count = time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count + end end \ No newline at end of file diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index b8adf5c8a..e016ca1dc 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -9,6 +9,7 @@ module ProjectOperable has_many :reporters, -> { joins(:roles).where(roles: { name: 'Reporter' }) }, class_name: 'Member' has_many :writable_members, -> { joins(:roles).where.not(roles: {name: 'Reporter'}) }, class_name: 'Member' has_many :team_projects, dependent: :destroy + has_many :teams, through: :team_projects, source: :team end def set_owner_permission(creator) diff --git a/app/models/project.rb b/app/models/project.rb index 9299abcdb..8141a56bf 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -111,7 +111,6 @@ class Project < ApplicationRecord has_many :praise_treads, as: :praise_tread_object, dependent: :destroy has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position" has_one :project_detail, dependent: :destroy - has_many :team_projects, dependent: :destroy has_many :project_units, dependent: :destroy has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy has_many :pinned_projects, dependent: :destroy diff --git a/app/models/user.rb b/app/models/user.rb index bac795dd5..56043f5f6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -167,6 +167,8 @@ class User < Owner has_many :pinned_projects, dependent: :destroy has_many :is_pinned_projects, through: :pinned_projects, source: :project accepts_nested_attributes_for :is_pinned_projects + has_many :issues, dependent: :destroy, foreign_key: :author_id + has_many :pull_requests, dependent: :destroy # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } @@ -201,7 +203,7 @@ class User < Owner # 用户参与的所有项目 def full_member_projects normal_projects = Project.members_projects(self.id).to_sql - org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: self.id}).to_sql + org_projects = Project.joins(teams: :team_users).where(team_users: {user_id: self.id}).to_sql return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct end diff --git a/app/views/projects/_project_detail.json.jbuilder b/app/views/projects/_project_detail.json.jbuilder index 2e256fcb4..da5d67473 100644 --- a/app/views/projects/_project_detail.json.jbuilder +++ b/app/views/projects/_project_detail.json.jbuilder @@ -17,6 +17,7 @@ json.time_ago time_from_now(project.updated_on) json.forked_from_project_id project.forked_from_project_id json.open_devops project.open_devops? json.platform project.platform +json.is_pinned @project.has_pinned_users.include?(current_user) json.author do if project.educoder? project_educoder = project.project_educoder diff --git a/app/views/users/headmaps/index.json.jbuilder b/app/views/users/headmaps/index.json.jbuilder index 7011b2559..0e6a540b5 100644 --- a/app/views/users/headmaps/index.json.jbuilder +++ b/app/views/users/headmaps/index.json.jbuilder @@ -1,5 +1,5 @@ json.total_contributions @headmaps.collect{|map| map["contributions"]}.reduce(0, :+) json.headmaps @headmaps.each do |map| - json.date map["timestamp"] + json.date Time.at(map["timestamp"].to_i).strftime("%Y-%m-%d") json.contributions map["contributions"] end diff --git a/app/views/users/statistics/develop.json.jbuilder b/app/views/users/statistics/develop.json.jbuilder new file mode 100644 index 000000000..9d530fbbe --- /dev/null +++ b/app/views/users/statistics/develop.json.jbuilder @@ -0,0 +1,19 @@ +json.platform do + json.influence @platform_influence + json.contribution @platform_contribution + json.activity @platform_activity + json.experience @platform_experience + json.language @platform_language + json.languages_percent @platform_languages_percent + json.each_language_score @platform_each_language_score +end + +json.user do + json.influence @influence + json.contribution @contribution + json.activity @activity + json.experience @experience + json.language @language + json.languages_percent @languages_percent + json.each_language_score @each_language_score +end \ No newline at end of file diff --git a/app/views/users/statistics/role.json.jbuilder b/app/views/users/statistics/role.json.jbuilder new file mode 100644 index 000000000..5ca290586 --- /dev/null +++ b/app/views/users/statistics/role.json.jbuilder @@ -0,0 +1,19 @@ +json.total_projects_count @full_member_projects_count +json.role do + json.owner do + json.count @owner_projects_count + json.percent (@owner_projects_count.to_f/@full_member_projects_count).round(2) + end + json.manager do + json.count @manager_projects_count + json.percent (@manager_projects_count.to_f/@full_member_projects_count).round(2) + end + json.developer do + json.count @developer_projects_count + json.percent (@developer_projects_count.to_f/@full_member_projects_count).round(2) + end + json.reporter do + json.count @reporter_projects_count + json.percent (@reporter_projects_count.to_f/@full_member_projects_count).round(2) + end +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 2363b89df..cfadf4941 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -271,6 +271,14 @@ Rails.application.routes.draw do post :pin end end + resources :statistics, only: [:index] do + collection do + get :activity + get :develop + get :role + get :major + end + end resources :project_trends, only: [:index] resources :organizations, only: [:index] # resources :projects, only: [:index] From 1872ad00d56f3e3e8f32538b980b8f3fe136525e Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 16:04:52 +0800 Subject: [PATCH 185/643] uupdate: api docs --- .../users/statistics_controller.rb | 2 +- app/docs/slate/source/includes/_users.md | 609 +++++++++++++- public/docs/api.html | 795 +++++++++++++++++- 3 files changed, 1346 insertions(+), 60 deletions(-) diff --git a/app/controllers/users/statistics_controller.rb b/app/controllers/users/statistics_controller.rb index 7ab9a4bf4..d508176e2 100644 --- a/app/controllers/users/statistics_controller.rb +++ b/app/controllers/users/statistics_controller.rb @@ -17,7 +17,7 @@ class Users::StatisticsController < Users::BaseController date_commit_data = commit_data.select{|item| item["timestamp"] == date.to_time.to_i} @commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i) end - render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commtis_count: @commit_data} + render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data} end # 开发能力 diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index b2c3ebccb..d7e8ed488 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -176,6 +176,82 @@ await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json') ``` +## 用户近期活动统计 +用户近期活动统计, 默认显示近一周的数据 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/statistics/activity.json +``` + +```javascript +await octokit.request('GET /api/users/:login/statistics/activity.json') +``` + +### HTTP 请求 +`GET /api/users/:login/statistics/activity.json` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|dates |array |时间 | +|issues_count |array |易修数量| +|pull_requests_count |array |合并请求数量| +|commtis_count |array |贡献数量| + + +> 返回的JSON示例: + +```json +{ + "dates": [ + "2021.05.21", + "2021.05.22", + "2021.05.23", + "2021.05.24", + "2021.05.25", + "2021.05.26", + "2021.05.27", + "2021.05.28" + ], + "issues_count": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "pull_requests_count": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "commits_count": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] +} +``` + + + ## 获取用户贡献度 获取用户贡献度 @@ -192,6 +268,12 @@ await octokit.request('GET /api/users/:login/headmaps.json') ### HTTP 请求 `GET api/users/:login/headmaps.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|year |string |年份 | + ### 返回字段说明: 参数 | 类型 | 字段说明 --------- | ----------- | ----------- @@ -207,87 +289,87 @@ await octokit.request('GET /api/users/:login/headmaps.json') "total_contributions": 139, "headmaps": [ { - "date": 1612627200, + "date": "2021-02-07", "contributions": 1 }, { - "date": 1613836800, + "date": "2021-02-21", "contributions": 13 }, { - "date": 1614182400, + "date": "2021-02-25", "contributions": 5 }, { - "date": 1614528000, + "date": "2021-03-01", "contributions": 2 }, { - "date": 1614787200, + "date": "2021-03-04", "contributions": 1 }, { - "date": 1615737600, + "date": "2021-03-15", "contributions": 9 }, { - "date": 1616342400, + "date": "2021-03-22", "contributions": 14 }, { - "date": 1616515200, + "date": "2021-03-24", "contributions": 1 }, { - "date": 1617033600, + "date": "2021-03-30", "contributions": 11 }, { - "date": 1617638400, + "date": "2021-04-06", "contributions": 1 }, { - "date": 1618156800, + "date": "2021-04-12", "contributions": 1 }, { - "date": 1618243200, + "date": "2021-04-13", "contributions": 2 }, { - "date": 1618761600, + "date": "2021-04-19", "contributions": 3 }, { - "date": 1619107200, + "date": "2021-04-23", "contributions": 37 }, { - "date": 1619280000, + "date": "2021-04-25", "contributions": 2 }, { - "date": 1619366400, + "date": "2021-04-26", "contributions": 6 }, { - "date": 1619539200, + "date": "2021-04-28", "contributions": 1 }, { - "date": 1619625600, + "date": "2021-04-29", "contributions": 18 }, { - "date": 1619712000, + "date": "2021-04-30", "contributions": 9 }, { - "date": 1620057600, + "date": "2021-05-04", "contributions": 1 }, { - "date": 1620230400, + "date": "2021-05-06", "contributions": 1 } ] @@ -297,6 +379,489 @@ await octokit.request('GET /api/users/:login/headmaps.json') Success Data. +## 获取用户动态 +获取用户动态 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/project_trends.json +``` + +```javascript +await octokit.request('GET /api/users/:login/project_trends.json') +``` + +### HTTP 请求 +`GET api/users/:login/project_trends.json` + + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|date |string |日期,格式: 2021-05-28 | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_count |int |所选时间内的总动态数 | +|project_trends.trend_type |string|动态类型,Issue:易修,VersionRelease:版本发布,PullRequest:合并请求| +|project_trends.action_type |string|操作类型| +|project_trends.trend_id |integer|动态id| +|project_trends.user_name |string|用户名称| +|project_trends.user_login |string|用户用户名| +|project_trends.user_avatar |string|用户头像| +|project_trends.action_time |string|操作时间| +|project_trends.name |string|动态标题| + +> 返回的JSON示例: + +```json +{ + "total_count": 16, + "project_trends": [ + { + "id": 27, + "trend_type": "Issue", + "action_type": "创建了工单", + "trend_id": 18, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "21天前", + "name": "31213123123", + "issue_type": "1", + "status_id": 2, + "priority_id": 4, + "created_at": "2021-05-07 15:39", + "updated_at": "2021-05-27 15:42", + "assign_user_name": "yystopf", + "assign_user_login": "yystopf", + "issue_journal_size": 1, + "issue_journals": [] + }, + { + "id": 8, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 8, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "24天前", + "name": "heihei1", + "tag_name": "v1.0", + "target_commitish": "master", + "tarball_url": "http://localhost:10080/forgeceshiorg1/ceshi1/archive/v1.0.tar.gz", + "zipball_url": "http://localhost:10080/forgeceshiorg1/ceshi1/archive/v1.0.zip", + "url": "http://localhost:10080/api/v1/repos/forgeceshiorg1/ceshi1/releases/84", + "version_gid": "84", + "created_at": "2021-05-04 12:04" + }, + { + "id": 25, + "trend_type": "PullRequest", + "action_type": "关闭了合并请求", + "trend_id": 14, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "13", + "created_at": "2021-04-30 15:39" + }, + { + "id": 24, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 13, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "211212", + "created_at": "2021-04-30 15:37" + }, + { + "id": 23, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 12, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "奇偶哦iu", + "created_at": "2021-04-30 10:19" + }, + { + "id": 22, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 11, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "2112123", + "created_at": "2021-04-29 18:46" + }, + { + "id": 21, + "trend_type": "PullRequest", + "action_type": "关闭了合并请求", + "trend_id": 10, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "23123", + "created_at": "2021-04-29 18:45" + }, + { + "id": 20, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 9, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "33", + "created_at": "2021-04-29 18:37" + }, + { + "id": 19, + "trend_type": "PullRequest", + "action_type": "关闭了合并请求", + "trend_id": 8, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "28天前", + "name": "gggg", + "created_at": "2021-04-29 17:51" + }, + { + "id": 16, + "trend_type": "Issue", + "action_type": "创建了工单", + "trend_id": 8, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "1个月前", + "name": "hjhkj", + "issue_type": "1", + "status_id": 1, + "priority_id": 2, + "created_at": "2021-04-19 10:52", + "updated_at": "2021-04-19 10:52", + "assign_user_name": null, + "assign_user_login": null, + "issue_journal_size": 0, + "issue_journals": [] + }, + { + "id": 7, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 7, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "1个月前", + "name": "v3.0.1", + "tag_name": "v3.0.1", + "target_commitish": "master", + "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.1.tar.gz", + "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.1.zip", + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/78", + "version_gid": "78", + "created_at": "2021-03-30 15:51" + }, + { + "id": 6, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 6, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "1个月前", + "name": "v3.0.0", + "tag_name": "v3.0.0", + "target_commitish": "master", + "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.0.tar.gz", + "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.0.zip", + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/77", + "version_gid": "77", + "created_at": "2021-03-30 15:33" + }, + { + "id": 5, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 5, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "1个月前", + "name": "v1.0.0", + "tag_name": "v1.0.0", + "target_commitish": "master", + "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v1.0.0.tar.gz", + "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v1.0.0.zip", + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/76", + "version_gid": "76", + "created_at": "2021-03-30 15:27" + }, + { + "id": 2, + "trend_type": "VersionRelease", + "action_type": "创建了版本发布", + "trend_id": 2, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "2个月前", + "name": "vvvv", + "tag_name": "v1.1", + "target_commitish": "dev", + "tarball_url": "http://localhost:10080/yystopf/virus_blog/archive/v1.1.tar.gz", + "zipball_url": "http://localhost:10080/yystopf/virus_blog/archive/v1.1.zip", + "url": "http://localhost:10080/api/v1/repos/yystopf/virus_blog/releases/6", + "version_gid": "6", + "created_at": "2021-03-15 14:18" + }, + { + "id": 2, + "trend_type": "PullRequest", + "action_type": "创建了合并请求", + "trend_id": 2, + "user_name": "yystopf", + "user_login": "yystopf", + "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png", + "action_time": "3个月前", + "name": "444", + "created_at": "2021-02-25 17:31" + } + ] +} +``` + + +## 用户开发能力 +用户开发能力, 默认为所有时间下的开发能力 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/statistics/develop.json +``` + +```javascript +await octokit.request('GET /api/users/:login/statistics/develop.json') +``` + +### HTTP 请求 +`GET /api/users/:login/statistics/develop.json` + + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|start_time |integer |时间戳,开始时间,格式:1621526400| +|end_time |integer |时间戳,结束时间,格式:1622131200| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|influence |int |影响力 | +|contribution |int |贡献度| +|activity |int |活跃度| +|experience |int |项目经验| +|language |int |语言能力| +|languages_percent |float |语言百分比| +|each_language_score |int |各门语言分数| + + +> 返回的JSON示例: + +```json +{ + "platform": { + "influence": 61, + "contribution": 75, + "activity": 66, + "experience": 95, + "language": 87, + "languages_percent": { + "CSS": 0.03, + "C#": 0.13, + "Ruby": 0.04, + "Go": 0.05, + "C": 0.19, + "Java": 0.34, + "Python": 0.09, + "C+": 0.01, + "C++": 0.11, + "Scala": 0.01, + "HTML": 0.01 + }, + "each_language_score": { + "CSS": 71, + "C#": 86, + "Ruby": 75, + "Go": 77, + "C": 90, + "Java": 93, + "Python": 83, + "C+": 66, + "C++": 85, + "Scala": 66, + "HTML": 66 + } + }, + "user": { + "influence": 60, + "contribution": 72, + "activity": 65, + "experience": 88, + "language": 84, + "languages_percent": { + "C": 0.25, + "C#": 0.33, + "C++": 0.13, + "CSS": 0.08, + "Go": 0.04, + "HTML": 0.04, + "Java": 0.04, + "Ruby": 0.08 + }, + "each_language_score": { + "C": 81, + "C#": 84, + "C++": 75, + "CSS": 71, + "Go": 66, + "HTML": 66, + "Java": 66, + "Ruby": 71 + } + } +} +``` + + +## 用户角色定位 +用户角色定位,默认显示所有时间下的角色定位数据 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/statistics/role.json +``` + +```javascript +await octokit.request('GET /api/users/:login/statistics/role.json') +``` + +### HTTP 请求 +`GET /api/users/:login/statistics/role.json` + + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|start_time |integer |时间戳,开始时间,格式:1621526400| +|end_time |integer |时间戳,结束时间,格式:1622131200| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_projects_count |int |用户所有的项目数量 | +|role.object.count |int |用户该语言下的项目数量| +|role.object.percent |float |用户该语言下的项目占比| + +> 返回的JSON示例: + +```json +{ + "total_projects_count": 27, + "role": { + "owner": { + "count": 24, + "percent": 0.89 + }, + "manager": { + "count": 1, + "percent": 0.04 + }, + "developer": { + "count": 2, + "percent": 0.07 + }, + "reporter": { + "count": 0, + "percent": 0.0 + } + } +} +``` + + +## 用户专业定位 +用户专业定位,默认显示所有时间下的专业定位数据 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/statistics/major.json +``` + +```javascript +await octokit.request('GET /api/users/:login/statistics/major.json') +``` + +### HTTP 请求 +`GET /api/users/:login/statistics/major.json` + + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|start_time |integer |时间戳,开始时间,格式:1621526400| +|end_time |integer |时间戳,结束时间,格式:1622131200| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|categories |int |用户项目分类 | + +> 返回的JSON示例: + +```json +{ + "categories": [ + "大数据", + "机器学习", + "深度学习", + "人工智能", + "智慧医疗", + "云计算" + ] +} +``` + ## 待办事项-用户通知信息 待办事项-用户通知信息 diff --git a/public/docs/api.html b/public/docs/api.html index 9bd9bb6ea..616803e4e 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -337,9 +337,24 @@
  • 用户添加星标项目
  • +
  • + 用户近期活动统计 +
  • 获取用户贡献度
  • +
  • + 获取用户动态 +
  • +
  • + 用户开发能力 +
  • +
  • + 用户角色定位 +
  • +
  • + 用户专业定位 +
  • 待办事项-用户通知信息
  • @@ -596,7 +611,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -886,7 +901,96 @@ Success — a happy kitten is an authenticated kitten! "status": 0, "message": "success" } -

    获取用户贡献度

    +

    用户近期活动统计

    +

    用户近期活动统计, 默认显示近一周的数据

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/activity.json
    +
    await octokit.request('GET /api/users/:login/statistics/activity.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/statistics/activity.json

    +

    返回字段说明:

    +
    参数
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    datesarray时间
    issues_countarray易修数量
    pull_requests_countarray合并请求数量
    commtis_countarray贡献数量
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "dates": [
    +        "2021.05.21",
    +        "2021.05.22",
    +        "2021.05.23",
    +        "2021.05.24",
    +        "2021.05.25",
    +        "2021.05.26",
    +        "2021.05.27",
    +        "2021.05.28"
    +    ],
    +    "issues_count": [
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0
    +    ],
    +    "pull_requests_count": [
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0
    +    ],
    +    "commits_count": [
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0,
    +        0
    +    ]
    +}
    +
    + +

    获取用户贡献度

    获取用户贡献度

    @@ -894,9 +998,23 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
     
    await octokit.request('GET /api/users/:login/headmaps.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/headmaps.json

    -

    返回字段说明:

    +

    请求字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    yearstring年份
    +

    返回字段说明:

    @@ -928,87 +1046,87 @@ Success — a happy kitten is an authenticated kitten! "total_contributions": 139, "headmaps": [ { - "date": 1612627200, + "date": "2021-02-07", "contributions": 1 }, { - "date": 1613836800, + "date": "2021-02-21", "contributions": 13 }, { - "date": 1614182400, + "date": "2021-02-25", "contributions": 5 }, { - "date": 1614528000, + "date": "2021-03-01", "contributions": 2 }, { - "date": 1614787200, + "date": "2021-03-04", "contributions": 1 }, { - "date": 1615737600, + "date": "2021-03-15", "contributions": 9 }, { - "date": 1616342400, + "date": "2021-03-22", "contributions": 14 }, { - "date": 1616515200, + "date": "2021-03-24", "contributions": 1 }, { - "date": 1617033600, + "date": "2021-03-30", "contributions": 11 }, { - "date": 1617638400, + "date": "2021-04-06", "contributions": 1 }, { - "date": 1618156800, + "date": "2021-04-12", "contributions": 1 }, { - "date": 1618243200, + "date": "2021-04-13", "contributions": 2 }, { - "date": 1618761600, + "date": "2021-04-19", "contributions": 3 }, { - "date": 1619107200, + "date": "2021-04-23", "contributions": 37 }, { - "date": 1619280000, + "date": "2021-04-25", "contributions": 2 }, { - "date": 1619366400, + "date": "2021-04-26", "contributions": 6 }, { - "date": 1619539200, + "date": "2021-04-28", "contributions": 1 }, { - "date": 1619625600, + "date": "2021-04-29", "contributions": 18 }, { - "date": 1619712000, + "date": "2021-04-30", "contributions": 9 }, { - "date": 1620057600, + "date": "2021-05-04", "contributions": 1 }, { - "date": 1620230400, + "date": "2021-05-06", "contributions": 1 } ] @@ -1017,6 +1135,609 @@ Success — a happy kitten is an authenticated kitten! +

    获取用户动态

    +

    获取用户动态

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/project_trends.json
    +
    await octokit.request('GET /api/users/:login/project_trends.json')
    +

    HTTP 请求

    +

    GET api/users/:login/project_trends.json

    +

    请求字段说明:

    +
    参数
    + + + + + + + + + + + +
    参数类型字段说明
    datestring日期,格式: 2021-05-28
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_countint所选时间内的总动态数
    project_trends.trend_typestring动态类型,Issue:易修,VersionRelease:版本发布,PullRequest:合并请求
    project_trends.action_typestring操作类型
    project_trends.trend_idinteger动态id
    project_trends.user_namestring用户名称
    project_trends.user_loginstring用户用户名
    project_trends.user_avatarstring用户头像
    project_trends.action_timestring操作时间
    project_trends.namestring动态标题
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_count": 16,
    +    "project_trends": [
    +        {
    +            "id": 27,
    +            "trend_type": "Issue",
    +            "action_type": "创建了工单",
    +            "trend_id": 18,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "21天前",
    +            "name": "31213123123",
    +            "issue_type": "1",
    +            "status_id": 2,
    +            "priority_id": 4,
    +            "created_at": "2021-05-07 15:39",
    +            "updated_at": "2021-05-27 15:42",
    +            "assign_user_name": "yystopf",
    +            "assign_user_login": "yystopf",
    +            "issue_journal_size": 1,
    +            "issue_journals": []
    +        },
    +        {
    +            "id": 8,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 8,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "24天前",
    +            "name": "heihei1",
    +            "tag_name": "v1.0",
    +            "target_commitish": "master",
    +            "tarball_url": "http://localhost:10080/forgeceshiorg1/ceshi1/archive/v1.0.tar.gz",
    +            "zipball_url": "http://localhost:10080/forgeceshiorg1/ceshi1/archive/v1.0.zip",
    +            "url": "http://localhost:10080/api/v1/repos/forgeceshiorg1/ceshi1/releases/84",
    +            "version_gid": "84",
    +            "created_at": "2021-05-04 12:04"
    +        },
    +        {
    +            "id": 25,
    +            "trend_type": "PullRequest",
    +            "action_type": "关闭了合并请求",
    +            "trend_id": 14,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "13",
    +            "created_at": "2021-04-30 15:39"
    +        },
    +        {
    +            "id": 24,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 13,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "211212",
    +            "created_at": "2021-04-30 15:37"
    +        },
    +        {
    +            "id": 23,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 12,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "奇偶哦iu",
    +            "created_at": "2021-04-30 10:19"
    +        },
    +        {
    +            "id": 22,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 11,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "2112123",
    +            "created_at": "2021-04-29 18:46"
    +        },
    +        {
    +            "id": 21,
    +            "trend_type": "PullRequest",
    +            "action_type": "关闭了合并请求",
    +            "trend_id": 10,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "23123",
    +            "created_at": "2021-04-29 18:45"
    +        },
    +        {
    +            "id": 20,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 9,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "33",
    +            "created_at": "2021-04-29 18:37"
    +        },
    +        {
    +            "id": 19,
    +            "trend_type": "PullRequest",
    +            "action_type": "关闭了合并请求",
    +            "trend_id": 8,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "28天前",
    +            "name": "gggg",
    +            "created_at": "2021-04-29 17:51"
    +        },
    +        {
    +            "id": 16,
    +            "trend_type": "Issue",
    +            "action_type": "创建了工单",
    +            "trend_id": 8,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "1个月前",
    +            "name": "hjhkj",
    +            "issue_type": "1",
    +            "status_id": 1,
    +            "priority_id": 2,
    +            "created_at": "2021-04-19 10:52",
    +            "updated_at": "2021-04-19 10:52",
    +            "assign_user_name": null,
    +            "assign_user_login": null,
    +            "issue_journal_size": 0,
    +            "issue_journals": []
    +        },
    +        {
    +            "id": 7,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 7,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "1个月前",
    +            "name": "v3.0.1",
    +            "tag_name": "v3.0.1",
    +            "target_commitish": "master",
    +            "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.1.tar.gz",
    +            "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.1.zip",
    +            "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/78",
    +            "version_gid": "78",
    +            "created_at": "2021-03-30 15:51"
    +        },
    +        {
    +            "id": 6,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 6,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "1个月前",
    +            "name": "v3.0.0",
    +            "tag_name": "v3.0.0",
    +            "target_commitish": "master",
    +            "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.0.tar.gz",
    +            "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v3.0.0.zip",
    +            "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/77",
    +            "version_gid": "77",
    +            "created_at": "2021-03-30 15:33"
    +        },
    +        {
    +            "id": 5,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 5,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "1个月前",
    +            "name": "v1.0.0",
    +            "tag_name": "v1.0.0",
    +            "target_commitish": "master",
    +            "tarball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v1.0.0.tar.gz",
    +            "zipball_url": "http://localhost:10080/yystopf/ceshirepo1/archive/v1.0.0.zip",
    +            "url": "http://localhost:10080/api/v1/repos/yystopf/ceshirepo1/releases/76",
    +            "version_gid": "76",
    +            "created_at": "2021-03-30 15:27"
    +        },
    +        {
    +            "id": 2,
    +            "trend_type": "VersionRelease",
    +            "action_type": "创建了版本发布",
    +            "trend_id": 2,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "2个月前",
    +            "name": "vvvv",
    +            "tag_name": "v1.1",
    +            "target_commitish": "dev",
    +            "tarball_url": "http://localhost:10080/yystopf/virus_blog/archive/v1.1.tar.gz",
    +            "zipball_url": "http://localhost:10080/yystopf/virus_blog/archive/v1.1.zip",
    +            "url": "http://localhost:10080/api/v1/repos/yystopf/virus_blog/releases/6",
    +            "version_gid": "6",
    +            "created_at": "2021-03-15 14:18"
    +        },
    +        {
    +            "id": 2,
    +            "trend_type": "PullRequest",
    +            "action_type": "创建了合并请求",
    +            "trend_id": 2,
    +            "user_name": "yystopf",
    +            "user_login": "yystopf",
    +            "user_avatar": "system/lets/letter_avatars/2/Y/241_125_89/120.png",
    +            "action_time": "3个月前",
    +            "name": "444",
    +            "created_at": "2021-02-25 17:31"
    +        }
    +    ]
    +}
    +
    + +

    用户开发能力

    +

    用户开发能力, 默认为所有时间下的开发能力

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/develop.json
    +
    await octokit.request('GET /api/users/:login/statistics/develop.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/statistics/develop.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    start_timeinteger时间戳,开始时间,格式:1621526400
    end_timeinteger时间戳,结束时间,格式:1622131200
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    influenceint影响力
    contributionint贡献度
    activityint活跃度
    experienceint项目经验
    languageint语言能力
    languages_percentfloat语言百分比
    each_language_scoreint各门语言分数
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "platform": {
    +        "influence": 61,
    +        "contribution": 75,
    +        "activity": 66,
    +        "experience": 95,
    +        "language": 87,
    +        "languages_percent": {
    +            "CSS": 0.03,
    +            "C#": 0.13,
    +            "Ruby": 0.04,
    +            "Go": 0.05,
    +            "C": 0.19,
    +            "Java": 0.34,
    +            "Python": 0.09,
    +            "C+": 0.01,
    +            "C++": 0.11,
    +            "Scala": 0.01,
    +            "HTML": 0.01
    +        },
    +        "each_language_score": {
    +            "CSS": 71,
    +            "C#": 86,
    +            "Ruby": 75,
    +            "Go": 77,
    +            "C": 90,
    +            "Java": 93,
    +            "Python": 83,
    +            "C+": 66,
    +            "C++": 85,
    +            "Scala": 66,
    +            "HTML": 66
    +        }
    +    },
    +    "user": {
    +        "influence": 60,
    +        "contribution": 72,
    +        "activity": 65,
    +        "experience": 88,
    +        "language": 84,
    +        "languages_percent": {
    +            "C": 0.25,
    +            "C#": 0.33,
    +            "C++": 0.13,
    +            "CSS": 0.08,
    +            "Go": 0.04,
    +            "HTML": 0.04,
    +            "Java": 0.04,
    +            "Ruby": 0.08
    +        },
    +        "each_language_score": {
    +            "C": 81,
    +            "C#": 84,
    +            "C++": 75,
    +            "CSS": 71,
    +            "Go": 66,
    +            "HTML": 66,
    +            "Java": 66,
    +            "Ruby": 71
    +        }
    +    }
    +}
    +
    + +

    用户角色定位

    +

    用户角色定位,默认显示所有时间下的角色定位数据

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/role.json
    +
    await octokit.request('GET /api/users/:login/statistics/role.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/statistics/role.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    start_timeinteger时间戳,开始时间,格式:1621526400
    end_timeinteger时间戳,结束时间,格式:1622131200
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_projects_countint用户所有的项目数量
    role.object.countint用户该语言下的项目数量
    role.object.percentfloat用户该语言下的项目占比
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_projects_count": 27,
    +    "role": {
    +        "owner": {
    +            "count": 24,
    +            "percent": 0.89
    +        },
    +        "manager": {
    +            "count": 1,
    +            "percent": 0.04
    +        },
    +        "developer": {
    +            "count": 2,
    +            "percent": 0.07
    +        },
    +        "reporter": {
    +            "count": 0,
    +            "percent": 0.0
    +        }
    +    }
    +}
    +
    + +

    用户专业定位

    +

    用户专业定位,默认显示所有时间下的专业定位数据

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/major.json
    +
    await octokit.request('GET /api/users/:login/statistics/major.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/statistics/major.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    start_timeinteger时间戳,开始时间,格式:1621526400
    end_timeinteger时间戳,结束时间,格式:1622131200
    +

    返回字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    categoriesint用户项目分类
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "categories": [
    +        "大数据",
    +        "机器学习",
    +        "深度学习",
    +        "人工智能",
    +        "智慧医疗",
    +        "云计算"
    +    ]
    +}
    +
    +

    待办事项-用户通知信息

    待办事项-用户通知信息

    @@ -1025,9 +1746,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    -

    请求字段说明:

    +

    请求字段说明:

    @@ -1041,7 +1762,7 @@ Success — a happy kitten is an authenticated kitten!
    参数用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1262,9 +1983,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1278,7 +1999,7 @@ Success — a happy kitten is an authenticated kitten!
    参数用户标识
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1454,9 +2175,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1475,7 +2196,7 @@ Success — a happy kitten is an authenticated kitten!
    参数迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -1645,9 +2366,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1666,7 +2387,7 @@ Success — a happy kitten is an authenticated kitten!
    参数迁移id
    -

    返回字段说明:

    +

    返回字段说明:

    From cdce7049ad07cb58820cbb925551398b7cc1c807 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 16:08:49 +0800 Subject: [PATCH 186/643] fix --- app/views/projects/_project_detail.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/_project_detail.json.jbuilder b/app/views/projects/_project_detail.json.jbuilder index da5d67473..c9e03fa22 100644 --- a/app/views/projects/_project_detail.json.jbuilder +++ b/app/views/projects/_project_detail.json.jbuilder @@ -17,7 +17,7 @@ json.time_ago time_from_now(project.updated_on) json.forked_from_project_id project.forked_from_project_id json.open_devops project.open_devops? json.platform project.platform -json.is_pinned @project.has_pinned_users.include?(current_user) +json.is_pinned project.has_pinned_users.include?(current_user) json.author do if project.educoder? project_educoder = project.project_educoder From 7fa1cdf73e9f76de973b2065d1b74c61f589cb21 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 16:53:37 +0800 Subject: [PATCH 187/643] add: user created time --- app/views/users/show.json.jbuilder | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index e80ac7494..c529cf79f 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -17,4 +17,5 @@ json.user_composes_count @user_composes_count json.user_org_count @user_org_count json.common_projects_count @projects_common_count json.mirror_projects_count @projects_mirrior_count -json.sync_mirror_projects_count @projects_sync_mirrior_count \ No newline at end of file +json.sync_mirror_projects_count @projects_sync_mirrior_count +json.created_time format_time(@user.created_on) \ No newline at end of file From dc4c99c30596e5265d5884a0abfcbd750e5058df Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 28 May 2021 18:00:53 +0800 Subject: [PATCH 188/643] fix: psimple issue field --- app/views/issues/_simple_issue_item.json.jbuilder | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/issues/_simple_issue_item.json.jbuilder b/app/views/issues/_simple_issue_item.json.jbuilder index 3f9c22e9e..d21c9fcae 100644 --- a/app/views/issues/_simple_issue_item.json.jbuilder +++ b/app/views/issues/_simple_issue_item.json.jbuilder @@ -1,7 +1,10 @@ json.name issue.try(:subject) -json.issue_type issue.try(:issue_type) +json.issue_type issue.issue_type == "1" ? "普通" : "悬赏" json.status_id issue.try(:status_id) +json.issue_status issue.issue_status.try(:name) +json.priority issue.priority.try(:name) json.priority_id issue.try(:priority_id) +json.version issue.version.try(:name) json.created_at format_time(issue.try(:created_on)) json.updated_at format_time(issue.try(:updated_on)) json.assign_user_name issue&.get_assign_user.try(:show_real_name) From 86f0f2051d357a466fcf485d0ceac8e20da82081 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 31 May 2021 18:39:49 +0800 Subject: [PATCH 189/643] add: update user_info --- app/controllers/users_controller.rb | 15 ++- app/docs/slate/source/includes/_users.md | 53 +++++++- app/models/user.rb | 2 +- app/models/user_extension.rb | 6 +- app/views/users/show.json.jbuilder | 7 +- ...531100250_add_fields_to_user_extensions.rb | 8 ++ public/docs/api.html | 124 ++++++++++++++---- 7 files changed, 180 insertions(+), 35 deletions(-) create mode 100644 db/migrate/20210531100250_add_fields_to_user_extensions.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3c62b1145..4cbb2cbdf 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -72,9 +72,13 @@ class UsersController < ApplicationController end def update - @user = User.find params[:id] - @user.update!(user_params) - render_ok + return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id]) + @user.attributes = user_params + if @user.save + render_ok + else + render_error(@user.errors.full_messages.join(", ")) + end end def me @@ -274,11 +278,12 @@ class UsersController < ApplicationController end def user_params - params.require(:user).permit(:nickname, :lastname, :show_realname,:login,:mail, + params.require(:user).permit(:nickname, user_extension_attributes: [ :gender, :location, :location_city, :occupation, :technical_title, - :school_id, :department_id,:identity, :student_id, :description] + :school_id, :department_id, :province, :city, + :custom_department, :identity, :student_id, :description] ) end diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index d7e8ed488..573e171eb 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -47,6 +47,57 @@ await octokit.request('GET /api/users/me.json') Success Data. +## 更改用户信息 +更改用户信息 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/users/yystopf.json +``` + +```javascript +await octokit.request('PATCH/PUT /api/users/:login.json') +``` + +### HTTP 请求 +`PATCH/PUT /api/users/:login.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|user.nickname |string |用户昵称 | +|user.user_extension_attributes.gender |int |性别, 0男 1女 | +|user.user_extension_attributes.province |string |省份 | +|user.user_extension_attributes.city |string |城市 | +|user.user_extension_attributes.description |string |个性签名 | +|user.user_extension_attributes.custom_department|string |单位名称 | + +> 请求的JSON示例: + +```json +{ + "user": { + "nickname": "xxx", + "user_extension_attributes": { + "gender": 0, + "province": "湖南", + "city": "长沙", + "description": "个性签名", + "custom_department": "湖南智擎科技有限公司", + } + } +} +``` + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` ## 获取用户星标项目 获取用户星标项目 diff --git a/app/models/user.rb b/app/models/user.rb index 56043f5f6..e190e82ea 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -181,7 +181,7 @@ class User < Owner attr_accessor :password, :password_confirmation - delegate :gender, :department_id, :school_id, :location, :location_city, :technical_title, to: :user_extension, allow_nil: true + delegate :description, :gender, :department_id, :school_id, :location, :location_city, :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true before_save :update_hashed_password after_create do diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 4afd89bd5..56eed12bd 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -22,9 +22,9 @@ # school_id :integer # description :string(255) default("") # department_id :integer -# honor :text(65535) -# edu_background :integer -# edu_entry_year :integer +# province :string(255) +# city :string(255) +# custom_department :string(255) # # Indexes # diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index c529cf79f..560c207d6 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -18,4 +18,9 @@ json.user_org_count @user_org_count json.common_projects_count @projects_common_count json.mirror_projects_count @projects_mirrior_count json.sync_mirror_projects_count @projects_sync_mirrior_count -json.created_time format_time(@user.created_on) \ No newline at end of file +json.created_time format_time(@user.created_on) +json.email @user.mail +json.province @user.province +json.city @user.city +json.custom_department @user.custom_department +json.description @user.description \ No newline at end of file diff --git a/db/migrate/20210531100250_add_fields_to_user_extensions.rb b/db/migrate/20210531100250_add_fields_to_user_extensions.rb new file mode 100644 index 000000000..880438405 --- /dev/null +++ b/db/migrate/20210531100250_add_fields_to_user_extensions.rb @@ -0,0 +1,8 @@ +class AddFieldsToUserExtensions < ActiveRecord::Migration[5.2] + def change + add_column :user_extensions, :province, :string # 省份 + add_column :user_extensions, :city, :string # 城市 + add_column :user_extensions, :custom_department, :string #自己填写的单位名称 + remove_column :users, :description + end +end diff --git a/public/docs/api.html b/public/docs/api.html index 616803e4e..e713ea1d0 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -331,6 +331,9 @@
  • 获取当前登陆用户信息
  • +
  • + 更改用户信息 +
  • 获取用户星标项目
  • @@ -611,7 +614,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -673,7 +676,80 @@ Success — a happy kitten is an authenticated kitten! -

    获取用户星标项目

    +

    更改用户信息

    +

    更改用户信息

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/users/yystopf.json
    +
    await octokit.request('PATCH/PUT /api/users/:login.json')
    +

    HTTP 请求

    +

    PATCH/PUT /api/users/:login.json

    +

    请求字段说明:

    +
    参数
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    user.nicknamestring用户昵称
    user.user_extension_attributes.genderint性别, 0男 1女
    user.user_extension_attributes.provincestring省份
    user.user_extension_attributes.citystring城市
    user.user_extension_attributes.descriptionstring个性签名
    user.user_extension_attributes.custom_departmentstring单位名称
    + +
    +

    请求的JSON示例:

    +
    +
    {
    +    "user": {
    +        "nickname": "xxx",
    +        "user_extension_attributes": {
    +            "gender": 0,
    +            "province": "湖南",
    +            "city": "长沙",
    +            "description": "个性签名",
    +            "custom_department": "湖南智擎科技有限公司",
    +        }
    +    }
    +}
    +
    +
    +

    返回的JSON示例:

    +
    +
    {
    +    "status": 0,
    +    "message": "success"
    +}
    +

    获取用户星标项目

    获取用户星标项目

    @@ -681,7 +757,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/is_pinned_projects.json
     
    await octokit.request('GET /api/users/:login/is_pinned_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/is_pinned_projects.json

    返回字段说明:

    @@ -863,9 +939,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/is_pinned_projects/pin.json
     
    await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json')
    -

    HTTP 请求

    +

    HTTP 请求

    POST /api/users/:login/is_pinned_projects/pin.json

    -

    请求字段说明:

    同时设定多个星标项目

    +

    请求字段说明:

    同时设定多个星标项目

    @@ -909,7 +985,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/activity.json
     
    await octokit.request('GET /api/users/:login/statistics/activity.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/activity.json

    返回字段说明:

    参数
    @@ -998,9 +1074,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
     
    await octokit.request('GET /api/users/:login/headmaps.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/headmaps.json

    -

    请求字段说明:

    +

    请求字段说明:

    @@ -1143,9 +1219,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/project_trends.json
     
    await octokit.request('GET /api/users/:login/project_trends.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/project_trends.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1460,9 +1536,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/develop.json
     
    await octokit.request('GET /api/users/:login/statistics/develop.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/develop.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1603,9 +1679,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/role.json
     
    await octokit.request('GET /api/users/:login/statistics/role.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/role.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1685,9 +1761,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/major.json
     
    await octokit.request('GET /api/users/:login/statistics/major.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/major.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1746,9 +1822,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1983,9 +2059,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2175,9 +2251,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2366,9 +2442,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    From dc91cd43461bd856a653b79d2a6f5abe7aa94ef4 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 31 May 2021 18:46:39 +0800 Subject: [PATCH 190/643] fix --- db/migrate/20210531100250_add_fields_to_user_extensions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20210531100250_add_fields_to_user_extensions.rb b/db/migrate/20210531100250_add_fields_to_user_extensions.rb index 880438405..890cd35ae 100644 --- a/db/migrate/20210531100250_add_fields_to_user_extensions.rb +++ b/db/migrate/20210531100250_add_fields_to_user_extensions.rb @@ -3,6 +3,6 @@ class AddFieldsToUserExtensions < ActiveRecord::Migration[5.2] add_column :user_extensions, :province, :string # 省份 add_column :user_extensions, :city, :string # 城市 add_column :user_extensions, :custom_department, :string #自己填写的单位名称 - remove_column :users, :description + # remove_column :users, :description end end From 21d47513271f0e6c827a2b531c6a21b99a6b8cf8 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 1 Jun 2021 10:07:01 +0800 Subject: [PATCH 191/643] add: update user image --- app/controllers/application_controller.rb | 19 +++++++++++++++++++ .../organizations/organizations_controller.rb | 19 ------------------- app/controllers/users_controller.rb | 6 ++++-- app/docs/slate/source/includes/_users.md | 3 ++- app/queries/projects/list_my_query.rb | 2 +- public/docs/api.html | 7 ++++++- 6 files changed, 32 insertions(+), 24 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6875b8155..8536147ca 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -773,7 +773,26 @@ class ApplicationController < ActionController::Base def base_url request.base_url end + + def convert_image! + @image = params[:image] || user_params[:image] + return unless @image.present? + max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M + if @image.class == ActionDispatch::Http::UploadedFile + render_error('请上传文件') if @image.size.zero? + render_error('文件大小超过限制') if @image.size > max_size.to_i + else + image = @image.to_s.strip + return render_error('请上传正确的图片') if image.blank? + @image = Util.convert_base64_image(image, max_size: max_size.to_i) + end + rescue Base64ImageConverter::Error => ex + render_error(ex.message) + end + def avatar_path(object) + ApplicationController.helpers.disk_filename(object.class, object.id) + end private def object_not_found diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index 29cb15a6a..7be9390d7 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -70,25 +70,6 @@ class Organizations::OrganizationsController < Organizations::BaseController end private - def convert_image! - return unless params[:image].present? - max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M - if params[:image].class == ActionDispatch::Http::UploadedFile - @image = params[:image] - render_error('请上传文件') if @image.size.zero? - render_error('文件大小超过限制') if @image.size > max_size.to_i - else - image = params[:image].to_s.strip - return render_error('请上传正确的图片') if image.blank? - @image = Util.convert_base64_image(image, max_size: max_size.to_i) - end - rescue Base64ImageConverter::Error => ex - render_error(ex.message) - end - - def avatar_path(organization) - ApplicationController.helpers.disk_filename(organization.class, organization.id) - end def organization_params params.permit(:name, :description, :website, :location, diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4cbb2cbdf..6c28271db 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -6,6 +6,7 @@ class UsersController < ApplicationController before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard] before_action :require_login, only: %i[me list sync_user_info] before_action :connect_to_ci_db, only: [:get_user_info] + before_action :convert_image!, only: [:update] skip_before_action :check_sign, only: [:attachment_show] def connect_to_ci_db(options={}) @@ -73,7 +74,8 @@ class UsersController < ApplicationController def update return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id]) - @user.attributes = user_params + Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? + @user.attributes = user_params.except(:image) if @user.save render_ok else @@ -278,7 +280,7 @@ class UsersController < ApplicationController end def user_params - params.require(:user).permit(:nickname, + params.require(:user).permit(:nickname, :image, user_extension_attributes: [ :gender, :location, :location_city, :occupation, :technical_title, diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 573e171eb..b72ee0c12 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -67,6 +67,7 @@ await octokit.request('PATCH/PUT /api/users/:login.json') 参数 | 类型 | 字段说明 --------- | ----------- | ----------- |user.nickname |string |用户昵称 | +|user.image |string/file |用户头像 | |user.user_extension_attributes.gender |int |性别, 0男 1女 | |user.user_extension_attributes.province |string |省份 | |user.user_extension_attributes.city |string |城市 | diff --git a/app/queries/projects/list_my_query.rb b/app/queries/projects/list_my_query.rb index 5bda56120..5c508c961 100644 --- a/app/queries/projects/list_my_query.rb +++ b/app/queries/projects/list_my_query.rb @@ -53,7 +53,7 @@ class Projects::ListMyQuery < ApplicationQuery q = projects.ransack(name_or_identifier_cont: params[:search]) - scope = q.result.includes(:project_category, :project_language,:owner, :repository) + scope = q.result.includes(:project_category, :project_language,:owner, :repository, :has_pinned_users) sort = params[:sort_by] || "updated_on" sort_direction = params[:sort_direction] || "desc" diff --git a/public/docs/api.html b/public/docs/api.html index e713ea1d0..71753c32b 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -614,7 +614,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -700,6 +700,11 @@ Success — a happy kitten is an authenticated kitten!
    + + + + + From 7ba45bc86657b56557a05fcf5fed51052838fe5a Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 2 Jun 2021 15:29:00 +0800 Subject: [PATCH 192/643] fix: some bug --- app/views/project_trends/_detail.json.jbuilder | 4 ++-- app/views/users/_watch_user_detail.json.jbuilder | 2 +- app/views/users/watch_users.json.jbuilder | 2 +- config/locales/zh-CN.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/views/project_trends/_detail.json.jbuilder b/app/views/project_trends/_detail.json.jbuilder index 7ffa9f152..75bcf2237 100644 --- a/app/views/project_trends/_detail.json.jbuilder +++ b/app/views/project_trends/_detail.json.jbuilder @@ -12,6 +12,6 @@ if trend.trend_type == "Issue" elsif trend.trend_type == "VersionRelease" json.partial! "version_releases/simple_version_release", locals: {version: trend.trend} else - json.name trend.trend.title - json.created_at format_time(trend.trend.created_at) + json.name trend.trend&.title + json.created_at format_time(trend.trend&.created_at) end diff --git a/app/views/users/_watch_user_detail.json.jbuilder b/app/views/users/_watch_user_detail.json.jbuilder index 80a711626..8c4881bcc 100644 --- a/app/views/users/_watch_user_detail.json.jbuilder +++ b/app/views/users/_watch_user_detail.json.jbuilder @@ -3,7 +3,7 @@ json.format_time target.created_at.strftime("%Y-%m-%d") json.name user.try(:show_real_name) json.login user.try(:login) json.image_url url_to_avatar(user) -json.is_current_user current_user.try(:id) == target.user_id +json.is_current_user current_user.try(:id) == user.id json.is_watch current_user&.watched?(user) diff --git a/app/views/users/watch_users.json.jbuilder b/app/views/users/watch_users.json.jbuilder index b265e2e0a..ed2697f0c 100644 --- a/app/views/users/watch_users.json.jbuilder +++ b/app/views/users/watch_users.json.jbuilder @@ -1,7 +1,7 @@ json.count @watchers_count json.users do json.array! @watchers do |watcher| - json.partial! "/users/watch_user_detail", locals: {target: watcher, user: watcher.watchable} + json.partial! "/users/watch_user_detail", target: watcher, user: watcher.watchable end # json.partial! "/users/watch_user_detail", collection: @watchers, as: :target end \ No newline at end of file diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index c040f9bd1..db1030163 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -15,7 +15,7 @@ zh-CN: 'refused': '已拒绝' 'agreed': '已同意' trend: - Issue: 工单 + Issue: 易修(Issue) PullRequest: 合并请求 VersionRelease: 版本发布 create: 创建了 From 16c293562ac284892c17b9b1a6fabfa2c7c2e0cf Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 2 Jun 2021 16:40:40 +0800 Subject: [PATCH 193/643] add: pinned projects order by position --- .../users/is_pinned_projects_controller.rb | 19 +++- app/docs/slate/source/includes/_users.md | 44 ++++++++- .../is_pinned_projects/index.json.jbuilder | 4 +- config/routes.rb | 2 +- public/docs/api.html | 91 ++++++++++++++----- 5 files changed, 134 insertions(+), 26 deletions(-) diff --git a/app/controllers/users/is_pinned_projects_controller.rb b/app/controllers/users/is_pinned_projects_controller.rb index 4f3f4e37e..1ddadd277 100644 --- a/app/controllers/users/is_pinned_projects_controller.rb +++ b/app/controllers/users/is_pinned_projects_controller.rb @@ -1,7 +1,7 @@ class Users::IsPinnedProjectsController < Users::BaseController before_action :private_user_resources!, only: [:pin] def index - @is_pinned_projects = observed_user.is_pinned_projects.includes(:project_category, :project_language, :repository).order(position: :desc) + @is_pinned_projects = observed_user.pinned_projects.order(position: :desc, created_at: :asc).includes(project: [:project_category, :project_language, :repository]).order(position: :desc) @is_pinned_projects = kaminari_paginate(@is_pinned_projects) end @@ -15,6 +15,19 @@ class Users::IsPinnedProjectsController < Users::BaseController tip_exception(e.message) end + def update + @pinned_project = PinnedProject.find_by_id(params[:id]) + @pinned_project.attributes = pinned_project_params + if @pinned_project.save + render_ok + else + render_error + end + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + private def is_pinned_project_ids if params[:is_pinned_project_ids].present? @@ -25,4 +38,8 @@ class Users::IsPinnedProjectsController < Users::BaseController return observed_user.is_pinned_project_ids.include?(params[:is_pinned_project_id].to_i) ? observed_user.is_pinned_project_ids : observed_user.is_pinned_project_ids.push(params[:is_pinned_project_id].to_i) end end + + def pinned_project_params + params.require(:pinned_project).permit(:position) + end end \ No newline at end of file diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index b72ee0c12..5771f757f 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -53,7 +53,7 @@ await octokit.request('GET /api/users/me.json') > 示例: ```shell -curl -X POST http://localhost:3000/api/users/yystopf.json +curl -X PATCH/PUT http://localhost:3000/api/users/yystopf.json ``` ```javascript @@ -141,6 +141,7 @@ await octokit.request('GET /api/users/:login/is_pinned_projects.json') |author.image_url |string |项目拥有者头像| |category.name |string |项目分类名称| |language.name |string |项目语言名称| +|position |int |项目排序| > 返回的JSON示例: @@ -228,6 +229,45 @@ await octokit.request('GET /api/users/:login/is_pinned_projects/pin.json') ``` +## 星标项目展示排序 +星标项目展示排序 + +> 示例: + +```shell +curl -X PATCH http://localhost:3000/api/users/yystopf/is_pinned_projects/11.json +``` + +```javascript +await octokit.request('PATCH/PUT /api/users/:login/is_pinned_projects/:id.json') +``` + +### HTTP 请求 +`PATCH/PUT /api/users/:login/is_pinned_projects/:id.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|pinned_projects.position |int |排序,数字越大排名越前 | + +> 请求的JSON示例: + +```json +{ + "pinned_project": { + "position": 1 + } +} +``` + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` ## 用户近期活动统计 用户近期活动统计, 默认显示近一周的数据 diff --git a/app/views/users/is_pinned_projects/index.json.jbuilder b/app/views/users/is_pinned_projects/index.json.jbuilder index facc158b9..a96ecf986 100644 --- a/app/views/users/is_pinned_projects/index.json.jbuilder +++ b/app/views/users/is_pinned_projects/index.json.jbuilder @@ -1,4 +1,6 @@ json.total_count @is_pinned_projects.total_count json.projects @is_pinned_projects.each do |project| - json.partial! "projects/project_detail", project: project + json.partial! "projects/project_detail", project: project&.project + json.id project.id + json.position project.position end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index cfadf4941..1160a4072 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -266,7 +266,7 @@ Rails.application.routes.draw do end end resources :headmaps, only: [:index] - resources :is_pinned_projects, only: [:index] do + resources :is_pinned_projects, only: [:index, :update] do collection do post :pin end diff --git a/public/docs/api.html b/public/docs/api.html index 71753c32b..c8fa29fa2 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -340,6 +340,9 @@
  • 用户添加星标项目
  • +
  • + 星标项目展示排序 +
  • 用户近期活动统计
  • @@ -614,7 +617,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -682,7 +685,7 @@ Success — a happy kitten is an authenticated kitten!

    示例:

    -
    curl -X POST http://localhost:3000/api/users/yystopf.json
    +
    curl -X PATCH/PUT http://localhost:3000/api/users/yystopf.json
     
    await octokit.request('PATCH/PUT /api/users/:login.json')
     

    HTTP 请求

    PATCH/PUT /api/users/:login.json

    @@ -887,6 +890,11 @@ Success — a happy kitten is an authenticated kitten!
    + + + + +
    参数用户昵称
    user.imagestring/file用户头像
    user.user_extension_attributes.gender int 性别, 0男 1女string 项目语言名称
    positionint项目排序
    @@ -975,6 +983,47 @@ Success — a happy kitten is an authenticated kitten! +
    +

    返回的JSON示例:

    +
    +
    {
    +    "status": 0,
    +    "message": "success"
    +}
    +

    星标项目展示排序

    +

    星标项目展示排序

    + +
    +

    示例:

    +
    +
    curl -X PATCH http://localhost:3000/api/users/yystopf/is_pinned_projects/11.json
    +
    await octokit.request('PATCH/PUT /api/users/:login/is_pinned_projects/:id.json')
    +

    HTTP 请求

    +

    PATCH/PUT /api/users/:login/is_pinned_projects/:id.json

    +

    请求字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    pinned_projects.positionint排序,数字越大排名越前
    + +
    +

    请求的JSON示例:

    +
    +
    {
    +    "pinned_project": {
    +        "position": 1
    +    }
    +}
    +

    返回的JSON示例:

    @@ -990,7 +1039,7 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/activity.json
     
    await octokit.request('GET /api/users/:login/statistics/activity.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/activity.json

    返回字段说明:

    @@ -1079,9 +1128,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/headmaps.json
     
    await octokit.request('GET /api/users/:login/headmaps.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/headmaps.json

    -

    请求字段说明:

    +

    请求字段说明:

    @@ -1224,9 +1273,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/project_trends.json
     
    await octokit.request('GET /api/users/:login/project_trends.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET api/users/:login/project_trends.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1541,9 +1590,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/develop.json
     
    await octokit.request('GET /api/users/:login/statistics/develop.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/develop.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1684,9 +1733,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/role.json
     
    await octokit.request('GET /api/users/:login/statistics/role.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/role.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1766,9 +1815,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/statistics/major.json
     
    await octokit.request('GET /api/users/:login/statistics/major.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/statistics/major.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -1827,9 +1876,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
     
    await octokit.request('GET /api/users/:login/applied_messages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_messages.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2064,9 +2113,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2256,9 +2305,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    @@ -2447,9 +2496,9 @@ Success — a happy kitten is an authenticated kitten!
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
     
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    -

    请求字段说明:

    +

    请求字段说明:

    参数
    From fff790bb1935b58ae7b650ea03eb1cc3d16b7d52 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 2 Jun 2021 17:29:11 +0800 Subject: [PATCH 194/643] add: pinned projects project_id --- app/views/users/is_pinned_projects/index.json.jbuilder | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/users/is_pinned_projects/index.json.jbuilder b/app/views/users/is_pinned_projects/index.json.jbuilder index a96ecf986..7790607d6 100644 --- a/app/views/users/is_pinned_projects/index.json.jbuilder +++ b/app/views/users/is_pinned_projects/index.json.jbuilder @@ -3,4 +3,5 @@ json.projects @is_pinned_projects.each do |project| json.partial! "projects/project_detail", project: project&.project json.id project.id json.position project.position + json.project_id project.project_id end \ No newline at end of file From 0368c0321f7be39c868fb2e1541034e089155b12 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 3 Jun 2021 09:48:58 +0800 Subject: [PATCH 195/643] fix: org transfer bug --- app/services/projects/transfer_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index a2da34f09..0b4f1d998 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -34,7 +34,7 @@ class Projects::TransferService < ApplicationService def update_visit_teams if new_owner.is_a?(Organization) # 为包含组织所有项目的团队创建项目访问权限 - new_owner.build_permit_team_projects(project.id) + new_owner.build_permit_team_projects!(project.id) else project.team_projects.each(&:destroy!) end From 7dc21ff38840907d7ec673f8cf93c3dc181fc82b Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Thu, 3 Jun 2021 10:19:33 +0800 Subject: [PATCH 196/643] add: update user more info --- app/controllers/users_controller.rb | 3 ++- app/docs/slate/source/includes/_users.md | 12 ++++++--- app/models/user.rb | 4 ++- app/models/user_extension.rb | 3 +++ app/views/users/show.json.jbuilder | 8 +++--- ...7_add_show_condition_to_user_extensions.rb | 7 +++++ public/docs/api.html | 26 ++++++++++++++++--- 7 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 db/migrate/20210603020327_add_show_condition_to_user_extensions.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6c28271db..3f7cd4170 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -285,7 +285,8 @@ class UsersController < ApplicationController :gender, :location, :location_city, :occupation, :technical_title, :school_id, :department_id, :province, :city, - :custom_department, :identity, :student_id, :description] + :custom_department, :identity, :student_id, :description, + :show_email, :show_location, :show_department] ) end diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 5771f757f..72bf724a5 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -66,13 +66,17 @@ await octokit.request('PATCH/PUT /api/users/:login.json') ### 请求字段说明: 参数 | 类型 | 字段说明 --------- | ----------- | ----------- -|user.nickname |string |用户昵称 | -|user.image |string/file |用户头像 | +|user.nickname |string |用户昵称 | +|user.image |base64/file |用户头像 | |user.user_extension_attributes.gender |int |性别, 0男 1女 | |user.user_extension_attributes.province |string |省份 | |user.user_extension_attributes.city |string |城市 | -|user.user_extension_attributes.description |string |个性签名 | +|user.user_extension_attributes.description |string |简介 | |user.user_extension_attributes.custom_department|string |单位名称 | +|user.user_extension_attributes.technical_title |string |职业 | +|user.user_extension_attributes.show_email |bool |是否展示邮箱 | +|user.user_extension_attributes.show_location |bool |是否展示位置 | +|user.user_extension_attributes.show_department |bool |是否展示公司 | > 请求的JSON示例: diff --git a/app/models/user.rb b/app/models/user.rb index e190e82ea..09880b8cd 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -181,7 +181,9 @@ class User < Owner attr_accessor :password, :password_confirmation - delegate :description, :gender, :department_id, :school_id, :location, :location_city, :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true + delegate :description, :gender, :department_id, :school_id, :location, :location_city, + :show_email, :show_location, :show_department, + :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true before_save :update_hashed_password after_create do diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 56eed12bd..47b27c08b 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -25,6 +25,9 @@ # province :string(255) # city :string(255) # custom_department :string(255) +# show_email :boolean default("0") +# show_location :boolean default("0") +# show_department :boolean default("0") # # Indexes # diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index 560c207d6..06fab129f 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -19,8 +19,8 @@ json.common_projects_count @projects_common_count json.mirror_projects_count @projects_mirrior_count json.sync_mirror_projects_count @projects_sync_mirrior_count json.created_time format_time(@user.created_on) -json.email @user.mail -json.province @user.province -json.city @user.city -json.custom_department @user.custom_department +json.email @user.show_email ? @user.mail : nil +json.province @user.show_location ? @user.province : nil +json.city @user.show_location ? @user.city : nil +json.custom_department @user.show_department ? @user.custom_department : nil json.description @user.description \ No newline at end of file diff --git a/db/migrate/20210603020327_add_show_condition_to_user_extensions.rb b/db/migrate/20210603020327_add_show_condition_to_user_extensions.rb new file mode 100644 index 000000000..e64da0b71 --- /dev/null +++ b/db/migrate/20210603020327_add_show_condition_to_user_extensions.rb @@ -0,0 +1,7 @@ +class AddShowConditionToUserExtensions < ActiveRecord::Migration[5.2] + def change + add_column :user_extensions, :show_email, :boolean, default: false + add_column :user_extensions, :show_location, :boolean, default: false + add_column :user_extensions, :show_department, :boolean, default: false + end +end diff --git a/public/docs/api.html b/public/docs/api.html index c8fa29fa2..0cf007cf1 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -617,7 +617,7 @@ Success — a happy kitten is an authenticated kitten!

    Users

    获取当前登陆用户信息

    @@ -704,7 +704,7 @@ Success — a happy kitten is an authenticated kitten!
    - + @@ -725,13 +725,33 @@ Success — a happy kitten is an authenticated kitten! - + + + + + + + + + + + + + + + + + + + + +
    参数
    user.imagestring/filebase64/file 用户头像
    user.user_extension_attributes.description string个性签名简介
    user.user_extension_attributes.custom_department string 单位名称
    user.user_extension_attributes.technical_titlestring职业
    user.user_extension_attributes.show_emailbool是否展示邮箱
    user.user_extension_attributes.show_locationbool是否展示位置
    user.user_extension_attributes.show_departmentbool是否展示公司
    From c58b074173a5c99157ca116319ebf9ec472409b3 Mon Sep 17 00:00:00 2001 From: viletyy Date: Thu, 3 Jun 2021 11:26:14 +0800 Subject: [PATCH 197/643] fix: init project --- app/models/attachment.rb | 8 +- app/models/ci/user.rb | 13 ++- app/models/issue.rb | 5 +- app/models/laboratory.rb | 1 - app/models/organization.rb | 13 ++- app/models/project.rb | 133 +++++++++++++--------------- app/models/project_category.rb | 5 ++ app/models/pull_request.rb | 5 -- app/models/repository.rb | 1 + app/models/user.rb | 13 ++- app/models/user_action.rb | 4 +- app/models/user_agent.rb | 5 +- app/models/user_extension.rb | 6 -- db/init_data.sql | 95 ++++++++++++++++++++ db/structure.sql | 95 -------------------- lib/tasks/sync_table_structure.rake | 18 ++++ 16 files changed, 204 insertions(+), 216 deletions(-) create mode 100644 db/init_data.sql diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 1ca173458..461c835fe 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -17,7 +17,7 @@ # disk_directory :string(255) # attachtype :integer default("1") # is_public :integer default("1") -# copy_from :string(255) +# copy_from :integer # quotes :integer default("0") # is_publish :integer default("1") # publish_time :datetime @@ -26,15 +26,15 @@ # cloud_url :string(255) default("") # course_second_category_id :integer default("0") # delay_publish :boolean default("0") -# link :string(255) -# clone_id :integer # # Indexes # # index_attachments_on_author_id (author_id) -# index_attachments_on_clone_id (clone_id) # index_attachments_on_container_id_and_container_type (container_id,container_type) +# index_attachments_on_course_second_category_id (course_second_category_id) # index_attachments_on_created_on (created_on) +# index_attachments_on_is_public (is_public) +# index_attachments_on_quotes (quotes) # class Attachment < ApplicationRecord diff --git a/app/models/ci/user.rb b/app/models/ci/user.rb index e4a4d0623..cd6246753 100644 --- a/app/models/ci/user.rb +++ b/app/models/ci/user.rb @@ -39,15 +39,13 @@ # business :boolean default("0") # profile_completed :boolean default("0") # laboratory_id :integer -# is_shixun_marker :boolean default("0") -# admin_visitable :boolean default("0") -# collaborator :boolean default("0") +# platform :string(255) default("0") +# gitea_token :string(255) # gitea_uid :integer +# is_shixun_marker :boolean default("0") # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") -# gitea_token :string(255) -# platform :string(255) # # Indexes # @@ -55,9 +53,8 @@ # index_users_on_homepage_engineer (homepage_engineer) # index_users_on_homepage_teacher (homepage_teacher) # index_users_on_laboratory_id (laboratory_id) -# index_users_on_login (login) UNIQUE -# index_users_on_mail (mail) UNIQUE -# index_users_on_phone (phone) UNIQUE +# index_users_on_login (login) +# index_users_on_mail (mail) # index_users_on_type (type) # diff --git a/app/models/issue.rb b/app/models/issue.rb index 69de1eae2..58607ebdd 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -6,7 +6,7 @@ # tracker_id :integer not null # project_id :integer not null # subject :string(255) default(""), not null -# description :text(4294967295) +# description :text(65535) # due_date :date # category_id :integer # status_id :integer not null @@ -14,6 +14,7 @@ # priority_id :integer not null # fixed_version_id :integer # author_id :integer not null +# lock_version :integer default("0"), not null # created_on :datetime # updated_on :datetime # start_date :date @@ -27,7 +28,7 @@ # closed_on :datetime # project_issues_index :integer # issue_type :string(255) -# token :integer default("0") +# token :string(255) # issue_tags_value :string(255) # is_lock :boolean default("0") # issue_classify :string(255) diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb index 9d3ca07dd..699800c92 100644 --- a/app/models/laboratory.rb +++ b/app/models/laboratory.rb @@ -10,7 +10,6 @@ # sync_course :boolean default("0") # sync_subject :boolean default("0") # sync_shixun :boolean default("0") -# is_local :boolean default("0") # # Indexes # diff --git a/app/models/organization.rb b/app/models/organization.rb index 444938e72..988ecd7fb 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -39,15 +39,13 @@ # business :boolean default("0") # profile_completed :boolean default("0") # laboratory_id :integer -# is_shixun_marker :boolean default("0") -# admin_visitable :boolean default("0") -# collaborator :boolean default("0") +# platform :string(255) default("0") +# gitea_token :string(255) # gitea_uid :integer +# is_shixun_marker :boolean default("0") # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") -# gitea_token :string(255) -# platform :string(255) # # Indexes # @@ -55,9 +53,8 @@ # index_users_on_homepage_engineer (homepage_engineer) # index_users_on_homepage_teacher (homepage_teacher) # index_users_on_laboratory_id (laboratory_id) -# index_users_on_login (login) UNIQUE -# index_users_on_mail (mail) UNIQUE -# index_users_on_phone (phone) UNIQUE +# index_users_on_login (login) +# index_users_on_mail (mail) # index_users_on_type (type) # diff --git a/app/models/project.rb b/app/models/project.rb index 8141a56bf..19739f93d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,75 +1,64 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(4294967295) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# license_id :integer -# ignore_id :integer -# default_branch :string(255) default("master") -# website :string(255) -# lesson_url :string(255) -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(65535) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# license_id :integer +# ignore_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + class Project < ApplicationRecord diff --git a/app/models/project_category.rb b/app/models/project_category.rb index 67b802998..3a9819816 100644 --- a/app/models/project_category.rb +++ b/app/models/project_category.rb @@ -8,6 +8,11 @@ # projects_count :integer default("0") # created_at :datetime not null # updated_at :datetime not null +# ancestry :string(255) +# +# Indexes +# +# index_project_categories_on_ancestry (ancestry) # class ProjectCategory < ApplicationRecord diff --git a/app/models/pull_request.rb b/app/models/pull_request.rb index 62d6c3cc6..c3eefb0db 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -16,11 +16,6 @@ # head :string(255) # base :string(255) # issue_id :integer -# fork_project_id :integer -# is_original :boolean default("0") -# comments_count :integer default("0") -# commits_count :integer default("0") -# files_count :integer default("0") # class PullRequest < ApplicationRecord diff --git a/app/models/repository.rb b/app/models/repository.rb index 0daa4b916..a58dec900 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -27,6 +27,7 @@ # # Indexes # +# index_repositories_on_identifier (identifier) # index_repositories_on_project_id (project_id) # index_repositories_on_user_id (user_id) # diff --git a/app/models/user.rb b/app/models/user.rb index 09880b8cd..99b1e7cd7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -39,15 +39,13 @@ # business :boolean default("0") # profile_completed :boolean default("0") # laboratory_id :integer -# is_shixun_marker :boolean default("0") -# admin_visitable :boolean default("0") -# collaborator :boolean default("0") +# platform :string(255) default("0") +# gitea_token :string(255) # gitea_uid :integer +# is_shixun_marker :boolean default("0") # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") -# gitea_token :string(255) -# platform :string(255) # # Indexes # @@ -55,9 +53,8 @@ # index_users_on_homepage_engineer (homepage_engineer) # index_users_on_homepage_teacher (homepage_teacher) # index_users_on_laboratory_id (laboratory_id) -# index_users_on_login (login) UNIQUE -# index_users_on_mail (mail) UNIQUE -# index_users_on_phone (phone) UNIQUE +# index_users_on_login (login) +# index_users_on_mail (mail) # index_users_on_type (type) # diff --git a/app/models/user_action.rb b/app/models/user_action.rb index 179359695..3ad8010ea 100644 --- a/app/models/user_action.rb +++ b/app/models/user_action.rb @@ -12,9 +12,7 @@ # # Indexes # -# index_user_actions_on_ip (ip) -# index_user_actions_on_user_id (user_id) -# index_user_actions_on_user_id_and_action_type (user_id,action_type) +# index_user_actions_on_ip (ip) # class UserAction < ApplicationRecord diff --git a/app/models/user_agent.rb b/app/models/user_agent.rb index ba519d6fb..49d7b35a1 100644 --- a/app/models/user_agent.rb +++ b/app/models/user_agent.rb @@ -10,13 +10,10 @@ # updated_at :datetime not null # register_status :integer default("0") # action_status :integer default("0") -# is_delete :boolean default("0") -# user_id :integer # # Indexes # -# index_user_agents_on_ip (ip) -# index_user_agents_on_user_id (user_id) +# index_user_agents_on_ip (ip) UNIQUE # class UserAgent < ApplicationRecord diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 47b27c08b..20e2b5c4f 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -22,12 +22,6 @@ # school_id :integer # description :string(255) default("") # department_id :integer -# province :string(255) -# city :string(255) -# custom_department :string(255) -# show_email :boolean default("0") -# show_location :boolean default("0") -# show_department :boolean default("0") # # Indexes # diff --git a/db/init_data.sql b/db/init_data.sql new file mode 100644 index 000000000..33288736a --- /dev/null +++ b/db/init_data.sql @@ -0,0 +1,95 @@ + +-- ---------------------------- +-- Records of roles +-- ---------------------------- +BEGIN; +INSERT INTO `roles` (`id`, `name`, `position`, `assignable`, `builtin`, `permissions`, `issues_visibility`) VALUES +(1, 'Non member', 1, 1, 1, '---\n- :upload_attachments\n- :memos_attachments_download\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :add_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), +(2, 'Anonymous', 2, 1, 2, '---\n- :memos_attachments_download\n- :view_course_files\n- :view_calendar\n- :view_documents\n- :view_files\n- :view_gantt\n- :view_issues\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), +(3, 'Manager', 3, 1, 0, '---\n- :add_project\n- :edit_project\n- :close_project\n- :select_project_modules\n- :manage_members\n- :manage_versions\n- :add_subprojects\n- :is_manager\n- :projects_attachments_download\n- :as_teacher\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :quote_project\n- :manage_boards\n- :add_messages\n- :edit_messages\n- :edit_own_messages\n- :delete_messages\n- :delete_own_messages\n- :view_calendar\n- :view_code_review\n- :add_code_review\n- :edit_code_review\n- :delete_code_review\n- :assign_code_review\n- :code_review_setting\n- :add_documents\n- :edit_documents\n- :delete_documents\n- :view_documents\n- :manage_files\n- :view_files\n- :view_gantt\n- :manage_categories\n- :view_issues\n- :add_issues\n- :edit_issues\n- :manage_issue_relations\n- :manage_subtasks\n- :set_issues_private\n- :set_own_issues_private\n- :add_issue_notes\n- :edit_issue_notes\n- :edit_own_issue_notes\n- :view_private_notes\n- :set_notes_private\n- :move_issues\n- :delete_issues\n- :manage_public_queries\n- :save_queries\n- :view_issue_watchers\n- :add_issue_watchers\n- :delete_issue_watchers\n- :manage_news\n- :comment_news\n- :manage_repository\n- :browse_repository\n- :view_changesets\n- :commit_access\n- :manage_related_issues\n- :log_time\n- :view_time_entries\n- :edit_time_entries\n- :edit_own_time_entries\n- :manage_project_activities\n- :manage_wiki\n- :rename_wiki_pages\n- :delete_wiki_pages\n- :view_wiki_pages\n- :export_wiki_pages\n- :view_wiki_edits\n- :edit_wiki_pages\n- :delete_wiki_pages_attachments\n- :protect_wiki_pages\n', 'all'), +(4, 'Developer', 5, 1, 0, '---\n- :add_project\n- :manage_versions\n- :projects_attachments_download\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :paret_in_homework\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :manage_contestnotifications\n- :notificationcomment_contestnotifications\n- :manage_boards\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :manage_files\n- :view_files\n- :view_gantt\n- :manage_categories\n- :view_issues\n- :add_issues\n- :edit_issues\n- :manage_issue_relations\n- :manage_subtasks\n- :set_issues_private\n- :set_own_issues_private\n- :add_issue_notes\n- :edit_issue_notes\n- :edit_own_issue_notes\n- :view_private_notes\n- :set_notes_private\n- :move_issues\n- :delete_issues\n- :manage_public_queries\n- :save_queries\n- :view_issue_watchers\n- :add_issue_watchers\n- :delete_issue_watchers\n- :manage_repository\n- :browse_repository\n- :view_changesets\n- :commit_access\n- :manage_related_issues\n', 'all'), +(5, 'Reporter', 4, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :manage_boards\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :view_code_review\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :add_issues\n- :edit_issues\n- :add_issue_notes\n- :edit_own_issue_notes\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_wiki_pages\n- :export_wiki_pages\n- :view_wiki_edits\n- :edit_wiki_pages\n- :delete_wiki_pages_attachments\n', 'all'), +(7, 'TeachingAsistant', 6, 1, 0, '---\n- :add_project\n- :edit_project\n- :manage_members\n- :projects_attachments_download\n- :as_teacher\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :manage_boards\n- :add_messages\n- :edit_own_messages\n- :delete_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :add_issues\n- :add_issue_notes\n- :save_queries\n- :manage_news\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :export_wiki_pages\n- :view_wiki_edits\n- :edit_wiki_pages\n- :delete_wiki_pages_attachments\n', 'default'), +(9, 'Teacher', 7, 1, 0, '---\n- :upload_attachments\n- :memos_attachments_download\n- :add_project\n- :edit_project\n- :close_project\n- :select_project_modules\n- :manage_members\n- :manage_versions\n- :add_subprojects\n- :projects_attachments_download\n- :as_teacher\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :manage_boards\n- :add_messages\n- :edit_messages\n- :edit_own_messages\n- :delete_messages\n- :delete_own_messages\n- :view_calendar\n- :add_documents\n- :edit_documents\n- :delete_documents\n- :view_documents\n- :manage_files\n- :view_files\n- :view_gantt\n- :manage_categories\n- :view_issues\n- :add_issues\n- :edit_issues\n- :manage_issue_relations\n- :manage_subtasks\n- :set_issues_private\n- :set_own_issues_private\n- :add_issue_notes\n- :edit_own_issue_notes\n- :view_private_notes\n- :set_notes_private\n- :move_issues\n- :delete_issues\n- :manage_public_queries\n- :save_queries\n- :view_issue_watchers\n- :add_issue_watchers\n- :delete_issue_watchers\n- :manage_news\n- :comment_news\n- :manage_repository\n- :browse_repository\n- :view_changesets\n- :commit_access\n- :manage_related_issues\n- :log_time\n- :view_time_entries\n- :edit_time_entries\n- :edit_own_time_entries\n- :manage_project_activities\n- :manage_wiki\n- :rename_wiki_pages\n- :delete_wiki_pages\n- :view_wiki_pages\n- :export_wiki_pages\n- :view_wiki_edits\n- :edit_wiki_pages\n- :delete_wiki_pages_attachments\n- :protect_wiki_pages\n', 'default'), +(10, 'Student', 9, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :as_student\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :paret_in_homework\n- :manage_boards\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :add_issues\n- :add_issue_notes\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), +(11, 'orgManager', 8, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :add_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), +(12, 'orgMember', 10, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :add_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), +(13, 'ContestManager', 11, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :manage_contestnotifications\n- :notificationcomment_contestnotifications\n- :manage_boards\n- :add_messages\n- :edit_messages\n- :edit_own_messages\n- :delete_messages\n- :delete_own_messages\n- :view_calendar\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :browse_repository\n- :view_changesets\n', 'default'), +(14, 'Judge', 12, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :manage_contestnotifications\n- :notificationcomment_contestnotifications\n- :manage_boards\n- :add_messages\n- :edit_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :browse_repository\n- :view_changesets\n', 'default'), +(15, 'Contestant', 13, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :notificationcomment_contestnotifications\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :browse_repository\n- :view_changesets\n', 'default'); +COMMIT; + + +-- ---------------------------- +-- Records of ci_languages +-- ---------------------------- +BEGIN; +INSERT INTO `ci_languages` (`id`, `name`, `content`, `usage_amount`, `created_at`, `updated_at`, `cover_id`) VALUES +(1, 'C', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdjYwogIGNvbW1hbmRzOgogIC0gLi9jb25maWd1cmUKICAtIG1h\na2UKICAtIG1ha2UgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(2, 'C++', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdjYwogIGNvbW1hbmRzOgogIC0gLi9jb25maWd1cmUKICAtIG1h\na2UKICAtIG1ha2UgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(3, 'Docker', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgdm9sdW1lczoKICAtIG5hbWU6IGRvY2tl\ncnNvY2sKICAgIHBhdGg6IC92YXIvcnVuL2RvY2tlci5zb2NrCiAgICBjb21t\nYW5kczoKICAgIC0gZG9ja2VyIHBzIC1hCgp2b2x1bWVzOgotIG5hbWU6IGRv\nY2tlcnNvY2sKICBob3N0OgogICAgcGF0aDogL3Zhci9ydW4vZG9ja2VyLnNv\nY2s=\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:35:20', 351688), +(4, 'Java', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hdmVuOjMtamRrLTEwCiAgY29tbWFuZHM6CiAgLSBtdm4gaW5z\ndGFsbCAtRHNraXBUZXN0cz10cnVlIC1EbWF2ZW4uamF2YWRvYy5za2lwPXRy\ndWUgLUIgLVYKICAtIG12biB0ZXN0IC1C\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(5, 'R', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHItYmFzZQogIGNvbW1hbmRzOgogIC0gUiAtZSAnaW5zdGFsbC5w\nYWNrYWdlcyhjKCdwYWNrYWdlMScsJ3BhY2thZ2UyJykpJwogIC0gUiBDTUQg\nYnVpbGQgLg==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(6, 'Ruby', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1YnkKICBjb21tYW5kczoKICAtIGJ1bmRsZSBpbnN0YWxsIC0t\nam9icz0zIC0tcmV0cnk9MwogIC0gcmFrZQ==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(7, 'PHP', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiBpbnN0YWxs\nCiAgaW1hZ2U6IGNvbXBvc2VyCiAgY29tbWFuZHM6CiAgLSBjb21wb3NlciBp\nbnN0YWxsCgotIG5hbWU6IHRlc3QKICBpbWFnZTogcGhwOjcKICBjb21tYW5k\nczoKICAtIHZlbmRvci9iaW4vcGhwdW5pdCAtLWNvbmZpZ3VyYXRpb24gY29u\nZmlnLnhtbA==\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:37:04', 351690), +(8, 'Python', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHB5dGhvbgogIGNvbW1hbmRzOgogIC0gcGlwIGluc3RhbGwgLXIg\ncmVxdWlyZW1lbnRzLnR4dAogIC0gcHl0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:40:00', 351693), +(9, 'MySQL', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG15c3FsCiAgY29tbWFuZHM6CiAgLSBzbGVlcCAxNQogIC0gbXlz\ncWwgLXUgcm9vdCAtaCBkYXRhYmFzZSAtLWV4ZWN1dGU9J1NFTEVDVCBWRVJT\nSU9OKCk7JwoKc2VydmljZXM6Ci0gbmFtZTogZGF0YWJhc2UKICBpbWFnZTog\nbXlzcWwKICBlbnZpcm9ubWVudDoKICAgIE1ZU1FMX0FMTE9XX0VNUFRZX1BB\nU1NXT1JEOiAneWVzJwogICAgTVlTUUxfREFUQUJBU0U6IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(10, 'MongoDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiBwaW5nCiAg\naW1hZ2U6IG1vbmdvOjQKICBjb21tYW5kczoKICAtIHNsZWVwIDUKICAtIG1v\nbmdvIC0taG9zdCBtb25nbyAtLWV2YWwgJ2RiLnZlcnNpb24oKScKCnNlcnZp\nY2VzOgotIG5hbWU6IG1vbmdvCiAgaW1hZ2U6IG1vbmdvOjQKICBjb21tYW5k\nOiBbIC0tc21hbGxmaWxlcyBd\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(11, 'Clojure', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNsb2p1cmUKICBjb21tYW5kczoKICAtIGxlaW4gdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(12, 'CouchDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNvdWNoZGI6Mi4yCiAgY29tbWFuZHM6CiAgLSBzbGVlcCAxNQog\nIC0gY3VybCBodHRwOi8vZGF0YWJhc2U6NTk4NAoKc2VydmljZXM6Ci0gbmFt\nZTogZGF0YWJhc2UKICBpbWFnZTogY291Y2hkYjoyLjI=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(13, 'Crystal', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNyeXN0YWxsYW5nL2NyeXN0YWwKICBjb21tYW5kczoKICAtIHNo\nYXJkcyBpbnN0YWxsCiAgLSBjcnlzdGFsIHNwZWMuMg==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(14, 'D', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRsYW5ndWFnZS9kbWQKICBjb21tYW5kczoKICAtIGR1YiB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(15, 'Dart', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdvb2dsZS9kYXJ0CiAgY29tbWFuZHM6CiAgLSBwdWIgZ2V0CiAg\nLSBwdWIgcnVuIHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(16, 'Docker (dind)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgdm9sdW1lczoKICAtIG5hbWU6IGRvY2tl\ncnNvY2sKICAgIHBhdGg6IC92YXIvcnVuCiAgICBjb21tYW5kczoKICAgIC0g\nc2xlZXAgNSAjIGdpdmUgZG9ja2VyIGVub3VnaCB0aW1lIHRvIHN0YXJ0CiAg\nICAtIGRvY2tlciBwcyAtYQoKc2VydmljZXM6Ci0gbmFtZTogZG9ja2VyCiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgcHJpdmlsZWdlZDogdHJ1ZQogIHZvbHVt\nZXM6CiAgLSBuYW1lOiBkb2NrZXJzb2NrCiAgICBwYXRoOiAvdmFyL3J1bgoK\ndm9sdW1lczoKLSBuYW1lOiBkb2NrZXJzb2NrCiAgdGVtcDoge30=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(17, 'Elasticsearch', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGFscGluZTozLjgKICBjb21tYW5kczoKICAtIGFwayBhZGQgY3Vy\nbAogIC0gc2xlZXAgNDUKICAtIGN1cmwgaHR0cDovL2RhdGFiYXNlOjkyMDAK\nCnNlcnZpY2VzOgotIG5hbWU6IGRhdGFiYXNlCiAgaW1hZ2U6IGVsYXN0aWNz\nZWFyY2g6NS1hbHBpbmU=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(18, 'Elixir', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGVsaXhpcjoxLjUKICBjb21tYW5kczoKICAtIG1peCBsb2NhbC5y\nZWJhciAtLWZvcmNlCiAgLSBtaXggbG9jYWwuaGV4IC0tZm9yY2UKICAtIG1p\neCBkZXBzLmdldAogIC0gbWl4IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(19, 'Erlang', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGVybGFuZzoyMQogIGNvbW1hbmRzOgogIC0gcmViYXIgZ2V0LWRl\ncHMKICAtIHJlYmFyIGNvbXBpbGUKICAtIHJlYmFyIHNraXBfZGVwcz10cnVl\nIGV1bml0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(20, '20.Go (with Gopath)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0Cgp3b3Jrc3BhY2U6CiAgYmFzZTogL2dv\nCiAgcGF0aDogc3JjL2hlbGxvLXdvcmxkCgpzdGVwczoKLSBuYW1lOiB0ZXN0\nCiAgaW1hZ2U6IGdvbGFuZwogIGNvbW1hbmRzOgogIC0gZ28gZ2V0CiAgLSBn\nbyB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(21, '21.Go (with Modules)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdvbGFuZwogIGNvbW1hbmRzOgogIC0gZ28gdGVzdAogIC0gZ28g\nYnVpbGQ=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(22, 'Gradle', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdyYWRsZTpqZGsxMAogIGNvbW1hbmRzOgogIC0gZ3JhZGxlIGFz\nc2VtYmxlCiAgLSBncmFkbGUgY2hlY2s=\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:36:17', 351689), +(23, 'Groovy', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdyYWRsZToyLjUtamRrOAogIGNvbW1hbmRzOgogIC0gLi9ncmFk\nbGV3IGFzc2VtYmxlCiAgLSAuL2dyYWRsZXcgY2hlY2s=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(24, 'Haskell', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGhhc2tlbGwKICBjb21tYW5kczoKICAtIGNhYmFsIGluc3RhbGwg\nLS1vbmx5LWRlcGVuZGVuY2llcyAtLWVuYWJsZS10ZXN0cwogIC0gY2FiYWwg\nY29uZmlndXJlIC0tZW5hYmxlLXRlc3RzCiAgLSBjYWJhbCBidWlsZAogIC0g\nY2FiYWwgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(25, 'Haxe', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGhheGUKICBjb21tYW5kczoKICAtIGhheGVsaWIgaW5zdGFsbCBi\ndWlsZC5oeG1sCiAgLSBoYXhlIGJ1aWxkLmh4bWw=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(26, 'MariaDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hcmlhZGIKICBjb21tYW5kczoKICAtIHNsZWVwIDE1CiAgLSBt\neXNxbCAtdSByb290IC1oIGRhdGFiYXNlIC0tZXhlY3V0ZT0nU0VMRUNUIFZF\nUlNJT04oKTsnCgpzZXJ2aWNlczoKLSBuYW1lOiBkYXRhYmFzZQogIGltYWdl\nOiBtYXJpYWRiCiAgZW52aXJvbm1lbnQ6CiAgICBNWVNRTF9BTExPV19FTVBU\nWV9QQVNTV09SRDogJ3llcycKICAgIE1ZU1FMX0RBVEFCQVNFOiB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(27, 'Maven', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hdmVuOjMtamRrLTEwCiAgY29tbWFuZHM6CiAgLSBtdm4gaW5z\ndGFsbCAtRHNraXBUZXN0cz10cnVlIC1EbWF2ZW4uamF2YWRvYy5za2lwPXRy\ndWUgLUIgLVYKICAtIG12biB0ZXN0IC1C\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(28, 'Memcached', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHVidW50dQogIGNvbW1hbmRzOgogIC0gYXB0LWdldCB1cGRhdGUg\nLXFxCiAgLSBhcHQtZ2V0IGluc3RhbGwgLXkgLXFxIHRlbG5ldCA+IC9kZXYv\nbnVsbAogIC0gKHNsZWVwIDE7IGVjaG8gJ3N0YXRzJzsgc2xlZXAgMjsgZWNo\nbyAncXVpdCc7KSB8IHRlbG5ldCBjYWNoZSAxMTIxMSB8fCB0cnVlCgpzZXJ2\naWNlczoKLSBuYW1lOiBjYWNoZQogIGltYWdlOiBtZW1jYWNoZWQ6YWxwaW5l\nCiAgY29tbWFuZDogWyAtdnYgXQ==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(29, 'Nats', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1Ynk6MgogIGNvbW1hbmRzOgogIC0gZ2VtIGluc3RhbGwgbmF0\ncwogIC0gbmF0cy1wdWIgLXMgdGNwOi8vbmF0czo0MjIyIGdyZWV0aW5nICdo\nZWxsbycKICAtIG5hdHMtcHViIC1zIHRjcDovL25hdHM6NDIyMiBncmVldGlu\nZyAnd29ybGQnCgpzZXJ2aWNlczoKLSBuYW1lOiBuYXRzCiAgaW1hZ2U6IG5h\ndHM6MS4zLjA=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(30, 'Node', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG5vZGUKICBjb21tYW5kczoKICAtIG5wbSBpbnN0YWxsCiAgLSBu\ncG0gdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(31, 'Perl', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHBlcmwKICBjb21tYW5kczoKICAtIGNwYW5tIC0tcXVpZXQgLS1p\nbnN0YWxsZGVwcyAtLW5vdGVzdCAuCiAgLSBwZXJsIEJ1aWxkLlBMCiAgLSAu\nL0J1aWxkIHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(32, 'Postgres', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHBvc3RncmVzOjktYWxwaW5lCiAgY29tbWFuZHM6CiAgLSBwc3Fs\nIC1VIHBvc3RncmVzIC1kIHRlc3QgLWggZGF0YWJhc2UKCnNlcnZpY2VzOgot\nIG5hbWU6IGRhdGFiYXNlCiAgaW1hZ2U6IHBvc3RncmVzOjktYWxwaW5lCiAg\nZW52aXJvbm1lbnQ6CiAgICBQT1NUR1JFU19VU0VSOiBwb3N0Z3JlcwogICAg\nUE9TVEdSRVNfREI6IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(33, 'Redis', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJlZGlzCiAgY29tbWFuZHM6CiAgLSBzbGVlcCA1CiAgLSByZWRp\ncy1jbGkgLWggcmVkaXMgcGluZwogIC0gcmVkaXMtY2xpIC1oIHJlZGlzIHNl\ndCBGT08gYmFyCiAgLSByZWRpcy1jbGkgLWggcmVkaXMgZ2V0IEZPTwoKc2Vy\ndmljZXM6Ci0gbmFtZTogcmVkaXMKICBpbWFnZTogcmVkaXM=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(34, 'RethinkDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG5vZGU6OQogIGNvbW1hbmRzOgogIC0gbnBtIGluc3RhbGwgLXMg\nLWcgcmVjbGkKICAtIHJlY2xpIC1oIGRhdGFiYXNlIC1qICdyLmRiKCdyZXRo\naW5rZGInKS50YWJsZSgnc3RhdHMnKScKCnNlcnZpY2VzOgotIG5hbWU6IGRh\ndGFiYXNlCiAgaW1hZ2U6IHJldGhpbmtkYjoyCiAgY29tbWFuZDogWyByZXRo\naW5rZGIsIC0tYmluZCwgYWxsIF0=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(35, 'Rust', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1c3Q6MS4zMAogIGNvbW1hbmRzOgogIC0gY2FyZ28gYnVpbGQg\nLS12ZXJib3NlIC0tYWxsCiAgLSBjYXJnbyB0ZXN0IC0tdmVyYm9zZSAtLWFs\nbA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(36, 'Swift', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHN3aWZ0OjQKICBjb21tYW5kczoKICAtIHN3aWZ0IGJ1aWxkCiAg\nLSBzd2lmdCB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), +(37, 'Vault', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHZhdWx0OjEuMC4wLWJldGEyCiAgZW52aXJvbm1lbnQ6CiAgICBW\nQVVMVF9BRERSOiBodHRwOi8vdmF1bHQ6ODIwMAogICAgVkFVTFRfVE9LRU46\nIGR1bW15CiBjb21tYW5kczoKIC0gc2xlZXAgNQogLSB2YXVsdCBrdiBwdXQg\nc2VjcmV0L215LXNlY3JldCBteS12YWx1ZT1zM2NyM3QKIC0gdmF1bHQga3Yg\nZ2V0IHNlY3JldC9teS1zZWNyZXQKCnNlcnZpY2VzOgotIG5hbWU6IHZhdWx0\nCiAgaW1hZ2U6IHZhdWx0OjEuMC4wLWJldGEyCiAgZW52aXJvbm1lbnQ6CiAg\nICBWQVVMVF9ERVZfUk9PVF9UT0tFTl9JRDogZHVtbXk=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL); +COMMIT; + +-- ---------------------------- +-- Records of ci_templates +-- ---------------------------- +BEGIN; +INSERT INTO `ci_templates` (`id`, `template_name`, `stage_type`, `category`, `content`, `created_at`, `updated_at`, `parent_category`, `login`) VALUES +(2, 'linux/amd64', 'init', '初始化', 'kind: pipeline\r\ntype: docker\r\nname: {name}\r\nplatform:\r\n os: linux\r\n arch: amd64', '2021-01-12 02:44:23', '2021-02-02 10:51:36', '初始化', 'admin'), +(3, 'linux/arm64', 'init', '初始化', 'kind: pipeline\r\ntype: docker\r\nname: {name}\r\nplatform:\r\n os: linux\r\n arch: arm64', '2021-01-12 02:45:17', '2021-02-02 10:51:47', '初始化', 'admin'), +(4, 'maven', 'build', 'Java', '- name: maven\r\n image: maven:3-jdk-10\r\n commands:\r\n - mvn install -DskipTests=true', '2021-01-12 02:53:29', '2021-01-12 02:53:29', '编译构建', 'admin'), +(5, 'maven单元测试', 'customize', 'Java', '- name: maven\r\n image: maven:3-jdk-10\r\n commands:\r\n - mvn test', '2021-01-12 02:53:29', '2021-01-12 02:53:29', '单元测试', 'admin'), +(6, 'golang单元测试', 'customize', 'Golang', '- name: golang单元测试\r\n image: golang\r\n commands:\r\n - go test', '2021-01-12 03:03:35', '2021-01-12 03:03:35', '单元测试', 'admin'), +(8, 'gradle', 'build', 'Java', '- name: gradle\r\n image: gradle:jdk10\r\n commands:\r\n - gradle build -x test', '2021-01-12 03:05:33', '2021-01-12 03:05:33', '编译构建', 'admin'), +(9, 'gradle单元测试', 'customize', 'Java', '- name: gradle\r\n image: gradle:jdk10\r\n commands:\r\n - gradle test', '2021-01-12 03:05:33', '2021-01-12 03:05:33', '单元测试', 'admin'), +(10, '远程主机部署', 'deploy', '部署', '# 需要将软件包与部署脚本提前上传到远程主机(见文件上传模板)\r\n# host、username、password可在参数管理中配置\r\n- name: 远程主机部署\r\n image: appleboy/drone-ssh\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n script:\r\n - chmod +x /home/deploy.sh\r\n - ./home/deploy.sh', '2021-01-12 03:32:46', '2021-03-05 06:22:02', '部署', 'admin'), +(11, '远程命令', 'customize', '其他', '# host、username、password可在参数管理中配置\r\n- name: 远程命令\r\n image: appleboy/drone-ssh\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n script:\r\n - echo ''hello world!''', '2021-01-12 03:40:38', '2021-03-05 06:19:44', '其他', 'admin'), +(12, '上传文件', 'customize', '其他', '# 本模板示例为上传软件包和部署脚本到home目录\r\n# host、username、password可在参数管理中配置\r\n- name: 上传文件\r\n image: appleboy/drone-scp\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n target: /home\r\n source: \r\n - target/*.jar\r\n - deploy.sh', '2021-01-12 03:40:55', '2021-03-05 06:22:22', '其他', 'admin'), +(17, 'make-c', 'build', 'C', '- name: 编译\r\n image: gcc\r\n commands:\r\n - ./configure\r\n - make', '2021-01-15 01:19:38', '2021-02-02 10:52:15', '编译构建', 'admin'), +(19, 'make-c++', 'build', 'C++', '- name: 编译构建\r\n image: gcc\r\n commands:\r\n - ./configure\r\n - make', '2021-01-15 01:21:05', '2021-01-15 01:21:05', '编译构建', 'admin'), +(20, 'python', 'build', 'Python', '- name: 编译构建\r\n image: python\r\n commands:\r\n - pip install -r requirements.txt', '2021-01-15 01:22:36', '2021-01-15 01:22:36', '编译构建', 'admin'), +(21, 'Docker', 'build', 'Docker', '# 构建Docker镜像并推送到仓库\r\n# 定义镜像Hub路径以及账号密码\r\n- name: Docker镜像构建\r\n image: plugins/docker\r\n settings:\r\n username: username\r\n password: pwd\r\n repo: repoUrl\r\n tags: latest', '2021-01-15 01:23:16', '2021-02-03 03:40:49', '编译构建', 'admin'), +(22, '空白模板', 'customize', 'customize', '', '2021-01-15 02:53:02', '2021-01-15 02:53:02', '其他', 'admin'), +(25, 'Go (with Gopath)', 'build', 'Go', '- name: golang\r\n image: golang\r\n commands:\r\n - go get\r\n - go test', '2021-02-03 00:57:32', '2021-02-03 03:36:15', '编译构建', 'admin'), +(26, 'PHP', 'build', 'PHP', '- name: install\r\n image: composer\r\n commands:\r\n - composer install', '2021-02-03 00:59:15', '2021-02-03 00:59:15', '编译构建', 'admin'), +(27, 'Ruby', 'build', 'Ruby', '- name: ruby\r\n image: ruby\r\n commands:\r\n - bundle install --jobs=3 --retry=3\r\n - rake', '2021-02-03 00:59:52', '2021-02-03 00:59:52', '编译构建', 'admin'), +(29, 'Go (with Modules)', 'build', 'Go', '- name: test\r\n image: golang\r\n commands:\r\n - go test\r\n - go build', '2021-02-03 03:35:45', '2021-02-03 03:35:45', '编译构建', 'admin'), +(30, 'Node', 'build', 'Node', '- name: Node编译\r\n image: node\r\n commands:\r\n - npm install\r\n - npm test', '2021-02-03 03:37:31', '2021-02-03 03:37:31', '编译构建', 'admin'), +(31, 'Perl ', 'build', 'Perl', '- name: perl\r\n image: perl\r\n commands:\r\n - cpanm --quiet --installdeps --notest .\r\n - perl Build.PL\r\n - ./Build test', '2021-02-03 03:38:06', '2021-02-03 03:38:06', '编译构建', 'admin'), +(32, 'Rust ', 'build', 'Rust', '- name: rust\r\n image: rust:1.30\r\n commands:\r\n - cargo build --verbose --all\r\n - cargo test --verbose --all', '2021-02-03 03:38:37', '2021-02-03 03:38:37', '编译构建', 'admin'), +(33, 'test', 'init', '初始化', 'qqqq', '2021-02-04 09:02:42', '2021-02-04 09:02:42', '初始化', 'admin'); +COMMIT; diff --git a/db/structure.sql b/db/structure.sql index 26208e576..3b1b437eb 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -3424,98 +3424,3 @@ COMMIT; BEGIN; INSERT INTO `laboratory_settings` VALUES (1, 1, '{\"name\":\"EduCoder\",\"navbar\":[{\"name\":\"实践课程\",\"link\":\"/paths\",\"hidden\":false},{\"name\":\"翻转课堂\",\"link\":\"/courses\",\"hidden\":false},{\"name\":\"实现项目\",\"link\":\"/shixuns\",\"hidden\":false},{\"name\":\"在线竞赛\",\"link\":\"/competitions\",\"hidden\":false},{\"name\":\"教学案例\",\"link\":\"/moop_cases\",\"hidden\":false},{\"name\":\"交流问答\",\"link\":\"/forums\",\"hidden\":false}],\"footer\":\"\\n\\u003cp class=\\\"footer_con-p inline lineh-30 font-14\\\"\\u003e\\n \\u003cspan class=\\\"font-18 fl\\\"\\u003e©\\u003c/span\\u003e\\u0026nbsp;2019\\u0026nbsp;EduCoder\\n \\u003ca target=\\\"_blank\\\" href=\\\"http://beian.miit.gov.cn/\\\" class=\\\"ml15 mr15\\\" style=\\\"color: rgb(136, 136, 136);\\\"\\u003e湘ICP备17009477号\\u003c/a\\u003e\\n \\u003ca target=\\\"_blank\\\" href=\\\"http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=43019002000962\\\" class=\\\"mr15\\\" style=\\\"color: rgb(136, 136, 136);\\\"\\u003e\\n \\u003cimg class=\\\"vertical4\\\" src=\\\"https://ali-cdn.educoder.net/react/build/static/media/beian.d0289dc0.png\\\"\\u003e湘公网安备43019002000962号\\n \\u003c/a\\u003e\\n \\u003ca href=\\\"https://team.trustie.net\\\" target=\\\"_blank\\\" style=\\\"color: rgb(136, 136, 136);\\\"\\u003eTrustie\\u003c/a\\u003e\\n \\u0026nbsp;\\u0026nbsp;\\u0026nbsp;\\u0026amp;\\u0026nbsp;\\u0026nbsp;\\u0026nbsp;IntelliDE inside.\\n \\u003cspan class=\\\"mr15\\\"\\u003e版权所有 湖南智擎科技有限公司\\u003c/span\\u003e\\u003c/p\\u003e\\n \"}'); COMMIT; - --- ---------------------------- --- Records of roles --- ---------------------------- -BEGIN; -INSERT INTO `roles` (`id`, `name`, `position`, `assignable`, `builtin`, `permissions`, `issues_visibility`) VALUES -(1, 'Non member', 1, 1, 1, '---\n- :upload_attachments\n- :memos_attachments_download\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :add_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), -(2, 'Anonymous', 2, 1, 2, '---\n- :memos_attachments_download\n- :view_course_files\n- :view_calendar\n- :view_documents\n- :view_files\n- :view_gantt\n- :view_issues\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), -(3, 'Manager', 3, 1, 0, '---\n- :add_project\n- :edit_project\n- :close_project\n- :select_project_modules\n- :manage_members\n- :manage_versions\n- :add_subprojects\n- :is_manager\n- :projects_attachments_download\n- :as_teacher\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :quote_project\n- :manage_boards\n- :add_messages\n- :edit_messages\n- :edit_own_messages\n- :delete_messages\n- :delete_own_messages\n- :view_calendar\n- :view_code_review\n- :add_code_review\n- :edit_code_review\n- :delete_code_review\n- :assign_code_review\n- :code_review_setting\n- :add_documents\n- :edit_documents\n- :delete_documents\n- :view_documents\n- :manage_files\n- :view_files\n- :view_gantt\n- :manage_categories\n- :view_issues\n- :add_issues\n- :edit_issues\n- :manage_issue_relations\n- :manage_subtasks\n- :set_issues_private\n- :set_own_issues_private\n- :add_issue_notes\n- :edit_issue_notes\n- :edit_own_issue_notes\n- :view_private_notes\n- :set_notes_private\n- :move_issues\n- :delete_issues\n- :manage_public_queries\n- :save_queries\n- :view_issue_watchers\n- :add_issue_watchers\n- :delete_issue_watchers\n- :manage_news\n- :comment_news\n- :manage_repository\n- :browse_repository\n- :view_changesets\n- :commit_access\n- :manage_related_issues\n- :log_time\n- :view_time_entries\n- :edit_time_entries\n- :edit_own_time_entries\n- :manage_project_activities\n- :manage_wiki\n- :rename_wiki_pages\n- :delete_wiki_pages\n- :view_wiki_pages\n- :export_wiki_pages\n- :view_wiki_edits\n- :edit_wiki_pages\n- :delete_wiki_pages_attachments\n- :protect_wiki_pages\n', 'all'), -(4, 'Developer', 5, 1, 0, '---\n- :add_project\n- :manage_versions\n- :projects_attachments_download\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :paret_in_homework\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :manage_contestnotifications\n- :notificationcomment_contestnotifications\n- :manage_boards\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :manage_files\n- :view_files\n- :view_gantt\n- :manage_categories\n- :view_issues\n- :add_issues\n- :edit_issues\n- :manage_issue_relations\n- :manage_subtasks\n- :set_issues_private\n- :set_own_issues_private\n- :add_issue_notes\n- :edit_issue_notes\n- :edit_own_issue_notes\n- :view_private_notes\n- :set_notes_private\n- :move_issues\n- :delete_issues\n- :manage_public_queries\n- :save_queries\n- :view_issue_watchers\n- :add_issue_watchers\n- :delete_issue_watchers\n- :manage_repository\n- :browse_repository\n- :view_changesets\n- :commit_access\n- :manage_related_issues\n', 'all'), -(5, 'Reporter', 4, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :manage_boards\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :view_code_review\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :add_issues\n- :edit_issues\n- :add_issue_notes\n- :edit_own_issue_notes\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_wiki_pages\n- :export_wiki_pages\n- :view_wiki_edits\n- :edit_wiki_pages\n- :delete_wiki_pages_attachments\n', 'all'), -(7, 'TeachingAsistant', 6, 1, 0, '---\n- :add_project\n- :edit_project\n- :manage_members\n- :projects_attachments_download\n- :as_teacher\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :manage_boards\n- :add_messages\n- :edit_own_messages\n- :delete_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :add_issues\n- :add_issue_notes\n- :save_queries\n- :manage_news\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :export_wiki_pages\n- :view_wiki_edits\n- :edit_wiki_pages\n- :delete_wiki_pages_attachments\n', 'default'), -(9, 'Teacher', 7, 1, 0, '---\n- :upload_attachments\n- :memos_attachments_download\n- :add_project\n- :edit_project\n- :close_project\n- :select_project_modules\n- :manage_members\n- :manage_versions\n- :add_subprojects\n- :projects_attachments_download\n- :as_teacher\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :manage_boards\n- :add_messages\n- :edit_messages\n- :edit_own_messages\n- :delete_messages\n- :delete_own_messages\n- :view_calendar\n- :add_documents\n- :edit_documents\n- :delete_documents\n- :view_documents\n- :manage_files\n- :view_files\n- :view_gantt\n- :manage_categories\n- :view_issues\n- :add_issues\n- :edit_issues\n- :manage_issue_relations\n- :manage_subtasks\n- :set_issues_private\n- :set_own_issues_private\n- :add_issue_notes\n- :edit_own_issue_notes\n- :view_private_notes\n- :set_notes_private\n- :move_issues\n- :delete_issues\n- :manage_public_queries\n- :save_queries\n- :view_issue_watchers\n- :add_issue_watchers\n- :delete_issue_watchers\n- :manage_news\n- :comment_news\n- :manage_repository\n- :browse_repository\n- :view_changesets\n- :commit_access\n- :manage_related_issues\n- :log_time\n- :view_time_entries\n- :edit_time_entries\n- :edit_own_time_entries\n- :manage_project_activities\n- :manage_wiki\n- :rename_wiki_pages\n- :delete_wiki_pages\n- :view_wiki_pages\n- :export_wiki_pages\n- :view_wiki_edits\n- :edit_wiki_pages\n- :delete_wiki_pages_attachments\n- :protect_wiki_pages\n', 'default'), -(10, 'Student', 9, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :as_student\n- :add_course\n- :edit_course\n- :close_course\n- :select_course_modules\n- :view_course_journals_for_messages\n- :course_attachments_download\n- :view_course_files\n- :view_homework_attaches\n- :paret_in_homework\n- :manage_boards\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :add_issues\n- :add_issue_notes\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), -(11, 'orgManager', 8, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :add_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), -(12, 'orgMember', 10, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :add_messages\n- :delete_own_messages\n- :view_calendar\n- :view_documents\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :comment_news\n- :browse_repository\n- :view_changesets\n- :view_time_entries\n- :view_wiki_pages\n- :view_wiki_edits\n', 'default'), -(13, 'ContestManager', 11, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :manage_contestnotifications\n- :notificationcomment_contestnotifications\n- :manage_boards\n- :add_messages\n- :edit_messages\n- :edit_own_messages\n- :delete_messages\n- :delete_own_messages\n- :view_calendar\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :browse_repository\n- :view_changesets\n', 'default'), -(14, 'Judge', 12, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :manage_contestnotifications\n- :notificationcomment_contestnotifications\n- :manage_boards\n- :add_messages\n- :edit_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :browse_repository\n- :view_changesets\n', 'default'), -(15, 'Contestant', 13, 1, 0, '---\n- :add_project\n- :projects_attachments_download\n- :add_course\n- :course_attachments_download\n- :view_course_files\n- :select_contest_modules\n- :quote_project\n- :contest_attachments_download\n- :notificationcomment_contestnotifications\n- :add_messages\n- :edit_own_messages\n- :delete_own_messages\n- :view_calendar\n- :manage_files\n- :view_files\n- :view_gantt\n- :view_issues\n- :save_queries\n- :browse_repository\n- :view_changesets\n', 'default'); -COMMIT; - - --- ---------------------------- --- Records of ci_languages --- ---------------------------- -BEGIN; -INSERT INTO `ci_languages` (`id`, `name`, `content`, `usage_amount`, `created_at`, `updated_at`, `cover_id`) VALUES -(1, 'C', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdjYwogIGNvbW1hbmRzOgogIC0gLi9jb25maWd1cmUKICAtIG1h\na2UKICAtIG1ha2UgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(2, 'C++', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdjYwogIGNvbW1hbmRzOgogIC0gLi9jb25maWd1cmUKICAtIG1h\na2UKICAtIG1ha2UgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(3, 'Docker', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgdm9sdW1lczoKICAtIG5hbWU6IGRvY2tl\ncnNvY2sKICAgIHBhdGg6IC92YXIvcnVuL2RvY2tlci5zb2NrCiAgICBjb21t\nYW5kczoKICAgIC0gZG9ja2VyIHBzIC1hCgp2b2x1bWVzOgotIG5hbWU6IGRv\nY2tlcnNvY2sKICBob3N0OgogICAgcGF0aDogL3Zhci9ydW4vZG9ja2VyLnNv\nY2s=\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:35:20', 351688), -(4, 'Java', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hdmVuOjMtamRrLTEwCiAgY29tbWFuZHM6CiAgLSBtdm4gaW5z\ndGFsbCAtRHNraXBUZXN0cz10cnVlIC1EbWF2ZW4uamF2YWRvYy5za2lwPXRy\ndWUgLUIgLVYKICAtIG12biB0ZXN0IC1C\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(5, 'R', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHItYmFzZQogIGNvbW1hbmRzOgogIC0gUiAtZSAnaW5zdGFsbC5w\nYWNrYWdlcyhjKCdwYWNrYWdlMScsJ3BhY2thZ2UyJykpJwogIC0gUiBDTUQg\nYnVpbGQgLg==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(6, 'Ruby', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1YnkKICBjb21tYW5kczoKICAtIGJ1bmRsZSBpbnN0YWxsIC0t\nam9icz0zIC0tcmV0cnk9MwogIC0gcmFrZQ==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(7, 'PHP', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiBpbnN0YWxs\nCiAgaW1hZ2U6IGNvbXBvc2VyCiAgY29tbWFuZHM6CiAgLSBjb21wb3NlciBp\nbnN0YWxsCgotIG5hbWU6IHRlc3QKICBpbWFnZTogcGhwOjcKICBjb21tYW5k\nczoKICAtIHZlbmRvci9iaW4vcGhwdW5pdCAtLWNvbmZpZ3VyYXRpb24gY29u\nZmlnLnhtbA==\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:37:04', 351690), -(8, 'Python', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHB5dGhvbgogIGNvbW1hbmRzOgogIC0gcGlwIGluc3RhbGwgLXIg\ncmVxdWlyZW1lbnRzLnR4dAogIC0gcHl0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:40:00', 351693), -(9, 'MySQL', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG15c3FsCiAgY29tbWFuZHM6CiAgLSBzbGVlcCAxNQogIC0gbXlz\ncWwgLXUgcm9vdCAtaCBkYXRhYmFzZSAtLWV4ZWN1dGU9J1NFTEVDVCBWRVJT\nSU9OKCk7JwoKc2VydmljZXM6Ci0gbmFtZTogZGF0YWJhc2UKICBpbWFnZTog\nbXlzcWwKICBlbnZpcm9ubWVudDoKICAgIE1ZU1FMX0FMTE9XX0VNUFRZX1BB\nU1NXT1JEOiAneWVzJwogICAgTVlTUUxfREFUQUJBU0U6IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(10, 'MongoDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiBwaW5nCiAg\naW1hZ2U6IG1vbmdvOjQKICBjb21tYW5kczoKICAtIHNsZWVwIDUKICAtIG1v\nbmdvIC0taG9zdCBtb25nbyAtLWV2YWwgJ2RiLnZlcnNpb24oKScKCnNlcnZp\nY2VzOgotIG5hbWU6IG1vbmdvCiAgaW1hZ2U6IG1vbmdvOjQKICBjb21tYW5k\nOiBbIC0tc21hbGxmaWxlcyBd\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(11, 'Clojure', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNsb2p1cmUKICBjb21tYW5kczoKICAtIGxlaW4gdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(12, 'CouchDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNvdWNoZGI6Mi4yCiAgY29tbWFuZHM6CiAgLSBzbGVlcCAxNQog\nIC0gY3VybCBodHRwOi8vZGF0YWJhc2U6NTk4NAoKc2VydmljZXM6Ci0gbmFt\nZTogZGF0YWJhc2UKICBpbWFnZTogY291Y2hkYjoyLjI=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(13, 'Crystal', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGNyeXN0YWxsYW5nL2NyeXN0YWwKICBjb21tYW5kczoKICAtIHNo\nYXJkcyBpbnN0YWxsCiAgLSBjcnlzdGFsIHNwZWMuMg==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(14, 'D', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRsYW5ndWFnZS9kbWQKICBjb21tYW5kczoKICAtIGR1YiB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(15, 'Dart', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdvb2dsZS9kYXJ0CiAgY29tbWFuZHM6CiAgLSBwdWIgZ2V0CiAg\nLSBwdWIgcnVuIHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(16, 'Docker (dind)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgdm9sdW1lczoKICAtIG5hbWU6IGRvY2tl\ncnNvY2sKICAgIHBhdGg6IC92YXIvcnVuCiAgICBjb21tYW5kczoKICAgIC0g\nc2xlZXAgNSAjIGdpdmUgZG9ja2VyIGVub3VnaCB0aW1lIHRvIHN0YXJ0CiAg\nICAtIGRvY2tlciBwcyAtYQoKc2VydmljZXM6Ci0gbmFtZTogZG9ja2VyCiAg\naW1hZ2U6IGRvY2tlcjpkaW5kCiAgcHJpdmlsZWdlZDogdHJ1ZQogIHZvbHVt\nZXM6CiAgLSBuYW1lOiBkb2NrZXJzb2NrCiAgICBwYXRoOiAvdmFyL3J1bgoK\ndm9sdW1lczoKLSBuYW1lOiBkb2NrZXJzb2NrCiAgdGVtcDoge30=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(17, 'Elasticsearch', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGFscGluZTozLjgKICBjb21tYW5kczoKICAtIGFwayBhZGQgY3Vy\nbAogIC0gc2xlZXAgNDUKICAtIGN1cmwgaHR0cDovL2RhdGFiYXNlOjkyMDAK\nCnNlcnZpY2VzOgotIG5hbWU6IGRhdGFiYXNlCiAgaW1hZ2U6IGVsYXN0aWNz\nZWFyY2g6NS1hbHBpbmU=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(18, 'Elixir', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGVsaXhpcjoxLjUKICBjb21tYW5kczoKICAtIG1peCBsb2NhbC5y\nZWJhciAtLWZvcmNlCiAgLSBtaXggbG9jYWwuaGV4IC0tZm9yY2UKICAtIG1p\neCBkZXBzLmdldAogIC0gbWl4IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(19, 'Erlang', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGVybGFuZzoyMQogIGNvbW1hbmRzOgogIC0gcmViYXIgZ2V0LWRl\ncHMKICAtIHJlYmFyIGNvbXBpbGUKICAtIHJlYmFyIHNraXBfZGVwcz10cnVl\nIGV1bml0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(20, '20.Go (with Gopath)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0Cgp3b3Jrc3BhY2U6CiAgYmFzZTogL2dv\nCiAgcGF0aDogc3JjL2hlbGxvLXdvcmxkCgpzdGVwczoKLSBuYW1lOiB0ZXN0\nCiAgaW1hZ2U6IGdvbGFuZwogIGNvbW1hbmRzOgogIC0gZ28gZ2V0CiAgLSBn\nbyB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(21, '21.Go (with Modules)', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdvbGFuZwogIGNvbW1hbmRzOgogIC0gZ28gdGVzdAogIC0gZ28g\nYnVpbGQ=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(22, 'Gradle', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdyYWRsZTpqZGsxMAogIGNvbW1hbmRzOgogIC0gZ3JhZGxlIGFz\nc2VtYmxlCiAgLSBncmFkbGUgY2hlY2s=\n', 0, '2020-10-21 10:14:22', '2020-11-26 01:36:17', 351689), -(23, 'Groovy', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGdyYWRsZToyLjUtamRrOAogIGNvbW1hbmRzOgogIC0gLi9ncmFk\nbGV3IGFzc2VtYmxlCiAgLSAuL2dyYWRsZXcgY2hlY2s=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(24, 'Haskell', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGhhc2tlbGwKICBjb21tYW5kczoKICAtIGNhYmFsIGluc3RhbGwg\nLS1vbmx5LWRlcGVuZGVuY2llcyAtLWVuYWJsZS10ZXN0cwogIC0gY2FiYWwg\nY29uZmlndXJlIC0tZW5hYmxlLXRlc3RzCiAgLSBjYWJhbCBidWlsZAogIC0g\nY2FiYWwgdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(25, 'Haxe', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IGhheGUKICBjb21tYW5kczoKICAtIGhheGVsaWIgaW5zdGFsbCBi\ndWlsZC5oeG1sCiAgLSBoYXhlIGJ1aWxkLmh4bWw=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(26, 'MariaDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hcmlhZGIKICBjb21tYW5kczoKICAtIHNsZWVwIDE1CiAgLSBt\neXNxbCAtdSByb290IC1oIGRhdGFiYXNlIC0tZXhlY3V0ZT0nU0VMRUNUIFZF\nUlNJT04oKTsnCgpzZXJ2aWNlczoKLSBuYW1lOiBkYXRhYmFzZQogIGltYWdl\nOiBtYXJpYWRiCiAgZW52aXJvbm1lbnQ6CiAgICBNWVNRTF9BTExPV19FTVBU\nWV9QQVNTV09SRDogJ3llcycKICAgIE1ZU1FMX0RBVEFCQVNFOiB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(27, 'Maven', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG1hdmVuOjMtamRrLTEwCiAgY29tbWFuZHM6CiAgLSBtdm4gaW5z\ndGFsbCAtRHNraXBUZXN0cz10cnVlIC1EbWF2ZW4uamF2YWRvYy5za2lwPXRy\ndWUgLUIgLVYKICAtIG12biB0ZXN0IC1C\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(28, 'Memcached', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHVidW50dQogIGNvbW1hbmRzOgogIC0gYXB0LWdldCB1cGRhdGUg\nLXFxCiAgLSBhcHQtZ2V0IGluc3RhbGwgLXkgLXFxIHRlbG5ldCA+IC9kZXYv\nbnVsbAogIC0gKHNsZWVwIDE7IGVjaG8gJ3N0YXRzJzsgc2xlZXAgMjsgZWNo\nbyAncXVpdCc7KSB8IHRlbG5ldCBjYWNoZSAxMTIxMSB8fCB0cnVlCgpzZXJ2\naWNlczoKLSBuYW1lOiBjYWNoZQogIGltYWdlOiBtZW1jYWNoZWQ6YWxwaW5l\nCiAgY29tbWFuZDogWyAtdnYgXQ==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(29, 'Nats', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1Ynk6MgogIGNvbW1hbmRzOgogIC0gZ2VtIGluc3RhbGwgbmF0\ncwogIC0gbmF0cy1wdWIgLXMgdGNwOi8vbmF0czo0MjIyIGdyZWV0aW5nICdo\nZWxsbycKICAtIG5hdHMtcHViIC1zIHRjcDovL25hdHM6NDIyMiBncmVldGlu\nZyAnd29ybGQnCgpzZXJ2aWNlczoKLSBuYW1lOiBuYXRzCiAgaW1hZ2U6IG5h\ndHM6MS4zLjA=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(30, 'Node', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG5vZGUKICBjb21tYW5kczoKICAtIG5wbSBpbnN0YWxsCiAgLSBu\ncG0gdGVzdA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(31, 'Perl', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHBlcmwKICBjb21tYW5kczoKICAtIGNwYW5tIC0tcXVpZXQgLS1p\nbnN0YWxsZGVwcyAtLW5vdGVzdCAuCiAgLSBwZXJsIEJ1aWxkLlBMCiAgLSAu\nL0J1aWxkIHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(32, 'Postgres', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHBvc3RncmVzOjktYWxwaW5lCiAgY29tbWFuZHM6CiAgLSBwc3Fs\nIC1VIHBvc3RncmVzIC1kIHRlc3QgLWggZGF0YWJhc2UKCnNlcnZpY2VzOgot\nIG5hbWU6IGRhdGFiYXNlCiAgaW1hZ2U6IHBvc3RncmVzOjktYWxwaW5lCiAg\nZW52aXJvbm1lbnQ6CiAgICBQT1NUR1JFU19VU0VSOiBwb3N0Z3JlcwogICAg\nUE9TVEdSRVNfREI6IHRlc3Q=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(33, 'Redis', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJlZGlzCiAgY29tbWFuZHM6CiAgLSBzbGVlcCA1CiAgLSByZWRp\ncy1jbGkgLWggcmVkaXMgcGluZwogIC0gcmVkaXMtY2xpIC1oIHJlZGlzIHNl\ndCBGT08gYmFyCiAgLSByZWRpcy1jbGkgLWggcmVkaXMgZ2V0IEZPTwoKc2Vy\ndmljZXM6Ci0gbmFtZTogcmVkaXMKICBpbWFnZTogcmVkaXM=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(34, 'RethinkDB', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IG5vZGU6OQogIGNvbW1hbmRzOgogIC0gbnBtIGluc3RhbGwgLXMg\nLWcgcmVjbGkKICAtIHJlY2xpIC1oIGRhdGFiYXNlIC1qICdyLmRiKCdyZXRo\naW5rZGInKS50YWJsZSgnc3RhdHMnKScKCnNlcnZpY2VzOgotIG5hbWU6IGRh\ndGFiYXNlCiAgaW1hZ2U6IHJldGhpbmtkYjoyCiAgY29tbWFuZDogWyByZXRo\naW5rZGIsIC0tYmluZCwgYWxsIF0=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(35, 'Rust', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHJ1c3Q6MS4zMAogIGNvbW1hbmRzOgogIC0gY2FyZ28gYnVpbGQg\nLS12ZXJib3NlIC0tYWxsCiAgLSBjYXJnbyB0ZXN0IC0tdmVyYm9zZSAtLWFs\nbA==\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(36, 'Swift', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHN3aWZ0OjQKICBjb21tYW5kczoKICAtIHN3aWZ0IGJ1aWxkCiAg\nLSBzd2lmdCB0ZXN0\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL), -(37, 'Vault', 'CmtpbmQ6IHBpcGVsaW5lCm5hbWU6IGRlZmF1bHQKCnBsYXRmb3JtOgogIG9z\nOiBsaW51eAogIGFyY2g6IGFybTY0CgpzdGVwczoKLSBuYW1lOiB0ZXN0CiAg\naW1hZ2U6IHZhdWx0OjEuMC4wLWJldGEyCiAgZW52aXJvbm1lbnQ6CiAgICBW\nQVVMVF9BRERSOiBodHRwOi8vdmF1bHQ6ODIwMAogICAgVkFVTFRfVE9LRU46\nIGR1bW15CiBjb21tYW5kczoKIC0gc2xlZXAgNQogLSB2YXVsdCBrdiBwdXQg\nc2VjcmV0L215LXNlY3JldCBteS12YWx1ZT1zM2NyM3QKIC0gdmF1bHQga3Yg\nZ2V0IHNlY3JldC9teS1zZWNyZXQKCnNlcnZpY2VzOgotIG5hbWU6IHZhdWx0\nCiAgaW1hZ2U6IHZhdWx0OjEuMC4wLWJldGEyCiAgZW52aXJvbm1lbnQ6CiAg\nICBWQVVMVF9ERVZfUk9PVF9UT0tFTl9JRDogZHVtbXk=\n', 0, '2020-10-21 10:14:22', '2020-10-21 10:14:22', NULL); -COMMIT; - --- ---------------------------- --- Records of ci_templates --- ---------------------------- -BEGIN; -INSERT INTO `ci_templates` (`id`, `template_name`, `stage_type`, `category`, `content`, `created_at`, `updated_at`, `parent_category`, `login`) VALUES -(2, 'linux/amd64', 'init', '初始化', 'kind: pipeline\r\ntype: docker\r\nname: {name}\r\nplatform:\r\n os: linux\r\n arch: amd64', '2021-01-12 02:44:23', '2021-02-02 10:51:36', '初始化', 'admin'), -(3, 'linux/arm64', 'init', '初始化', 'kind: pipeline\r\ntype: docker\r\nname: {name}\r\nplatform:\r\n os: linux\r\n arch: arm64', '2021-01-12 02:45:17', '2021-02-02 10:51:47', '初始化', 'admin'), -(4, 'maven', 'build', 'Java', '- name: maven\r\n image: maven:3-jdk-10\r\n commands:\r\n - mvn install -DskipTests=true', '2021-01-12 02:53:29', '2021-01-12 02:53:29', '编译构建', 'admin'), -(5, 'maven单元测试', 'customize', 'Java', '- name: maven\r\n image: maven:3-jdk-10\r\n commands:\r\n - mvn test', '2021-01-12 02:53:29', '2021-01-12 02:53:29', '单元测试', 'admin'), -(6, 'golang单元测试', 'customize', 'Golang', '- name: golang单元测试\r\n image: golang\r\n commands:\r\n - go test', '2021-01-12 03:03:35', '2021-01-12 03:03:35', '单元测试', 'admin'), -(8, 'gradle', 'build', 'Java', '- name: gradle\r\n image: gradle:jdk10\r\n commands:\r\n - gradle build -x test', '2021-01-12 03:05:33', '2021-01-12 03:05:33', '编译构建', 'admin'), -(9, 'gradle单元测试', 'customize', 'Java', '- name: gradle\r\n image: gradle:jdk10\r\n commands:\r\n - gradle test', '2021-01-12 03:05:33', '2021-01-12 03:05:33', '单元测试', 'admin'), -(10, '远程主机部署', 'deploy', '部署', '# 需要将软件包与部署脚本提前上传到远程主机(见文件上传模板)\r\n# host、username、password可在参数管理中配置\r\n- name: 远程主机部署\r\n image: appleboy/drone-ssh\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n script:\r\n - chmod +x /home/deploy.sh\r\n - ./home/deploy.sh', '2021-01-12 03:32:46', '2021-03-05 06:22:02', '部署', 'admin'), -(11, '远程命令', 'customize', '其他', '# host、username、password可在参数管理中配置\r\n- name: 远程命令\r\n image: appleboy/drone-ssh\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n script:\r\n - echo ''hello world!''', '2021-01-12 03:40:38', '2021-03-05 06:19:44', '其他', 'admin'), -(12, '上传文件', 'customize', '其他', '# 本模板示例为上传软件包和部署脚本到home目录\r\n# host、username、password可在参数管理中配置\r\n- name: 上传文件\r\n image: appleboy/drone-scp\r\n settings:\r\n host: \r\n from_secret: ip\r\n username: \r\n from_secret: name\r\n password: \r\n from_secret: pwd\r\n port: 22\r\n target: /home\r\n source: \r\n - target/*.jar\r\n - deploy.sh', '2021-01-12 03:40:55', '2021-03-05 06:22:22', '其他', 'admin'), -(17, 'make-c', 'build', 'C', '- name: 编译\r\n image: gcc\r\n commands:\r\n - ./configure\r\n - make', '2021-01-15 01:19:38', '2021-02-02 10:52:15', '编译构建', 'admin'), -(19, 'make-c++', 'build', 'C++', '- name: 编译构建\r\n image: gcc\r\n commands:\r\n - ./configure\r\n - make', '2021-01-15 01:21:05', '2021-01-15 01:21:05', '编译构建', 'admin'), -(20, 'python', 'build', 'Python', '- name: 编译构建\r\n image: python\r\n commands:\r\n - pip install -r requirements.txt', '2021-01-15 01:22:36', '2021-01-15 01:22:36', '编译构建', 'admin'), -(21, 'Docker', 'build', 'Docker', '# 构建Docker镜像并推送到仓库\r\n# 定义镜像Hub路径以及账号密码\r\n- name: Docker镜像构建\r\n image: plugins/docker\r\n settings:\r\n username: username\r\n password: pwd\r\n repo: repoUrl\r\n tags: latest', '2021-01-15 01:23:16', '2021-02-03 03:40:49', '编译构建', 'admin'), -(22, '空白模板', 'customize', 'customize', '', '2021-01-15 02:53:02', '2021-01-15 02:53:02', '其他', 'admin'), -(25, 'Go (with Gopath)', 'build', 'Go', '- name: golang\r\n image: golang\r\n commands:\r\n - go get\r\n - go test', '2021-02-03 00:57:32', '2021-02-03 03:36:15', '编译构建', 'admin'), -(26, 'PHP', 'build', 'PHP', '- name: install\r\n image: composer\r\n commands:\r\n - composer install', '2021-02-03 00:59:15', '2021-02-03 00:59:15', '编译构建', 'admin'), -(27, 'Ruby', 'build', 'Ruby', '- name: ruby\r\n image: ruby\r\n commands:\r\n - bundle install --jobs=3 --retry=3\r\n - rake', '2021-02-03 00:59:52', '2021-02-03 00:59:52', '编译构建', 'admin'), -(29, 'Go (with Modules)', 'build', 'Go', '- name: test\r\n image: golang\r\n commands:\r\n - go test\r\n - go build', '2021-02-03 03:35:45', '2021-02-03 03:35:45', '编译构建', 'admin'), -(30, 'Node', 'build', 'Node', '- name: Node编译\r\n image: node\r\n commands:\r\n - npm install\r\n - npm test', '2021-02-03 03:37:31', '2021-02-03 03:37:31', '编译构建', 'admin'), -(31, 'Perl ', 'build', 'Perl', '- name: perl\r\n image: perl\r\n commands:\r\n - cpanm --quiet --installdeps --notest .\r\n - perl Build.PL\r\n - ./Build test', '2021-02-03 03:38:06', '2021-02-03 03:38:06', '编译构建', 'admin'), -(32, 'Rust ', 'build', 'Rust', '- name: rust\r\n image: rust:1.30\r\n commands:\r\n - cargo build --verbose --all\r\n - cargo test --verbose --all', '2021-02-03 03:38:37', '2021-02-03 03:38:37', '编译构建', 'admin'), -(33, 'test', 'init', '初始化', 'qqqq', '2021-02-04 09:02:42', '2021-02-04 09:02:42', '初始化', 'admin'); -COMMIT; diff --git a/lib/tasks/sync_table_structure.rake b/lib/tasks/sync_table_structure.rake index 026d52140..4cf5f8912 100644 --- a/lib/tasks/sync_table_structure.rake +++ b/lib/tasks/sync_table_structure.rake @@ -18,4 +18,22 @@ namespace :sync_table_structure do puts "init success" end + + task data: :environment do + puts "init table data......." + + database_config = Rails.configuration.database_configuration + + database = database_config[Rails.env]["database"] + database_username = database_config[Rails.env]["username"] + database_password = database_config[Rails.env]["password"] + database_host = database_config[Rails.env]["host"] + database_port = database_config[Rails.env]["port"] || 3306 + + puts "bash: mysql -u#{database_username} -p#{database_password} -P#{database_port} -h#{database_host} #{database}" + + system "mysql -u#{database_username} -p#{database_password} -P#{database_port} -h#{database_host} #{database} < #{Rails.root}/db/init_data.sql" + + puts "init success" + end end From 317c211de918042a6b3c9f77b85a7c36107d2f75 Mon Sep 17 00:00:00 2001 From: viletyy Date: Thu, 3 Jun 2021 11:56:32 +0800 Subject: [PATCH 198/643] add: user info add show field --- Gemfile.lock | 4 +++- app/views/users/get_user_info.json.jbuilder | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 015c0a515..b1dc2cca7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -176,7 +176,9 @@ GEM mimemagic (~> 0.3.2) maruku (0.7.3) method_source (0.9.2) - mimemagic (0.3.4) + mimemagic (0.3.10) + nokogiri (~> 1) + rake mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.14.0) diff --git a/app/views/users/get_user_info.json.jbuilder b/app/views/users/get_user_info.json.jbuilder index d9aa44025..fd74b780e 100644 --- a/app/views/users/get_user_info.json.jbuilder +++ b/app/views/users/get_user_info.json.jbuilder @@ -14,3 +14,9 @@ json.profile_completed @user.profile_completed? json.professional_certification @user.professional_certification json.devops_step @user.devops_step json.ci_certification @user.ci_certification? +json.email @user.mail +json.province @user.province +json.city @user.city +json.custom_department @user.custom_department +json.description @user.description +json.(@user, :show_email, :show_department, :show_location) \ No newline at end of file From 6b436acfaf942b9cabfdba3e0fee998fe718e01f Mon Sep 17 00:00:00 2001 From: viletyy Date: Thu, 3 Jun 2021 15:22:08 +0800 Subject: [PATCH 199/643] add: user info add gender --- app/views/users/get_user_info.json.jbuilder | 1 + app/views/users/show.json.jbuilder | 1 + 2 files changed, 2 insertions(+) diff --git a/app/views/users/get_user_info.json.jbuilder b/app/views/users/get_user_info.json.jbuilder index fd74b780e..50296f524 100644 --- a/app/views/users/get_user_info.json.jbuilder +++ b/app/views/users/get_user_info.json.jbuilder @@ -1,5 +1,6 @@ json.username @user.full_name json.real_name @user.real_name +json.gender @user.gender json.login @user.login json.user_id @user.id json.image_url url_to_avatar(@user) diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index 06fab129f..aee46cb01 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -2,6 +2,7 @@ json.username @user.full_name json.real_name @user.real_name +json.gender @user.gender json.login @user.login json.user_id @user.id json.image_url url_to_avatar(@user) From 93169f8c9621e4e21addb50f1d4e07a07eb6df57 Mon Sep 17 00:00:00 2001 From: viletyy Date: Thu, 3 Jun 2021 15:43:36 +0800 Subject: [PATCH 200/643] fix: user update return info --- app/controllers/users_controller.rb | 5 ++--- app/views/users/_user.json.jbuilder | 21 +++++++++++++++++---- app/views/users/show.json.jbuilder | 22 ++-------------------- app/views/users/update.json.jbuilder | 1 + 4 files changed, 22 insertions(+), 27 deletions(-) create mode 100644 app/views/users/update.json.jbuilder diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3f7cd4170..237ce9e6a 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -74,11 +74,10 @@ class UsersController < ApplicationController def update return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id]) + return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id) Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? @user.attributes = user_params.except(:image) - if @user.save - render_ok - else + unless @user.save render_error(@user.errors.full_messages.join(", ")) end end diff --git a/app/views/users/_user.json.jbuilder b/app/views/users/_user.json.jbuilder index 96299c7eb..dc43d6bc8 100644 --- a/app/views/users/_user.json.jbuilder +++ b/app/views/users/_user.json.jbuilder @@ -1,7 +1,20 @@ json.user_id user.id -json.login user.login json.name user.full_name +json.username @user.full_name +json.real_name @user.real_name json.grade user.grade -json.identity user&.user_extension&.identity -# json.email user.mail # 邮箱原则上不暴露的,如果实在需要的话只能对某些具体的接口公开 -json.image_url url_to_avatar(user) +json.gender @user.gender +json.login @user.login +json.user_id @user.id +json.image_url url_to_avatar(@user) +json.admin @user.admin? +json.user_identity @user.identity +json.is_watch current_user&.watched?(@user) +json.watched_count @user.fan_count #粉丝 +json.watching_count @user.follow_count #关注数 +json.created_time format_time(@user.created_on) +json.email @user.show_email ? @user.mail : nil +json.province @user.show_location ? @user.province : nil +json.city @user.show_location ? @user.city : nil +json.custom_department @user.show_department ? @user.custom_department : nil +json.description @user.description \ No newline at end of file diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index aee46cb01..0bbd915bb 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -1,16 +1,4 @@ -# json.partial! 'users/user', locals: { user: @user } - -json.username @user.full_name -json.real_name @user.real_name -json.gender @user.gender -json.login @user.login -json.user_id @user.id -json.image_url url_to_avatar(@user) -json.admin @user.admin? -json.user_identity @user.identity -json.is_watch current_user&.watched?(@user) -json.watched_count @user.fan_count #粉丝 -json.watching_count @user.follow_count #关注数 +json.partial! 'users/user', locals: { user: @user } json.undo_messages @waiting_applied_messages.size json.undo_transfer_projects @common_applied_transfer_projects.size json.undo_events @undo_events @@ -18,10 +6,4 @@ json.user_composes_count @user_composes_count json.user_org_count @user_org_count json.common_projects_count @projects_common_count json.mirror_projects_count @projects_mirrior_count -json.sync_mirror_projects_count @projects_sync_mirrior_count -json.created_time format_time(@user.created_on) -json.email @user.show_email ? @user.mail : nil -json.province @user.show_location ? @user.province : nil -json.city @user.show_location ? @user.city : nil -json.custom_department @user.show_department ? @user.custom_department : nil -json.description @user.description \ No newline at end of file +json.sync_mirror_projects_count @projects_sync_mirrior_count \ No newline at end of file diff --git a/app/views/users/update.json.jbuilder b/app/views/users/update.json.jbuilder new file mode 100644 index 000000000..2b31e1826 --- /dev/null +++ b/app/views/users/update.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'users/user', locals: { user: @user } From 2b82b2c4f509b91f52999ecada66c84225497b42 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 3 Jun 2021 16:56:54 +0800 Subject: [PATCH 201/643] =?UTF-8?q?FIX=20=20[bug]=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E6=98=93=E4=BF=AEapi=E4=B8=AD=20=E6=9B=B4=E6=96=B0=E7=9B=B8?= =?UTF-8?q?=E5=85=B3cache=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/tag_chosen_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/tag_chosen_helper.rb b/app/helpers/tag_chosen_helper.rb index 348062c77..5193c9ab4 100644 --- a/app/helpers/tag_chosen_helper.rb +++ b/app/helpers/tag_chosen_helper.rb @@ -109,7 +109,7 @@ module TagChosenHelper end def render_cache_milestones(project) - cache_key = "project-#{project.id}/all_milestones/size-#{project.version}/#{project.versions.maximum('updated_on')}" + cache_key = "project-#{project.id}/all_milestones/size-#{project.versions.size}/#{project.versions.maximum('updated_on')}" Rails.cache.fetch(cache_key) do project.versions.select(:id, :name, :status).collect do |event| From fcf8033fbfbde3bc2bd08861b0d12807fb6bd608 Mon Sep 17 00:00:00 2001 From: jasder Date: Thu, 3 Jun 2021 17:04:22 +0800 Subject: [PATCH 202/643] =?UTF-8?q?FIX=20=E8=A7=A3=E5=86=B3=E9=95=9C?= =?UTF-8?q?=E5=83=8F=E9=A1=B9=E7=9B=AE=E6=89=8B=E5=8A=A8=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E9=95=9C=E5=83=8F=E4=B8=8D=E6=88=90=E5=8A=9F=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/jobs/sync_mirrored_repository_job.rb | 22 ++++- app/models/repository.rb | 3 + .../gitea/accelerator/base_service.rb | 96 ++++++++++++++++++ .../gitea/accelerator/migrate_service.rb | 97 +------------------ .../accelerator/sync_mirrored_service.rb | 31 ++++++ 5 files changed, 153 insertions(+), 96 deletions(-) create mode 100644 app/services/gitea/accelerator/base_service.rb create mode 100644 app/services/gitea/accelerator/sync_mirrored_service.rb diff --git a/app/jobs/sync_mirrored_repository_job.rb b/app/jobs/sync_mirrored_repository_job.rb index f0617146a..a1408153f 100644 --- a/app/jobs/sync_mirrored_repository_job.rb +++ b/app/jobs/sync_mirrored_repository_job.rb @@ -5,7 +5,27 @@ class SyncMirroredRepositoryJob < ApplicationJob repo = Repository.find_by(id: repo_id) current_user = User.find_by(id: user_id) return if repo.blank? || current_user.blank? - result = Gitea::Repository::SyncMirroredService.new(repo.owner.login, repo.identifier, token: current_user.gitea_token).call + + # TODO + # 先同步镜像库 + if repo.config_accelerator? + puts "[gitea-accelerator]: ###### 镜像库开始同步 ######" + result = Gitea::Accelerator::SyncMirroredService.call(repo.identifier) + puts "[gitea-accelerator]: ###### 镜像库同步状态为 #{result[:status]}" + + # TODO 暂时解决从镜像库镜像动作时间先执行的问题 + # 避免了Gitea::Repository::SyncMirroredService先执行后,加速器Gitea::Accelerator::SyncMirroredService + # 再执行的导致Gitea::Repository::SyncMirroredService执行镜像不是最新代码的问题 + sleep 3.seconds + end + + sync_common!(repo, current_user) + end + + def sync_common!(repo, user) + result = Gitea::Repository::SyncMirroredService.call(repo.owner.login, + repo.identifier, token: user.gitea_token) repo&.mirror.set_status! if result[:status] === 200 end + end diff --git a/app/models/repository.rb b/app/models/repository.rb index 0daa4b916..a012b449a 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -82,5 +82,8 @@ class Repository < ApplicationRecord source_clone_url.blank? ? mirror_url : source_clone_url end + def config_accelerator? + !source_clone_url.blank? + end end diff --git a/app/services/gitea/accelerator/base_service.rb b/app/services/gitea/accelerator/base_service.rb new file mode 100644 index 000000000..e63d77aab --- /dev/null +++ b/app/services/gitea/accelerator/base_service.rb @@ -0,0 +1,96 @@ +class Gitea::Accelerator::BaseService < ApplicationService + + def post(url, params) + puts "[gitea] request params: #{params}" + puts "[gitea] access_username: #{access_username}" + puts "[gitea] access_password: #{access_password}" + conn.post do |req| + req.url full_url(url) + req.body = params.to_json + end + end + + private + def conn + @client ||= begin + Faraday.new(url: domain) do |req| + req.request :url_encoded + req.headers['Content-Type'] = 'application/json' + req.response :logger # 显示日志 + req.adapter Faraday.default_adapter + req.basic_auth(access_username, access_password) + end + end + @client + end + + def base_url + accelerator["base_url"] + end + + def domain + accelerator["domain"] + end + + def api_url + [domain, base_url].join('') + end + + def full_url(api_rest, action='post') + url = [api_url, api_rest].join('').freeze + url = action === 'get' ? url : URI.escape(url) + puts "[gitea] request url: #{url}" + url + end + + def access_username + accelerator["access_key_id"] + end + + def access_password + accelerator["access_key_secret"] + end + + def access_uid + accelerator["access_admin_uid"] + end + + def accelerator + Gitea.gitea_config[:accelerator] + end + + def render_status(response) + puts "[gitea] response status: #{response.status}" + puts "[gitea] response body: #{response.body}" + case response.status + when 201 + success + when 403 + error('APIForbiddenError') + when 422 + error('APIValidationError') + else + error("MigrateError") + end + end + + def error(message) + { + status: :error, + message: message, + data: nil + } + end + + def success(data=nil) + { + status: :success, + message: nil, + data: data + } + end + + def check_accelerator! + accelerator.blank? || access_username.blank? || access_password.blank? || domain.blank? + end +end \ No newline at end of file diff --git a/app/services/gitea/accelerator/migrate_service.rb b/app/services/gitea/accelerator/migrate_service.rb index 015a09b16..26541b48e 100644 --- a/app/services/gitea/accelerator/migrate_service.rb +++ b/app/services/gitea/accelerator/migrate_service.rb @@ -1,4 +1,4 @@ -class Gitea::Accelerator::MigrateService < ApplicationService +class Gitea::Accelerator::MigrateService < Gitea::Accelerator::BaseService attr_reader :params # params description: @@ -36,8 +36,8 @@ class Gitea::Accelerator::MigrateService < ApplicationService render_status(response) end - private + private def request_params { uid: access_uid, @@ -52,97 +52,4 @@ class Gitea::Accelerator::MigrateService < ApplicationService def url "/repos/migrate".freeze end - - def post(url, params) - puts "[gitea] request params: #{params}" - puts "[gitea] access_username: #{access_username}" - puts "[gitea] access_password: #{access_password}" - conn.post do |req| - req.url full_url(url) - req.body = params.to_json - end - end - - def conn - @client ||= begin - Faraday.new(url: domain) do |req| - req.request :url_encoded - req.headers['Content-Type'] = 'application/json' - req.response :logger # 显示日志 - req.adapter Faraday.default_adapter - req.basic_auth(access_username, access_password) - end - end - @client - end - - def base_url - accelerator["base_url"] - end - - def domain - accelerator["domain"] - end - - def api_url - [domain, base_url].join('') - end - - def full_url(api_rest, action='post') - url = [api_url, api_rest].join('').freeze - url = action === 'get' ? url : URI.escape(url) - puts "[gitea] request url: #{url}" - url - end - - def access_username - accelerator["access_key_id"] - end - - def access_password - accelerator["access_key_secret"] - end - - def access_uid - accelerator["access_admin_uid"] - end - - def accelerator - Gitea.gitea_config[:accelerator] - end - - def render_status(response) - puts "[gitea] response status: #{response.status}" - puts "[gitea] response body: #{response.body}" - case response.status - when 201 - success - when 403 - error('APIForbiddenError') - when 422 - error('APIValidationError') - else - error("MigrateError") - end - end - - def error(message) - { - status: :error, - message: message, - data: nil - } - end - - def success(data=nil) - { - status: :success, - message: nil, - data: data - } - end - - def check_accelerator! - accelerator.blank? || access_username.blank? || access_password.blank? || domain.blank? - end end \ No newline at end of file diff --git a/app/services/gitea/accelerator/sync_mirrored_service.rb b/app/services/gitea/accelerator/sync_mirrored_service.rb new file mode 100644 index 000000000..0e0a7ca94 --- /dev/null +++ b/app/services/gitea/accelerator/sync_mirrored_service.rb @@ -0,0 +1,31 @@ +# Sync a mirrored repository +class Gitea::Accelerator::SyncMirroredService < Gitea::Accelerator::BaseService + attr_reader :repo, :token + + # repo * + # name of the repo to sync + # example: + # Gitea::Accelerator::SyncMirroredService.call(repo.identifier) + def initialize(repo, token=nil) + @repo = repo + @token = token + end + + def call + return error('[gitea:] accelerator config missing') if check_accelerator! + + response = post(url, request_params) + + {status: response.status} + end + + private + + def request_params + Hash.new.merge(token: token).compact + end + + def url + "/repos/#{access_username}/#{repo}/mirror-sync".freeze + end +end From ed8d646d479bdcd84784909a024949bb8e4f093f Mon Sep 17 00:00:00 2001 From: viletyy Date: Thu, 3 Jun 2021 17:12:27 +0800 Subject: [PATCH 203/643] add: user update password --- app/controllers/accounts_controller.rb | 19 +++++++++++++++++++ config/routes.rb | 1 + 2 files changed, 20 insertions(+) diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 09dfdbdb7..0745726b9 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -196,6 +196,25 @@ class AccountsController < ApplicationController # session[:user_id] = @user.id end + def change_password + @user = User.find_by(login: params[:login]) + return render_error("未找到相关用户!") if @user.blank? + return render_error("旧密码不正确") unless @user.check_password?(params[:old_password]) + + 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 + # 忘记密码 def reset_password begin diff --git a/config/routes.rb b/config/routes.rb index 1160a4072..9796f774e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -190,6 +190,7 @@ Rails.application.routes.draw do post :remote_update post :remote_login post :remote_password + post :change_password end end From 8133fcd37a890466adde458fde426bb151656e1b Mon Sep 17 00:00:00 2001 From: jasder Date: Fri, 4 Jun 2021 11:33:21 +0800 Subject: [PATCH 204/643] =?UTF-8?q?FIX=20=E6=9B=B4=E6=94=B9=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E9=A1=B9=E7=9B=AE=E6=8E=92=E5=BA=8F=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 7612003f2..3e40619c5 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -177,7 +177,7 @@ class ProjectsController < ApplicationController end def recommend - @projects = Project.recommend.includes(:repository, :project_category, :owner).order(id: :desc) + @projects = Project.recommend.includes(:repository, :project_category, :owner).order(visits: :desc) end def about From 2ea9fcd4d7a86b0f1fa0f615a47973baee774aaa Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 4 Jun 2021 18:35:35 +0800 Subject: [PATCH 205/643] add: projects filter choosed --- app/queries/projects/list_my_query.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/queries/projects/list_my_query.rb b/app/queries/projects/list_my_query.rb index 5c508c961..c9f4544df 100644 --- a/app/queries/projects/list_my_query.rb +++ b/app/queries/projects/list_my_query.rb @@ -57,6 +57,11 @@ class Projects::ListMyQuery < ApplicationQuery sort = params[:sort_by] || "updated_on" sort_direction = params[:sort_direction] || "desc" - scope.order("projects.#{sort} #{sort_direction}") + + if params[:choosed].present? && params[:choosed].is_a?(Array) + scope.order("FIELD(id, #{params[:choosed].reverse.join(",")}) desc") + else + scope.order("projects.#{sort} #{sort_direction}") + end end end From c211c38d8721bbe04ebcc9ba7d77fbce4b3f9262 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 4 Jun 2021 18:41:19 +0800 Subject: [PATCH 206/643] fix --- app/models/project.rb | 82 ++---------------------------------- app/models/user_extension.rb | 47 ++++++++++----------- 2 files changed, 25 insertions(+), 104 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 46adf9d7a..f41e980d7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,11 +1,10 @@ -<<<<<<< HEAD # == Schema Information # # Table name: projects # # id :integer not null, primary key # name :string(255) default(""), not null -# description :text(4294967295) +# description :text(65535) # homepage :string(255) default("") # is_public :boolean default("1"), not null # parent_id :integer @@ -38,24 +37,12 @@ # rep_identifier :string(255) # project_category_id :integer # project_language_id :integer +# license_id :integer +# ignore_id :integer # praises_count :integer default("0") # watchers_count :integer default("0") # issues_count :integer default("0") # pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# license_id :integer -# ignore_id :integer -# default_branch :string(255) default("master") -# website :string(255) -# lesson_url :string(255) # # Indexes # @@ -72,69 +59,6 @@ # index_projects_on_updated_on (updated_on) # -======= -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(65535) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# license_id :integer -# ignore_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# - ->>>>>>> ed8d646d479bdcd84784909a024949bb8e4f093f class Project < ApplicationRecord diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 6d6ed13b9..0749d1f79 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -22,15 +22,12 @@ # school_id :integer # description :string(255) default("") # department_id :integer -<<<<<<< HEAD # province :string(255) # city :string(255) # custom_department :string(255) # show_email :boolean default("0") # show_location :boolean default("0") # show_department :boolean default("0") -======= ->>>>>>> ed8d646d479bdcd84784909a024949bb8e4f093f # # Indexes # @@ -39,25 +36,25 @@ # index_user_extensions_on_user_id (user_id) # -class UserExtension < ApplicationRecord - # identity 0: 教师教授 1: 学生, 2: 专业人士, 3: 开发者 - enum identity: { teacher: 0, student: 1, professional: 2, developer: 3, enterprise: 4, unselect: -1 } - - belongs_to :user, touch: true - belongs_to :school, optional: true - # belongs_to :department, optional: true - - # before_save :set_laboratory_school - - def identity_text - I18n.t("user.identity.#{identity}") - end - - private - - def set_laboratory_school - # return unless new_record? - - # self.school_id = Laboratory.current.school_id if school_id.blank? && !Laboratory.current.main_site? - end -end +class UserExtension < ApplicationRecord + # identity 0: 教师教授 1: 学生, 2: 专业人士, 3: 开发者 + enum identity: { teacher: 0, student: 1, professional: 2, developer: 3, enterprise: 4, unselect: -1 } + + belongs_to :user, touch: true + belongs_to :school, optional: true + # belongs_to :department, optional: true + + # before_save :set_laboratory_school + + def identity_text + I18n.t("user.identity.#{identity}") + end + + private + + def set_laboratory_school + # return unless new_record? + + # self.school_id = Laboratory.current.school_id if school_id.blank? && !Laboratory.current.main_site? + end +end From e8f4b3f17c28dfc0471ec168c56ed5a7217afe3c Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Fri, 4 Jun 2021 18:43:12 +0800 Subject: [PATCH 207/643] fix --- app/controllers/users_controller.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e2efb7cf8..237ce9e6a 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -74,18 +74,10 @@ class UsersController < ApplicationController def update return render_not_found unless @user = User.find_by_id(params[:id]) || User.find_by(login: params[:id]) -<<<<<<< HEAD - Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? - @user.attributes = user_params.except(:image) - if @user.save - render_ok - else -======= return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id) Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? @user.attributes = user_params.except(:image) unless @user.save ->>>>>>> ed8d646d479bdcd84784909a024949bb8e4f093f render_error(@user.errors.full_messages.join(", ")) end end From d5a65112ca46edb72be908970af58cd95c205c59 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 7 Jun 2021 14:17:12 +0800 Subject: [PATCH 208/643] fix: statistics develop load slowly --- .../users/statistics_controller.rb | 145 +++++++++++++++--- 1 file changed, 121 insertions(+), 24 deletions(-) diff --git a/app/controllers/users/statistics_controller.rb b/app/controllers/users/statistics_controller.rb index d508176e2..255f0e948 100644 --- a/app/controllers/users/statistics_controller.rb +++ b/app/controllers/users/statistics_controller.rb @@ -162,29 +162,126 @@ class Users::StatisticsController < Users::BaseController end def preload_develop_data - # 用户被follow数量 - @follow_count = time_filter(Watcher.where(watchable: observed_user), 'created_at').count - @platform_follow_count = time_filter(Watcher.where(watchable_type: 'User'), 'created_at').count - # 用户pr数量 - @pullrequest_count = time_filter(PullRequest.where(user_id: observed_user.id), 'created_at').count - @platform_pullrequest_count = time_filter(PullRequest, 'created_at').count - # 用户issue数量 - @issues_count = time_filter(Issue.where(author_id: observed_user.id), 'created_on').count - @platform_issues_count = time_filter(Issue, 'created_on').count - # 用户总项目数 @fork_count + @project_watchers_count + @project_praises_count - @project_count = filter_member_projects_by_role("Owner").count - @platform_project_count = time_filter(Project, 'created_on').count - # 用户项目被fork数量 - @fork_count = filter_member_projects_by_role("Owner").sum("forked_count") - @platform_fork_count = time_filter(Project, 'created_on').sum("forked_count") - # 用户项目关注数 - @project_watchers_count = filter_member_projects_by_role("Owner").sum("watchers_count") - @platform_project_watchers_count = time_filter(Project, 'created_on').sum("watchers_count") - # 用户项目点赞数 - @project_praises_count = filter_member_projects_by_role("Owner").sum("praises_count") - @platform_project_praises_count = time_filter(Project, 'created_on').sum("praises_count") - # 用户不同语言项目数量 - @project_languages_count = filter_member_projects_by_role("Owner").joins(:project_language).group("project_languages.name").count - @platform_project_languages_count = time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count + if params[:start_time].present? && params[:end_time].present? + # 用户被follow数量 + @follow_count = Rails.cache.fetch("user-follow-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Watcher.where(watchable: observed_user).maximum('created_at').to_i}") do + time_filter(Watcher.where(watchable: observed_user), 'created_at').count + end + @platform_follow_count = Rails.cache.fetch("platform-follow-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Watcher.where(watchable_type: 'User').maximum('created_at').to_i}") do + time_filter(Watcher.where(watchable_type: 'User'), 'created_at').count + end + # 用户pr数量 + @pullrequest_count = Rails.cache.fetch("user-pullrequest-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{PullRequest.where(user_id: observed_user.id).maximum('created_at').to_i}") do + time_filter(PullRequest.where(user_id: observed_user.id), 'created_at').count + end + @platform_pullrequest_count = Rails.cache.fetch("platform-pullrequest-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{PullRequest.maximum('created_at').to_i}") do + time_filter(PullRequest, 'created_at').count + end + # 用户issue数量 + @issues_count = Rails.cache.fetch("user-issue-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Issue.where(author_id: observed_user.id).maximum('created_on').to_i}") do + time_filter(Issue.where(author_id: observed_user.id), 'created_on').count + end + @platform_issues_count = Rails.cache.fetch("platform-issue-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Issue.maximum('created_on').to_i}") do + time_filter(Issue, 'created_on').count + end + # 用户总项目数 + @project_count = Rails.cache.fetch("user-project-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Project.where(user_id:observed_user.id).maximum('created_on').to_i}") do + time_filter(Project.where(user_id:observed_user.id), 'created_on').count + end + @platform_project_count = Rails.cache.fetch("platform-project-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Project.maximum('created_on').to_i}") do + time_filter(Project, 'created_on').count + end + # 用户项目被fork数量 + @fork_count = Rails.cache.fetch("user-fork-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{ForkUser.joins(:project).where(projects: {user_id: observed_user.id}).maximum('created_at').to_i}") do + time_filter(Project.where(user_id:observed_user.id), 'created_on').sum("forked_count") + end + @platform_fork_count = Rails.cache.fetch("platform-fork-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{ForkUser.maximum('created_at').to_i}") do + time_filter(Project, 'created_on').sum("forked_count") + end + + # 用户项目关注数 + @project_watchers_count = Rails.cache.fetch("user-watchers-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{observed_user.id}-#{Watcher.where(watchable_type: 'Project', watchable_id: observed_user.projects).maximum('created_at').to_i}") do + time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("watchers_count") + end + @platform_project_watchers_count = Rails.cache.fetch("platform-watchers-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Watcher.where(watchable_type: 'Project').maximum('created_at').to_i}") do + time_filter(Project, 'created_on').sum("watchers_count") + end + + # 用户项目点赞数 + @project_praises_count = Rails.cache.fetch("user-praises-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: observed_user.projects).maximum('created_at').to_i}") do + time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("praises_count") + end + @platform_project_praises_count = Rails.cache.fetch("user-praises-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: observed_user.projects).maximum('created_at').to_i}") do + time_filter(Project, 'created_on').sum("praises_count") + end + + # 用户不同语言项目数量 + @project_languages_count = Rails.cache.fetch("user-languages-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Project.where(user_id:observed_user.id).maximum('created_on').to_i}") do + time_filter(Project.where(user_id: observed_user.id), 'created_on').joins(:project_language).group("project_languages.name").count + end + @platform_project_languages_count = Rails.cache.fetch("platform-languages-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Project.maximum('created_on').to_i}") do + time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count + end + else + # 用户被follow数量 + @follow_count = Rails.cache.fetch("user-follow-count-#{observed_user.id}-#{Watcher.where(watchable: observed_user).maximum('created_at').to_i}") do + time_filter(Watcher.where(watchable: observed_user), 'created_at').count + end + @platform_follow_count = Rails.cache.fetch("platform-follow-count-#{Watcher.where(watchable_type: 'User').maximum('created_at').to_i}") do + time_filter(Watcher.where(watchable_type: 'User'), 'created_at').count + end + # 用户pr数量 + @pullrequest_count = Rails.cache.fetch("user-pullrequest-count-#{observed_user.id}-#{PullRequest.where(user_id: observed_user.id).maximum('created_at').to_i}") do + time_filter(PullRequest.where(user_id: observed_user.id), 'created_at').count + end + @platform_pullrequest_count = Rails.cache.fetch("platform-pullrequest-count-#{PullRequest.maximum('created_at').to_i}") do + time_filter(PullRequest, 'created_at').count + end + # 用户issue数量 + @issues_count = Rails.cache.fetch("user-issue-count-#{observed_user.id}-#{Issue.where(author_id: observed_user.id).maximum('created_on').to_i}") do + time_filter(Issue.where(author_id: observed_user.id), 'created_on').count + end + @platform_issues_count = Rails.cache.fetch("platform-issue-count-#{Issue.maximum('created_on').to_i}") do + time_filter(Issue, 'created_on').count + end + # 用户总项目数 + @project_count = Rails.cache.fetch("user-project-count-#{observed_user.id}-#{Project.where(user_id:observed_user.id).maximum('created_on').to_i}") do + time_filter(Project.where(user_id:observed_user.id), 'created_on').count + end + @platform_project_count = Rails.cache.fetch("platform-project-count-#{Project.maximum('created_on').to_i}") do + time_filter(Project, 'created_on').count + end + # 用户项目被fork数量 + @fork_count = Rails.cache.fetch("user-fork-count-#{observed_user.id}-#{ForkUser.joins(:project).where(projects: {user_id: observed_user.id}).maximum('created_at').to_i}") do + time_filter(Project.where(user_id:observed_user.id), 'created_on').sum("forked_count") + end + @platform_fork_count = Rails.cache.fetch("platform-fork-count-#{ForkUser.maximum('created_at').to_i}") do + time_filter(Project, 'created_on').sum("forked_count") + end + + # 用户项目关注数 + @project_watchers_count = Rails.cache.fetch("user-watchers-count-#{observed_user.id}-#{Watcher.where(watchable_type: 'Project', watchable_id: observed_user.projects).maximum('created_at').to_i}") do + time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("watchers_count") + end + @platform_project_watchers_count = Rails.cache.fetch("platform-watchers-count-#{Watcher.where(watchable_type: 'Project').maximum('created_at').to_i}") do + time_filter(Project, 'created_on').sum("watchers_count") + end + + # 用户项目点赞数 + @project_praises_count = Rails.cache.fetch("user-praises-count-#{observed_user.id}-#{PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: observed_user.projects).maximum('created_at').to_i}") do + time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("praises_count") + end + @platform_project_praises_count = Rails.cache.fetch("user-praises-count-#{observed_user.id}-#{PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: observed_user.projects).maximum('created_at').to_i}") do + time_filter(Project, 'created_on').sum("praises_count") + end + + # 用户不同语言项目数量 + @project_languages_count = Rails.cache.fetch("user-languages-count-#{observed_user.id}-#{Project.where(user_id:observed_user.id).maximum('created_on').to_i}") do + time_filter(Project.where(user_id: observed_user.id), 'created_on').joins(:project_language).group("project_languages.name").count + end + @platform_project_languages_count = Rails.cache.fetch("platform-languages-count-#{Project.maximum('created_on').to_i}") do + time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count + end + end end end \ No newline at end of file From a5b98bcad442a3c7fa6137c27ec4fad0df73134c Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Mon, 7 Jun 2021 14:34:51 +0800 Subject: [PATCH 209/643] fix: concat nickname --- .../admins/auth_schools_controller.rb | 2 +- .../admins/laboratories_controller.rb | 4 +- app/controllers/members_controller.rb | 2 +- .../organization_users_controller.rb | 2 +- app/controllers/users_controller.rb | 2 +- .../users_for_private_messages_controller.rb | 2 +- app/controllers/weapps/courses_controller.rb | 4 +- app/controllers/zips_controller.rb | 4 +- app/models/attachment.rb | 80 +++++++++---------- app/models/user.rb | 2 +- app/queries/admins/apply_item_bank_query.rb | 2 +- .../admins/apply_user_authentication_query.rb | 2 +- app/queries/admins/course_list_query.rb | 2 +- app/queries/admins/course_query.rb | 2 +- app/queries/admins/laboratory_shixun_query.rb | 2 +- .../admins/laboratory_subject_query.rb | 2 +- app/queries/admins/subject_query.rb | 2 +- app/queries/admins/user_query.rb | 4 +- app/queries/user_query.rb | 2 +- app/services/admins/import_user_service.rb | 2 +- 20 files changed, 63 insertions(+), 63 deletions(-) diff --git a/app/controllers/admins/auth_schools_controller.rb b/app/controllers/admins/auth_schools_controller.rb index e7c0253b6..825c04cdc 100644 --- a/app/controllers/admins/auth_schools_controller.rb +++ b/app/controllers/admins/auth_schools_controller.rb @@ -32,7 +32,7 @@ class Admins::AuthSchoolsController < Admins::BaseController def search_manager school = School.find_by(id: params[:school_id]) user_ids = school&.ec_school_users&.pluck(:user_id) - @users = User.where.not(id: user_ids).where("concat(lastname, firstname) like ?", "%#{params[:name].strip.to_s}%").limit(10) + @users = User.where.not(id: user_ids).where("CONCAT_WS(lastname, firstname, nickname) like ?", "%#{params[:name].strip.to_s}%").limit(10) end # 添加认证学校管理员 diff --git a/app/controllers/admins/laboratories_controller.rb b/app/controllers/admins/laboratories_controller.rb index f397b0f34..46463fed0 100644 --- a/app/controllers/admins/laboratories_controller.rb +++ b/app/controllers/admins/laboratories_controller.rb @@ -32,7 +32,7 @@ class Admins::LaboratoriesController < Admins::BaseController keyword = params[:keyword].to_s.strip if keyword.present? - like_sql = 'shixuns.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword '\ + like_sql = 'shixuns.name LIKE :keyword OR CONCAT_WS(users.lastname, users.firstname, users.nickname) LIKE :keyword '\ 'OR mirror_repositories.name LIKE :keyword' shixuns = shixuns.joins(:user, :mirror_repositories).where(like_sql, keyword: "%#{keyword}%") end @@ -48,7 +48,7 @@ class Admins::LaboratoriesController < Admins::BaseController keyword = params[:keyword].to_s.strip if keyword.present? - like_sql = 'subjects.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword' + like_sql = 'subjects.name LIKE :keyword OR CONCAT_WS(users.lastname, users.firstname, users.nickname) LIKE :keyword' subjects = subjects.joins(:user).where(like_sql, keyword: "%#{keyword}%") end diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index bea4a0d29..fea57fa72 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -18,7 +18,7 @@ class MembersController < ApplicationController 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(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.mail, users.nickname)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present? scope = scope.joins(:roles).where("roles.name LIKE ?", "%#{role}%") if role.present? @total_count = scope.size diff --git a/app/controllers/organizations/organization_users_controller.rb b/app/controllers/organizations/organization_users_controller.rb index 8a7755a1b..d2d6963a4 100644 --- a/app/controllers/organizations/organization_users_controller.rb +++ b/app/controllers/organizations/organization_users_controller.rb @@ -5,7 +5,7 @@ class Organizations::OrganizationUsersController < Organizations::BaseController def index @organization_users = @organization.organization_users.includes(:user) search = params[:search].to_s.downcase - @organization_users = @organization_users.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.mail)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present? + @organization_users = @organization_users.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.mail, users.nickname)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present? @organization_users = kaminari_paginate(@organization_users) end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 237ce9e6a..163b5849f 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -63,7 +63,7 @@ class UsersController < ApplicationController 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 = watchers.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.nickname)) LIKE ?", "%#{params[:search].split(" ").join('|')}%") if params[:search].present? @watchers_count = watchers.size @watchers = paginate(watchers) diff --git a/app/controllers/users_for_private_messages_controller.rb b/app/controllers/users_for_private_messages_controller.rb index 610bf5d52..3a53a1af8 100644 --- a/app/controllers/users_for_private_messages_controller.rb +++ b/app/controllers/users_for_private_messages_controller.rb @@ -11,7 +11,7 @@ class UsersForPrivateMessagesController < ApplicationController return end - users = users.where('LOWER(concat(lastname, firstname, nickname)) LIKE ?', "%#{keyword}%") + users = users.where('LOWER(CONCAT_WS(lastname, firstname, nickname)) LIKE ?', "%#{keyword}%") @users = users.limit(10).includes(:user_extension) end diff --git a/app/controllers/weapps/courses_controller.rb b/app/controllers/weapps/courses_controller.rb index ccd5d1bcf..72782f5cc 100644 --- a/app/controllers/weapps/courses_controller.rb +++ b/app/controllers/weapps/courses_controller.rb @@ -86,7 +86,7 @@ class Weapps::CoursesController < Weapps::BaseController end if search.present? - @teacher_list = @teacher_list.joins(:user).where("LOWER(CONCAT(users.lastname, users.firstname)) like ?", "%#{search}%") + @teacher_list = @teacher_list.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.nickname)) like ?", "%#{search}%") end @teacher_list_size = @teacher_list.size @@ -127,7 +127,7 @@ class Weapps::CoursesController < Weapps::BaseController @students = CourseMember.students(@course) if search.present? - @students = @students.joins(user: :user_extension).where("LOWER(CONCAT(users.lastname, users.firstname)) like ? or + @students = @students.joins(user: :user_extension).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.nickname)) like ? or user_extensions.student_id like ?", "%#{search}%", "%#{search}%") end diff --git a/app/controllers/zips_controller.rb b/app/controllers/zips_controller.rb index 3ed1eb8b3..0c226211f 100644 --- a/app/controllers/zips_controller.rb +++ b/app/controllers/zips_controller.rb @@ -86,7 +86,7 @@ class ZipsController < ApplicationController #搜索 if params[:search].present? - @ex_users = @ex_users.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") + @ex_users = @ex_users.joins(user: :user_extension).where("CONCAT_WS(lastname, firstname, nickname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") end default_ex_users_size = @ex_users&.size @@ -130,7 +130,7 @@ class ZipsController < ApplicationController end unless params[:search].blank? - @all_student_works = @all_student_works.joins(user: :user_extension).where("concat(lastname, firstname) like ? + @all_student_works = @all_student_works.joins(user: :user_extension).where("CONCAT_WS(lastname, firstname, nickname) like ? or student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%") end diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 461c835fe..3bfc9a8ce 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -1,42 +1,42 @@ -# == Schema Information -# -# Table name: attachments -# -# id :integer not null, primary key -# container_id :integer -# container_type :string(30) -# filename :string(255) default(""), not null -# disk_filename :string(255) default(""), not null -# filesize :integer default("0"), not null -# content_type :string(255) default("") -# digest :string(60) default(""), not null -# downloads :integer default("0"), not null -# author_id :integer default("0"), not null -# created_on :datetime -# description :text(65535) -# disk_directory :string(255) -# attachtype :integer default("1") -# is_public :integer default("1") -# copy_from :integer -# quotes :integer default("0") -# is_publish :integer default("1") -# publish_time :datetime -# resource_bank_id :integer -# unified_setting :boolean default("1") -# cloud_url :string(255) default("") -# course_second_category_id :integer default("0") -# delay_publish :boolean default("0") -# -# Indexes -# -# index_attachments_on_author_id (author_id) -# index_attachments_on_container_id_and_container_type (container_id,container_type) -# index_attachments_on_course_second_category_id (course_second_category_id) -# index_attachments_on_created_on (created_on) -# index_attachments_on_is_public (is_public) -# index_attachments_on_quotes (quotes) -# - +# == Schema Information +# +# Table name: attachments +# +# id :integer not null, primary key +# container_id :integer +# container_type :string(30) +# filename :string(255) default(""), not null +# disk_filename :string(255) default(""), not null +# filesize :integer default("0"), not null +# content_type :string(255) default("") +# digest :string(60) default(""), not null +# downloads :integer default("0"), not null +# author_id :integer default("0"), not null +# created_on :datetime +# description :text(65535) +# disk_directory :string(255) +# attachtype :integer default("1") +# is_public :integer default("1") +# copy_from :integer +# quotes :integer default("0") +# is_publish :integer default("1") +# publish_time :datetime +# resource_bank_id :integer +# unified_setting :boolean default("1") +# cloud_url :string(255) default("") +# course_second_category_id :integer default("0") +# delay_publish :boolean default("0") +# +# Indexes +# +# index_attachments_on_author_id (author_id) +# index_attachments_on_container_id_and_container_type (container_id,container_type) +# index_attachments_on_course_second_category_id (course_second_category_id) +# index_attachments_on_created_on (created_on) +# index_attachments_on_is_public (is_public) +# index_attachments_on_quotes (quotes) +# + class Attachment < ApplicationRecord include BaseModel include Publicable @@ -51,7 +51,7 @@ class Attachment < ApplicationRecord # 二级目录 # belongs_to :course_second_category, optional: true - scope :by_filename_or_user_name, -> (keywords) { joins(:author).where("filename like :search or LOWER(concat(users.lastname, users.firstname)) LIKE :search", + scope :by_filename_or_user_name, -> (keywords) { joins(:author).where("filename like :search or LOWER(CONCAT_WS(users.lastname, users.firstname, users.nickname)) LIKE :search", :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? } scope :by_keywords, -> (keywords) { where("filename LIKE ?", "%#{keywords.split(" ").join('|')}%") unless keywords.blank? } scope :ordered, -> (opts = {}) { order("#{opts[:sort_type]} #{opts[:sort] == 1 ? 'asc': 'desc'}") } diff --git a/app/models/user.rb b/app/models/user.rb index 99b1e7cd7..9d917f4c8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -170,7 +170,7 @@ class User < Owner # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } scope :like, lambda { |keywords| - sql = "CONCAT(lastname, firstname) LIKE :search OR login LIKE :search OR mail LIKE :search OR nickname LIKE :search" + sql = "CONCAT_WS(lastname, firstname, nickname) LIKE :search OR login LIKE :search OR mail LIKE :search OR nickname LIKE :search" where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? } diff --git a/app/queries/admins/apply_item_bank_query.rb b/app/queries/admins/apply_item_bank_query.rb index 37b6d25a6..922d136ef 100644 --- a/app/queries/admins/apply_item_bank_query.rb +++ b/app/queries/admins/apply_item_bank_query.rb @@ -26,7 +26,7 @@ class Admins::ApplyItemBankQuery < ApplicationQuery keyword = params[:keyword].to_s.strip if keyword.present? applies = applies.joins(user: { user_extension: :school }) - .where('CONCAT(lastname,firstname) LIKE :keyword OR schools.name LIKE :keyword', keyword: "%#{keyword}%") + .where('CONCAT_WS(lastname,firstname, nickname) LIKE :keyword OR schools.name LIKE :keyword', keyword: "%#{keyword}%") end custom_sort(applies, params[:sort_by], params[:sort_direction]) diff --git a/app/queries/admins/apply_user_authentication_query.rb b/app/queries/admins/apply_user_authentication_query.rb index a4d1c2a4a..60b781d1c 100644 --- a/app/queries/admins/apply_user_authentication_query.rb +++ b/app/queries/admins/apply_user_authentication_query.rb @@ -26,7 +26,7 @@ class Admins::ApplyUserAuthenticationQuery < ApplicationQuery keyword = params[:keyword].to_s.strip if keyword.present? applies = applies.joins(user: { user_extension: :school }) - .where('CONCAT(lastname,firstname) LIKE :keyword OR schools.name LIKE :keyword', keyword: "%#{keyword}%") + .where('CONCAT_WS(lastname,firstname,nickname) LIKE :keyword OR schools.name LIKE :keyword', keyword: "%#{keyword}%") end custom_sort(applies, params[:sort_by], params[:sort_direction]) diff --git a/app/queries/admins/course_list_query.rb b/app/queries/admins/course_list_query.rb index 24eedaf1b..b97a9cebe 100644 --- a/app/queries/admins/course_list_query.rb +++ b/app/queries/admins/course_list_query.rb @@ -19,7 +19,7 @@ class Admins::CourseListQuery < ApplicationQuery case search_type when "0" course_lists = course_lists.joins(:user) - .where('CONCAT(lastname, firstname) like :keyword', keyword: "%#{keyword}%") + .where('CONCAT_WS(lastname, firstname, nickname) like :keyword', keyword: "%#{keyword}%") when "1" course_lists = course_lists.where('name like :keyword', keyword: "%#{keyword}%") end diff --git a/app/queries/admins/course_query.rb b/app/queries/admins/course_query.rb index e883650d0..b1466e22f 100644 --- a/app/queries/admins/course_query.rb +++ b/app/queries/admins/course_query.rb @@ -35,7 +35,7 @@ class Admins::CourseQuery < ApplicationQuery # 关键字 keyword = params[:keyword].to_s.strip if keyword - sql = 'CONCAT(lastname, firstname) LIKE :keyword OR courses.name LIKE :keyword OR course_lists.name LIKE :keyword' + sql = 'CONCAT_WS(lastname, firstname, nickname) LIKE :keyword OR courses.name LIKE :keyword OR course_lists.name LIKE :keyword' courses = courses.joins(:teacher, :course_list).where(sql, keyword: "%#{keyword}%") end diff --git a/app/queries/admins/laboratory_shixun_query.rb b/app/queries/admins/laboratory_shixun_query.rb index d489aed21..9b9bf6a21 100644 --- a/app/queries/admins/laboratory_shixun_query.rb +++ b/app/queries/admins/laboratory_shixun_query.rb @@ -11,7 +11,7 @@ class Admins::LaboratoryShixunQuery < ApplicationQuery keyword = params[:keyword].to_s.strip if keyword.present? - like_sql = 'shixuns.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword' + like_sql = 'shixuns.name LIKE :keyword OR CONCAT_WS(users.lastname, users.firstname, users.nickname) LIKE :keyword' laboratory_shixuns = laboratory_shixuns.joins(shixun: :user).where(like_sql, keyword: "%#{keyword}%") end diff --git a/app/queries/admins/laboratory_subject_query.rb b/app/queries/admins/laboratory_subject_query.rb index 316ea9743..619aeb2c2 100644 --- a/app/queries/admins/laboratory_subject_query.rb +++ b/app/queries/admins/laboratory_subject_query.rb @@ -11,7 +11,7 @@ class Admins::LaboratorySubjectQuery < ApplicationQuery keyword = params[:keyword].to_s.strip if keyword.present? - like_sql = 'subjects.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword' + like_sql = 'subjects.name LIKE :keyword OR CONCAT_WS(users.lastname, users.firstname, users.nickname) LIKE :keyword' laboratory_subjects = laboratory_subjects.joins(subject: :user).where(like_sql, keyword: "%#{keyword}%") end diff --git a/app/queries/admins/subject_query.rb b/app/queries/admins/subject_query.rb index 0415deb9f..df2ac40ef 100644 --- a/app/queries/admins/subject_query.rb +++ b/app/queries/admins/subject_query.rb @@ -40,7 +40,7 @@ class Admins::SubjectQuery < ApplicationQuery # 关键字 keyword = params[:keyword].to_s.strip if keyword - sql = 'CONCAT(lastname, firstname) LIKE :keyword OR subjects.name LIKE :keyword' + sql = 'CONCAT_WS(lastname, firstname, nickname) LIKE :keyword OR subjects.name LIKE :keyword' subjects = subjects.joins(:user).where(sql, keyword: "%#{keyword}%") end diff --git a/app/queries/admins/user_query.rb b/app/queries/admins/user_query.rb index cdf158c67..670eef58d 100644 --- a/app/queries/admins/user_query.rb +++ b/app/queries/admins/user_query.rb @@ -30,14 +30,14 @@ class Admins::UserQuery < ApplicationQuery # 关键字检索 keyword = params[:keyword].to_s.strip.presence if keyword - sql = 'CONCAT(lastname, firstname) LIKE :keyword OR login LIKE :keyword OR mail LIKE :keyword OR phone LIKE :keyword' + sql = 'CONCAT_WS(lastname, firstname, nickname) LIKE :keyword OR login LIKE :keyword OR mail LIKE :keyword OR phone LIKE :keyword' users = users.where(sql, keyword: "%#{keyword}%") end # 姓名 name = params[:name].to_s.strip.presence if name.present? - users = users.where('CONCAT(lastname, firstname) LIKE :name', name: "%#{name}%") + users = users.where('CONCAT_WS(lastname, firstname, nickname) LIKE :name', name: "%#{name}%") end # 单位ID diff --git a/app/queries/user_query.rb b/app/queries/user_query.rb index 326665fe9..f2964c7dc 100644 --- a/app/queries/user_query.rb +++ b/app/queries/user_query.rb @@ -10,7 +10,7 @@ class UserQuery < ApplicationQuery # 真实姓名 if name = strip_param(:name) - users = users.where('LOWER(CONCAT(users.lastname, users.firstname)) LIKE ?', "%#{name.downcase}%") + users = users.where('LOWER(CONCAT_WS(users.lastname, users.firstname, users.nickname)) LIKE ?', "%#{name.downcase}%") end # 单位名称 diff --git a/app/services/admins/import_user_service.rb b/app/services/admins/import_user_service.rb index f3408051b..298bf1e16 100644 --- a/app/services/admins/import_user_service.rb +++ b/app/services/admins/import_user_service.rb @@ -84,7 +84,7 @@ class Admins::ImportUserService < ApplicationService if data.identity.to_i == 1 users = users.where(user_extensions: { student_id: data.student_id }) else - users = users.where(user_extensions: { technical_title: data.technical_title }).where('CONCAT(users.lastname,users.firstname) = ?', data.name) + users = users.where(user_extensions: { technical_title: data.technical_title }).where('CONCAT_WS(users.lastname,users.firstname,users.nickname) = ?', data.name) end users.first From 02fe8a8966d8cdc895875bd5586fcd0c84c96f40 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 8 Jun 2021 11:51:46 +0800 Subject: [PATCH 210/643] add: user and platform cache --- .../users/statistics_controller.rb | 150 +++++------------- app/jobs/reset_platform_cache_job.rb | 14 ++ app/jobs/reset_user_cache_job.rb | 14 ++ app/models/application_record.rb | 8 + app/models/fork_user.rb | 8 + app/models/issue.rb | 7 +- app/models/praise_tread.rb | 43 +++-- app/models/project.rb | 11 +- app/models/pull_request.rb | 8 + app/models/watcher.rb | 28 +++- .../cache/platform_follow_count_service.rb | 41 +++++ .../cache/platform_issue_count_service.rb | 41 +++++ .../cache/platform_project_count_service.rb | 41 +++++ .../platform_project_fork_count_service.rb | 41 +++++ ...latform_project_languages_count_service.rb | 57 +++++++ .../platform_project_praises_count_service.rb | 41 +++++ ...platform_project_watchers_count_service.rb | 41 +++++ .../platform_pullrequest_count_service.rb | 41 +++++ .../cache/user_follow_count_service.rb | 43 +++++ .../cache/user_issue_count_service.rb | 43 +++++ .../cache/user_project_count_service.rb | 43 +++++ .../cache/user_project_fork_count_service.rb | 43 +++++ .../user_project_languages_count_service.rb | 60 +++++++ .../user_project_praises_count_service.rb | 43 +++++ .../user_project_watchers_count_service.rb | 43 +++++ .../cache/user_pullrequest_count_service.rb | 43 +++++ .../users/statistics/develop.json.jbuilder | 4 +- config/initializers/redis_cache.rb | 3 + config/sidekiq.yml | 1 + 29 files changed, 866 insertions(+), 138 deletions(-) create mode 100644 app/jobs/reset_platform_cache_job.rb create mode 100644 app/jobs/reset_user_cache_job.rb create mode 100644 app/services/cache/platform_follow_count_service.rb create mode 100644 app/services/cache/platform_issue_count_service.rb create mode 100644 app/services/cache/platform_project_count_service.rb create mode 100644 app/services/cache/platform_project_fork_count_service.rb create mode 100644 app/services/cache/platform_project_languages_count_service.rb create mode 100644 app/services/cache/platform_project_praises_count_service.rb create mode 100644 app/services/cache/platform_project_watchers_count_service.rb create mode 100644 app/services/cache/platform_pullrequest_count_service.rb create mode 100644 app/services/cache/user_follow_count_service.rb create mode 100644 app/services/cache/user_issue_count_service.rb create mode 100644 app/services/cache/user_project_count_service.rb create mode 100644 app/services/cache/user_project_fork_count_service.rb create mode 100644 app/services/cache/user_project_languages_count_service.rb create mode 100644 app/services/cache/user_project_praises_count_service.rb create mode 100644 app/services/cache/user_project_watchers_count_service.rb create mode 100644 app/services/cache/user_pullrequest_count_service.rb create mode 100644 config/initializers/redis_cache.rb diff --git a/app/controllers/users/statistics_controller.rb b/app/controllers/users/statistics_controller.rb index 255f0e948..c6cc0d889 100644 --- a/app/controllers/users/statistics_controller.rb +++ b/app/controllers/users/statistics_controller.rb @@ -85,19 +85,19 @@ class Users::StatisticsController < Users::BaseController for key in @project_languages_count.keys do @languages_percent[key] = (@project_languages_count[key].to_f / @project_languages_count.values.sum).round(2) end - @platform_languages_percent = Hash.new - for key in @platform_project_languages_count.keys do - @platform_languages_percent[key] = (@platform_project_languages_count[key].to_f / @platform_project_languages_count.values.sum).round(2) - end + # @platform_languages_percent = Hash.new + # for key in @platform_project_languages_count.keys do + # @platform_languages_percent[key] = (@platform_project_languages_count[key].to_f / @platform_project_languages_count.values.sum).round(2) + # end # 各门语言分数 @each_language_score = Hash.new for key in @project_languages_count.keys do @each_language_score[key] = (60.0 + @project_languages_count[key] / (@project_languages_count[key] + 5.0) * 40.0).to_i end - @platform_each_language_score = Hash.new - for key in @platform_project_languages_count.keys do - @platform_each_language_score[key] = (60.0 + @platform_project_languages_count[key] / (@platform_project_languages_count[key] + 5.0) * 40.0).to_i - end + # @platform_each_language_score = Hash.new + # for key in @platform_project_languages_count.keys do + # @platform_each_language_score[key] = (60.0 + @platform_project_languages_count[key] / (@platform_project_languages_count[key] + 5.0) * 40.0).to_i + # end end end @@ -164,124 +164,54 @@ class Users::StatisticsController < Users::BaseController def preload_develop_data if params[:start_time].present? && params[:end_time].present? # 用户被follow数量 - @follow_count = Rails.cache.fetch("user-follow-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Watcher.where(watchable: observed_user).maximum('created_at').to_i}") do - time_filter(Watcher.where(watchable: observed_user), 'created_at').count - end - @platform_follow_count = Rails.cache.fetch("platform-follow-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Watcher.where(watchable_type: 'User').maximum('created_at').to_i}") do - time_filter(Watcher.where(watchable_type: 'User'), 'created_at').count - end + @follow_count = time_filter(Watcher.where(watchable: observed_user), 'created_at').count + @platform_follow_count = time_filter(Watcher.where(watchable_type: 'User'), 'created_at').count # 用户pr数量 - @pullrequest_count = Rails.cache.fetch("user-pullrequest-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{PullRequest.where(user_id: observed_user.id).maximum('created_at').to_i}") do - time_filter(PullRequest.where(user_id: observed_user.id), 'created_at').count - end - @platform_pullrequest_count = Rails.cache.fetch("platform-pullrequest-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{PullRequest.maximum('created_at').to_i}") do - time_filter(PullRequest, 'created_at').count - end + @pullrequest_count = time_filter(PullRequest.where(user_id: observed_user.id), 'created_at').count + @platform_pullrequest_count = time_filter(PullRequest, 'created_at').count # 用户issue数量 - @issues_count = Rails.cache.fetch("user-issue-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Issue.where(author_id: observed_user.id).maximum('created_on').to_i}") do - time_filter(Issue.where(author_id: observed_user.id), 'created_on').count - end - @platform_issues_count = Rails.cache.fetch("platform-issue-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Issue.maximum('created_on').to_i}") do - time_filter(Issue, 'created_on').count - end + @issues_count = time_filter(Issue.where(author_id: observed_user.id), 'created_on').count + @platform_issues_count = time_filter(Issue, 'created_on').count # 用户总项目数 - @project_count = Rails.cache.fetch("user-project-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Project.where(user_id:observed_user.id).maximum('created_on').to_i}") do - time_filter(Project.where(user_id:observed_user.id), 'created_on').count - end - @platform_project_count = Rails.cache.fetch("platform-project-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Project.maximum('created_on').to_i}") do - time_filter(Project, 'created_on').count - end + @project_count = time_filter(Project.where(user_id:observed_user.id), 'created_on').count + @platform_project_count = time_filter(Project, 'created_on').count # 用户项目被fork数量 - @fork_count = Rails.cache.fetch("user-fork-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{ForkUser.joins(:project).where(projects: {user_id: observed_user.id}).maximum('created_at').to_i}") do - time_filter(Project.where(user_id:observed_user.id), 'created_on').sum("forked_count") - end - @platform_fork_count = Rails.cache.fetch("platform-fork-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{ForkUser.maximum('created_at').to_i}") do - time_filter(Project, 'created_on').sum("forked_count") - end - + @fork_count = time_filter(Project.where(user_id:observed_user.id), 'created_on').sum("forked_count") + @platform_fork_count = time_filter(Project, 'created_on').sum("forked_count") # 用户项目关注数 - @project_watchers_count = Rails.cache.fetch("user-watchers-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{observed_user.id}-#{Watcher.where(watchable_type: 'Project', watchable_id: observed_user.projects).maximum('created_at').to_i}") do - time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("watchers_count") - end - @platform_project_watchers_count = Rails.cache.fetch("platform-watchers-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Watcher.where(watchable_type: 'Project').maximum('created_at').to_i}") do - time_filter(Project, 'created_on').sum("watchers_count") - end - + @project_watchers_count = time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("watchers_count") + @platform_project_watchers_count = time_filter(Project, 'created_on').sum("watchers_count") # 用户项目点赞数 - @project_praises_count = Rails.cache.fetch("user-praises-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: observed_user.projects).maximum('created_at').to_i}") do - time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("praises_count") - end - @platform_project_praises_count = Rails.cache.fetch("user-praises-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: observed_user.projects).maximum('created_at').to_i}") do - time_filter(Project, 'created_on').sum("praises_count") - end - + @project_praises_count = time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("praises_count") + @platform_project_praises_count = time_filter(Project, 'created_on').sum("praises_count") # 用户不同语言项目数量 - @project_languages_count = Rails.cache.fetch("user-languages-count-#{observed_user.id}-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Project.where(user_id:observed_user.id).maximum('created_on').to_i}") do - time_filter(Project.where(user_id: observed_user.id), 'created_on').joins(:project_language).group("project_languages.name").count - end - @platform_project_languages_count = Rails.cache.fetch("platform-languages-count-start:#{params[:start_time]}-end:#{params[:end_time]}-#{Project.maximum('created_on').to_i}") do - time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count - end + @project_languages_count = time_filter(Project.where(user_id: observed_user.id), 'created_on').joins(:project_language).group("project_languages.name").count + @platform_project_languages_count = time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count else # 用户被follow数量 - @follow_count = Rails.cache.fetch("user-follow-count-#{observed_user.id}-#{Watcher.where(watchable: observed_user).maximum('created_at').to_i}") do - time_filter(Watcher.where(watchable: observed_user), 'created_at').count - end - @platform_follow_count = Rails.cache.fetch("platform-follow-count-#{Watcher.where(watchable_type: 'User').maximum('created_at').to_i}") do - time_filter(Watcher.where(watchable_type: 'User'), 'created_at').count - end + @follow_count = Cache::UserFollowCountService.call(observed_user) + @platform_follow_count = Cache::PlatformFollowCountService.call # 用户pr数量 - @pullrequest_count = Rails.cache.fetch("user-pullrequest-count-#{observed_user.id}-#{PullRequest.where(user_id: observed_user.id).maximum('created_at').to_i}") do - time_filter(PullRequest.where(user_id: observed_user.id), 'created_at').count - end - @platform_pullrequest_count = Rails.cache.fetch("platform-pullrequest-count-#{PullRequest.maximum('created_at').to_i}") do - time_filter(PullRequest, 'created_at').count - end + @pullrequest_count = Cache::UserPullrequestCountService.call(observed_user) + @platform_pullrequest_count = Cache::PlatformPullrequestCountService.call # 用户issue数量 - @issues_count = Rails.cache.fetch("user-issue-count-#{observed_user.id}-#{Issue.where(author_id: observed_user.id).maximum('created_on').to_i}") do - time_filter(Issue.where(author_id: observed_user.id), 'created_on').count - end - @platform_issues_count = Rails.cache.fetch("platform-issue-count-#{Issue.maximum('created_on').to_i}") do - time_filter(Issue, 'created_on').count - end + @issues_count = Cache::UserIssueCountService.call(observed_user) + @platform_issues_count = Cache::PlatformIssueCountService.call # 用户总项目数 - @project_count = Rails.cache.fetch("user-project-count-#{observed_user.id}-#{Project.where(user_id:observed_user.id).maximum('created_on').to_i}") do - time_filter(Project.where(user_id:observed_user.id), 'created_on').count - end - @platform_project_count = Rails.cache.fetch("platform-project-count-#{Project.maximum('created_on').to_i}") do - time_filter(Project, 'created_on').count - end + @project_count = Cache::UserProjectCountService.call(observed_user) + @platform_project_count = Cache::PlatformProjectCountService.call # 用户项目被fork数量 - @fork_count = Rails.cache.fetch("user-fork-count-#{observed_user.id}-#{ForkUser.joins(:project).where(projects: {user_id: observed_user.id}).maximum('created_at').to_i}") do - time_filter(Project.where(user_id:observed_user.id), 'created_on').sum("forked_count") - end - @platform_fork_count = Rails.cache.fetch("platform-fork-count-#{ForkUser.maximum('created_at').to_i}") do - time_filter(Project, 'created_on').sum("forked_count") - end - + @fork_count = Cache::UserProjectForkCountService.call(observed_user) + @platform_fork_count = Cache::PlatformProjectForkCountService.call # 用户项目关注数 - @project_watchers_count = Rails.cache.fetch("user-watchers-count-#{observed_user.id}-#{Watcher.where(watchable_type: 'Project', watchable_id: observed_user.projects).maximum('created_at').to_i}") do - time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("watchers_count") - end - @platform_project_watchers_count = Rails.cache.fetch("platform-watchers-count-#{Watcher.where(watchable_type: 'Project').maximum('created_at').to_i}") do - time_filter(Project, 'created_on').sum("watchers_count") - end - + @project_watchers_count = Cache::UserProjectWatchersCountService.call(observed_user) + @platform_project_watchers_count = Cache::PlatformProjectWatchersCountService.call # 用户项目点赞数 - @project_praises_count = Rails.cache.fetch("user-praises-count-#{observed_user.id}-#{PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: observed_user.projects).maximum('created_at').to_i}") do - time_filter(Project.where(user_id: observed_user.id), 'created_on').sum("praises_count") - end - @platform_project_praises_count = Rails.cache.fetch("user-praises-count-#{observed_user.id}-#{PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: observed_user.projects).maximum('created_at').to_i}") do - time_filter(Project, 'created_on').sum("praises_count") - end - + @project_praises_count = Cache::UserProjectPraisesCountService.call(observed_user) + @platform_project_praises_count = Cache::PlatformProjectPraisesCountService.call # 用户不同语言项目数量 - @project_languages_count = Rails.cache.fetch("user-languages-count-#{observed_user.id}-#{Project.where(user_id:observed_user.id).maximum('created_on').to_i}") do - time_filter(Project.where(user_id: observed_user.id), 'created_on').joins(:project_language).group("project_languages.name").count - end - @platform_project_languages_count = Rails.cache.fetch("platform-languages-count-#{Project.maximum('created_on').to_i}") do - time_filter(Project, 'created_on').joins(:project_language).group("project_languages.name").count - end + @project_languages_count = Cache::UserProjectLanguagesCountService.call(observed_user) + @platform_project_languages_count = Cache::PlatformProjectLanguagesCountService.call end end end \ No newline at end of file diff --git a/app/jobs/reset_platform_cache_job.rb b/app/jobs/reset_platform_cache_job.rb new file mode 100644 index 000000000..bdc5b6aaa --- /dev/null +++ b/app/jobs/reset_platform_cache_job.rb @@ -0,0 +1,14 @@ +class ResetPlatformCacheJob < ApplicationJob + queue_as :cache + + def perform + Cache::PlatformFollowCountService.new.reset + Cache::PlatformIssueCountService.new.reset + Cache::PlatformProjectCountService.new.reset + Cache::PlatformProjectForkCountService.new.reset + Cache::PlatformProjectLanguagesCountService.new.reset + Cache::PlatformProjectPraisesCountService.new.reset + Cache::PlatformProjectWatchersCountService.new.reset + Cache::PlatformPullrequestCountService.new.reset + end +end \ No newline at end of file diff --git a/app/jobs/reset_user_cache_job.rb b/app/jobs/reset_user_cache_job.rb new file mode 100644 index 000000000..3562475ce --- /dev/null +++ b/app/jobs/reset_user_cache_job.rb @@ -0,0 +1,14 @@ +class ResetUserCacheJob < ApplicationJob + queue_as :cache + + def perform(user) + Cache::UserFollowCountService.new(user).reset + Cache::UserIssueCountService.new(user).reset + Cache::UserProjectCountService.new(user).reset + Cache::UserProjectForkCountService.new(user).reset + Cache::UserProjectLanguagesCountService.new(user).reset + Cache::UserProjectPraisesCountService.new(user).reset + Cache::UserProjectWatchersCountService.new(user).reset + Cache::UserPullrequestCountService.new(user).reset + end +end \ No newline at end of file diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 888c65423..3ab2b11e8 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -16,4 +16,12 @@ class ApplicationRecord < ActiveRecord::Base def allow_sync_to_trustie? Rails.env.production? && EduSetting.get('host_name') == 'https://www.educoder.net' end + + def reset_user_cache_async_job(user) + ResetUserCacheJob.perform_later(user) + end + + def reset_platform_cache_async_job + ResetPlatformCacheJob.perform_later + end end diff --git a/app/models/fork_user.rb b/app/models/fork_user.rb index d0915f152..0936f6bfa 100644 --- a/app/models/fork_user.rb +++ b/app/models/fork_user.rb @@ -20,4 +20,12 @@ class ForkUser < ApplicationRecord belongs_to :user belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id + after_save :reset_cache_data + after_destroy :reset_cache_data + + def reset_cache_data + self.reset_platform_cache_async_job + self.reset_user_cache_async_job(self.project.owner) + end + end diff --git a/app/models/issue.rb b/app/models/issue.rb index 58607ebdd..b43f5a3d2 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -76,8 +76,13 @@ class Issue < ApplicationRecord scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)} after_update :change_versions_count - after_destroy :update_closed_issues_count_in_project! + after_save :reset_cache_data + after_destroy :update_closed_issues_count_in_project!, :reset_cache_data + def reset_cache_data + self.reset_platform_cache_async_job + self.reset_user_cache_async_job(self.user) + end def get_assign_user User&.find_by_id(self.assigned_to_id) if self.assigned_to_id.present? diff --git a/app/models/praise_tread.rb b/app/models/praise_tread.rb index d13c17ddd..04008eaf6 100644 --- a/app/models/praise_tread.rb +++ b/app/models/praise_tread.rb @@ -1,26 +1,35 @@ -# == Schema Information -# -# Table name: praise_treads -# -# id :integer not null, primary key -# user_id :integer not null -# praise_tread_object_id :integer -# praise_tread_object_type :string(255) -# praise_or_tread :integer default("1") -# created_at :datetime not null -# updated_at :datetime not null -# -# Indexes -# -# praise_tread (praise_tread_object_id,praise_tread_object_type) -# - +# == Schema Information +# +# Table name: praise_treads +# +# id :integer not null, primary key +# user_id :integer not null +# praise_tread_object_id :integer +# praise_tread_object_type :string(255) +# praise_or_tread :integer default("1") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# praise_tread (praise_tread_object_id,praise_tread_object_type) +# + class PraiseTread < ApplicationRecord belongs_to :user belongs_to :praise_tread_object, polymorphic: true, counter_cache: :praises_count has_many :tidings, :as => :container, :dependent => :destroy after_create :send_tiding + after_save :reset_cache_data + after_destroy :reset_cache_data + + def reset_cache_data + self.reset_platform_cache_async_job + if self.praise_tread_object.is_a?(Project) + self.reset_user_cache_async_job(self.praise_tread_object&.owner) + end + end def send_tiding case self.praise_tread_object_type diff --git a/app/models/project.rb b/app/models/project.rb index f41e980d7..b61f05689 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -105,7 +105,8 @@ class Project < ApplicationRecord has_many :pinned_projects, dependent: :destroy has_many :has_pinned_users, through: :pinned_projects, source: :user - after_save :check_project_members + after_save :check_project_members, :reset_cache_data + after_destroy :reset_cache_data scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)} scope :recommend, -> { visible.project_statics_select.where(recommend: true) } @@ -113,6 +114,14 @@ class Project < ApplicationRecord delegate :content, to: :project_detail, allow_nil: true delegate :name, to: :license, prefix: true, allow_nil: true + def reset_cache_data + if changes[:user_id].present? + first_owner = Owner.find_by_id(changes[:user_id].first) + self.reset_user_cache_async_job(first_owner) + end + self.reset_platform_cache_async_job + self.reset_user_cache_async_job(self.owner) + end def self.search_project(search) ransack(name_or_identifier_cont: search) diff --git a/app/models/pull_request.rb b/app/models/pull_request.rb index c3eefb0db..97f4a9164 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -33,6 +33,14 @@ class PullRequest < ApplicationRecord has_many :project_trends, as: :trend, dependent: :destroy has_many :attachments, as: :container, dependent: :destroy + after_save :reset_cache_data + after_destroy :reset_cache_data + + def reset_cache_data + self.reset_platform_cache_async_job + self.reset_user_cache_async_job(self.user) + end + def fork_project Project.find_by(id: self.fork_project_id) end diff --git a/app/models/watcher.rb b/app/models/watcher.rb index 76a82702b..ccc8eefaa 100644 --- a/app/models/watcher.rb +++ b/app/models/watcher.rb @@ -15,10 +15,24 @@ # watchers_user_id_type (user_id,watchable_type) # -class Watcher < ApplicationRecord - belongs_to :user - - belongs_to :watchable, polymorphic: true, counter_cache: :watchers_count - - scope :watching_users, ->(watchable_id){ where("watchable_type = ? and user_id = ?",'User',watchable_id)} -end +class Watcher < ApplicationRecord + belongs_to :user + + belongs_to :watchable, polymorphic: true, counter_cache: :watchers_count + + scope :watching_users, ->(watchable_id){ where("watchable_type = ? and user_id = ?",'User',watchable_id)} + + after_save :reset_cache_data + after_destroy :reset_cache_data + + def reset_cache_data + if self.watchable.is_a?(User) + self.reset_user_cache_async_job(self.watchable) + end + if self.watchable.is_a?(Project) + self.reset_user_cache_async_job(self.watchable&.owner) + end + self.reset_platform_cache_async_job + end + +end diff --git a/app/services/cache/platform_follow_count_service.rb b/app/services/cache/platform_follow_count_service.rb new file mode 100644 index 000000000..5398da5a8 --- /dev/null +++ b/app/services/cache/platform_follow_count_service.rb @@ -0,0 +1,41 @@ +class Cache::PlatformFollowCountService < ApplicationService + attr_reader :increment_count + + def initialize(increment_count=0) + @increment_count = increment_count + end + + def call + set_platform_follow_count + + platform_follow_count + end + + def reset + reset_platform_follow_count + + platform_follow_count + end + + private + + def platform_follow_count_key + "platform-follow-count" + end + + def platform_follow_count + $redis_cache.get(platform_follow_count_key).to_i + end + + def set_platform_follow_count + if $redis_cache.exists(platform_follow_count_key) + $redis_cache.incrby(platform_follow_count_key, increment_count) + else + reset_platform_follow_count + end + end + + def reset_platform_follow_count + $redis_cache.set(platform_follow_count_key, Watcher.where(watchable_type: 'User').count) + end +end \ No newline at end of file diff --git a/app/services/cache/platform_issue_count_service.rb b/app/services/cache/platform_issue_count_service.rb new file mode 100644 index 000000000..95511f480 --- /dev/null +++ b/app/services/cache/platform_issue_count_service.rb @@ -0,0 +1,41 @@ +class Cache::PlatformIssueCountService < ApplicationService + attr_reader :increment_count + + def initialize(increment_count=0) + @increment_count = increment_count + end + + def call + set_platform_issue_count + + platform_issue_count + end + + def reset + reset_platform_issue_count + + platform_issue_count + end + + private + + def platform_issue_count_key + "platform-issue-count" + end + + def platform_issue_count + $redis_cache.get(platform_issue_count_key).to_i + end + + def set_platform_issue_count + if $redis_cache.exists(platform_issue_count_key) + $redis_cache.incrby(platform_issue_count_key, increment_count) + else + reset_platform_issue_count + end + end + + def reset_platform_issue_count + $redis_cache.set(platform_issue_count_key, Issue.count) + end +end \ No newline at end of file diff --git a/app/services/cache/platform_project_count_service.rb b/app/services/cache/platform_project_count_service.rb new file mode 100644 index 000000000..d807682f1 --- /dev/null +++ b/app/services/cache/platform_project_count_service.rb @@ -0,0 +1,41 @@ +class Cache::PlatformProjectCountService < ApplicationService + attr_reader :increment_count + + def initialize(increment_count=0) + @increment_count = increment_count + end + + def call + set_platform_project_count + + platform_project_count + end + + def reset + reset_platform_project_count + + platform_project_count + end + + private + + def platform_project_count_key + "platform-project-count" + end + + def platform_project_count + $redis_cache.get(platform_project_count_key).to_i + end + + def set_platform_project_count + if $redis_cache.exists(platform_project_count_key) + $redis_cache.incrby(platform_project_count_key, increment_count) + else + reset_platform_project_count + end + end + + def reset_platform_project_count + $redis_cache.set(platform_project_count_key, Project.count) + end +end \ No newline at end of file diff --git a/app/services/cache/platform_project_fork_count_service.rb b/app/services/cache/platform_project_fork_count_service.rb new file mode 100644 index 000000000..21d6c0636 --- /dev/null +++ b/app/services/cache/platform_project_fork_count_service.rb @@ -0,0 +1,41 @@ +class Cache::PlatformProjectForkCountService < ApplicationService + attr_reader :increment_count + + def initialize(increment_count=0) + @increment_count = increment_count + end + + def call + set_platform_project_fork_count + + platform_project_fork_count + end + + def reset + reset_platform_project_fork_count + + platform_project_fork_count + end + + private + + def platform_project_fork_count_key + "platform-project-fork-count" + end + + def platform_project_fork_count + $redis_cache.get(platform_project_fork_count_key).to_i + end + + def set_platform_project_fork_count + if $redis_cache.exists(platform_project_fork_count_key) + $redis_cache.incrby(platform_project_fork_count_key, increment_count) + else + reset_platform_project_fork_count + end + end + + def reset_platform_project_fork_count + $redis_cache.set(platform_project_fork_count_key, ForkUser.count) + end +end \ No newline at end of file diff --git a/app/services/cache/platform_project_languages_count_service.rb b/app/services/cache/platform_project_languages_count_service.rb new file mode 100644 index 000000000..2b4f0fae4 --- /dev/null +++ b/app/services/cache/platform_project_languages_count_service.rb @@ -0,0 +1,57 @@ +class Cache::PlatformProjectLanguagesCountService < ApplicationService + attr_reader :key, :increment_count + + def initialize(key=nil, increment_count=0) + @key = key + @increment_count = increment_count + end + + def call + set_platform_project_language_count + + platform_project_language_count + end + + def reset_by_key + reset_platform_project_language_count_by_key + + platform_project_language_count + end + + def reset + reset_platform_project_language_count + + platform_project_language_count + end + + private + + def platform_project_language_count_key + "platform-project-language-count" + end + + def platform_project_language_count + $redis_cache.hgetall(platform_project_language_count_key).transform_values(&:to_i) + end + + def set_platform_project_language_count + if $redis_cache.hlen(platform_project_language_count_key) == 0 + reset_platform_project_language_count + elsif $redis_cache.hget(platform_project_language_count_key, key).nil? + reset_platform_project_language_count_by_key + else + $redis_cache.hincrby(platform_project_language_count_key, key, increment_count) + end + end + + def reset_platform_project_language_count_by_key + return if key.nil? + $redis_cache.hset(platform_project_language_count_key, key, Project.joins(:project_language).where(project_languages: {name: key}).count) + end + + def reset_platform_project_language_count + Project.joins(:project_language).group("project_languages.name").count.each do |k, v| + $redis_cache.hset(platform_project_language_count_key, k, v) + end + end +end \ No newline at end of file diff --git a/app/services/cache/platform_project_praises_count_service.rb b/app/services/cache/platform_project_praises_count_service.rb new file mode 100644 index 000000000..6c78b8022 --- /dev/null +++ b/app/services/cache/platform_project_praises_count_service.rb @@ -0,0 +1,41 @@ +class Cache::PlatformProjectPraisesCountService < ApplicationService + attr_reader :increment_count + + def initialize(increment_count=0) + @increment_count = increment_count + end + + def call + set_platform_project_praises_count + + platform_project_praises_count + end + + def reset + reset_platform_project_praises_count + + platform_project_praises_count + end + + private + + def platform_project_praises_count_key + "platform-project-praises-count" + end + + def platform_project_praises_count + $redis_cache.get(platform_project_praises_count_key).to_i + end + + def set_platform_project_praises_count + if $redis_cache.exists(platform_project_praises_count_key) + $redis_cache.incrby(platform_project_praises_count_key, increment_count) + else + reset_platform_project_praises_count + end + end + + def reset_platform_project_praises_count + $redis_cache.set(platform_project_praises_count_key, PraiseTread.where(praise_tread_object_type: "Project").count) + end +end \ No newline at end of file diff --git a/app/services/cache/platform_project_watchers_count_service.rb b/app/services/cache/platform_project_watchers_count_service.rb new file mode 100644 index 000000000..70c834d2e --- /dev/null +++ b/app/services/cache/platform_project_watchers_count_service.rb @@ -0,0 +1,41 @@ +class Cache::PlatformProjectWatchersCountService < ApplicationService + attr_reader :increment_count + + def initialize(increment_count=0) + @increment_count = increment_count + end + + def call + set_platform_project_watchers_count + + platform_project_watchers_count + end + + def reset + reset_platform_project_watchers_count + + platform_project_watchers_count + end + + private + + def platform_project_watchers_count_key + "platform-project-watchers-count" + end + + def platform_project_watchers_count + $redis_cache.get(platform_project_watchers_count_key).to_i + end + + def set_platform_project_watchers_count + if $redis_cache.exists(platform_project_watchers_count_key) + $redis_cache.incrby(platform_project_watchers_count_key, increment_count) + else + reset_platform_project_watchers_count + end + end + + def reset_platform_project_watchers_count + $redis_cache.set(platform_project_watchers_count_key, Watcher.where(watchable_type: 'Project').count) + end +end \ No newline at end of file diff --git a/app/services/cache/platform_pullrequest_count_service.rb b/app/services/cache/platform_pullrequest_count_service.rb new file mode 100644 index 000000000..c497c488a --- /dev/null +++ b/app/services/cache/platform_pullrequest_count_service.rb @@ -0,0 +1,41 @@ +class Cache::PlatformPullrequestCountService < ApplicationService + attr_reader :increment_count + + def initialize(increment_count=0) + @increment_count = increment_count + end + + def call + set_platform_pullrequest_count + + platform_pullrequest_count + end + + def reset + reset_platform_pullrequest_count + + platform_pullrequest_count + end + + private + + def platform_pullrequest_count_key + "platform-pullrequest-count" + end + + def platform_pullrequest_count + $redis_cache.get(platform_pullrequest_count_key).to_i + end + + def set_platform_pullrequest_count + if $redis_cache.exists(platform_pullrequest_count_key) + $redis_cache.incrby(platform_pullrequest_count_key, increment_count) + else + reset_platform_pullrequest_count + end + end + + def reset_platform_pullrequest_count + $redis_cache.set(platform_pullrequest_count_key, PullRequest.count) + end +end \ No newline at end of file diff --git a/app/services/cache/user_follow_count_service.rb b/app/services/cache/user_follow_count_service.rb new file mode 100644 index 000000000..c583c32b6 --- /dev/null +++ b/app/services/cache/user_follow_count_service.rb @@ -0,0 +1,43 @@ +class Cache::UserFollowCountService < ApplicationService + attr_reader :user, :increment_count + + def initialize(user, increment_count=0) + @user = user + @increment_count = increment_count + end + + def call + set_user_follow_count + + user_follow_count + end + + def reset + reset_user_follow_count + + user_follow_count + end + + private + + def user_follow_count_key + "user-follow-count-#{user.id}" + end + + def user_follow_count + $redis_cache.get(user_follow_count_key).to_i + end + + def set_user_follow_count + if $redis_cache.exists(user_follow_count_key) + $redis_cache.incrby(user_follow_count_key, increment_count) + else + reset_user_follow_count + end + end + + def reset_user_follow_count + return if user.nil? + $redis_cache.set(user_follow_count_key, Watcher.where(watchable: user).count) + end +end \ No newline at end of file diff --git a/app/services/cache/user_issue_count_service.rb b/app/services/cache/user_issue_count_service.rb new file mode 100644 index 000000000..9e5f2d491 --- /dev/null +++ b/app/services/cache/user_issue_count_service.rb @@ -0,0 +1,43 @@ +class Cache::UserIssueCountService < ApplicationService + attr_reader :user, :increment_count + + def initialize(user, increment_count=0) + @user = user + @increment_count = increment_count + end + + def call + set_user_issue_count + + user_issue_count + end + + def reset + reset_user_issue_count + + user_issue_count + end + + private + + def user_issue_count_key + "user-issue-count-#{user.id}" + end + + def user_issue_count + $redis_cache.get(user_issue_count_key).to_i + end + + def set_user_issue_count + if $redis_cache.exists(user_issue_count_key) + $redis_cache.incrby(user_issue_count_key, increment_count) + else + reset_user_issue_count + end + end + + def reset_user_issue_count + return if user.nil? + $redis_cache.set(user_issue_count_key, Issue.where(author_id: user.id).count) + end +end \ No newline at end of file diff --git a/app/services/cache/user_project_count_service.rb b/app/services/cache/user_project_count_service.rb new file mode 100644 index 000000000..677184161 --- /dev/null +++ b/app/services/cache/user_project_count_service.rb @@ -0,0 +1,43 @@ +class Cache::UserProjectCountService < ApplicationService + attr_reader :user, :increment_count + + def initialize(user, increment_count=0) + @user = user + @increment_count = increment_count + end + + def call + set_user_project_count + + user_project_count + end + + def reset + reset_user_project_count + + user_project_count + end + + private + + def user_project_count_key + "user-project-count-#{user.id}" + end + + def user_project_count + $redis_cache.get(user_project_count_key).to_i + end + + def set_user_project_count + if $redis_cache.exists(user_project_count_key) + $redis_cache.incrby(user_project_count_key, increment_count) + else + reset_user_project_count + end + end + + def reset_user_project_count + return if user.nil? + $redis_cache.set(user_project_count_key, user.projects.count) + end +end \ No newline at end of file diff --git a/app/services/cache/user_project_fork_count_service.rb b/app/services/cache/user_project_fork_count_service.rb new file mode 100644 index 000000000..134e4ed65 --- /dev/null +++ b/app/services/cache/user_project_fork_count_service.rb @@ -0,0 +1,43 @@ +class Cache::UserProjectForkCountService < ApplicationService + attr_reader :user, :increment_count + + def initialize(user, increment_count=0) + @user = user + @increment_count = increment_count + end + + def call + set_user_project_fork_count + + user_project_fork_count + end + + def reset + reset_user_project_fork_count + + user_project_fork_count + end + + private + + def user_project_fork_count_key + "user-project-fork-count-#{user.id}" + end + + def user_project_fork_count + $redis_cache.get(user_project_fork_count_key).to_i + end + + def set_user_project_fork_count + if $redis_cache.exists(user_project_fork_count_key) + $redis_cache.incrby(user_project_fork_count_key, increment_count) + else + reset_user_project_fork_count + end + end + + def reset_user_project_fork_count + return if user.nil? + $redis_cache.set(user_project_fork_count_key, ForkUser.joins(:project).where(projects: {user_id: user.id}).count) + end +end \ No newline at end of file diff --git a/app/services/cache/user_project_languages_count_service.rb b/app/services/cache/user_project_languages_count_service.rb new file mode 100644 index 000000000..35b8a418e --- /dev/null +++ b/app/services/cache/user_project_languages_count_service.rb @@ -0,0 +1,60 @@ +class Cache::UserProjectLanguagesCountService < ApplicationService + attr_reader :user, :key, :increment_count + + def initialize(user, key=nil, increment_count=0) + @user = user + @key = key + @increment_count = increment_count + end + + def call + set_user_project_language_count + + user_project_language_count + end + + def reset_by_key + reset_user_project_language_count_by_key + + user_project_language_count + end + + def reset + reset_user_project_language_count + + user_project_language_count + end + + private + + def user_project_language_count_key + "user-project-language-count-#{user.id}" + end + + def user_project_language_count + $redis_cache.hgetall(user_project_language_count_key).transform_values(&:to_i) + end + + def set_user_project_language_count + if $redis_cache.hlen(user_project_language_count_key) == 0 + reset_user_project_language_count + elsif $redis_cache.hget(user_project_language_count_key, key).nil? + reset_user_project_language_count_by_key + else + $redis_cache.hincrby(user_project_language_count_key, key, increment_count) + end + end + + def reset_user_project_language_count_by_key + return if user.nil? + return if key.nil? + $redis_cache.hset(user_project_language_count_key, key, user.projects.joins(:project_language).where(project_languages: {name: key}).count) + end + + def reset_user_project_language_count + return if user.nil? + user.projects.joins(:project_language).group("project_languages.name").count.each do |k, v| + $redis_cache.hset(user_project_language_count_key, k, v) + end + end +end \ No newline at end of file diff --git a/app/services/cache/user_project_praises_count_service.rb b/app/services/cache/user_project_praises_count_service.rb new file mode 100644 index 000000000..0c7d49e3c --- /dev/null +++ b/app/services/cache/user_project_praises_count_service.rb @@ -0,0 +1,43 @@ +class Cache::UserProjectPraisesCountService < ApplicationService + attr_reader :user, :increment_count + + def initialize(user, increment_count=0) + @user = user + @increment_count = increment_count + end + + def call + set_user_project_praises_count + + user_project_praises_count + end + + def reset + reset_user_project_praises_count + + user_project_praises_count + end + + private + + def user_project_praises_count_key + "user-project-praises-count-#{user.id}" + end + + def user_project_praises_count + $redis_cache.get(user_project_praises_count_key).to_i + end + + def set_user_project_praises_count + if $redis_cache.exists(user_project_praises_count_key) + $redis_cache.incrby(user_project_praises_count_key, increment_count) + else + reset_user_project_praises_count + end + end + + def reset_user_project_praises_count + return if user.nil? + $redis_cache.set(user_project_praises_count_key, PraiseTread.where(praise_tread_object_type: 'Project', praise_tread_object_id: user.projects).count) + end +end \ No newline at end of file diff --git a/app/services/cache/user_project_watchers_count_service.rb b/app/services/cache/user_project_watchers_count_service.rb new file mode 100644 index 000000000..50733cad7 --- /dev/null +++ b/app/services/cache/user_project_watchers_count_service.rb @@ -0,0 +1,43 @@ +class Cache::UserProjectWatchersCountService < ApplicationService + attr_reader :user, :increment_count + + def initialize(user, increment_count=0) + @user = user + @increment_count = increment_count + end + + def call + set_user_project_watchers_count + + user_project_watchers_count + end + + def reset + reset_user_project_watchers_count + + user_project_watchers_count + end + + private + + def user_project_watchers_count_key + "user-project-watchers-count-#{user.id}" + end + + def user_project_watchers_count + $redis_cache.get(user_project_watchers_count_key).to_i + end + + def set_user_project_watchers_count + if $redis_cache.exists(user_project_watchers_count_key) + $redis_cache.incrby(user_project_watchers_count_key, increment_count) + else + reset_user_project_watchers_count + end + end + + def reset_user_project_watchers_count + return if user.nil? + $redis_cache.set(user_project_watchers_count_key, Watcher.where(watchable_type: 'Project', watchable_id: user.projects).count) + end +end \ No newline at end of file diff --git a/app/services/cache/user_pullrequest_count_service.rb b/app/services/cache/user_pullrequest_count_service.rb new file mode 100644 index 000000000..da478b2af --- /dev/null +++ b/app/services/cache/user_pullrequest_count_service.rb @@ -0,0 +1,43 @@ +class Cache::UserPullrequestCountService < ApplicationService + attr_reader :user, :increment_count + + def initialize(user, increment_count=0) + @user = user + @increment_count = increment_count + end + + def call + set_user_pullrequest_count + + user_pullrequest_count + end + + def reset + reset_user_pullrequest_count + + user_pullrequest_count + end + + private + + def user_pullrequest_count_key + "user-pullrequest-count-#{user.id}" + end + + def user_pullrequest_count + $redis_cache.get(user_pullrequest_count_key).to_i + end + + def set_user_pullrequest_count + if $redis_cache.exists(user_pullrequest_count_key) + $redis_cache.incrby(user_pullrequest_count_key, increment_count) + else + reset_user_pullrequest_count + end + end + + def reset_user_pullrequest_count + return if user.nil? + $redis_cache.set(user_pullrequest_count_key, PullRequest.where(user_id: user.id).count) + end +end \ No newline at end of file diff --git a/app/views/users/statistics/develop.json.jbuilder b/app/views/users/statistics/develop.json.jbuilder index 9d530fbbe..85f66f5c9 100644 --- a/app/views/users/statistics/develop.json.jbuilder +++ b/app/views/users/statistics/develop.json.jbuilder @@ -4,8 +4,8 @@ json.platform do json.activity @platform_activity json.experience @platform_experience json.language @platform_language - json.languages_percent @platform_languages_percent - json.each_language_score @platform_each_language_score + # json.languages_percent @platform_languages_percent + # json.each_language_score @platform_each_language_score end json.user do diff --git a/config/initializers/redis_cache.rb b/config/initializers/redis_cache.rb new file mode 100644 index 000000000..67f52ec7b --- /dev/null +++ b/config/initializers/redis_cache.rb @@ -0,0 +1,3 @@ +redis_config = Rails.application.config_for(:redis) +cache_url = redis_config["url"] || 'redis://localhost:6379' +$redis_cache = Redis.new(url: cache_url, db: 2) \ No newline at end of file diff --git a/config/sidekiq.yml b/config/sidekiq.yml index dda6a32eb..a50c1c1aa 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -7,3 +7,4 @@ - [searchkick, 10] - [notify, 100] - [mailers, 101] + - [cache, 10] From 39acaa7f217079071c084f07d9d8da4e74ef3344 Mon Sep 17 00:00:00 2001 From: jasder Date: Tue, 8 Jun 2021 14:34:03 +0800 Subject: [PATCH 211/643] =?UTF-8?q?FIX=20=E8=A7=A3=E5=86=B3=E5=A4=B4?= =?UTF-8?q?=E6=AD=8C=E7=89=88=E6=9C=AC=E5=BA=93=E6=97=A0=E6=B3=95=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/repositories/detail.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 39f2563a4..3cf3858d6 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -48,7 +48,7 @@ if @result[:repo] json.size replace_bytes_to_b(number_to_human_size(@result[:repo]['size'].to_i*1024)) json.ssh_url @result[:repo]['ssh_url'] json.clone_url @result[:repo]['clone_url'] - json.default_branch @result[:repo]['default_branch'] + json.default_branch @project.educoder? ? "master" : @result[:repo]['default_branch'] json.empty @result[:repo]['empty'] json.full_name @result[:repo]['full_name'] json.private @result[:repo]['private'] From 1fca089949062dcf274e44c616e1332481a07be1 Mon Sep 17 00:00:00 2001 From: jasder Date: Wed, 9 Jun 2021 09:43:34 +0800 Subject: [PATCH 212/643] FIX change license --- LICENSE | 137 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 120 insertions(+), 17 deletions(-) diff --git a/LICENSE b/LICENSE index 8aa26455d..2b9b385e6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,124 @@ -MIT License +木兰宽松许可证, 第2版 -Copyright (c) [year] [fullname] +2020年1月 http://license.coscl.org.cn/MulanPSL2 -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +0. 定义 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +“软件” 是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + +“贡献” 是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + +“贡献者” 是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + +“法人实体” 是指提交贡献的机构及其“关联实体”。 + +“关联实体” 是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + +1. 授予版权许可 + +每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + +2. 授予专利许可 + +每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + +3. 无商标许可 + +“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + +4. 分发限制 + +您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + +5. 免责声明与责任限制 + +“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + +6. 语言 + +“本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + +条款结束 + +如何将木兰宽松许可证,第2版,应用到您的软件 + +如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + +1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + +2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + +3, 请将如下声明文本放入每个源文件的头部注释中。 + +Copyright (c) [Year] [name of copyright holder] +[Software Name] is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. +Mulan Permissive Software License,Version 2 +Mulan Permissive Software License,Version 2 (Mulan PSL v2) + +January 2020 http://license.coscl.org.cn/MulanPSL2 + +Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + +0. Definition + +Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + +Contribution means the copyrightable work licensed by a particular Contributor under this License. + +Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + +Legal Entity means the entity making a Contribution and all its Affiliates. + +Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + +1. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + +2. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + +3. No Trademark License + +No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in section 4. + +4. Distribution Restriction + +You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + +5. Disclaimer of Warranty and Limitation of Liability + +THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +6. Language + +THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + +END OF THE TERMS AND CONDITIONS + +How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + +To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + +Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; +Create a file named "LICENSE" which contains the whole context of this License in the first directory of your software package; +Attach the statement to the appropriate annotated syntax at the beginning of each source file. +Copyright (c) [Year] [name of copyright holder] +[Software Name] is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. \ No newline at end of file From d4b8b3e24faa7322694a2dfce4552647d48ed905 Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Tue, 8 Jun 2021 14:56:43 +0800 Subject: [PATCH 213/643] add: invite code --- app/models/applied_project.rb | 5 +++-- app/models/concerns/dcodes.rb | 13 +++++++++++++ app/models/project.rb | 9 ++++++++- app/views/repositories/detail.json.jbuilder | 1 + 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 app/models/concerns/dcodes.rb diff --git a/app/models/applied_project.rb b/app/models/applied_project.rb index 68095d0ea..8362cfa70 100644 --- a/app/models/applied_project.rb +++ b/app/models/applied_project.rb @@ -14,7 +14,8 @@ class AppliedProject < ApplicationRecord belongs_to :project has_many :applied_messages, as: :applied, dependent: :destroy - has_many :forge_activities, as: :forge_act, dependent: :destroy + # has_many :forge_activities, as: :forge_act, dependent: :destroy + + enum status: {canceled: -1, common: 0, accepted: 1, refused: 2} # -1 已取消 0 待操作 1 已接收 2 已拒绝 - scope :pending, -> { where(status: 0) } end diff --git a/app/models/concerns/dcodes.rb b/app/models/concerns/dcodes.rb new file mode 100644 index 000000000..f76b4b0f8 --- /dev/null +++ b/app/models/concerns/dcodes.rb @@ -0,0 +1,13 @@ +module Dcodes + DCODES = %W(1 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) + + extend ActiveSupport::Concern + + def generate_dcode(field, num, pre='') + code = DCODES.sample(num).join + while self.class.exists?("#{field}": pre+code) do + code = DCODES.sample(num).join + end + code + end +end \ No newline at end of file diff --git a/app/models/project.rb b/app/models/project.rb index b61f05689..f58f9f236 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -66,6 +66,7 @@ class Project < ApplicationRecord include Publicable include Watchable include ProjectOperable + include Dcodes # common:开源托管项目 # mirror:普通镜像项目,没有定时同步功能 @@ -105,7 +106,7 @@ class Project < ApplicationRecord has_many :pinned_projects, dependent: :destroy has_many :has_pinned_users, through: :pinned_projects, source: :user - after_save :check_project_members, :reset_cache_data + after_save :check_project_members, :reset_cache_data, :set_invite_code after_destroy :reset_cache_data scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)} @@ -123,6 +124,12 @@ class Project < ApplicationRecord self.reset_user_cache_async_job(self.owner) end + def set_invite_code + if self.invite_code.nil? + self.update(invite_code: self.generate_dcode('invite_code', 6)) + end + end + def self.search_project(search) ransack(name_or_identifier_cont: search) end diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder index 3cf3858d6..1da871486 100644 --- a/app/views/repositories/detail.json.jbuilder +++ b/app/views/repositories/detail.json.jbuilder @@ -7,6 +7,7 @@ else json.readme @result[:readme].merge(content: readme_render_decode64_content(@result[:readme]["content"], nil)) end json.identifier render_identifier(@project) +json.invite_code @project.invite_code json.name @project.name json.description @project.description json.project_id @project.id From 5489ea9fbc7e0adcfdcf3b01dc4cb65ac0fb89dc Mon Sep 17 00:00:00 2001 From: "vilet.yy" Date: Wed, 9 Jun 2021 16:53:09 +0800 Subject: [PATCH 214/643] add: applied join project --- .../applied_projects_controller.rb | 13 + .../users/applied_messages_controller.rb | 2 +- .../users/applied_projects_controller.rb | 39 + .../applied_transfer_projects_controller.rb | 2 +- app/docs/slate/source/includes/_projects.md | 86 ++ app/docs/slate/source/includes/_users.md | 290 ++++++- .../projects/add_member_interactor.rb | 17 +- .../send_join_project_applied_message_job.rb | 27 + app/models/applied_project.rb | 3 + app/models/attachment.rb | 77 +- app/models/ci/user.rb | 4 + app/models/concerns/project_operable.rb | 4 +- app/models/issue.rb | 5 +- app/models/license.rb | 1 + app/models/member.rb | 1 + app/models/organization.rb | 12 + app/models/praise_tread.rb | 33 +- app/models/project.rb | 15 +- app/models/pull_request.rb | 5 + app/models/user.rb | 11 + app/services/projects/accept_join_service.rb | 61 ++ app/services/projects/apply_join_service.rb | 36 +- app/services/projects/refuse_join_service.rb | 39 + .../applied_projects/_detail.json.jbuilder | 18 + .../applied_projects/create.json.jbuilder | 1 + .../applied_messages/_detail.json.jbuilder | 7 +- .../applied_projects/accept.json.jbuilder | 1 + .../applied_projects/index.json.jbuilder | 4 + .../applied_projects/refuse.json.jbuilder | 1 + config/routes.rb | 8 + ...72904_add_timestamp_to_applied_projects.rb | 5 + public/docs/api.html | 801 +++++++++++++++++- 32 files changed, 1497 insertions(+), 132 deletions(-) create mode 100644 app/controllers/applied_projects_controller.rb create mode 100644 app/controllers/users/applied_projects_controller.rb create mode 100644 app/jobs/send_join_project_applied_message_job.rb create mode 100644 app/services/projects/accept_join_service.rb create mode 100644 app/services/projects/refuse_join_service.rb create mode 100644 app/views/applied_projects/_detail.json.jbuilder create mode 100644 app/views/applied_projects/create.json.jbuilder create mode 100644 app/views/users/applied_projects/accept.json.jbuilder create mode 100644 app/views/users/applied_projects/index.json.jbuilder create mode 100644 app/views/users/applied_projects/refuse.json.jbuilder create mode 100644 db/migrate/20210609072904_add_timestamp_to_applied_projects.rb diff --git a/app/controllers/applied_projects_controller.rb b/app/controllers/applied_projects_controller.rb new file mode 100644 index 000000000..e2f55b27a --- /dev/null +++ b/app/controllers/applied_projects_controller.rb @@ -0,0 +1,13 @@ +class AppliedProjectsController < ApplicationController + before_action :require_login + def create + @applied_project = Projects::ApplyJoinService.call(current_user, applied_params) + rescue Projects::ApplyJoinService::Error => ex + render_error(ex.message) + end + + private + def applied_params + params.require(:applied_project).permit(:code, :role) + end +end \ No newline at end of file diff --git a/app/controllers/users/applied_messages_controller.rb b/app/controllers/users/applied_messages_controller.rb index e80cabf92..950caa2b3 100644 --- a/app/controllers/users/applied_messages_controller.rb +++ b/app/controllers/users/applied_messages_controller.rb @@ -9,7 +9,7 @@ class Users::AppliedMessagesController < Users::BaseController private def check_auth - return render_forbidden unless observed_logged_user? + return render_forbidden unless current_user.admin? || observed_logged_user? end def view_messages diff --git a/app/controllers/users/applied_projects_controller.rb b/app/controllers/users/applied_projects_controller.rb new file mode 100644 index 000000000..3663a6d34 --- /dev/null +++ b/app/controllers/users/applied_projects_controller.rb @@ -0,0 +1,39 @@ +class Users::AppliedProjectsController < Users::BaseController + before_action :check_auth + before_action :find_applied_project, except: [:index] + before_action :find_project, except: [:index] + + def index + @applied_projects = AppliedProject.where(project_id: observed_user.full_admin_projects) + @applied_projects = paginate @applied_projects.order("created_at desc") + end + + # 接受申请 + def accept + @applied_project = Projects::AcceptJoinService.call(current_user, @applied_project) + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + # 拒绝申请 + def refuse + @applied_project = Projects::RefuseJoinService.call(current_user, @applied_project) + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def check_auth + return render_forbidden unless current_user.admin? || observed_logged_user? + end + + def find_applied_project + @applied_project = AppliedProject.find_by_id params[:id] + end + + def find_project + @project = @applied_project.project + end +end \ No newline at end of file diff --git a/app/controllers/users/applied_transfer_projects_controller.rb b/app/controllers/users/applied_transfer_projects_controller.rb index b1777f526..a40833943 100644 --- a/app/controllers/users/applied_transfer_projects_controller.rb +++ b/app/controllers/users/applied_transfer_projects_controller.rb @@ -28,7 +28,7 @@ class Users::AppliedTransferProjectsController < Users::BaseController private def check_auth - return render_forbidden unless observed_logged_user? + return render_forbidden unless current_user.admin? || observed_logged_user? end def find_applied_transfer_project diff --git a/app/docs/slate/source/includes/_projects.md b/app/docs/slate/source/includes/_projects.md index 87a37c45b..2b6dd76d0 100644 --- a/app/docs/slate/source/includes/_projects.md +++ b/app/docs/slate/source/includes/_projects.md @@ -1,5 +1,91 @@ # Projects +## 申请加入项目 +申请加入项目 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/applied_projects.json +``` + +```javascript +await octokit.request('POST /api/appliedr_projects.json') +``` + +### HTTP 请求 +`POST /api/applied_projects.json` + +### 请求参数 +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|applied_project.code |是| |string |邀请码 | +|applied_project.role |否| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 | + +> 请求的JSON示例 + +```json +{ + "applied_project": { + "code": "1una34", + "role": "developer" + } +} +``` + +### 返回字段说明 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |申请id | +|status |string |申请状态,canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝| +|time_ago |string |项目申请创建的时间 | +|project.id |int |申请项目的id | +|project.identifier |string |申请项目的标识 | +|project.name |string |申请项目的名称 | +|project.description |string |申请项目的描述 | +|project.is_public |bool |申请项目是否公开 | +|project.owner.id |bool |申请项目拥有者id | +|project.owner.type |string |申请项目拥有者类型 | +|project.owner.name |string |申请项目拥有者昵称 | +|project.owner.login |string |申请项目拥有者标识 | +|project.owner.image_url |string |申请项目拥有者头像 | +|user.id |int |申请创建者的id | +|user.type |string |申请创建者的类型 | +|user.name |string |申请创建者的名称 | +|user.login |string |申请创建者的标识 | +|user.image_url |string |申请创建者头像 | +> 返回的JSON示例: + +```json +{ + "project": { + "id": 74, + "identifier": "hehuisssjssjjsjs", + "name": "hehuisssjssjjsjs", + "description": "wwww", + "is_public": false, + "owner": { + "id": 10, + "type": "User", + "name": "testforge1", + "login": "testforge1", + "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "何慧", + "login": "yystopf", + "image_url": "images/avatars/User/6?t=1622513134" + }, + "id": 7, + "status": "common", + "created_at": "2021-06-09 16:41", + "time_ago": "1分钟前" +} +``` + ## 获取项目列表 获取项目列表,也可以更加相关条件过滤搜素 diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 72bf724a5..d2960b3e5 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,7 +1,7 @@ # Users @@ -1002,11 +1002,11 @@ await octokit.request('GET /api/users/:login/applied_messages.json') |applied.user.name |string |通知主体的迁移创建者的名称 | |applied.user.login |string |通知主体的迁移创建者的标识 | |applied.user.image_url |string |通知主体的迁移创建者头像 | -|applied.owner.id |int |通知主体的迁移接受者的id | -|applied.owner.type |string |通知主体的迁移接受者的类型 | -|applied.owner.name |string |通知主体的迁移接受者的名称 | -|applied.owner.login |string |通知主体的迁移接受者的标识 | -|applied.owner.image_url |string |通知主体的迁移接受者头像 | +|applied_user.id |int |通知发起者的id | +|applied_user.type |string |通知发起者的类型 | +|applied_user.name |string |通知发起者的名称 | +|applied_user.login |string |通知发起者的标识 | +|applied_user.image_url |string |通知发起者头像 | |applied_type |string |通知类型 | |name |string | 通知内容 | |viewed |string|是否已读,waiting:未读,viewed:已读| @@ -1020,6 +1020,48 @@ await octokit.request('GET /api/users/:login/applied_messages.json') { "total_count": 5, "applied_messages": [ + { + "applied": { + "project": { + "id": 74, + "identifier": "hehuisssjssjjsjs", + "name": "hehuisssjssjjsjs", + "description": "wwww", + "is_public": false, + "owner": { + "id": 10, + "type": "User", + "name": "testforge1", + "login": "testforge1", + "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "何慧", + "login": "yystopf", + "image_url": "images/avatars/User/6?t=1622513134" + }, + "id": 6, + "status": "accepted", + "created_at": "2021-06-09 16:34", + "time_ago": "1分钟前" + }, + "applied_user": { + "id": 6, + "type": "User", + "name": "何慧", + "login": "yystopf", + "image_url": "images/avatars/User/6?t=1622513134" + }, + "applied_type": "AppliedProject", + "name": "已通过你加入【hehuisssjssjjsjs】仓库的申请。", + "viewed": "waiting", + "status": "successed", + "created_at": "2021-06-09 16:34", + "time_ago": "1分钟前" + }, { "applied": { "project": { @@ -1344,4 +1386,240 @@ await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refus "created_at": "2021-04-25 18:06", "time_ago": "16小时前" } +``` + + +## 待办事项-项目申请 +待办事项-项目申请 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/users/yystopf/applied_projects.json +``` + +```javascript +await octokit.request('GET /api/users/:login/applied_projects.json') +``` + +### HTTP 请求 +`GET /api/users/:login/applied_projects.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|login |string |用户标识 | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |申请id | +|status |string |申请状态,canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝| +|time_ago |string |申请创建的时间 | +|project.id |int |申请项目的id | +|project.identifier |string |申请项目的标识 | +|project.name |string |申请项目的名称 | +|project.description |string |申请项目的描述 | +|project.is_public |bool |申请项目是否公开 | +|project.owner.id |bool |申请项目拥有者id | +|project.owner.type |string |申请项目拥有者类型 | +|project.owner.name |string |申请项目拥有者昵称 | +|project.owner.login |string |申请项目拥有者标识 | +|project.owner.image_url |string |申请项目拥有者头像 | +|user.id |int |申请创建者的id | +|user.type |string |申请创建者的类型 | +|user.name |string |申请创建者的名称 | +|user.login |string |申请创建者的标识 | +|user.image_url |string |申请创建者头像 | + + +> 返回的JSON示例: + +```json +{ + "total_count": 4, + "applied_transfer_projects": [ + { + "project": { + "id": 74, + "identifier": "hehuisssjssjjsjs", + "name": "hehuisssjssjjsjs", + "description": "wwww", + "is_public": false, + "owner": { + "id": 10, + "type": "User", + "name": "testforge1", + "login": "testforge1", + "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "何慧", + "login": "yystopf", + "image_url": "images/avatars/User/6?t=1622513134" + }, + "id": 7, + "status": "common", + "created_at": "2021-06-09 16:41", + "time_ago": "7分钟前" + }, + ... + ] +} +``` + +## 用户接受迁移 +用户接受迁移 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/users/yystopf/applied_projects/2/accept.json +``` + +```javascript +await octokit.request('GET /api/users/:login/applied_projects/:id/accept.json') +``` + +### HTTP 请求 +`GET /api/users/:login/applied_projects/:id/accept.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|login |string |用户标识 | +|id |int |申请id | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |申请id | +|status |string |申请状态,canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝| +|time_ago |string |申请创建的时间 | +|project.id |int |申请项目的id | +|project.identifier |string |申请项目的标识 | +|project.name |string |申请项目的名称 | +|project.description |string |申请项目的描述 | +|project.is_public |bool |申请项目是否公开 | +|project.owner.id |bool |申请项目拥有者id | +|project.owner.type |string |申请项目拥有者类型 | +|project.owner.name |string |申请项目拥有者昵称 | +|project.owner.login |string |申请项目拥有者标识 | +|project.owner.image_url |string |申请项目拥有者头像 | +|user.id |int |申请创建者的id | +|user.type |string |申请创建者的类型 | +|user.name |string |申请创建者的名称 | +|user.login |string |申请创建者的标识 | +|user.image_url |string |申请创建者头像 | + + +> 返回的JSON示例: + +```json +{ + "project": { + "id": 74, + "identifier": "hehuisssjssjjsjs", + "name": "hehuisssjssjjsjs", + "description": "wwww", + "is_public": false, + "owner": { + "id": 10, + "type": "User", + "name": "testforge1", + "login": "testforge1", + "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "何慧", + "login": "yystopf", + "image_url": "images/avatars/User/6?t=1622513134" + }, + "id": 7, + "status": "accept", + "created_at": "2021-06-09 16:41", + "time_ago": "7分钟前" +} +``` + +## 用户拒绝迁移 +用户拒绝迁移 + +> 示例: + +```shell +curl -X POST http://localhost:3000/api/users/yystopf/applied_projects/2/refuse.json +``` + +```javascript +await octokit.request('GET /api/users/:login/applied_projects/:id/refuse.json') +``` + +### HTTP 请求 +`GET /api/users/:login/applied_projects/:id/refuse.json` + +### 请求字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|login |string |用户标识 | +|id |int |申请id | + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|id |int |申请id | +|status |string |申请状态,canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝| +|time_ago |string |申请创建的时间 | +|project.id |int |申请项目的id | +|project.identifier |string |申请项目的标识 | +|project.name |string |申请项目的名称 | +|project.description |string |申请项目的描述 | +|project.is_public |bool |申请项目是否公开 | +|project.owner.id |bool |申请项目拥有者id | +|project.owner.type |string |申请项目拥有者类型 | +|project.owner.name |string |申请项目拥有者昵称 | +|project.owner.login |string |申请项目拥有者标识 | +|project.owner.image_url |string |申请项目拥有者头像 | +|user.id |int |申请创建者的id | +|user.type |string |申请创建者的类型 | +|user.name |string |申请创建者的名称 | +|user.login |string |申请创建者的标识 | +|user.image_url |string |申请创建者头像 | + +> 返回的JSON示例: + +```json +{ + "project": { + "id": 74, + "identifier": "hehuisssjssjjsjs", + "name": "hehuisssjssjjsjs", + "description": "wwww", + "is_public": false, + "owner": { + "id": 10, + "type": "User", + "name": "testforge1", + "login": "testforge1", + "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" + } + }, + "user": { + "id": 6, + "type": "User", + "name": "何慧", + "login": "yystopf", + "image_url": "images/avatars/User/6?t=1622513134" + }, + "id": 7, + "status": "accept", + "created_at": "2021-06-09 16:41", + "time_ago": "7分钟前" +} ``` \ No newline at end of file diff --git a/app/interactors/projects/add_member_interactor.rb b/app/interactors/projects/add_member_interactor.rb index a3fe9e33e..0c3785c69 100644 --- a/app/interactors/projects/add_member_interactor.rb +++ b/app/interactors/projects/add_member_interactor.rb @@ -23,7 +23,7 @@ module Projects ActiveRecord::Base.transaction do gitea_result = Gitea::Repository::Members::AddService.new(owner, project.identifier, collaborator.login, permission).call if gitea_result.status == 204 - project.add_member!(collaborator.id) + project.add_member!(collaborator.id, role_name) end fail!(nil) end @@ -38,5 +38,20 @@ module Projects @error = error end + def role_name + case permission + when 'read' + 'Reporter' + when 'write' + 'Developer' + when 'admin' + 'Manager' + when 'owner' + 'Manager' + else + 'Reporter' + end + end + end end diff --git a/app/jobs/send_join_project_applied_message_job.rb b/app/jobs/send_join_project_applied_message_job.rb new file mode 100644 index 000000000..557878ede --- /dev/null +++ b/app/jobs/send_join_project_applied_message_job.rb @@ -0,0 +1,27 @@ +class SendJoinProjectAppliedMessageJob < ApplicationJob + queue_as :default + + def perform(applied_project, applied_user, message_status) + project = applied_project.project + return unless project.present? + return unless applied_user.present? + return unless applied_project.user.present? + AppliedMessage.find_or_create_by!(user_id: applied_project.user_id, + applied: applied_project, + status: message_status, + name: build_name(project.name, message_status), + applied_user_id: applied_user.id, + project_id: project.id) + end + + private + def build_name(repo_name, message_status, applied_name="") + case message_status + when 'successed' + return "已通过你加入【#{repo_name}】仓库的申请。" + when 'failure' + return "已拒绝你加入【#{repo_name}】仓库的申请。" + end + "" + end +end \ No newline at end of file diff --git a/app/models/applied_project.rb b/app/models/applied_project.rb index 8362cfa70..d1fea2f77 100644 --- a/app/models/applied_project.rb +++ b/app/models/applied_project.rb @@ -7,6 +7,8 @@ # user_id :integer not null # role :integer default("0") # status :integer default("0") +# created_at :datetime +# updated_at :datetime # class AppliedProject < ApplicationRecord @@ -16,6 +18,7 @@ class AppliedProject < ApplicationRecord has_many :applied_messages, as: :applied, dependent: :destroy # has_many :forge_activities, as: :forge_act, dependent: :destroy + enum role: {manager: 3, developer: 4, reporter: 5} enum status: {canceled: -1, common: 0, accepted: 1, refused: 2} # -1 已取消 0 待操作 1 已接收 2 已拒绝 end diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 3bfc9a8ce..721cf84ba 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -1,41 +1,42 @@ -# == Schema Information -# -# Table name: attachments -# -# id :integer not null, primary key -# container_id :integer -# container_type :string(30) -# filename :string(255) default(""), not null -# disk_filename :string(255) default(""), not null -# filesize :integer default("0"), not null -# content_type :string(255) default("") -# digest :string(60) default(""), not null -# downloads :integer default("0"), not null -# author_id :integer default("0"), not null -# created_on :datetime -# description :text(65535) -# disk_directory :string(255) -# attachtype :integer default("1") -# is_public :integer default("1") -# copy_from :integer -# quotes :integer default("0") -# is_publish :integer default("1") -# publish_time :datetime -# resource_bank_id :integer -# unified_setting :boolean default("1") -# cloud_url :string(255) default("") -# course_second_category_id :integer default("0") -# delay_publish :boolean default("0") -# -# Indexes -# -# index_attachments_on_author_id (author_id) -# index_attachments_on_container_id_and_container_type (container_id,container_type) -# index_attachments_on_course_second_category_id (course_second_category_id) -# index_attachments_on_created_on (created_on) -# index_attachments_on_is_public (is_public) -# index_attachments_on_quotes (quotes) -# +# == Schema Information +# +# Table name: attachments +# +# id :integer not null, primary key +# container_id :integer +# container_type :string(30) +# filename :string(255) default(""), not null +# disk_filename :string(255) default(""), not null +# filesize :integer default("0"), not null +# content_type :string(255) default("") +# digest :string(60) default(""), not null +# downloads :integer default("0"), not null +# author_id :integer default("0"), not null +# created_on :datetime +# description :text(65535) +# disk_directory :string(255) +# attachtype :integer default("1") +# is_public :integer default("1") +# copy_from :integer +# quotes :integer default("0") +# is_publish :integer default("1") +# publish_time :datetime +# resource_bank_id :integer +# unified_setting :boolean default("1") +# cloud_url :string(255) default("") +# course_second_category_id :integer default("0") +# delay_publish :boolean default("0") +# +# Indexes +# +# index_attachments_on_author_id (author_id) +# index_attachments_on_container_id_and_container_type (container_id,container_type) +# index_attachments_on_course_second_category_id (course_second_category_id) +# index_attachments_on_created_on (created_on) +# index_attachments_on_is_public (is_public) +# index_attachments_on_quotes (quotes) +# + class Attachment < ApplicationRecord include BaseModel diff --git a/app/models/ci/user.rb b/app/models/ci/user.rb index cd6246753..c263a1723 100644 --- a/app/models/ci/user.rb +++ b/app/models/ci/user.rb @@ -46,6 +46,10 @@ # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") +# sponsor_certification :integer default("0") +# sponsor_num :integer default("0") +# sponsored_num :integer default("0") +# award_time :datetime # # Indexes # diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index e016ca1dc..79d099a2e 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -65,7 +65,7 @@ module ProjectOperable if owner.is_a?(User) managers.exists?(user_id: user.id) elsif owner.is_a?(Organization) - managers.exists?(user_id: user.id) || owner.is_admin?(user.id) + managers.exists?(user_id: user.id) || owner.is_only_admin?(user.id) else false end @@ -76,7 +76,7 @@ module ProjectOperable if owner.is_a?(User) developers.exists?(user_id: user.id) elsif owner.is_a?(Organization) - developers.exists?(user_id: user.id) || owner.is_write?(user.id) + developers.exists?(user_id: user.id) || owner.is_only_write?(user.id) else false end diff --git a/app/models/issue.rb b/app/models/issue.rb index b43f5a3d2..ce4b0a5fa 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -6,7 +6,7 @@ # tracker_id :integer not null # project_id :integer not null # subject :string(255) default(""), not null -# description :text(65535) +# description :text(4294967295) # due_date :date # category_id :integer # status_id :integer not null @@ -14,7 +14,6 @@ # priority_id :integer not null # fixed_version_id :integer # author_id :integer not null -# lock_version :integer default("0"), not null # created_on :datetime # updated_on :datetime # start_date :date @@ -28,7 +27,7 @@ # closed_on :datetime # project_issues_index :integer # issue_type :string(255) -# token :string(255) +# token :integer default("0") # issue_tags_value :string(255) # is_lock :boolean default("0") # issue_classify :string(255) diff --git a/app/models/license.rb b/app/models/license.rb index 0a14fb85e..dcd5528fb 100644 --- a/app/models/license.rb +++ b/app/models/license.rb @@ -7,6 +7,7 @@ # content :text(65535) # created_at :datetime not null # updated_at :datetime not null +# is_secret :boolean default("0") # class License < ApplicationRecord diff --git a/app/models/member.rb b/app/models/member.rb index e72ae7c6b..408710a03 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -11,6 +11,7 @@ # course_group_id :integer default("0") # is_collect :integer default("1") # graduation_group_id :integer default("0") +# is_apply_signature :boolean default("0") # # Indexes # diff --git a/app/models/organization.rb b/app/models/organization.rb index 988ecd7fb..666e13ff2 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -46,6 +46,10 @@ # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") +# sponsor_certification :integer default("0") +# sponsor_num :integer default("0") +# sponsored_num :integer default("0") +# award_time :datetime # # Indexes # @@ -106,6 +110,14 @@ class Organization < Owner team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read write admin owner)}).present? end + def is_only_admin?(user_id) + team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(admin)}).present? + end + + def is_only_write?(user_id) + team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(write)}).present? + end + def is_only_read?(user_id) team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read)}).present? end diff --git a/app/models/praise_tread.rb b/app/models/praise_tread.rb index 04008eaf6..5a9c19164 100644 --- a/app/models/praise_tread.rb +++ b/app/models/praise_tread.rb @@ -1,19 +1,20 @@ -# == Schema Information -# -# Table name: praise_treads -# -# id :integer not null, primary key -# user_id :integer not null -# praise_tread_object_id :integer -# praise_tread_object_type :string(255) -# praise_or_tread :integer default("1") -# created_at :datetime not null -# updated_at :datetime not null -# -# Indexes -# -# praise_tread (praise_tread_object_id,praise_tread_object_type) -# +# == Schema Information +# +# Table name: praise_treads +# +# id :integer not null, primary key +# user_id :integer not null +# praise_tread_object_id :integer +# praise_tread_object_type :string(255) +# praise_or_tread :integer default("1") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# praise_tread (praise_tread_object_id,praise_tread_object_type) +# + class PraiseTread < ApplicationRecord belongs_to :user diff --git a/app/models/project.rb b/app/models/project.rb index f58f9f236..55cce6c72 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -4,7 +4,7 @@ # # id :integer not null, primary key # name :string(255) default(""), not null -# description :text(65535) +# description :text(4294967295) # homepage :string(255) default("") # is_public :boolean default("1"), not null # parent_id :integer @@ -43,6 +43,19 @@ # watchers_count :integer default("0") # issues_count :integer default("0") # pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# default_branch :string(255) default("master") +# website :string(255) +# order_index :integer default("0") +# lesson_url :string(255) # # Indexes # diff --git a/app/models/pull_request.rb b/app/models/pull_request.rb index 97f4a9164..d2e61f128 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -16,6 +16,11 @@ # head :string(255) # base :string(255) # issue_id :integer +# fork_project_id :integer +# is_original :boolean default("0") +# comments_count :integer default("0") +# commits_count :integer default("0") +# files_count :integer default("0") # class PullRequest < ApplicationRecord diff --git a/app/models/user.rb b/app/models/user.rb index 9d917f4c8..39cf3de46 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -46,6 +46,10 @@ # is_sync_pwd :boolean default("1") # watchers_count :integer default("0") # devops_step :integer default("0") +# sponsor_certification :integer default("0") +# sponsor_num :integer default("0") +# sponsored_num :integer default("0") +# award_time :datetime # # Indexes # @@ -206,6 +210,13 @@ class User < Owner return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct end + # 用户管理的所有项目 + def full_admin_projects + normal_projects = Project.joins(members: :roles).where(roles: {name: 'Manager'}, members: {user_id: self.id}).to_sql + org_projects = Project.joins(teams: :team_users).where(teams: {authorize: %w(admin owner)}, team_users: {user_id: self.id}).to_sql + return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct + end + def name login end diff --git a/app/services/projects/accept_join_service.rb b/app/services/projects/accept_join_service.rb new file mode 100644 index 000000000..4cc539907 --- /dev/null +++ b/app/services/projects/accept_join_service.rb @@ -0,0 +1,61 @@ +class Projects::AcceptJoinService < ApplicationService + attr_accessor :applied_project, :owner + attr_reader :user, :project + + def initialize(user, applied_project) + @user = user + @project = applied_project.project + @applied_project = applied_project + end + + def call + Rails.logger.info("###### Project accept_join_service begin ######") + ActiveRecord::Base.transaction do + validate! + update_apply + operate_project_member + send_apply_message + end + + Rails.logger.info("##### Project accept_join_service end ######") + + + return @applied_project + end + + private + def permission + case @applied_project.role + when 'manager' + 'admin' + when 'developer' + 'write' + when 'reporter' + 'read' + else + 'read' + end + end + + def validate! + raise Error, '该申请已经被接受' if @applied_project.accepted? + raise Error, '该申请不存在' unless @applied_project.present? + raise Error, '未拥有接受申请权限' unless is_permit_operator + end + + def is_permit_operator + return @user.admin? || @project.manager?(@user) + end + + def update_apply + @applied_project.update!(status: 'accepted') + end + + def operate_project_member + Projects::AddMemberInteractor.call(@project.owner, @project, @user, permission) + end + + def send_apply_message + SendJoinProjectAppliedMessageJob.perform_now(@applied_project, @user, 'successed') + end +end \ No newline at end of file diff --git a/app/services/projects/apply_join_service.rb b/app/services/projects/apply_join_service.rb index 0b57712d0..677ee20c1 100644 --- a/app/services/projects/apply_join_service.rb +++ b/app/services/projects/apply_join_service.rb @@ -9,26 +9,25 @@ class Projects::ApplyJoinService < ApplicationService end def call - validate! # 项目报告人员直接加入项目 - if params[:role] == 'reporter' - # Projects::JoinService.call(project, user, role: 'reporter') - return project - end + # if params[:role] == 'reporter' + # # Projects::JoinService.call(project, user, role: 'reporter') + # return project + # end ActiveRecord::Base.transaction do + validate! apply = user.applied_projects.create!(project: project, role: role_value) + apply + # apply.forge_activities.find_or_create_by!(user: user, project: project) - apply.forge_activities.find_or_create_by!(user: user, project: project) - - notify_project_manager!(apply) + # notify_project_manager!(apply) end # notify_project_owner - ApplyJoinProjectNotifyJob.perform_later(user.id, project.id, role_value) + # ApplyJoinProjectNotifyJob.perform_later(user.id, project.id, role_value) - project end private @@ -43,7 +42,8 @@ class Projects::ApplyJoinService < ApplicationService when 'manager' then 3 when 'developer' then 4 when 'reporter' then 5 - else raise Error, '角色无效' + else + 5 end end @@ -74,12 +74,18 @@ class Projects::ApplyJoinService < ApplicationService def validate! # params check raise Error, '邀请码不能为空' if params[:code].blank? - raise Error, '角色不能为空' if params[:role].blank? - raise Error, '角色无效' unless %w(manager developer reporter).include?(params[:role]) + raise Error, '请输入6位项目邀请码' unless valid_invite_code( params[:code]) # logical check raise Error, '邀请码无效' if project.blank? - raise Error, '您已在该项目中' if project.member?(user) - raise Error, '您已经提交过申请' if user.applied_projects.pending.exists?(project: project) + raise Error, '您已是项目成员' if project.member?(user) + raise Error, '您已经提交过申请' if user.applied_projects.common.exists?(project: project) + end + + def valid_invite_code(str) + if (str =~ /^[A-Za-z0-9]{6}+$/) + return true + end + return false end end \ No newline at end of file diff --git a/app/services/projects/refuse_join_service.rb b/app/services/projects/refuse_join_service.rb new file mode 100644 index 000000000..f9452586c --- /dev/null +++ b/app/services/projects/refuse_join_service.rb @@ -0,0 +1,39 @@ +class Projects::RefuseJoinService < ApplicationService + attr_accessor :applied_project, :owner + attr_reader :user, :project + + def initialize(user, applied_project) + @user = user + @project = applied_project.project + @applied_project = applied_project + end + + def call + Rails.logger.info("###### Project refuse_join_service begin ######") + validate! + update_apply + send_apply_message + Rails.logger.info("###### Project refuse_join_service end ######") + + return @applied_project + end + + private + def validate! + raise Error, '该申请已被拒绝' if @applied_project.refused? + raise Error, '该申请不存在' unless @applied_project.present? + raise Error, '未拥有接受申请权限' unless is_permit_operator + end + + def is_permit_operator + return @user.admin? || @project.manager?(@user) + end + + def update_apply + @applied_project.update!(status: 'refused') + end + + def send_apply_message + SendJoinProjectAppliedMessageJob.perform_now(@applied_project, @user, 'failure') + end +end \ No newline at end of file diff --git a/app/views/applied_projects/_detail.json.jbuilder b/app/views/applied_projects/_detail.json.jbuilder new file mode 100644 index 000000000..1dda3568b --- /dev/null +++ b/app/views/applied_projects/_detail.json.jbuilder @@ -0,0 +1,18 @@ +project = object.project +json.project do + json.id project.id + json.identifier project.identifier + json.name project.name + json.description project.description + json.is_public project.is_public + json.owner do + json.partial! "/users/user_simple", locals: {user: project.owner} + end +end +json.user do + json.partial! "/users/user_simple", locals: {user: object.user} +end +json.id object.id +json.status object.status +json.created_at format_time(object.created_at) +json.time_ago time_from_now(object.created_at) diff --git a/app/views/applied_projects/create.json.jbuilder b/app/views/applied_projects/create.json.jbuilder new file mode 100644 index 000000000..e2512880c --- /dev/null +++ b/app/views/applied_projects/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! "detail", locals: {object: @applied_project} diff --git a/app/views/users/applied_messages/_detail.json.jbuilder b/app/views/users/applied_messages/_detail.json.jbuilder index cca202c10..796d0387f 100644 --- a/app/views/users/applied_messages/_detail.json.jbuilder +++ b/app/views/users/applied_messages/_detail.json.jbuilder @@ -13,7 +13,12 @@ # json.partial! "/users/user_simple", locals: {user: object.user} # end json.applied do - json.partial! "/projects/applied_transfer_projects/detail", locals: {object: object.applied} + case object.applied_type + when 'AppliedTransferProject' + json.partial! "/projects/applied_transfer_projects/detail", locals: {object: object.applied} + when 'AppliedProject' + json.partial! "/applied_projects/detail", locals: {object: object.applied} + end end json.applied_user do json.partial! "/users/user_simple", locals: {user: object.applied_user} diff --git a/app/views/users/applied_projects/accept.json.jbuilder b/app/views/users/applied_projects/accept.json.jbuilder new file mode 100644 index 000000000..d13d24bed --- /dev/null +++ b/app/views/users/applied_projects/accept.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/applied_projects/detail", locals: {object: @applied_project} diff --git a/app/views/users/applied_projects/index.json.jbuilder b/app/views/users/applied_projects/index.json.jbuilder new file mode 100644 index 000000000..6e1a1a02b --- /dev/null +++ b/app/views/users/applied_projects/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @applied_projects.total_count +json.applied_projects @applied_projects do |apply| + json.partial! "/applied_projects/detail", locals: {object: apply} +end diff --git a/app/views/users/applied_projects/refuse.json.jbuilder b/app/views/users/applied_projects/refuse.json.jbuilder new file mode 100644 index 000000000..d13d24bed --- /dev/null +++ b/app/views/users/applied_projects/refuse.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/applied_projects/detail", locals: {object: @applied_project} diff --git a/config/routes.rb b/config/routes.rb index 9796f774e..5a883fcb1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -148,6 +148,8 @@ Rails.application.routes.draw do resources :issue_depends, only: [:create, :destroy] end + resources :applied_projects, only: [:create] + resources :project_categories, only: [:index, :show] do get :group_list, on: :collection end @@ -266,6 +268,12 @@ Rails.application.routes.draw do post :refuse end end + resources :applied_projects, only: [:index] do + member do + post :accept + post :refuse + end + end resources :headmaps, only: [:index] resources :is_pinned_projects, only: [:index, :update] do collection do diff --git a/db/migrate/20210609072904_add_timestamp_to_applied_projects.rb b/db/migrate/20210609072904_add_timestamp_to_applied_projects.rb new file mode 100644 index 000000000..d5d4067a8 --- /dev/null +++ b/db/migrate/20210609072904_add_timestamp_to_applied_projects.rb @@ -0,0 +1,5 @@ +class AddTimestampToAppliedProjects < ActiveRecord::Migration[5.2] + def change + add_timestamps(:applied_projects, null: true) + end +end diff --git a/public/docs/api.html b/public/docs/api.html index 0cf007cf1..9a5a58aa0 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -373,11 +373,23 @@
  • 用户拒绝迁移
  • +
  • + 待办事项-项目申请 +
  • +
  • + 用户接受迁移 +
  • +
  • + 用户拒绝迁移 +
  • Projects