Merge branch 'standalone_develop' into pre_trustie_server
This commit is contained in:
commit
70dd2768e5
|
@ -217,7 +217,7 @@ class AttachmentsController < ApplicationController
|
||||||
if @file.container && current_user.logged?
|
if @file.container && current_user.logged?
|
||||||
if @file.container.is_a?(Issue)
|
if @file.container.is_a?(Issue)
|
||||||
course = @file.container.project
|
course = @file.container.project
|
||||||
candown = course.member?(current_user)
|
candown = course.member?(current_user) || course.is_public
|
||||||
elsif @file.container.is_a?(Journal)
|
elsif @file.container.is_a?(Journal)
|
||||||
course = @file.container.issue.project
|
course = @file.container.issue.project
|
||||||
candown = course.member?(current_user)
|
candown = course.member?(current_user)
|
||||||
|
|
|
@ -16,6 +16,7 @@ class CompareController < ApplicationController
|
||||||
if @base.blank? || @head.blank?
|
if @base.blank? || @head.blank?
|
||||||
return -2, "请选择分支"
|
return -2, "请选择分支"
|
||||||
else
|
else
|
||||||
|
return -2, "目标仓库未开启合并请求(PR)功能" unless @project.has_menu_permission("pulls")
|
||||||
if @head.include?(":")
|
if @head.include?(":")
|
||||||
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
|
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
|
||||||
return -2, "请选择正确的仓库" unless fork_project.present?
|
return -2, "请选择正确的仓库" unless fork_project.present?
|
||||||
|
@ -50,6 +51,6 @@ class CompareController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def gitea_compare(base, head)
|
def gitea_compare(base, head)
|
||||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(base), CGI.escape(head), current_user.gitea_token)
|
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), current_user.gitea_token)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,7 +24,7 @@ class IssuesController < ApplicationController
|
||||||
@filter_issues = @all_issues
|
@filter_issues = @all_issues
|
||||||
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
|
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
|
||||||
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
|
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
|
||||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||||
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
|
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
|
||||||
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
|
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
|
||||||
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
|
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
|
||||||
|
|
|
@ -5,7 +5,11 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
|
||||||
def index
|
def index
|
||||||
@organization_users = @organization.organization_users.includes(:user)
|
@organization_users = @organization.organization_users.includes(:user)
|
||||||
search = params[:search].to_s.downcase
|
search = params[:search].to_s.downcase
|
||||||
@organization_users = @organization_users.joins(:user).merge(User.like(search))
|
user_condition_users = User.like(search).to_sql
|
||||||
|
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
|
||||||
|
users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
|
||||||
|
|
||||||
|
@organization_users = @organization_users.where(user_id: users).distinct
|
||||||
|
|
||||||
@organization_users = kaminari_paginate(@organization_users)
|
@organization_users = kaminari_paginate(@organization_users)
|
||||||
end
|
end
|
||||||
|
|
|
@ -135,7 +135,7 @@ class ProjectsController < ApplicationController
|
||||||
validate_params = project_params.slice(:name, :description,
|
validate_params = project_params.slice(:name, :description,
|
||||||
:project_category_id, :project_language_id, :private, :identifier)
|
:project_category_id, :project_language_id, :private, :identifier)
|
||||||
|
|
||||||
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate!
|
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate!
|
||||||
|
|
||||||
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
|
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ class PullRequestsController < ApplicationController
|
||||||
before_action :require_login, except: [:index, :show, :files, :commits]
|
before_action :require_login, except: [:index, :show, :files, :commits]
|
||||||
before_action :require_profile_completed, only: [:create]
|
before_action :require_profile_completed, only: [:create]
|
||||||
before_action :load_repository
|
before_action :load_repository
|
||||||
before_action :check_menu_authorize
|
before_action :check_menu_authorize, only: [:index, :show, :create, :update, :refuse_merge, :pr_merge]
|
||||||
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
||||||
before_action :load_pull_request, only: [:files, :commits]
|
before_action :load_pull_request, only: [:files, :commits]
|
||||||
before_action :find_atme_receivers, only: [:create, :update]
|
before_action :find_atme_receivers, only: [:create, :update]
|
||||||
|
@ -16,7 +16,7 @@ class PullRequestsController < ApplicationController
|
||||||
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
||||||
@all_issues = issues.distinct
|
@all_issues = issues.distinct
|
||||||
@filter_issues = @all_issues
|
@filter_issues = @all_issues
|
||||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||||
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
|
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
|
||||||
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
||||||
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
||||||
|
|
|
@ -241,7 +241,7 @@ class RepositoriesController < ApplicationController
|
||||||
def archive
|
def archive
|
||||||
domain = Gitea.gitea_config[:domain]
|
domain = Gitea.gitea_config[:domain]
|
||||||
api_url = Gitea.gitea_config[:base_url]
|
api_url = Gitea.gitea_config[:base_url]
|
||||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{CGI.escape(params[:archive])}"
|
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}"
|
||||||
|
|
||||||
file_path = [domain, api_url, archive_url].join
|
file_path = [domain, api_url, archive_url].join
|
||||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
||||||
|
@ -255,7 +255,7 @@ class RepositoriesController < ApplicationController
|
||||||
domain = Gitea.gitea_config[:domain]
|
domain = Gitea.gitea_config[:domain]
|
||||||
api_url = Gitea.gitea_config[:base_url]
|
api_url = Gitea.gitea_config[:base_url]
|
||||||
|
|
||||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}"
|
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{Addressable::URI.escape(params[:filepath])}?ref=#{Addressable::URI.escape(params[:ref])}"
|
||||||
file_path = [domain, api_url, url].join
|
file_path = [domain, api_url, url].join
|
||||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
|
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
class SettingsController < ApplicationController
|
class SettingsController < ApplicationController
|
||||||
def show
|
def show
|
||||||
@old_projects_url = nil
|
@old_projects_url = nil
|
||||||
|
get_navbar
|
||||||
get_add_menu
|
get_add_menu
|
||||||
get_common_menu
|
get_common_menu
|
||||||
get_personal_menu
|
get_personal_menu
|
||||||
|
@ -9,6 +10,14 @@ class SettingsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
def get_navbar
|
||||||
|
@navbar = default_laboratory.navbar
|
||||||
|
if User.current.logged?
|
||||||
|
pernal_index = {"name"=>"个人主页", "link"=>get_site_url("link", "/current_user"), "hidden"=>false}
|
||||||
|
@navbar << pernal_index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get_add_menu
|
def get_add_menu
|
||||||
@add = []
|
@add = []
|
||||||
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Users::StatisticsController < Users::BaseController
|
||||||
@commit_data = []
|
@commit_data = []
|
||||||
date_range.each do |date|
|
date_range.each do |date|
|
||||||
@date_data << date.strftime("%Y.%m.%d")
|
@date_data << date.strftime("%Y.%m.%d")
|
||||||
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
|
@issue_data << observed_user.issues.issue_issue.where("DATE(created_on) = ?", date).size
|
||||||
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
||||||
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
|
date_commit_data = commit_data.blank? ? nil : 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)
|
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
|
||||||
|
|
|
@ -49,7 +49,7 @@ class BaseForm
|
||||||
|
|
||||||
def check_verifi_code(verifi_code, code)
|
def check_verifi_code(verifi_code, code)
|
||||||
code = strip(code)
|
code = strip(code)
|
||||||
# return if code == "123123" # TODO 万能验证码,用于测试
|
return if code == "123123" && EduSetting.get("code_debug") # 万能验证码,用于测试 # TODO 万能验证码,用于测试
|
||||||
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?
|
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?
|
||||||
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
|
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class Projects::UpdateForm < BaseForm
|
class Projects::UpdateForm < BaseForm
|
||||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier
|
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier, :project_name
|
||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
validates :name, length: { maximum: 50 }
|
validates :name, length: { maximum: 50 }
|
||||||
validates :description, length: { maximum: 200 }
|
validates :description, length: { maximum: 200 }
|
||||||
|
@ -10,6 +10,7 @@ class Projects::UpdateForm < BaseForm
|
||||||
check_project_language(project_language_id)
|
check_project_language(project_language_id)
|
||||||
|
|
||||||
check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier
|
check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier
|
||||||
|
check_project_name(user_id, name) unless name.blank? || name == project_name
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -45,23 +45,40 @@ module RepositoriesHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def readme_render_decode64_content(str, owner, repo, ref)
|
def readme_render_decode64_content(str, owner, repo, ref, path)
|
||||||
return nil if str.blank?
|
return nil if str.blank?
|
||||||
begin
|
begin
|
||||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||||
|
|
||||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||||
src_regex = /src=\"(.*?)\"/
|
src_regex = /src=\"(.*?)\"/
|
||||||
|
src2_regex = /src='(.*?)'/
|
||||||
ss = content.to_s.scan(c_regex)
|
ss = content.to_s.scan(c_regex)
|
||||||
ss_src = content.to_s.scan(src_regex)
|
ss_src = content.scan(src_regex)
|
||||||
total_images = ss + ss_src
|
ss_src2 = content.scan(src2_regex)
|
||||||
|
total_images = ss + ss_src + ss_src2
|
||||||
if total_images.length > 0
|
if total_images.length > 0
|
||||||
total_images.each do |s|
|
total_images.each do |s|
|
||||||
|
begin
|
||||||
image_title = /\"(.*?)\"/
|
image_title = /\"(.*?)\"/
|
||||||
r_content = s[0]
|
r_content = s[0]
|
||||||
remove_title = r_content.to_s.scan(image_title)
|
remove_title = r_content.to_s.scan(image_title)
|
||||||
if remove_title.length > 0
|
# if remove_title.length > 0
|
||||||
r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||||
|
# end
|
||||||
|
path_last = r_content
|
||||||
|
path_current = ""
|
||||||
|
# 相对路径处理
|
||||||
|
if r_content.start_with?("../")
|
||||||
|
relative_path_length = r_content.split("../").size - 1
|
||||||
|
path_pre = path.split("/").size - 1 - relative_path_length
|
||||||
|
path_pre = 0 if path_pre < 0
|
||||||
|
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
||||||
|
path_last = r_content.split("../").last
|
||||||
|
elsif r_content.start_with?("/") # 根路径处理
|
||||||
|
path_last = r_content[1..r_content.size]
|
||||||
|
else
|
||||||
|
path_current = path
|
||||||
end
|
end
|
||||||
# if r_content.include?("?")
|
# if r_content.include?("?")
|
||||||
# new_r_content = r_content + "&raw=true"
|
# new_r_content = r_content + "&raw=true"
|
||||||
|
@ -72,9 +89,12 @@ module RepositoriesHelper
|
||||||
|
|
||||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||||
# new_r_content = "#{path}" + new_r_content
|
# new_r_content = "#{path}" + new_r_content
|
||||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{r_content}&ref=#{ref}"].join
|
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||||
|
end
|
||||||
|
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||||
|
rescue
|
||||||
|
next
|
||||||
end
|
end
|
||||||
content = content.gsub(/#{r_content}/, new_r_content)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -96,8 +116,10 @@ module RepositoriesHelper
|
||||||
|
|
||||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||||
if is_readme?(entry['type'], entry['name'])
|
if is_readme?(entry['type'], entry['name'])
|
||||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
# content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||||
readme_render_decode64_content(content, owner, repo, ref)
|
content = entry['content']
|
||||||
|
path = URI.escape(entry['path']).to_s.downcase.gsub("/readme.md","")
|
||||||
|
readme_render_decode64_content(content, owner, repo, ref, path)
|
||||||
else
|
else
|
||||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||||
if image_type?(file_type)
|
if image_type?(file_type)
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
module Trace
|
||||||
|
class << self
|
||||||
|
def trace_config
|
||||||
|
trace_config = {}
|
||||||
|
|
||||||
|
begin
|
||||||
|
config = Rails.application.config_for(:configuration).symbolize_keys!
|
||||||
|
trace_config = config[:trace].symbolize_keys!
|
||||||
|
raise 'trace config missing' if trace_config.blank?
|
||||||
|
rescue => exception
|
||||||
|
raise ex if Rails.env.production?
|
||||||
|
|
||||||
|
puts %Q{\033[33m [warning] gitea config or configuration.yml missing,
|
||||||
|
please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
|
||||||
|
trace_config = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
trace_config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -29,6 +29,11 @@ class Team < ApplicationRecord
|
||||||
has_many :team_units, dependent: :destroy
|
has_many :team_units, dependent: :destroy
|
||||||
has_many :team_users, dependent: :destroy
|
has_many :team_users, dependent: :destroy
|
||||||
|
|
||||||
|
scope :like, lambda { |keywords|
|
||||||
|
sql = "teams.nickname LIKE :search OR teams.name LIKE :search"
|
||||||
|
where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
|
||||||
|
}
|
||||||
|
|
||||||
validates :name, uniqueness: {scope: :organization_id}
|
validates :name, uniqueness: {scope: :organization_id}
|
||||||
|
|
||||||
enum authorize: {read: 1, write: 2, admin: 3, owner: 4}
|
enum authorize: {read: 1, write: 2, admin: 3, owner: 4}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: trace_users
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# user_id :integer
|
||||||
|
# username :string(255)
|
||||||
|
# password :string(255)
|
||||||
|
# unit :string(255)
|
||||||
|
# telnumber :string(255)
|
||||||
|
# email :string(255)
|
||||||
|
# name :string(255)
|
||||||
|
# token :text(65535)
|
||||||
|
# expired_at :datetime
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# index_trace_users_on_user_id (user_id)
|
||||||
|
#
|
||||||
|
|
||||||
|
# 代码溯源 用户
|
||||||
|
class TraceUser < ApplicationRecord
|
||||||
|
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
|
||||||
|
def build_self_data
|
||||||
|
return if user.nil?
|
||||||
|
|
||||||
|
self.username = user.login
|
||||||
|
self.password = SecureRandom.hex
|
||||||
|
self.unit = user.custom_department.blank? ? 'GitLink' : user.custom_department
|
||||||
|
self.telnumber = user.phone.blank? ? '13800000000' : user.phone
|
||||||
|
self.email = user.mail
|
||||||
|
self.name = user.nickname.blank? ? user.login : user.nickname
|
||||||
|
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def build_token
|
||||||
|
return if username.blank? || password.blank? || unit.blank? || telnumber.blank? || email.blank? || name.blank?
|
||||||
|
|
||||||
|
response = Trace::AddUserService.call(username, password, unit, telnumber, email, name)
|
||||||
|
self.token = response[1]['token']
|
||||||
|
self.expired_at = Time.now + 1.hours
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh_token
|
||||||
|
return if username.blank? || password.blank? || unit.blank? || telnumber.blank? || email.blank? || name.blank?
|
||||||
|
|
||||||
|
response = Trace::LoginService.call(username, password)
|
||||||
|
self.token = response[1]['token']
|
||||||
|
self.expired_at = Time.now + 1.hours
|
||||||
|
end
|
||||||
|
end
|
|
@ -174,6 +174,7 @@ class User < Owner
|
||||||
|
|
||||||
has_many :system_notification_histories
|
has_many :system_notification_histories
|
||||||
has_many :system_notifications, through: :system_notification_histories
|
has_many :system_notifications, through: :system_notification_histories
|
||||||
|
has_one :trace_user, dependent: :destroy
|
||||||
|
|
||||||
# Groups and active users
|
# Groups and active users
|
||||||
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
||||||
|
@ -789,6 +790,24 @@ class User < Owner
|
||||||
self.nickname.present? && self.mail.present?
|
self.nickname.present? && self.mail.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def trace_token
|
||||||
|
if trace_user.present?
|
||||||
|
if trace_user.expired_at < Time.now
|
||||||
|
trace_user.refresh_token
|
||||||
|
trace_user.save
|
||||||
|
end
|
||||||
|
return trace_user.token
|
||||||
|
else
|
||||||
|
tu = TraceUser.new
|
||||||
|
tu.user = self
|
||||||
|
tu.build_self_data
|
||||||
|
tu.build_token
|
||||||
|
tu.save
|
||||||
|
|
||||||
|
return tu.token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def validate_password_length
|
def validate_password_length
|
||||||
# 管理员的初始密码是5位
|
# 管理员的初始密码是5位
|
||||||
|
|
|
@ -27,12 +27,12 @@ class Issues::ListQueryService < ApplicationService
|
||||||
issues = issues.joins(:pull_request).where(pull_requests: {status: 1})
|
issues = issues.joins(:pull_request).where(pull_requests: {status: 1})
|
||||||
end
|
end
|
||||||
|
|
||||||
if search_name.present?
|
# if search_name.present?
|
||||||
issues = issues.where("subject LIKE ? OR description LIKE ? ", "%#{search_name}%", "%#{search_name}%")
|
# issues = issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{search_name}%", "%#{search_name}%")
|
||||||
end
|
# end
|
||||||
|
|
||||||
if start_time&.present? || end_time&.present?
|
if start_time&.present? || end_time&.present?
|
||||||
issues = issues.where("start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date)
|
issues = issues.where("issues.start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date)
|
||||||
end
|
end
|
||||||
|
|
||||||
issues = issues.where(author_id: params[:author_id]) if params[:author_id].present? && params[:author_id].to_s != "all"
|
issues = issues.where(author_id: params[:author_id]) if params[:author_id].present? && params[:author_id].to_s != "all"
|
||||||
|
|
|
@ -132,8 +132,8 @@ class PullRequests::CreateService < ApplicationService
|
||||||
end
|
end
|
||||||
|
|
||||||
def merge_original_pull_params
|
def merge_original_pull_params
|
||||||
base_pull_params[:head] = CGI.escape(base_pull_params[:head])
|
base_pull_params[:head] = Addressable::URI.escape(base_pull_params[:head])
|
||||||
base_pull_params[:base] = CGI.escape(base_pull_params[:base])
|
base_pull_params[:base] = Addressable::URI.escape(base_pull_params[:base])
|
||||||
if pull_request.is_original && @params[:merge_user_login]
|
if pull_request.is_original && @params[:merge_user_login]
|
||||||
base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{base_pull_params[:head]}")
|
base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{base_pull_params[:head]}")
|
||||||
else
|
else
|
||||||
|
@ -157,6 +157,7 @@ class PullRequests::CreateService < ApplicationService
|
||||||
raise "head参数不能为空" if @params[:head].blank?
|
raise "head参数不能为空" if @params[:head].blank?
|
||||||
raise "base参数不能为空" if @params[:base].blank?
|
raise "base参数不能为空" if @params[:base].blank?
|
||||||
raise "fork_project_id参数错误" if is_original && !@project.forked_projects.pluck(:id).include?(@params[:fork_project_id].to_i)
|
raise "fork_project_id参数错误" if is_original && !@project.forked_projects.pluck(:id).include?(@params[:fork_project_id].to_i)
|
||||||
|
raise "merge_user_login参数错误" if is_original && @project.fork_users.joins(:user).where(users: {login: @params[:merge_user_login]}).blank?
|
||||||
raise "分支内容相同,无需创建合并请求" if @params[:head] === @params[:base] && !is_original
|
raise "分支内容相同,无需创建合并请求" if @params[:head] === @params[:base] && !is_original
|
||||||
raise "合并请求已存在" if @project&.pull_requests.where(head: @params[:head], base: @params[:base], status: 0, is_original: is_original, fork_project_id: @params[:fork_project_id]).present?
|
raise "合并请求已存在" if @project&.pull_requests.where(head: @params[:head], base: @params[:base], status: 0, is_original: is_original, fork_project_id: @params[:fork_project_id]).present?
|
||||||
raise @pull_issue.errors.full_messages.join(", ") unless pull_issue.valid?
|
raise @pull_issue.errors.full_messages.join(", ") unless pull_issue.valid?
|
||||||
|
@ -165,7 +166,7 @@ class PullRequests::CreateService < ApplicationService
|
||||||
|
|
||||||
def compare_head_base!
|
def compare_head_base!
|
||||||
head = pull_request.is_original && @params[:merge_user_login] ? "#{@params[:merge_user_login]}/#{@project.identifier}:#{@params[:head]}" : @params[:head]
|
head = pull_request.is_original && @params[:merge_user_login] ? "#{@params[:merge_user_login]}/#{@project.identifier}:#{@params[:head]}" : @params[:head]
|
||||||
compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(@params[:base]), CGI.escape(head), @current_user.gitea_token)
|
compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(@params[:base]), Addressable::URI.escape(head), @current_user.gitea_token)
|
||||||
raise '分支内容相同,无需创建合并请求' if compare_result["Commits"].blank? && compare_result["Diff"].blank?
|
raise '分支内容相同,无需创建合并请求' if compare_result["Commits"].blank? && compare_result["Diff"].blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# 代码溯源 添加用户
|
||||||
|
class Trace::AddUserService < Trace::ClientService
|
||||||
|
|
||||||
|
# 用户名 密码 单位 手机号 邮箱 昵称
|
||||||
|
attr_accessor :username, :password, :unit, :telnumber, :email, :name
|
||||||
|
|
||||||
|
def initialize(username, password, unit, telnumber, email, name)
|
||||||
|
@username = username
|
||||||
|
@password = password
|
||||||
|
@unit = unit
|
||||||
|
@telnumber = telnumber
|
||||||
|
@email = email
|
||||||
|
@name = name
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
result = post(url, {data: request_params})
|
||||||
|
response = render_response(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def request_params
|
||||||
|
{
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
unit: unit,
|
||||||
|
telnumber: telnumber,
|
||||||
|
email: email,
|
||||||
|
name: name
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"/user/addccfuser".freeze
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,33 @@
|
||||||
|
# 代码溯源 查询检测结果
|
||||||
|
class Trace::CheckResultService < Trace::ClientService
|
||||||
|
|
||||||
|
attr_accessor :token, :project_name, :file_name, :page_num, :page_size
|
||||||
|
|
||||||
|
def initialize(token, project_name=nil, file_name=nil, page_num=1, page_size=15)
|
||||||
|
@token = token
|
||||||
|
@project_name = project_name
|
||||||
|
@file_name = file_name
|
||||||
|
@page_num = page_num
|
||||||
|
@page_size = page_size
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
result = authed_get(token, url, request_params)
|
||||||
|
reponse = render_response(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
{
|
||||||
|
product_name: project_name,
|
||||||
|
file_name: file_name,
|
||||||
|
pageNum: page_num,
|
||||||
|
pageSize: page_size,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"/user/checkresult".freeze
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
# 代码溯源 开始检测
|
||||||
|
class Trace::CheckService < Trace::ClientService
|
||||||
|
|
||||||
|
attr_accessor :token, :project, :if_branch, :branch_tag
|
||||||
|
|
||||||
|
def initialize(token, project, if_branch, branch_tag)
|
||||||
|
@token = token
|
||||||
|
@project = project
|
||||||
|
@if_branch = if_branch
|
||||||
|
@branch_tag = branch_tag
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
result = authed_post(token, url, {data: request_params})
|
||||||
|
reponse = render_response(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
repo = Gitea::Repository::GetService.call(project&.owner&.login, project&.identifier)
|
||||||
|
{
|
||||||
|
product_name: project&.name,
|
||||||
|
product_type: project&.category&.name,
|
||||||
|
code_type: project&.language&.name,
|
||||||
|
product_desc: project&.description,
|
||||||
|
git_url: repo['clone_url'],
|
||||||
|
if_branch: if_branch,
|
||||||
|
branch_tag: branch_tag
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"/user/check".freeze
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
class Trace::ClientService < ApplicationService
|
||||||
|
|
||||||
|
def post(url, params={})
|
||||||
|
puts "[trace][POST] request params: #{params}"
|
||||||
|
conn.post do |req|
|
||||||
|
req.url full_url(url)
|
||||||
|
req.body = params[:data].to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authed_post(token, url, params={})
|
||||||
|
puts "[trace][POST] request params: #{params}"
|
||||||
|
puts "[trace][POST] request token: #{token}"
|
||||||
|
conn.post do |req|
|
||||||
|
req.url full_url(url)
|
||||||
|
req.body = params[:data].to_json
|
||||||
|
req.headers['Authorization'] = token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(url, params={})
|
||||||
|
puts "[trace][GET] request params: #{params}"
|
||||||
|
conn.get do |req|
|
||||||
|
req.url full_url(url, 'get')
|
||||||
|
params.each_pair do |key, value|
|
||||||
|
req.params["#{key}"] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authed_get(token, url, params={})
|
||||||
|
puts "[trace][GET] request params: #{params}"
|
||||||
|
puts "[trace][GET] request token: #{token}"
|
||||||
|
conn.get do |req|
|
||||||
|
req.url full_url(url, 'get')
|
||||||
|
params.each_pair do |key, value|
|
||||||
|
req.params["#{key}"] = value
|
||||||
|
end
|
||||||
|
req.headers['Authorization'] = token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(url, params={})
|
||||||
|
puts "[trace][DELETE] request params: #{params}"
|
||||||
|
conn.delete do |req|
|
||||||
|
req.url full_url(url)
|
||||||
|
req.body = params[:data].to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authed_delete(token, url, params={})
|
||||||
|
puts "[trace][DELETE] request params: #{params}"
|
||||||
|
puts "[trace][DELETE] request token: #{token}"
|
||||||
|
conn.delete do |req|
|
||||||
|
req.url full_url(url)
|
||||||
|
req.body = params[:data].to_json
|
||||||
|
req.headers['Authorization'] = token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def patch(url, params={})
|
||||||
|
puts "[trace][PATCH] request params: #{params}"
|
||||||
|
conn.patch do |req|
|
||||||
|
req.url full_url(url)
|
||||||
|
req.body = params[:data].to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authed_patch(token, url, params={})
|
||||||
|
puts "[trace][PATCH] request params: #{params}"
|
||||||
|
puts "[trace][PATCH] request token: #{token}"
|
||||||
|
conn.patch do |req|
|
||||||
|
req.url full_url(url)
|
||||||
|
req.body = params[:data].to_json
|
||||||
|
req.headers['Authorization'] = token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def put(url, params={})
|
||||||
|
puts "[trace][PUT] request params: #{params}"
|
||||||
|
conn.put do |req|
|
||||||
|
req.url full_url(url)
|
||||||
|
req.body = params[:data].to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authed_put(token, url, params={})
|
||||||
|
puts "[trace][PUT] request params: #{params}"
|
||||||
|
puts "[trace][PUT] request token: #{token}"
|
||||||
|
conn.put do |req|
|
||||||
|
req.url full_url(url)
|
||||||
|
req.body = params[:data].to_json
|
||||||
|
req.headers['Authorization'] = token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def conn
|
||||||
|
@client ||= begin
|
||||||
|
Faraday.new(url: domain) do |req|
|
||||||
|
req.request :url_encoded
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.adapter Faraday.default_adapter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@client
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_url
|
||||||
|
Trace.trace_config[:base_url]
|
||||||
|
end
|
||||||
|
|
||||||
|
def domain
|
||||||
|
Trace.trace_config[: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)
|
||||||
|
url = URI.escape(url) unless url.ascii_only?
|
||||||
|
puts "[trace] request url: #{url}"
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_error(status, body)
|
||||||
|
puts "[trace] status: #{status}"
|
||||||
|
puts "[trace] body: #{body}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_response(response)
|
||||||
|
status = response.status
|
||||||
|
body = JSON.parse(response&.body)
|
||||||
|
|
||||||
|
log_error(status, body)
|
||||||
|
|
||||||
|
return [body["code"], body["Data"], body["Error"]]
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,29 @@
|
||||||
|
# 代码溯源 用户登录
|
||||||
|
class Trace::LoginService < Trace::ClientService
|
||||||
|
|
||||||
|
# 用户名 密码
|
||||||
|
attr_accessor :username, :password
|
||||||
|
|
||||||
|
def initialize(username, password)
|
||||||
|
@username = username
|
||||||
|
@password = password
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
result = post(url, {data: request_params})
|
||||||
|
response = render_response(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def request_params
|
||||||
|
{
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"/user/login".freeze
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,26 @@
|
||||||
|
# 代码溯源 导出pdf
|
||||||
|
class Trace::PdfReportService < Trace::ClientService
|
||||||
|
|
||||||
|
attr_accessor :token, :task_id
|
||||||
|
|
||||||
|
def initialize(token, task_id)
|
||||||
|
@token = token
|
||||||
|
@task_id = task_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
result = authed_get(token, url, request_params)
|
||||||
|
response = render_response(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
{
|
||||||
|
task_id: task_id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"/user/pdfreport".freeze
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,25 @@
|
||||||
|
# 代码溯源 重新检测
|
||||||
|
class Trace::ReloadCheckService < Trace::ClientService
|
||||||
|
|
||||||
|
attr_accessor :token, :fake_project_id
|
||||||
|
def initialize(token, fake_project_id)
|
||||||
|
@token = token
|
||||||
|
@fake_project_id = fake_project_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
result = authed_post(token, url, {data: request_params})
|
||||||
|
response = render_response(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
{
|
||||||
|
project_id: fake_project_id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
'/user/reloadcheck'.freeze
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,5 +3,5 @@ json.user do
|
||||||
json.partial! "organizations/user_detail", user: org_user.user
|
json.partial! "organizations/user_detail", user: org_user.user
|
||||||
end
|
end
|
||||||
|
|
||||||
json.team_names org_user.teams.pluck(:name)
|
json.team_names org_user.teams.pluck(:nickname)
|
||||||
json.created_at org_user.created_at.strftime("%Y-%m-%d")
|
json.created_at org_user.created_at.strftime("%Y-%m-%d")
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
if @project.forge?
|
if @project.forge?
|
||||||
|
is_dir = @sub_entries.is_a?(Array)
|
||||||
file_name = entry['name']
|
file_name = entry['name']
|
||||||
file_type = File.extname(file_name.to_s)[1..-1]
|
file_type = File.extname(file_name.to_s)[1..-1]
|
||||||
direct_download = download_type(file_type)
|
direct_download = download_type(file_type)
|
||||||
|
@ -9,16 +10,16 @@ if @project.forge?
|
||||||
json.type entry['type']
|
json.type entry['type']
|
||||||
json.size entry['size']
|
json.size entry['size']
|
||||||
|
|
||||||
json.content direct_download ? nil : decode64_content(entry, @owner, @repository, @ref, @path)
|
json.content (direct_download || image_type || is_dir) ? nil : decode64_content(entry, @owner, @repository, @ref, @path)
|
||||||
json.target entry['target']
|
json.target entry['target']
|
||||||
|
|
||||||
download_url =
|
download_url =
|
||||||
if image_type
|
if image_type
|
||||||
dir_path = [@owner.login, @repository.identifier, "raw/branch", @ref].join('/')
|
dir_path = [@owner.login, @repository.identifier, "raw/branch", @ref].join('/')
|
||||||
render_download_image_url(dir_path, entry['path'], decode64_content(entry, @owner, @repository, @ref))
|
is_dir ? "" : render_download_image_url(dir_path, entry['path'], decode64_content(entry, @owner, @repository, @ref))
|
||||||
else
|
else
|
||||||
# entry['download_url']
|
# entry['download_url']
|
||||||
render_download_file_url(@owner, @repository, entry['path'].to_s, @ref)
|
is_dir ? "" : render_download_file_url(@owner, @repository, entry['path'].to_s, @ref)
|
||||||
end
|
end
|
||||||
json.download_url download_url
|
json.download_url download_url
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ json.setting do
|
||||||
#
|
#
|
||||||
# end
|
# end
|
||||||
|
|
||||||
nav_bar = default_setting.navbar
|
# nav_bar = default_setting.navbar
|
||||||
|
|
||||||
# if User.current.logged?
|
# if User.current.logged?
|
||||||
# nav_bar[2]["link"] = "https://forgeplus.trustie.net/users/#{current_user.login}/projects"
|
# nav_bar[2]["link"] = "https://forgeplus.trustie.net/users/#{current_user.login}/projects"
|
||||||
|
@ -39,7 +39,7 @@ json.setting do
|
||||||
json.moop_cases_banner_url default_setting.moop_cases_banner_url&.[](1..-1)
|
json.moop_cases_banner_url default_setting.moop_cases_banner_url&.[](1..-1)
|
||||||
json.oj_banner_url default_setting.oj_banner_url&.[](1..-1)
|
json.oj_banner_url default_setting.oj_banner_url&.[](1..-1)
|
||||||
|
|
||||||
json.navbar nav_bar
|
json.navbar @navbar
|
||||||
|
|
||||||
json.footer default_setting.footer
|
json.footer default_setting.footer
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,10 @@ default: &default
|
||||||
read_domain: ''
|
read_domain: ''
|
||||||
base_url: ''
|
base_url: ''
|
||||||
|
|
||||||
|
trace:
|
||||||
|
domain: ''
|
||||||
|
base_url: ''
|
||||||
|
|
||||||
forum:
|
forum:
|
||||||
domain: ''
|
domain: ''
|
||||||
base_url: '/api'
|
base_url: '/api'
|
||||||
|
|
|
@ -146,6 +146,16 @@ Rails.application.routes.draw do
|
||||||
get :get_children_journals
|
get :get_children_journals
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resources :claims, only: [:index] do
|
||||||
|
collection do
|
||||||
|
post :create
|
||||||
|
delete :destroy
|
||||||
|
get :index
|
||||||
|
put :update
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
resources :issue_times, only: [:create] do
|
resources :issue_times, only: [:create] do
|
||||||
collection do
|
collection do
|
||||||
post :end_work
|
post :end_work
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
class CreateTraceUsers < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :trace_users do |t|
|
||||||
|
t.references :user
|
||||||
|
t.string :username
|
||||||
|
t.string :password
|
||||||
|
t.string :unit
|
||||||
|
t.string :telnumber
|
||||||
|
t.string :email
|
||||||
|
t.string :name
|
||||||
|
t.text :token
|
||||||
|
t.datetime :expired_at
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe TraceUser, type: :model do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
Loading…
Reference in New Issue