Merge branch 'develop' into sync_develop

This commit is contained in:
jasder
2021-06-08 09:39:14 +08:00
54 changed files with 2962 additions and 319 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -0,0 +1,45 @@
class Users::IsPinnedProjectsController < Users::BaseController
before_action :private_user_resources!, only: [:pin]
def index
@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
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
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?
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
def pinned_project_params
params.require(:pinned_project).permit(:position)
end
end

View File

@@ -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

View File

@@ -0,0 +1,190 @@
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, commits_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

View File

@@ -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={})
@@ -72,9 +73,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])
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
render_error(@user.errors.full_messages.join(", "))
end
end
def me
@@ -274,11 +279,13 @@ class UsersController < ApplicationController
end
def user_params
params.require(:user).permit(:nickname, :lastname, :show_realname,:login,:mail,
params.require(:user).permit(:nickname, :image,
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,
:show_email, :show_location, :show_department]
)
end