2021-07-12 16:14:51 +08:00
2021-06-29 17:36:15 +08:00
# == 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)
# order_index :integer default("0")
# lesson_url :string(255)
#
# Indexes
#
# index_projects_on_forked_from_project_id (forked_from_project_id)
# index_projects_on_identifier (identifier)
# index_projects_on_invite_code (invite_code)
# index_projects_on_is_public (is_public)
# index_projects_on_lft (lft)
# index_projects_on_license_id (license_id)
# index_projects_on_name (name)
# index_projects_on_platform (platform)
# index_projects_on_project_category_id (project_category_id)
# index_projects_on_project_language_id (project_language_id)
# 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)
#
2021-05-27 14:23:59 +08:00
2021-05-27 14:23:59 +08:00
2021-04-06 15:41:53 +08:00
2020-03-09 00:40:16 +08:00
class Project < ApplicationRecord
include Matchable
include Publicable
include Watchable
include ProjectOperable
2021-06-08 14:56:43 +08:00
include Dcodes
2020-03-09 00:40:16 +08:00
2020-05-18 18:25:01 +08:00
# common:开源托管项目
# mirror:普通镜像项目,没有定时同步功能
# sync_mirror:同步镜像项目,有系统定时同步功能,且用户可手动同步操作
#
enum project_type : { sync_mirror : 2 , mirror : 1 , common : 0 }
2020-03-09 00:40:16 +08:00
2020-10-19 22:59:41 +08:00
# forge: trustie平台项目, educoder: educoder平台项目, 默认为forge平台
enum platform : { forge : 0 , educoder : 1 }
2020-03-09 00:40:16 +08:00
belongs_to :ignore , optional : true
belongs_to :license , optional : true
2021-01-15 18:28:38 +08:00
belongs_to :owner , class_name : 'Owner' , foreign_key : :user_id , optional : true
2021-01-20 18:48:28 +08:00
belongs_to :organization_extension , foreign_key : :user_id , primary_key : :organization_id , optional : true , counter_cache : :num_projects
2020-05-25 13:46:08 +08:00
belongs_to :project_category , optional : true , :counter_cache = > true
belongs_to :project_language , optional : true , :counter_cache = > true
2021-06-29 17:36:15 +08:00
belongs_to :forked_from_project , class_name : 'Project' , optional : true , foreign_key : :forked_from_project_id
2020-03-09 00:40:16 +08:00
has_many :project_trends , dependent : :destroy
2020-05-15 17:05:53 +08:00
has_many :watchers , as : :watchable , dependent : :destroy
has_many :fork_users , dependent : :destroy
2020-08-29 12:07:06 +08:00
has_many :forked_users , class_name : 'ForkUser' , foreign_key : :fork_project_id , dependent : :destroy
2021-06-29 17:36:15 +08:00
has_many :forked_projects , class_name : 'Project' , foreign_key : :forked_from_project_id
2020-10-19 22:59:41 +08:00
has_one :project_educoder , dependent : :destroy
2020-03-09 00:40:16 +08:00
has_one :project_score , dependent : :destroy
has_one :repository , dependent : :destroy
has_many :pull_requests , dependent : :destroy
2020-06-08 11:38:03 +08:00
has_many :issue_tags , - > { order ( " issue_tags.created_at DESC " ) } , dependent : :destroy
2020-03-09 00:40:16 +08:00
has_many :issues , dependent : :destroy
2020-05-25 16:20:34 +08:00
# has_many :user_grades, dependent: :destroy
2020-03-09 00:40:16 +08:00
has_many :attachments , as : :container , dependent : :destroy
has_one :project_score , dependent : :destroy
2020-06-08 11:38:03 +08:00
has_many :versions , - > { order ( " versions.created_on DESC, versions.name DESC " ) } , dependent : :destroy
2020-03-09 00:40:16 +08:00
has_many :praise_treads , as : :praise_tread_object , dependent : :destroy
has_and_belongs_to_many :trackers , :order = > " #{ Tracker . table_name } .position "
2020-10-04 17:32:37 +08:00
has_one :project_detail , dependent : :destroy
2021-03-17 11:52:36 +08:00
has_many :project_units , dependent : :destroy
2021-04-26 11:32:59 +08:00
has_one :applied_transfer_project , - > { order created_at : :desc } , dependent : :destroy
2021-05-27 14:23:59 +08:00
has_many :pinned_projects , dependent : :destroy
has_many :has_pinned_users , through : :pinned_projects , source : :user
2021-07-26 17:25:06 +08:00
has_many :webhooks , class_name : " Gitea::Webhook " , primary_key : :gpid , foreign_key : :repo_id
2020-03-09 00:40:16 +08:00
2021-09-10 11:26:01 +08:00
after_save :check_project_members
before_save :set_invite_code , :reset_cache_data , :reset_unmember_followed
2021-06-08 11:51:46 +08:00
after_destroy :reset_cache_data
2020-03-09 00:40:16 +08:00
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 ) }
2020-04-22 09:32:39 +08:00
scope :no_anomory_projects , - > { where ( " projects.user_id is not null and projects.user_id != ? " , 2 ) }
2020-10-04 12:01:26 +08:00
scope :recommend , - > { visible . project_statics_select . where ( recommend : true ) }
2021-03-15 19:01:35 +08:00
delegate :content , to : :project_detail , allow_nil : true
delegate :name , to : :license , prefix : true , allow_nil : true
2020-03-09 00:40:16 +08:00
2021-09-07 17:19:38 +08:00
def self . all_visible ( user_id = nil )
user_projects_sql = Project . joins ( :owner ) . where ( users : { type : 'User' } ) . to_sql
org_public_projects_sql = Project . joins ( :owner ) . merge ( Organization . joins ( :organization_extension ) . where ( organization_extensions : { visibility : 'common' } ) ) . to_sql
if user_id . present?
org_limit_projects_sql = Project . joins ( :owner ) . merge ( Organization . joins ( :organization_extension ) . where ( organization_extensions : { visibility : 'limited' } ) ) . to_sql
org_privacy_projects_sql = Project . joins ( :owner ) . merge ( Organization . joins ( :organization_extension , :organization_users ) . where ( organization_extensions : { visibility : 'privacy' } , organization_users : { user_id : user_id } ) ) . to_sql
return Project . from ( " ( #{ user_projects_sql } UNION #{ org_public_projects_sql } UNION #{ org_limit_projects_sql } UNION #{ org_privacy_projects_sql } ) AS projects " ) . visible
else
return Project . from ( " ( #{ user_projects_sql } UNION #{ org_public_projects_sql } ) AS projects " ) . visible
end
end
2021-06-08 11:51:46 +08:00
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
2020-03-09 00:40:16 +08:00
2021-09-10 11:26:01 +08:00
def reset_unmember_followed
if changes [ :is_public ] . present? && changes [ :is_public ] == [ true , false ]
self . watchers . where . not ( user_id : self . all_collaborators ) . destroy_all
end
end
2021-06-08 14:56:43 +08:00
def set_invite_code
if self . invite_code . nil?
2021-06-11 09:30:22 +08:00
self . invite_code = self . generate_dcode ( 'invite_code' , 6 )
2021-06-08 14:56:43 +08:00
end
end
2020-07-03 15:14:25 +08:00
def self . search_project ( search )
ransack ( name_or_identifier_cont : search )
end
2020-03-09 00:40:16 +08:00
# 创建者
def creator
User . find ( user_id ) . full_name
end
def members_user_infos
2021-01-18 15:28:20 +08:00
members . joins ( :roles ) . where ( " roles.name in ('Manager', 'Developer', 'Reporter') " ) . joins ( " left join users on members.user_id = users.id " ) . includes ( :user ) . where ( " users.type = ? " , " User " )
2020-03-09 00:40:16 +08:00
# members.joins("left join users on members.user_id = users.id").select("users.id", "users.login","users.firstname","users.lastname")
# .pluck("users.id", "users.login","users.lastname", "users.firstname")
end
def to_param
self . identifier . parameterize
end
def get_issues_count ( status_id )
if status_id . present?
self & . issues . issue_issue . select ( :id , :status_id ) . where ( status_id : status_id ) & . pluck ( :id ) . size
else
self & . issues . issue_issue . select ( :id ) & . pluck ( :id ) . size
end
end
def get_pull_requests_count ( status_id )
if status_id . present?
self & . pull_requests . select ( :id , :status ) . where ( status : status_id ) & . pluck ( :id ) . size
else
self & . pull_requests . select ( :id ) & . pluck ( :id ) . size
end
end
#创建项目管理员
def check_project_members
2021-04-19 11:35:12 +08:00
return if owner . is_a? ( Organization )
unless members . present? && members . exists? ( user_id : self . user_id )
2020-03-09 00:40:16 +08:00
member_params = {
user_id : self . user_id ,
project_id : self . id
}
user_member = Member . new ( member_params )
if user_member . save
2020-03-11 20:01:44 +08:00
role_id = Role . select ( :id , :position ) . where ( position : 3 ) & . first & . id
MemberRole . create! ( member_id : user_member . id , role_id : role_id )
2020-03-09 00:40:16 +08:00
end
end
end
2020-03-19 17:18:17 +08:00
def self . init_bluck_repository
Project . includes ( :repository ) . find_each do | project |
puts project . id
next if project . owner . blank?
if project . repository . blank?
2020-03-20 13:10:25 +08:00
puts " # # # # # # # # # # # start create repositoy # # # # # # # # # # # # # "
2020-03-19 17:18:17 +08:00
Repository . create! ( project_id : project . id , identifier : Project . generate_identifier , user_id : project & . owner & . id )
end
end
end
def self . generate_identifier
str_arr = ( ( " a " .. " z " ) . to_a + ( " A " .. " Z " ) . to_a )
str = str_arr . shuffle [ 0 .. 8 ] . join
while Repository . exists? ( identifier : str )
str = str_arr . shuffle [ 0 .. 8 ] . join
end
str
end
2020-03-26 10:19:04 +08:00
def self . list_user_projects ( user_id )
2020-04-03 18:01:56 +08:00
projects = Project . is_private . select ( :id , :user_id )
user_not_show_1 = projects . where ( " user_id != ? " , user_id ) . pluck ( :id ) . uniq
2020-04-03 17:55:13 +08:00
user_show_2 = projects . joins ( :members ) . where ( " members.user_id = ? " , user_id ) . pluck ( :id ) . uniq
2020-04-22 09:19:43 +08:00
Project . where . not ( id : ( user_not_show_1 - user_show_2 ) . uniq )
2020-03-26 10:19:04 +08:00
end
2020-04-21 10:11:54 +08:00
def members_count
members . select ( :id ) . size
end
def can_visited?
2020-08-12 10:58:16 +08:00
is_public? || User . current . admin? || member? ( User . current )
2020-04-21 10:11:54 +08:00
end
2020-05-13 17:10:29 +08:00
def releases_size ( current_user_id , type )
2020-05-13 17:07:41 +08:00
if current_user_id == self . user_id && type . to_s == " all "
2020-05-18 18:25:01 +08:00
self . repository . version_releases_count
else
2020-05-13 17:07:41 +08:00
self . repository . version_releases . releases_size
end
end
def contributor_users
self . pull_requests . select ( :user_id ) . pluck ( :user_id ) . uniq . size
end
2020-05-21 18:37:32 +08:00
def open_issues_count
issues_count - closed_issues_count
end
2020-06-03 17:26:49 +08:00
def numerical_for_project_type
self . class . name . constantize . project_types [ " #{ self . project_type } " ]
end
2020-06-05 18:01:58 +08:00
def watched_by? user
watchers . pluck ( :user_id ) . include? user & . id
end
def praised_by? user
praise_treads . pluck ( :user_id ) . include? user & . id
end
def get_premission user
2021-04-06 15:41:53 +08:00
return " Owner " if owner? ( user )
return " Manager " if manager? ( user )
return " Developer " if develper? ( user )
return " Reporter " if reporter? ( user )
2020-06-05 18:01:58 +08:00
2021-04-06 16:33:14 +08:00
return " "
2020-06-05 18:01:58 +08:00
end
2020-08-11 23:20:04 +08:00
def fork_project
2020-06-29 17:06:46 +08:00
Project . find_by ( id : self . forked_from_project_id )
end
2020-07-07 13:54:57 +08:00
def self . members_projects ( member_user_id )
joins ( :members ) . where ( members : { user_id : member_user_id } )
end
2020-08-11 23:20:04 +08:00
def self . find_with_namespace ( namespace_path , identifier )
logger . info " # # # # # # # # namespace_path: #{ namespace_path } # # # # # # # # identifier: #{ identifier } "
2021-01-15 18:28:38 +08:00
user = Owner . find_by_login namespace_path
2020-11-11 10:14:41 +08:00
project = user & . projects & . find_by ( identifier : identifier ) || Project . find_by ( identifier : " #{ namespace_path } / #{ identifier } " )
2020-10-19 22:59:41 +08:00
return nil if project . blank?
2020-08-11 23:20:04 +08:00
2020-10-30 15:47:09 +08:00
[ project , user ]
2020-08-11 23:20:04 +08:00
end
2020-09-27 11:30:37 +08:00
def ci_reactivate?
open_devops_count > 0
end
def ci_reactivate! ( ci_repo )
ci_repo . update_column ( :repo_active , 1 )
update_column ( :open_devops , true )
increment! ( :open_devops_count )
end
2020-10-19 22:59:41 +08:00
def self . sync_educoder_shixun ( url , private_token , page , per_page )
2020-10-19 23:41:05 +08:00
SyncEducoderShixunJob . perform_later ( url , private_token , page , per_page )
2020-10-19 22:59:41 +08:00
end
2020-10-21 11:56:30 +08:00
2020-10-21 11:45:55 +08:00
def self . update_common_projects_count!
ps = ProjectStatistic . first
ps . increment! ( :common_projects_count ) unless ps . blank?
end
def self . update_mirror_projects_count!
ps = ProjectStatistic . first
ps . increment! ( :mirror_projects_count ) unless ps . blank?
end
2020-11-23 15:35:03 +08:00
2021-01-08 18:07:48 +08:00
def set_updated_on ( time )
return if time . blank?
update_column ( :updated_on , time )
end
2021-04-25 18:41:13 +08:00
def is_transfering
applied_transfer_project & . common? ? true : false
end
2020-03-09 00:40:16 +08:00
end