Merge pull request '20230220版本' (#332) from master into develop
This commit is contained in:
commit
5eee13ea87
|
@ -81,7 +81,6 @@ db/bak/
|
||||||
docker/
|
docker/
|
||||||
educoder.sql
|
educoder.sql
|
||||||
redis_data/
|
redis_data/
|
||||||
Dockerfile
|
|
||||||
dump.rdb
|
dump.rdb
|
||||||
.tags*
|
.tags*
|
||||||
ceshi_user.xlsx
|
ceshi_user.xlsx
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
FROM ubuntu:18.04
|
||||||
|
|
||||||
|
RUN apt update
|
||||||
|
|
||||||
|
RUN apt install -y openssl libssl-dev imagemagick git ruby-dev nodejs libmariadb-dev libmysqlclient-dev shared-mime-info libpq-dev libxml2-dev libxslt-dev
|
||||||
|
RUN DEBIAN_FRONTEND="noninteractive" apt -y install tzdata
|
||||||
|
RUN ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||||
|
|
||||||
|
WORKDIR /home/app/gitlink
|
||||||
|
|
||||||
|
ADD ./ /home/app/gitlink
|
||||||
|
|
||||||
|
RUN gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
|
||||||
|
|
||||||
|
RUN gem update --system
|
||||||
|
|
||||||
|
RUN gem install bundler
|
||||||
|
RUN gem install rake
|
||||||
|
|
||||||
|
RUN rm -rf Gemfile.lock
|
||||||
|
|
||||||
|
#RUN cp config/configuration.yml.example config/configuration.yml
|
||||||
|
#RUN cp config/database.yml.example config/database.yml
|
||||||
|
#RUN touch config/redis.yml
|
||||||
|
#RUN touch config/elasticsearch.yml
|
||||||
|
|
||||||
|
RUN bundle install
|
||||||
|
|
||||||
|
EXPOSE 4000
|
||||||
|
RUN rails s -p 4000 -b '0.0.0.0'
|
||||||
|
|
||||||
|
|
||||||
|
|
9
Gemfile
9
Gemfile
|
@ -1,4 +1,5 @@
|
||||||
source 'https://gems.ruby-china.com'
|
#source 'https://gems.ruby-china.com'
|
||||||
|
source 'https://mirrors.cloud.tencent.com/rubygems/'
|
||||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||||
|
|
||||||
gem 'rails', '~> 5.2.0'
|
gem 'rails', '~> 5.2.0'
|
||||||
|
@ -98,9 +99,9 @@ gem 'font-awesome-sass', '4.7.0'
|
||||||
gem 'rails-i18n', '~> 5.1'
|
gem 'rails-i18n', '~> 5.1'
|
||||||
|
|
||||||
# job
|
# job
|
||||||
gem 'sidekiq'
|
gem 'sidekiq',"5.2.8"
|
||||||
gem 'sinatra'
|
gem 'sinatra'
|
||||||
gem "sidekiq-cron", "~> 1.1"
|
gem "sidekiq-cron", "1.2.0"
|
||||||
|
|
||||||
# batch insert
|
# batch insert
|
||||||
gem 'bulk_insert'
|
gem 'bulk_insert'
|
||||||
|
@ -139,4 +140,4 @@ gem 'doorkeeper'
|
||||||
|
|
||||||
gem 'doorkeeper-jwt'
|
gem 'doorkeeper-jwt'
|
||||||
|
|
||||||
gem 'gitea-client', '~> 0.11.1'
|
gem 'gitea-client', '~> 0.11.6'
|
24
Gemfile.lock
24
Gemfile.lock
|
@ -106,6 +106,8 @@ GEM
|
||||||
activerecord (>= 3.1.0, < 7)
|
activerecord (>= 3.1.0, < 7)
|
||||||
diff-lcs (1.3)
|
diff-lcs (1.3)
|
||||||
diffy (3.3.0)
|
diffy (3.3.0)
|
||||||
|
domain_name (0.5.20190701)
|
||||||
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
doorkeeper (5.5.1)
|
doorkeeper (5.5.1)
|
||||||
railties (>= 5)
|
railties (>= 5)
|
||||||
doorkeeper-jwt (0.4.1)
|
doorkeeper-jwt (0.4.1)
|
||||||
|
@ -133,6 +135,8 @@ GEM
|
||||||
fugit (1.4.1)
|
fugit (1.4.1)
|
||||||
et-orbi (~> 1.1, >= 1.1.8)
|
et-orbi (~> 1.1, >= 1.1.8)
|
||||||
raabro (~> 1.4)
|
raabro (~> 1.4)
|
||||||
|
gitea-client (0.10.5)
|
||||||
|
rest-client (~> 2.1.0)
|
||||||
globalid (0.4.2)
|
globalid (0.4.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
grape-entity (0.7.1)
|
grape-entity (0.7.1)
|
||||||
|
@ -143,6 +147,9 @@ GEM
|
||||||
harmonious_dictionary (0.0.1)
|
harmonious_dictionary (0.0.1)
|
||||||
hashie (3.6.0)
|
hashie (3.6.0)
|
||||||
htmlentities (4.3.4)
|
htmlentities (4.3.4)
|
||||||
|
http-accept (1.7.0)
|
||||||
|
http-cookie (1.0.5)
|
||||||
|
domain_name (~> 0.5)
|
||||||
i18n (1.8.2)
|
i18n (1.8.2)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
io-like (0.3.1)
|
io-like (0.3.1)
|
||||||
|
@ -180,6 +187,9 @@ GEM
|
||||||
mimemagic (~> 0.3.2)
|
mimemagic (~> 0.3.2)
|
||||||
maruku (0.7.3)
|
maruku (0.7.3)
|
||||||
method_source (0.9.2)
|
method_source (0.9.2)
|
||||||
|
mime-types (3.4.1)
|
||||||
|
mime-types-data (~> 3.2015)
|
||||||
|
mime-types-data (3.2022.0105)
|
||||||
mimemagic (0.3.10)
|
mimemagic (0.3.10)
|
||||||
nokogiri (~> 1)
|
nokogiri (~> 1)
|
||||||
rake
|
rake
|
||||||
|
@ -193,6 +203,7 @@ GEM
|
||||||
mustermann (1.1.1)
|
mustermann (1.1.1)
|
||||||
ruby2_keywords (~> 0.0.1)
|
ruby2_keywords (~> 0.0.1)
|
||||||
mysql2 (0.5.3)
|
mysql2 (0.5.3)
|
||||||
|
netrc (0.11.0)
|
||||||
nio4r (2.5.2)
|
nio4r (2.5.2)
|
||||||
nokogiri (1.10.8)
|
nokogiri (1.10.8)
|
||||||
mini_portile2 (~> 2.4.0)
|
mini_portile2 (~> 2.4.0)
|
||||||
|
@ -292,6 +303,11 @@ GEM
|
||||||
regexp_parser (1.7.0)
|
regexp_parser (1.7.0)
|
||||||
request_store (1.5.0)
|
request_store (1.5.0)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
|
rest-client (2.1.0)
|
||||||
|
http-accept (>= 1.7.0, < 2.0)
|
||||||
|
http-cookie (>= 1.0.2, < 2.0)
|
||||||
|
mime-types (>= 1.16, < 4.0)
|
||||||
|
netrc (~> 0.8)
|
||||||
reverse_markdown (1.4.0)
|
reverse_markdown (1.4.0)
|
||||||
nokogiri
|
nokogiri
|
||||||
roo (2.8.3)
|
roo (2.8.3)
|
||||||
|
@ -418,6 +434,9 @@ GEM
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (4.2.0)
|
uglifier (4.2.0)
|
||||||
execjs (>= 0.3.0, < 3)
|
execjs (>= 0.3.0, < 3)
|
||||||
|
unf (0.1.4)
|
||||||
|
unf_ext
|
||||||
|
unf_ext (0.0.8.2)
|
||||||
unicode-display_width (1.6.1)
|
unicode-display_width (1.6.1)
|
||||||
web-console (3.7.0)
|
web-console (3.7.0)
|
||||||
actionview (>= 5.0)
|
actionview (>= 5.0)
|
||||||
|
@ -459,6 +478,7 @@ DEPENDENCIES
|
||||||
enumerize
|
enumerize
|
||||||
faraday (~> 0.15.4)
|
faraday (~> 0.15.4)
|
||||||
font-awesome-sass (= 4.7.0)
|
font-awesome-sass (= 4.7.0)
|
||||||
|
gitea-client (~> 0.10.2)
|
||||||
grape-entity (~> 0.7.1)
|
grape-entity (~> 0.7.1)
|
||||||
groupdate (~> 4.1.0)
|
groupdate (~> 4.1.0)
|
||||||
harmonious_dictionary (~> 0.0.1)
|
harmonious_dictionary (~> 0.0.1)
|
||||||
|
@ -496,8 +516,8 @@ DEPENDENCIES
|
||||||
sass-rails (~> 5.0)
|
sass-rails (~> 5.0)
|
||||||
searchkick
|
searchkick
|
||||||
selenium-webdriver
|
selenium-webdriver
|
||||||
sidekiq
|
sidekiq (= 5.2.8)
|
||||||
sidekiq-cron (~> 1.1)
|
sidekiq-cron (= 1.2.0)
|
||||||
simple_form
|
simple_form
|
||||||
simple_xlsx_reader
|
simple_xlsx_reader
|
||||||
sinatra
|
sinatra
|
||||||
|
|
92
README.md
92
README.md
|
@ -9,7 +9,7 @@ GitLink(确实开源)是中国计算机学会(CCF)官方指定的开源
|
||||||
|
|
||||||
- **分布式协作开发**:基于Git打造分布式代码托管环境,提供免费公、私有代码仓库,支持在线文件编辑、代码分支管理、协作贡献统计、代码仓库复刻(Fork)、贡献合并请求(PR)、群智贡献审阅等功能,让您的项目在这里健康、快速的成长!
|
- **分布式协作开发**:基于Git打造分布式代码托管环境,提供免费公、私有代码仓库,支持在线文件编辑、代码分支管理、协作贡献统计、代码仓库复刻(Fork)、贡献合并请求(PR)、群智贡献审阅等功能,让您的项目在这里健康、快速的成长!
|
||||||
|
|
||||||
- **一站式过程管理**:提供易修(Issue)、里程碑、通知提醒、标签归档等多样化任务管理工具,支持各类开发任务的发布、指派与跟踪,同时提供在线Wiki文档、组织多粒度管理等功能,为您搭建一站式的项目过程管理环境,让您的团队协作更高效、过程更透明!
|
- **一站式过程管理**:提供疑修(Issue)、里程碑、通知提醒、标签归档等多样化任务管理工具,支持各类开发任务的发布、指派与跟踪,同时提供在线Wiki文档、组织多粒度管理等功能,为您搭建一站式的项目过程管理环境,让您的团队协作更高效、过程更透明!
|
||||||
|
|
||||||
- **高效流水线运维**:融合DevOps思想,提供轻量级的工作流引擎(Engine),打通编码、测试、构建、部署等开发运维环节;支持自定义配置、代码静态扫描、构建自动触发、容器镜像托管等功能,同时支持接入第三方运维工具,让您的代码更加快速、可靠地形成高质量的产品!
|
- **高效流水线运维**:融合DevOps思想,提供轻量级的工作流引擎(Engine),打通编码、测试、构建、部署等开发运维环节;支持自定义配置、代码静态扫描、构建自动触发、容器镜像托管等功能,同时支持接入第三方运维工具,让您的代码更加快速、可靠地形成高质量的产品!
|
||||||
|
|
||||||
|
@ -34,18 +34,52 @@ GitLink(确实开源)是中国计算机学会(CCF)官方指定的开源
|
||||||
* imagemagick
|
* imagemagick
|
||||||
|
|
||||||
### 步骤
|
### 步骤
|
||||||
|
(1)安装 Rails 必要的一些三方库:
|
||||||
(1)克隆稳定版本
|
- Mac OS X
|
||||||
|
```bash
|
||||||
|
brew install imagemagick ghostscript libxml2 libxslt libiconv
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Ubuntu
|
||||||
|
```bash
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y openssl libssl-dev imagemagick git ruby-dev nodejs libmariadb-dev libmysqlclient-dev shared-mime-info libpq-dev libxml2-dev libxslt-dev
|
||||||
|
sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y tzdata
|
||||||
|
sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||||
|
```
|
||||||
|
|
||||||
|
(2)安装 Ruby, Rails 运行环境:[如何快速正确的安装 Ruby, Rails 运行环境](https://ruby-china.org/wiki/install_ruby_guide)
|
||||||
|
```bash
|
||||||
|
#检验环境是否正确
|
||||||
|
ruby -v
|
||||||
|
#ruby 2.4.x ...
|
||||||
|
|
||||||
|
gem -v
|
||||||
|
#3.x.x
|
||||||
|
|
||||||
|
bundle -v
|
||||||
|
#Bundler version 2.x.x
|
||||||
|
|
||||||
|
rails -v
|
||||||
|
#Rails 5.2.x
|
||||||
|
```
|
||||||
|
|
||||||
|
(3)克隆稳定版本
|
||||||
|
```bash
|
||||||
git clone -b master https://gitlink.org.cn/Gitlink/forgeplus.git
|
git clone -b master https://gitlink.org.cn/Gitlink/forgeplus.git
|
||||||
```
|
```
|
||||||
|
|
||||||
(2)安装依赖包
|
(4)安装依赖包
|
||||||
```bash
|
```bash
|
||||||
cd forgeplus && bundle install
|
#进入目录
|
||||||
|
cd forgeplus
|
||||||
|
#删除Gemfile.lock
|
||||||
|
rm -rf Gemfile.lock
|
||||||
|
#安装依赖包
|
||||||
|
bundle install
|
||||||
```
|
```
|
||||||
|
|
||||||
(3)配置初始化文件:进入项目根目录执行以下命令
|
(5)配置初始化文件:进入项目根目录执行以下命令
|
||||||
```bash
|
```bash
|
||||||
cp config/configuration.yml.example config/configuration.yml
|
cp config/configuration.yml.example config/configuration.yml
|
||||||
cp config/database.yml.example config/database.yml
|
cp config/database.yml.example config/database.yml
|
||||||
|
@ -53,8 +87,8 @@ touch config/redis.yml
|
||||||
touch config/elasticsearch.yml
|
touch config/elasticsearch.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
(4)配置数据库:数据库配置信息请查看/config/database.yml文件,项目默认采用mysql数据库, 如需更改,请自行修改配置信息,默认配置如下
|
(6)配置数据库:数据库配置信息请查看/config/database.yml文件,项目默认采用mysql数据库, 如需更改,请自行修改配置信息,默认配置如下
|
||||||
```bash
|
```yaml
|
||||||
default: &default
|
default: &default
|
||||||
adapter: mysql2
|
adapter: mysql2
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
|
@ -63,7 +97,7 @@ default: &default
|
||||||
password: 123456
|
password: 123456
|
||||||
```
|
```
|
||||||
|
|
||||||
(5)配置gitea服务(可选):如需要部署自己的gitea平台,请参考[gitea官方平台文档](https://docs.gitea.io/zh-cn/install-from-binary/)。因目前gitea平台api受限,暂时推荐从forge平台获取[gitea部署文件](https://www.gitlink.org.cn/Gitlink/gitea-binary)进行部署
|
(7)配置gitea服务(可选):如需要部署自己的gitea平台,请参考[gitea官方平台文档](https://docs.gitea.io/zh-cn/install-from-binary/)。因目前gitea平台api受限,暂时推荐从forge平台获取[gitea部署文件](https://www.gitlink.org.cn/Gitlink/gitea-binary)进行部署
|
||||||
|
|
||||||
- 配置gitea服务步骤:
|
- 配置gitea服务步骤:
|
||||||
|
|
||||||
|
@ -71,7 +105,7 @@ default: &default
|
||||||
|
|
||||||
-- 修改forge平台的 config/configuration.yml中的gitea服务指向地址,如:
|
-- 修改forge平台的 config/configuration.yml中的gitea服务指向地址,如:
|
||||||
|
|
||||||
```ruby
|
```yaml
|
||||||
gitea:
|
gitea:
|
||||||
access_key_id: 'root'
|
access_key_id: 'root'
|
||||||
access_key_secret: 'password'
|
access_key_secret: 'password'
|
||||||
|
@ -79,61 +113,59 @@ gitea:
|
||||||
base_url: '/api/v1'
|
base_url: '/api/v1'
|
||||||
```
|
```
|
||||||
|
|
||||||
(6)安装redis环境:请自行搜索各平台如何安装部署redis环境
|
(8)配置/config/database.yml文件(安装redis环境:请自行搜索各平台如何安装部署redis环境)
|
||||||
|
```yaml
|
||||||
|
default: &default
|
||||||
|
url: redis://localhost:6379
|
||||||
|
db: 1
|
||||||
|
|
||||||
(7)安装imagemagick插件:
|
production:
|
||||||
- Mac OS X
|
<<: *default
|
||||||
```bash
|
url: redis://localhost:6379
|
||||||
brew install imagemagick ghostscript
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- Linux
|
(9)创建数据库:开发环境为development, 生成环境为production
|
||||||
```bash
|
|
||||||
sudo apt-get install -y imagemagick
|
|
||||||
```
|
|
||||||
|
|
||||||
(8)创建数据库:开发环境为development, 生成环境为production
|
|
||||||
```bash
|
```bash
|
||||||
rails db:create RAILS_ENV=development
|
rails db:create RAILS_ENV=development
|
||||||
```
|
```
|
||||||
|
|
||||||
(9)导入数据表结构
|
(10)导入数据表结构
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bundle exec rake sync_table_structure:import_csv
|
bundle exec rake sync_table_structure:import_csv
|
||||||
```
|
```
|
||||||
|
|
||||||
(10)执行migrate迁移文件:开发环境为development, 生成环境为production
|
(11)执行migrate迁移文件:开发环境为development, 生成环境为production
|
||||||
```bash
|
```bash
|
||||||
rails db:migrate RAILS_ENV=development
|
rails db:migrate RAILS_ENV=development
|
||||||
```
|
```
|
||||||
|
|
||||||
(11)clone前端代码:将前端代码克隆到public/react目录下,目录结构应该是: public/react/build
|
(12)clone前端代码:将前端代码克隆到public/react目录下,目录结构应该是: public/react/build
|
||||||
```bash
|
```bash
|
||||||
git clone -b standalone https://gitlink.org.cn/Gitlink/build.git
|
git clone -b master https://gitlink.org.cn/Gitlink/build.git
|
||||||
```
|
```
|
||||||
|
|
||||||
(12)启动redis(此处以macOS系统为例)
|
(13)启动redis(此处以macOS系统为例)
|
||||||
```bash
|
```bash
|
||||||
redis-server&
|
redis-server&
|
||||||
```
|
```
|
||||||
|
|
||||||
(13)启动sidekiq:开发环境为development, 生成环境为production
|
(14)启动sidekiq:开发环境为development, 生成环境为production
|
||||||
```bash
|
```bash
|
||||||
bundle exec sidekiq -C config/sidekiq.yml -e production -d
|
bundle exec sidekiq -C config/sidekiq.yml -e production -d
|
||||||
```
|
```
|
||||||
|
|
||||||
(14)启动rails服务
|
(15)启动rails服务
|
||||||
```bash
|
```bash
|
||||||
rails s
|
rails s
|
||||||
```
|
```
|
||||||
|
|
||||||
(15)浏览器访问:在浏览器中输入如下地址访问
|
(16)浏览器访问:在浏览器中输入如下地址访问
|
||||||
```bash
|
```bash
|
||||||
http://localhost:3000/
|
http://localhost:3000/
|
||||||
```
|
```
|
||||||
|
|
||||||
(16)其他说明:通过页面注册以第一个用户为平台管理员用户
|
(17)其他说明:通过页面注册以第一个用户为平台管理员用户
|
||||||
|
|
||||||
|
|
||||||
## 页面展示
|
## 页面展示
|
||||||
|
|
|
@ -213,6 +213,7 @@ class AccountsController < ApplicationController
|
||||||
|
|
||||||
def change_password
|
def change_password
|
||||||
@user = User.find_by(login: params[:login])
|
@user = User.find_by(login: params[:login])
|
||||||
|
return render_error("此用户禁止修改密码!") if @user.id.to_i === 104691
|
||||||
return render_error("未找到相关用户!") if @user.blank?
|
return render_error("未找到相关用户!") if @user.blank?
|
||||||
return render_error("旧密码不正确") unless @user.check_password?(params[:old_password])
|
return render_error("旧密码不正确") unless @user.check_password?(params[:old_password])
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
class Admins::ProjectsRankController < Admins::BaseController
|
||||||
|
|
||||||
|
def index
|
||||||
|
@rank_date = rank_date
|
||||||
|
deleted_data = $redis_cache.smembers("v2-project-rank-deleted")
|
||||||
|
$redis_cache.zrem("v2-project-rank-#{rank_date}", deleted_data) unless deleted_data.blank?
|
||||||
|
@date_rank = $redis_cache.zrevrange("v2-project-rank-#{rank_date}", 0, -1, withscores: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def rank_date
|
||||||
|
params.fetch(:date, Date.today.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
class Admins::UsersRankController < Admins::BaseController
|
||||||
|
|
||||||
|
def index
|
||||||
|
@rank_date = rank_date
|
||||||
|
@date_rank = $redis_cache.zrevrange("v2-user-rank-#{rank_date}", 0, -1, withscores: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def rank_date
|
||||||
|
params.fetch(:date, Date.today.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
|
@ -1,16 +1,40 @@
|
||||||
class Api::V1::Projects::BranchesController < Api::V1::BaseController
|
class Api::V1::Projects::BranchesController < Api::V1::BaseController
|
||||||
before_action :require_public_and_member_above, only: [:all]
|
before_action :require_public_and_member_above, only: [:index, :all]
|
||||||
|
|
||||||
|
def index
|
||||||
|
@result_object = Api::V1::Projects::Branches::ListService.call(@project, {name: params[:keyword], page: page, limit: limit}, current_user&.gitea_token)
|
||||||
|
end
|
||||||
|
|
||||||
def all
|
def all
|
||||||
@result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
|
@result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
before_action :require_operate_above, only: [:create]
|
before_action :require_operate_above, only: [:create, :destroy]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
|
@result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@result_object = Api::V1::Projects::Branches::DeleteService.call(@project, params[:name], current_user&.gitea_token)
|
||||||
|
if @result_object
|
||||||
|
return render_ok
|
||||||
|
else
|
||||||
|
return render_error('删除分支失败!')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before_action :require_manager_above, only: [:update_default_branch]
|
||||||
|
|
||||||
|
def update_default_branch
|
||||||
|
@result_object = Api::V1::Projects::Branches::UpdateDefaultBranchService.call(@project, params[:name], current_user&.gitea_token)
|
||||||
|
if @result_object
|
||||||
|
return render_ok
|
||||||
|
else
|
||||||
|
return render_error('更新默认分支失败!')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def branch_params
|
def branch_params
|
||||||
params.require(:branch).permit(:new_branch_name, :old_branch_name)
|
params.require(:branch).permit(:new_branch_name, :old_branch_name)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
class Api::V1::Projects::TagsController < Api::V1::BaseController
|
||||||
|
before_action :require_public_and_member_above, only: [:index]
|
||||||
|
|
||||||
|
def index
|
||||||
|
@release_tags = @repository.version_releases.pluck(:tag_name)
|
||||||
|
@result_object = Api::V1::Projects::Tags::ListService.call(@project, {page: page, limit: limit}, current_user&.gitea_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
before_action :require_operate_above, only: [:destroy]
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@result_object = Api::V1::Projects::Tags::DeleteService.call(@project, params[:name], current_user&.gitea_token)
|
||||||
|
if @result_object
|
||||||
|
return render_ok
|
||||||
|
else
|
||||||
|
return render_error('删除标签失败!')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,6 @@
|
||||||
require 'oauth2'
|
require 'oauth2'
|
||||||
|
# require 'openssl'
|
||||||
|
# require 'jwt'
|
||||||
|
|
||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
include CodeExample
|
include CodeExample
|
||||||
|
@ -295,17 +297,24 @@ class ApplicationController < ActionController::Base
|
||||||
# Find the current user
|
# Find the current user
|
||||||
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
|
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
|
||||||
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
|
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
|
||||||
tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token?
|
if !valid_doorkeeper_token?
|
||||||
if @doorkeeper_token.present?
|
header = request.authorization
|
||||||
# client方法对接,需要一直带着用户标识uid
|
pattern = /^Bearer /i
|
||||||
if @doorkeeper_token.resource_owner_id.blank?
|
token = header.gsub(pattern, "")
|
||||||
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
|
User.current, message = Bot.decode_jwt_token(token)
|
||||||
User.current = User.find(params[:uid])
|
tip_exception(401, message) if message.present?
|
||||||
else
|
else
|
||||||
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
|
if @doorkeeper_token.present?
|
||||||
|
# client方法对接,需要一直带着用户标识uid
|
||||||
|
if @doorkeeper_token.resource_owner_id.blank?
|
||||||
|
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
|
||||||
|
User.current = User.find(params[:uid])
|
||||||
|
else
|
||||||
|
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
User.current = find_current_user
|
User.current = find_current_user
|
||||||
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
|
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ module Api::ProjectHelper
|
||||||
repo = params[:repo]
|
repo = params[:repo]
|
||||||
|
|
||||||
@project, @owner = Project.find_with_namespace(namespace, repo)
|
@project, @owner = Project.find_with_namespace(namespace, repo)
|
||||||
|
@repository = @project&.repository
|
||||||
|
|
||||||
if @project
|
if @project
|
||||||
logger.info "###########:project founded"
|
logger.info "###########:project founded"
|
||||||
@project
|
@project
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
class InstallationsController < ApplicationController
|
||||||
|
include RegisterHelper
|
||||||
|
before_action :require_login
|
||||||
|
|
||||||
|
def index
|
||||||
|
@install_bots = BotInstall.where(:installer_id => current_user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_secret
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
bot = Bot.find params[:id]
|
||||||
|
application = Doorkeeper::Application.find_by(uid: bot.client_id, secret: bot.client_secret)
|
||||||
|
bot.client_secret = Doorkeeper::OAuth::Helpers::UniqueToken.generate
|
||||||
|
bot.save!
|
||||||
|
application.secret = bot.client_secret
|
||||||
|
application.save!
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_private_key
|
||||||
|
bot = Bot.find params[:id]
|
||||||
|
bot.private_key = OpenSSL::PKey::RSA::generate(2048).to_s
|
||||||
|
bot.save!
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def auth_active
|
||||||
|
begin
|
||||||
|
@bot = Bot.find params[:id]
|
||||||
|
tip_exception("该Bot已激活") if Doorkeeper::Application.find_by(uid: @bot.client_id, secret: @bot.client_secret).present?
|
||||||
|
@bot.client_id = Doorkeeper::OAuth::Helpers::UniqueToken.generate if params[:client_id].blank?
|
||||||
|
@bot.client_secret = Doorkeeper::OAuth::Helpers::UniqueToken.generate if params[:client_secret].blank?
|
||||||
|
@bot.private_key = OpenSSL::PKey::RSA::generate(2048).to_s
|
||||||
|
@bot.owner_id = current_user.id
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
# 注册bot对应oauth应用
|
||||||
|
Doorkeeper::Application.create!(name: @bot.name, uid: @bot.client_id, secret: @bot.client_secret, redirect_uri: "https://gitlink.org.cn")
|
||||||
|
# 注册bot对应用户
|
||||||
|
result = autologin_register(User.generate_user_login('b'), nil, "#{SecureRandom.hex(6)}", 'bot', nickname: @bot.name)
|
||||||
|
tip_exception(-1, result[:message]) if result[:message].present?
|
||||||
|
@bot.uid = result[:user][:id]
|
||||||
|
@bot.save
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
tip_exception(-1, e.message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def access_tokens
|
||||||
|
@install_bot = BotInstall.find params[:id]
|
||||||
|
@bot = @install_bot.bot
|
||||||
|
@application = Doorkeeper::Application.find_by(uid: @bot.client_id, secret: @bot.client_secret)
|
||||||
|
tip_exception("该Bot未激活") if @application.blank?
|
||||||
|
# 给bot生成token,因为bot是机器人操作
|
||||||
|
@access_token = Doorkeeper::AccessToken.create!({ :application_id => @application.id,
|
||||||
|
:resource_owner_id => @bot.uid,
|
||||||
|
:scopes => "public write",
|
||||||
|
:expires_in => "604800",
|
||||||
|
:use_refresh_token => true
|
||||||
|
})
|
||||||
|
render_ok(token: @access_token.token)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -154,6 +154,8 @@ class IssuesController < ApplicationController
|
||||||
|
|
||||||
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||||
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
||||||
|
# 新增时向grimoirelab推送事件
|
||||||
|
IssueWebhookJob.set(wait: 5.seconds).perform_later(@issue.id)
|
||||||
|
|
||||||
render json: {status: 0, message: "创建成功", id: @issue.id}
|
render json: {status: 0, message: "创建成功", id: @issue.id}
|
||||||
else
|
else
|
||||||
|
|
|
@ -53,7 +53,7 @@ class ProjectsController < ApplicationController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
Projects::CreateForm.new(project_params).validate!
|
Projects::CreateForm.new(project_params).validate!
|
||||||
@project = Projects::CreateService.new(current_user, project_params).call
|
@project = Projects::CreateService.new(current_user, project_params).call
|
||||||
OpenProjectDevOpsJob.perform_later(@project&.id, current_user.id)
|
OpenProjectDevOpsJob.set(wait: 5.seconds).perform_later(@project&.id, current_user.id)
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
|
|
|
@ -213,5 +213,12 @@ module RepositoriesHelper
|
||||||
def tmp_dir
|
def tmp_dir
|
||||||
"repo"
|
"repo"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def repo_git_submodule_url(owner, repo, path)
|
||||||
|
unless (path.starts_with?('http://') || path.starts_with?('https://'))
|
||||||
|
path = File.expand_path(path, "/#{owner&.login}/#{repo&.identifier}")
|
||||||
|
end
|
||||||
|
|
||||||
|
return path
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
class IssueWebhookJob < ApplicationJob
|
||||||
|
include ApplicationHelper
|
||||||
|
queue_as :message
|
||||||
|
|
||||||
|
def perform(issue_id)
|
||||||
|
issue = Issue.find_by(id: issue_id)
|
||||||
|
return if issue.blank?
|
||||||
|
project = issue.project
|
||||||
|
user = issue.user
|
||||||
|
domain = "#{Rails.application.config_for(:configuration)['platform_url']}"
|
||||||
|
gitea_domain = GiteaService.gitea_config[:domain]
|
||||||
|
ssh_url = "git@#{gitea_domain.gsub("https://", "")}:#{project.owner.login}/#{project.identifier}.git"
|
||||||
|
event_json = {
|
||||||
|
"action": "opened",
|
||||||
|
"number": 1,
|
||||||
|
"issue": {
|
||||||
|
"id": issue.id,
|
||||||
|
"url": "#{domain}/api/v1/#{project.owner.login}/#{project.identifier}/issues/#{issue.id}",
|
||||||
|
"html_url": "#{domain}/#{project.owner.login}/#{project.identifier}/issues/#{issue.id}",
|
||||||
|
"number": 1,
|
||||||
|
"user": {
|
||||||
|
"id": user.id,
|
||||||
|
"login": "#{user.login}",
|
||||||
|
"full_name": "",
|
||||||
|
"email": "#{user.mail}",
|
||||||
|
"avatar_url": "#{domain}/#{url_to_avatar(user)}",
|
||||||
|
"language": "",
|
||||||
|
"is_admin": false,
|
||||||
|
"last_login": "#{user.last_login_on}",
|
||||||
|
"created": "#{user.created_on}",
|
||||||
|
"restricted": false,
|
||||||
|
"active": false,
|
||||||
|
"prohibit_login": false,
|
||||||
|
"location": "",
|
||||||
|
"website": "",
|
||||||
|
"description": "",
|
||||||
|
"visibility": "public",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "#{user.login}"
|
||||||
|
},
|
||||||
|
"original_author": "",
|
||||||
|
"original_author_id": 0,
|
||||||
|
"title": "#{issue.subject}",
|
||||||
|
"body": "#{issue.description}",
|
||||||
|
"ref": "",
|
||||||
|
"labels": [],
|
||||||
|
"milestone": nil,
|
||||||
|
"assignee": nil,
|
||||||
|
"assignees": nil,
|
||||||
|
"state": "open",
|
||||||
|
"is_locked": false,
|
||||||
|
"comments": 0,
|
||||||
|
"created_at": "#{issue.created_on}",
|
||||||
|
"updated_at": "#{issue.updated_on}",
|
||||||
|
"closed_at": nil,
|
||||||
|
"due_date": nil,
|
||||||
|
"pull_request": nil,
|
||||||
|
"repository": {
|
||||||
|
"id": 11307,
|
||||||
|
"name": "#{project.identifier}",
|
||||||
|
"owner": "#{project.owner.login}",
|
||||||
|
"full_name": "#{project.owner.login}/#{project.identifier}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"id": project.id,
|
||||||
|
"owner": {
|
||||||
|
"id": project.owner.id,
|
||||||
|
"login": "#{project.owner.login}",
|
||||||
|
"full_name": "",
|
||||||
|
"email": "#{project.owner.mail}",
|
||||||
|
"avatar_url": "#{domain}/#{url_to_avatar(project.owner)}",
|
||||||
|
"language": "",
|
||||||
|
"is_admin": false,
|
||||||
|
"last_login": "#{project.owner.last_login_on}",
|
||||||
|
"created": "#{project.owner.created_on}",
|
||||||
|
"restricted": false,
|
||||||
|
"active": false,
|
||||||
|
"prohibit_login": false,
|
||||||
|
"location": "",
|
||||||
|
"website": "",
|
||||||
|
"description": "",
|
||||||
|
"visibility": "public",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "#{project.owner.login}"
|
||||||
|
},
|
||||||
|
"name": "#{project.identifier}",
|
||||||
|
"full_name": "#{project.owner.login}/#{project.identifier}",
|
||||||
|
"description": "",
|
||||||
|
"empty": false,
|
||||||
|
"private": false,
|
||||||
|
"fork": false,
|
||||||
|
"template": false,
|
||||||
|
"parent": nil,
|
||||||
|
"mirror": false,
|
||||||
|
"size": 843,
|
||||||
|
"html_url": "#{domain}/#{project.owner.login}/#{project.identifier}",
|
||||||
|
"ssh_url": "#{ssh_url}",
|
||||||
|
"clone_url": "#{domain}/#{project.owner.login}/#{project.identifier}.git",
|
||||||
|
"original_url": "#{project.repository.mirror_url}",
|
||||||
|
"website": "",
|
||||||
|
"stars_count": 0,
|
||||||
|
"forks_count": 0,
|
||||||
|
"watchers_count": 1,
|
||||||
|
"open_issues_count": 1,
|
||||||
|
"open_pr_counter": 0,
|
||||||
|
"release_counter": 0,
|
||||||
|
"default_branch": "master",
|
||||||
|
"archived": false,
|
||||||
|
"created_at": "#{project.created_on}",
|
||||||
|
"updated_at": "#{project.updated_on}",
|
||||||
|
"permissions": {
|
||||||
|
"admin": true,
|
||||||
|
"push": true,
|
||||||
|
"pull": true
|
||||||
|
},
|
||||||
|
"has_issues": true,
|
||||||
|
"internal_tracker": {
|
||||||
|
"enable_time_tracker": true,
|
||||||
|
"allow_only_contributors_to_track_time": true,
|
||||||
|
"enable_issue_dependencies": true
|
||||||
|
},
|
||||||
|
"has_wiki": true,
|
||||||
|
"has_pull_requests": true,
|
||||||
|
"has_projects": false,
|
||||||
|
"ignore_whitespace_conflicts": false,
|
||||||
|
"allow_merge_commits": true,
|
||||||
|
"allow_rebase": true,
|
||||||
|
"allow_rebase_explicit": true,
|
||||||
|
"allow_squash_merge": true,
|
||||||
|
"default_merge_style": "merge",
|
||||||
|
"avatar_url": "",
|
||||||
|
"internal": false,
|
||||||
|
"mirror_interval": ""
|
||||||
|
},
|
||||||
|
"sender": {
|
||||||
|
"id": user.id,
|
||||||
|
"login": "#{user.login}",
|
||||||
|
"full_name": "",
|
||||||
|
"email": "#{user.mail}",
|
||||||
|
"avatar_url": "#{domain}/#{url_to_avatar(user)}",
|
||||||
|
"language": "",
|
||||||
|
"is_admin": false,
|
||||||
|
"last_login": "#{user.last_login_on}",
|
||||||
|
"created": "#{user.created_on}",
|
||||||
|
"restricted": false,
|
||||||
|
"active": false,
|
||||||
|
"prohibit_login": false,
|
||||||
|
"location": "",
|
||||||
|
"website": "",
|
||||||
|
"description": "",
|
||||||
|
"visibility": "public",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "#{user.login}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# puts "event_json:#{event_json.to_json}"
|
||||||
|
begin
|
||||||
|
url = URI("http://117.50.185.50:80")
|
||||||
|
http = Net::HTTP.new(url.host, url.port)
|
||||||
|
request = Net::HTTP::Post.new(url)
|
||||||
|
request["Content-Type"] = "application/json"
|
||||||
|
uuid = SecureRandom.uuid
|
||||||
|
request['X-GitHub-Delivery'] = uuid
|
||||||
|
request['X-Gitea-Delivery'] = uuid
|
||||||
|
request['X-Gogs-Delivery'] = uuid
|
||||||
|
request['X-GitHub-Event'] = 'issues'
|
||||||
|
request['X-Gitea-Event'] = 'issues'
|
||||||
|
request['X-Gogs-Event'] = 'issues'
|
||||||
|
request.body = JSON.dump(event_json)
|
||||||
|
|
||||||
|
response = http.request(request)
|
||||||
|
Rails.logger.info "issue #{issue_id} webhook event======#{response.read_body}"
|
||||||
|
rescue Exception => e
|
||||||
|
Rails.logger.info "issue #{issue_id} webhook event error======#{e.message}"
|
||||||
|
puts "issue: #{issue_id} webhook event error======#{e.message}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -15,7 +15,7 @@ class MigrateRemoteRepositoryJob < ApplicationJob
|
||||||
## open jianmu devops
|
## open jianmu devops
|
||||||
project_id = repo&.project&.id
|
project_id = repo&.project&.id
|
||||||
puts "############ mirror project_id,user_id: #{project_id},#{user_id} ############"
|
puts "############ mirror project_id,user_id: #{project_id},#{user_id} ############"
|
||||||
OpenProjectDevOpsJob.perform_later(project_id, user_id) if project_id.present? && user_id.present?
|
OpenProjectDevOpsJob.set(wait: 5.seconds).perform_later(project_id, user_id) if project_id.present? && user_id.present?
|
||||||
puts "############ mirror status: #{repo.mirror.status} ############"
|
puts "############ mirror status: #{repo.mirror.status} ############"
|
||||||
else
|
else
|
||||||
repo&.mirror&.failed!
|
repo&.mirror&.failed!
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: bot
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# bot_name :string(255)
|
||||||
|
# bot_des :text(4294967295)
|
||||||
|
# webhook :string(255)
|
||||||
|
# is_public :integer
|
||||||
|
# logo :string(255)
|
||||||
|
# state :integer
|
||||||
|
# client_id :string(255)
|
||||||
|
# client_secret :string(255)
|
||||||
|
# web_url :string(255)
|
||||||
|
# category :string(255)
|
||||||
|
# install_num :integer default("0")
|
||||||
|
# update_time :datetime not null
|
||||||
|
# create_time :datetime not null
|
||||||
|
# private_key :text(65535)
|
||||||
|
# uid :integer
|
||||||
|
# owner_id :integer
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# name (bot_name) UNIQUE
|
||||||
|
#
|
||||||
|
|
||||||
|
class Bot < ApplicationRecord
|
||||||
|
self.table_name = "bot"
|
||||||
|
|
||||||
|
has_many :install_bots
|
||||||
|
|
||||||
|
def name
|
||||||
|
self.bot_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.decode_jwt_token(token)
|
||||||
|
decoded_token = JWT.decode token, nil, false
|
||||||
|
return [nil, "Token已过期"] if Time.now.to_i - 60 - decoded_token[0]["exp"].to_i > 0
|
||||||
|
bot = Bot.find_by(id: decoded_token[0]["iss"])
|
||||||
|
return [nil, "Token不存在"] if bot.blank?
|
||||||
|
rsa_private = OpenSSL::PKey::RSA.new(bot.private_key)
|
||||||
|
rsa_public = rsa_private.public_key
|
||||||
|
JWT.decode token, rsa_public, true, { algorithm: 'RS256' }
|
||||||
|
[User.find_by(id: bot.owner_id), ""]
|
||||||
|
rescue JWT::DecodeError
|
||||||
|
Rails.logger.error "jwt token decode error:#{token}"
|
||||||
|
[nil, "无效Token"]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,20 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: install_bot
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# bot_id :integer not null
|
||||||
|
# installer_id :integer not null
|
||||||
|
# store_id :integer not null
|
||||||
|
# state :integer not null
|
||||||
|
# create_time :datetime not null
|
||||||
|
# update_time :datetime not null
|
||||||
|
#
|
||||||
|
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class BotInstall < ApplicationRecord
|
||||||
|
self.table_name = "install_bot"
|
||||||
|
belongs_to :bot
|
||||||
|
|
||||||
|
end
|
|
@ -188,7 +188,7 @@ class Project < ApplicationRecord
|
||||||
forked_project = self.forked_from_project
|
forked_project = self.forked_from_project
|
||||||
if forked_project.present?
|
if forked_project.present?
|
||||||
forked_project.decrement(:forked_count, 1)
|
forked_project.decrement(:forked_count, 1)
|
||||||
forked_project.update_column(:forked_count, forked_project.forked_count)
|
forked_project.update_attribute(:forked_count, forked_project.forked_count)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ class User < Owner
|
||||||
# trustie: 来自Trustie平台
|
# trustie: 来自Trustie平台
|
||||||
# forge: 平台本身注册的用户
|
# forge: 平台本身注册的用户
|
||||||
# military: 军科的用户
|
# military: 军科的用户
|
||||||
enumerize :platform, in: [:forge, :educoder, :trustie, :military, :github, :gitee, :qq, :wechat], default: :forge, scope: :shallow
|
enumerize :platform, in: [:forge, :educoder, :trustie, :military, :github, :gitee, :qq, :wechat, :bot], default: :forge, scope: :shallow
|
||||||
|
|
||||||
belongs_to :laboratory, optional: true
|
belongs_to :laboratory, optional: true
|
||||||
has_one :user_extension, dependent: :destroy
|
has_one :user_extension, dependent: :destroy
|
||||||
|
|
|
@ -11,21 +11,19 @@ class Projects::ListQuery < ApplicationQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
collection = Project.visible
|
collection = main_collection
|
||||||
# 增加私有组织中项目过滤
|
|
||||||
collection = collection.joins("left join organization_extensions on organization_extensions.organization_id = projects.user_id")
|
|
||||||
.where("organization_extensions.visibility is null or organization_extensions.visibility in (0,1)")
|
|
||||||
.where("projects.user_id > 0")
|
|
||||||
collection = filter_projects(collection)
|
collection = filter_projects(collection)
|
||||||
|
|
||||||
sort = params[:sort_by] || "updated_on"
|
sort = params[:sort_by] || "updated_on"
|
||||||
sort_direction = params[:sort_direction] || "desc"
|
sort_direction = params[:sort_direction] || "desc"
|
||||||
|
|
||||||
collection = optimize_sorting(collection, sort) if params[:category_id].present?
|
collection = optimize_sorting(collection, sort) if params[:category_id].present?
|
||||||
custom_sort(collection, sort, sort_direction)
|
# 如果有搜索关键字根据ES搜索结果排序
|
||||||
|
if params[:search].present? && @ids.present?
|
||||||
# scope = scope.reorder("projects.#{sort} #{sort_direction}")
|
collection.reorder(Arel.sql("FIELD(projects.id,#{@ids.join(',')})"))
|
||||||
# scope
|
else
|
||||||
|
custom_sort(collection, sort, sort_direction)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_projects(collection)
|
def filter_projects(collection)
|
||||||
|
@ -37,15 +35,25 @@ class Projects::ListQuery < ApplicationQuery
|
||||||
collection
|
collection
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def main_collection
|
||||||
|
collection = Project.visible
|
||||||
|
# 增加私有组织中项目过滤
|
||||||
|
collection = collection.joins("left join organization_extensions on organization_extensions.organization_id = projects.user_id")
|
||||||
|
.where("organization_extensions.visibility is null or organization_extensions.visibility in (0,1)")
|
||||||
|
.where("projects.user_id > 0")
|
||||||
|
collection
|
||||||
|
end
|
||||||
|
|
||||||
def by_search(items)
|
def by_search(items)
|
||||||
ids = Projects::ElasticsearchService.call(params[:search])
|
@ids = Projects::ElasticsearchService.call(params[:search])
|
||||||
items = items.where(platform: 'forge')
|
items = items.where(platform: 'forge')
|
||||||
if ids.present?
|
if @ids.present?
|
||||||
items = items.where(id: ids).by_name_or_identifier(params[:search])
|
# items = items.where(id: @ids).by_name_or_identifier(params[:search])
|
||||||
|
items = items.where(id: @ids)
|
||||||
else
|
else
|
||||||
items = items.by_name_or_identifier(params[:search])
|
items = items.by_name_or_identifier(params[:search]).or(main_collection.where(user_id: Owner.like(params[:search]).pluck(:id)))
|
||||||
end
|
end
|
||||||
items.or(items.where(user_id: Owner.like(params[:search]).pluck(:id)))
|
items
|
||||||
end
|
end
|
||||||
|
|
||||||
def by_project_type(items)
|
def by_project_type(items)
|
||||||
|
@ -78,5 +86,14 @@ class Projects::ListQuery < ApplicationQuery
|
||||||
relations
|
relations
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def by_recommend(items)
|
||||||
|
params[:recommend].to_s == "true" ? items.where(recommend: true) : items
|
||||||
|
end
|
||||||
|
|
||||||
|
def exclude_fork(items)
|
||||||
|
return items if params[:exclude_forked].blank?
|
||||||
|
params[:exclude_forked].to_s == "true" ? items.where("forked_from_project_id is null") : items.where("forked_from_project_id is not null")
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Api::V1::Projects::Branches::CreateService < ApplicationService
|
||||||
def call
|
def call
|
||||||
raise Error, errors.full_messages.join(",") unless valid?
|
raise Error, errors.full_messages.join(",") unless valid?
|
||||||
|
|
||||||
check_new_branch_exist
|
check_branch_exist
|
||||||
excute_data_to_gitea
|
excute_data_to_gitea
|
||||||
|
|
||||||
gitea_data
|
gitea_data
|
||||||
|
@ -43,9 +43,10 @@ class Api::V1::Projects::Branches::CreateService < ApplicationService
|
||||||
raise Error, '创建分支失败!' unless @gitea_data.is_a?(Hash)
|
raise Error, '创建分支失败!' unless @gitea_data.is_a?(Hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_new_branch_exist
|
def check_branch_exist
|
||||||
result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||||
raise Error, '查询分支名称失败!' unless result.is_a?(Hash)
|
raise Error, '查询分支名称失败!' unless result.is_a?(Hash)
|
||||||
raise Error, '分支已存在!' if result['branch_name'].include?(@new_branch_name)
|
raise Error, '旧分支不存在!' if !result['branch_name'].include?(@old_branch_name)
|
||||||
|
raise Error, '新分支已存在!' if result['branch_name'].include?(@new_branch_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,47 @@
|
||||||
|
class Api::V1::Projects::Branches::DeleteService < ApplicationService
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :project, :token, :owner, :repo, :branch_name
|
||||||
|
attr_accessor :gitea_data
|
||||||
|
|
||||||
|
validates :branch_name, presence: true
|
||||||
|
|
||||||
|
def initialize(project, branch_name, token=nil)
|
||||||
|
@project = project
|
||||||
|
@owner = project&.owner.login
|
||||||
|
@repo = project&.identifier
|
||||||
|
@branch_name = branch_name
|
||||||
|
@token = token
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
raise Error, errors.full_messages.join(",") unless valid?
|
||||||
|
|
||||||
|
check_branch_exist
|
||||||
|
excute_data_to_gitea
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
{
|
||||||
|
access_token: token
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def excute_data_to_gitea
|
||||||
|
begin
|
||||||
|
@gitea_data = $gitea_client.delete_repos_branches_by_owner_repo_branch(owner, repo, branch_name, {query: request_params})
|
||||||
|
rescue => e
|
||||||
|
raise Error, '保护分支无法删除!' if e.to_s.include?("branch protected")
|
||||||
|
raise Error, '删除分支失败!'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_branch_exist
|
||||||
|
result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||||
|
raise Error, '查询分支名称失败!' unless result.is_a?(Hash)
|
||||||
|
raise Error, '分支不存在!' if !result['branch_name'].include?(@branch_name)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,40 @@
|
||||||
|
class Api::V1::Projects::Branches::ListService < ApplicationService
|
||||||
|
|
||||||
|
attr_accessor :project, :token, :owner, :repo, :name, :page, :limit
|
||||||
|
attr_accessor :gitea_data
|
||||||
|
|
||||||
|
def initialize(project, params, token=nil)
|
||||||
|
@project = project
|
||||||
|
@owner = project&.owner.login
|
||||||
|
@repo = project&.identifier
|
||||||
|
@token = token
|
||||||
|
@name = params[:name]
|
||||||
|
@page = params[:page]
|
||||||
|
@limit = params[:limit]
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
load_gitea_data
|
||||||
|
|
||||||
|
gitea_data
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
params = {
|
||||||
|
access_token: token,
|
||||||
|
page: page,
|
||||||
|
limit: limit
|
||||||
|
}
|
||||||
|
params.merge!({name: name}) if name.present?
|
||||||
|
|
||||||
|
params
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_gitea_data
|
||||||
|
puts request_params
|
||||||
|
@gitea_data = $gitea_client.get_repos_branches_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||||
|
puts @gitea_data
|
||||||
|
raise Error, '获取分支列表失败!' unless @gitea_data.is_a?(Hash)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,55 @@
|
||||||
|
class Api::V1::Projects::Branches::UpdateDefaultBranchService < ApplicationService
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :project, :token, :owner, :repo, :new_default_branch
|
||||||
|
attr_accessor :gitea_data
|
||||||
|
|
||||||
|
validates :new_default_branch, presence: true
|
||||||
|
|
||||||
|
def initialize(project, new_default_branch, token=nil)
|
||||||
|
@project = project
|
||||||
|
@owner = project&.owner.login
|
||||||
|
@repo = project&.identifier
|
||||||
|
@new_default_branch = new_default_branch
|
||||||
|
@token = token
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
raise Error, errors.full_messages.join(",") unless valid?
|
||||||
|
|
||||||
|
check_branch_exist
|
||||||
|
update_project
|
||||||
|
excute_data_to_gitea
|
||||||
|
|
||||||
|
gitea_data
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
{
|
||||||
|
access_token: token
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_body
|
||||||
|
{
|
||||||
|
default_branch: new_default_branch
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_project
|
||||||
|
@project.attributes = request_body
|
||||||
|
raise Error, '更新默认分支失败!' unless @project.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def excute_data_to_gitea
|
||||||
|
@gitea_data = $gitea_client.patch_repos_by_owner_repo(owner, repo, {body: request_body.to_json, query: request_params}) rescue nil
|
||||||
|
raise Error, '更新默认分支失败!' unless @gitea_data.is_a?(Hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_branch_exist
|
||||||
|
result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||||
|
raise Error, '查询分支名称失败!' unless result.is_a?(Hash)
|
||||||
|
raise Error, '新默认分支不存在!' if !result['branch_name'].include?(@new_default_branch)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,6 @@
|
||||||
class Api::V1::Projects::CodeStats::ListService < ApplicationService
|
class Api::V1::Projects::CodeStats::ListService < ApplicationService
|
||||||
|
|
||||||
attr_reader :project, :ref, :owner, :repo, :token
|
attr_reader :project, :ref, :owner, :repo, :token, :page, :limit
|
||||||
attr_accessor :gitea_data
|
attr_accessor :gitea_data
|
||||||
|
|
||||||
def initialize(project, params, token=nil)
|
def initialize(project, params, token=nil)
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
class Api::V1::Projects::Tags::DeleteService < ApplicationService
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :project, :token, :owner, :repo, :tag_name
|
||||||
|
attr_accessor :gitea_data
|
||||||
|
|
||||||
|
validates :tag_name, presence: true
|
||||||
|
|
||||||
|
def initialize(project, tag_name, token=nil)
|
||||||
|
@project = project
|
||||||
|
@owner = project&.owner.login
|
||||||
|
@repo = project&.identifier
|
||||||
|
@tag_name = tag_name
|
||||||
|
@token = token
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
raise Error, errors.full_messages.join(",") unless valid?
|
||||||
|
|
||||||
|
check_tag_exist
|
||||||
|
excute_data_to_gitea
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
{
|
||||||
|
access_token: token
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def excute_data_to_gitea
|
||||||
|
begin
|
||||||
|
@gitea_data = $gitea_client.delete_repos_tags_by_owner_repo_tag(owner, repo, tag_name, {query: request_params})
|
||||||
|
rescue => e
|
||||||
|
raise Error, '请先删除发行版!' if e.to_s.include?("409")
|
||||||
|
raise Error, '删除标签失败!'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_tag_exist
|
||||||
|
result = $gitea_client.get_repos_tag_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||||
|
raise Error, '查询标签名称失败!' unless result.is_a?(Array)
|
||||||
|
raise Error, '标签不存在!' if !result.include?(@tag_name)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,36 @@
|
||||||
|
class Api::V1::Projects::Tags::ListService < ApplicationService
|
||||||
|
|
||||||
|
attr_accessor :project, :token, :owner, :repo, :page, :limit
|
||||||
|
attr_accessor :gitea_data
|
||||||
|
|
||||||
|
def initialize(project, params, token=nil)
|
||||||
|
@project = project
|
||||||
|
@owner = project&.owner.login
|
||||||
|
@repo = project&.identifier
|
||||||
|
@token = token
|
||||||
|
@page = params[:page]
|
||||||
|
@limit = params[:limit]
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
load_gitea_data
|
||||||
|
|
||||||
|
gitea_data
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def request_params
|
||||||
|
params = {
|
||||||
|
access_token: token,
|
||||||
|
page: page,
|
||||||
|
limit: limit
|
||||||
|
}
|
||||||
|
|
||||||
|
params
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_gitea_data
|
||||||
|
@gitea_data = $gitea_client.get_repos_tags_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||||
|
raise Error, '获取标签列表失败!' unless @gitea_data.is_a?(Hash)
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,6 +18,7 @@ class Api::V1::Users::UpdateEmailService < ApplicationService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
|
raise Error, "此用户禁止修改邮箱." if @user.id.to_i === 104691
|
||||||
raise Error, errors.full_messages.join(",") unless valid?
|
raise Error, errors.full_messages.join(",") unless valid?
|
||||||
raise Error, "密码不正确." unless @user.check_password?(@password)
|
raise Error, "密码不正确." unless @user.check_password?(@password)
|
||||||
exist_owner = Owner.find_by(mail: @mail)
|
exist_owner = Owner.find_by(mail: @mail)
|
||||||
|
@ -31,6 +32,7 @@ class Api::V1::Users::UpdateEmailService < ApplicationService
|
||||||
change_user_email
|
change_user_email
|
||||||
excute_data_to_gitea
|
excute_data_to_gitea
|
||||||
excute_change_email_from_gitea
|
excute_change_email_from_gitea
|
||||||
|
remove_old_cache_for_user
|
||||||
end
|
end
|
||||||
|
|
||||||
return gitea_data
|
return gitea_data
|
||||||
|
@ -68,4 +70,8 @@ class Api::V1::Users::UpdateEmailService < ApplicationService
|
||||||
$gitea_client.delete_user_emails({body: {emails: [@old_mail]}.to_json, query: request_params})
|
$gitea_client.delete_user_emails({body: {emails: [@old_mail]}.to_json, query: request_params})
|
||||||
$gitea_client.post_user_emails({body: {emails: [@mail]}.to_json, query: request_params})
|
$gitea_client.post_user_emails({body: {emails: [@mail]}.to_json, query: request_params})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_old_cache_for_user
|
||||||
|
$redis_cache.del("v2-owner-common:#{@user.login}-#{@old_mail}")
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -15,6 +15,7 @@ class Api::V1::Users::UpdatePhoneService < ApplicationService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
|
raise Error, "此用户禁止修改手机号." if @user.id.to_i === 104691
|
||||||
raise Error, errors.full_messages.join(",") unless valid?
|
raise Error, errors.full_messages.join(",") unless valid?
|
||||||
raise Error, "密码不正确." unless @user.check_password?(@password)
|
raise Error, "密码不正确." unless @user.check_password?(@password)
|
||||||
exist_owner = Owner.find_by(phone: @phone)
|
exist_owner = Owner.find_by(phone: @phone)
|
||||||
|
|
|
@ -28,6 +28,10 @@ class Cache::V2::ProjectDateRankService < ApplicationService
|
||||||
"v2-project-rank-#{@rank_date.to_s}"
|
"v2-project-rank-#{@rank_date.to_s}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def project_rank_statistic_key
|
||||||
|
"v2-project-statistic:#{@project_id}-#{@rank_date.to_s}"
|
||||||
|
end
|
||||||
|
|
||||||
def project_rank
|
def project_rank
|
||||||
$redis_cache.zscore(project_rank_key, @project_id)
|
$redis_cache.zscore(project_rank_key, @project_id)
|
||||||
end
|
end
|
||||||
|
@ -35,26 +39,37 @@ class Cache::V2::ProjectDateRankService < ApplicationService
|
||||||
def set_project_rank
|
def set_project_rank
|
||||||
if @visits.present?
|
if @visits.present?
|
||||||
$redis_cache.zincrby(project_rank_key, @visits.to_i * 1, @project_id)
|
$redis_cache.zincrby(project_rank_key, @visits.to_i * 1, @project_id)
|
||||||
|
$redis_cache.hincrby(project_rank_statistic_key, "visits", @visits.to_i)
|
||||||
end
|
end
|
||||||
if @watchers.present?
|
if @watchers.present?
|
||||||
$redis_cache.zincrby(project_rank_key, @watchers.to_i * 5, @project_id)
|
$redis_cache.zincrby(project_rank_key, @watchers.to_i * 5, @project_id)
|
||||||
|
$redis_cache.hincrby(project_rank_statistic_key, "watchers", @watchers.to_i)
|
||||||
end
|
end
|
||||||
if @praises.present?
|
if @praises.present?
|
||||||
$redis_cache.zincrby(project_rank_key, @praises.to_i * 5, @project_id)
|
$redis_cache.zincrby(project_rank_key, @praises.to_i * 5, @project_id)
|
||||||
|
$redis_cache.hincrby(project_rank_statistic_key, "praises", @praises.to_i)
|
||||||
end
|
end
|
||||||
if @forks.present?
|
if @forks.present?
|
||||||
$redis_cache.zincrby(project_rank_key, @forks.to_i * 10, @project_id)
|
$redis_cache.zincrby(project_rank_key, @forks.to_i * 10, @project_id)
|
||||||
|
$redis_cache.hincrby(project_rank_statistic_key, "forks", @forks.to_i)
|
||||||
end
|
end
|
||||||
if @issues.present?
|
if @issues.present?
|
||||||
$redis_cache.zincrby(project_rank_key, @issues.to_i * 5, @project_id)
|
$redis_cache.zincrby(project_rank_key, @issues.to_i * 5, @project_id)
|
||||||
|
$redis_cache.hincrby(project_rank_statistic_key, "issues", @issues.to_i)
|
||||||
end
|
end
|
||||||
if @pullrequests.present?
|
if @pullrequests.present?
|
||||||
$redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id)
|
$redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id)
|
||||||
|
$redis_cache.hincrby(project_rank_statistic_key, "pullrequests", @pullrequests.to_i)
|
||||||
end
|
end
|
||||||
if @commits.present?
|
if @commits.present?
|
||||||
$redis_cache.zincrby(project_rank_key, @commits.to_i * 5, @project_id)
|
$redis_cache.zincrby(project_rank_key, @commits.to_i * 5, @project_id)
|
||||||
|
$redis_cache.hincrby(project_rank_statistic_key, "commits", @commits.to_i)
|
||||||
end
|
end
|
||||||
|
|
||||||
$redis_cache.zscore(project_rank_key, @project_id)
|
$redis_cache.zscore(project_rank_key, @project_id)
|
||||||
|
|
||||||
|
# 设置过期时间(一个月)
|
||||||
|
$redis_cache.expireat(project_rank_key, (@rank_date+30.days).to_time.to_i)
|
||||||
|
$redis_cache.expireat(project_rank_statistic_key, (@rank_date+30.days).to_time.to_i)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -115,5 +115,9 @@ class Cache::V2::UserDateRankService < ApplicationService
|
||||||
$redis_cache.zadd(user_rank_key, score-300, @user_id) if score > 300
|
$redis_cache.zadd(user_rank_key, score-300, @user_id) if score > 300
|
||||||
|
|
||||||
$redis_cache.zscore(user_rank_key, @user_id)
|
$redis_cache.zscore(user_rank_key, @user_id)
|
||||||
|
|
||||||
|
# 设置过期时间(一个月)
|
||||||
|
$redis_cache.expireat(user_rank_key, (@rank_date+30.days).to_time.to_i)
|
||||||
|
$redis_cache.expireat(user_date_statistic_key, (@rank_date+30.days).to_time.to_i)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -29,7 +29,7 @@ class Projects::ForkService < ApplicationService
|
||||||
|
|
||||||
ProjectUnit.init_types(clone_project.id)
|
ProjectUnit.init_types(clone_project.id)
|
||||||
|
|
||||||
@project.update_column('forked_count', @project&.forked_count.to_i + 1)
|
@project.update_attribute('forked_count', @project&.forked_count.to_i + 1)
|
||||||
new_repository.update_column('url', result['clone_url']) if result
|
new_repository.update_column('url', result['clone_url']) if result
|
||||||
|
|
||||||
ForkUser.create(project_id: @project.id, fork_project_id: clone_project.id, user_id: clone_project.user_id)
|
ForkUser.create(project_id: @project.id, fork_project_id: clone_project.id, user_id: clone_project.user_id)
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('项目排行榜', admins_path) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="box search-form-container user-list-form">
|
||||||
|
<%= form_tag(admins_projects_rank_index_path, method: :get, class: 'form-inline search-form flex-1', id: 'project-rank-date-form') do %>
|
||||||
|
<div class="form-group mr-2">
|
||||||
|
<label for="status">日期:</label>
|
||||||
|
<% dates_array = (0..30).to_a.map { |item| [(Date.today-item.days).to_s, (Date.today-item.days).to_s] } %>
|
||||||
|
<%= select_tag(:date, options_for_select(dates_array, params[:date]), class:"form-control",id: "project-rank-date-select")%>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container project-language-list-container">
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="20%">排名</th>
|
||||||
|
<th width="20%">项目</th>
|
||||||
|
<th width="20%">得分</th>
|
||||||
|
<th width="20%">访问数</th>
|
||||||
|
<th width="20%">关注数</th>
|
||||||
|
<th width="20%">点赞数</th>
|
||||||
|
<th width="20%">fork数</th>
|
||||||
|
<th width="20%">疑修数</th>
|
||||||
|
<th width="20%">合并请求数</th>
|
||||||
|
<th width="20%">提交数</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% @date_rank.each_with_index do |item, index| %>
|
||||||
|
<tr class="">
|
||||||
|
<td><%= index + 1%></td>
|
||||||
|
<% project_common = $redis_cache.hgetall("v2-project-common:#{item[0]}") %>
|
||||||
|
<% owner_common = $redis_cache.hgetall("v2-owner-common:#{project_common["owner_id"]}")%>
|
||||||
|
<td>
|
||||||
|
<a href="/<%= owner_common["login"] %>/<%= project_common["identifier"]%>">
|
||||||
|
<%= project_common["name"] %>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td><%= item[1] %></td>
|
||||||
|
<% project_date_statistic_key = "v2-project-statistic:#{item[0]}-#{@rank_date}"%>
|
||||||
|
<% if $redis_cache.exists(project_date_statistic_key)%>
|
||||||
|
<% visits = $redis_cache.hget(project_date_statistic_key, "visits") %>
|
||||||
|
<td><%= visits || 0 %></td>
|
||||||
|
<% watchers = $redis_cache.hget(project_date_statistic_key, "watchers") %>
|
||||||
|
<td><%= watchers || 0 %></td>
|
||||||
|
<% praises = $redis_cache.hget(project_date_statistic_key, "praises") %>
|
||||||
|
<td><%= praises || 0 %></td>
|
||||||
|
<% forks = $redis_cache.hget(project_date_statistic_key, "forks") %>
|
||||||
|
<td><%= forks || 0 %></td>
|
||||||
|
<% issues = $redis_cache.hget(project_date_statistic_key, "issues") %>
|
||||||
|
<td><%= issues || 0 %></td>
|
||||||
|
<% pullrequests = $redis_cache.hget(project_date_statistic_key, "pullrequests") %>
|
||||||
|
<td><%= pullrequests || 0 %></td>
|
||||||
|
<% commits = $redis_cache.hget(project_date_statistic_key, "commits") %>
|
||||||
|
<td><%= commits || 0 %></td>
|
||||||
|
<% else %>
|
||||||
|
<td colspan="7">暂无数据</td>
|
||||||
|
<% end %>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$("#project-rank-date-select").on('change', function() {
|
||||||
|
$("#project-rank-date-form").submit()
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -14,6 +14,12 @@
|
||||||
<!-- Sidebar Links -->
|
<!-- Sidebar Links -->
|
||||||
<ul class="list-unstyled components">
|
<ul class="list-unstyled components">
|
||||||
<li><%= sidebar_item(admins_path, '概览', icon: 'dashboard', controller: 'admins-dashboards') %></li>
|
<li><%= sidebar_item(admins_path, '概览', icon: 'dashboard', controller: 'admins-dashboards') %></li>
|
||||||
|
<li>
|
||||||
|
<%= sidebar_item_group('#user-submenu', '排行榜', icon: 'user') do %>
|
||||||
|
<li><%= sidebar_item(admins_users_rank_index_path, '用户排行榜', icon: 'user', controller: 'admins-users_rank') %></li>
|
||||||
|
<li><%= sidebar_item(admins_projects_rank_index_path, '项目排行榜', icon: 'user', controller: 'admins-projects_rank') %></li>
|
||||||
|
<% end %>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %>
|
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %>
|
||||||
<li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %></li>
|
<li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %></li>
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('用户排行榜', admins_path) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="box search-form-container user-list-form">
|
||||||
|
<%= form_tag(admins_users_rank_index_path, method: :get, class: 'form-inline search-form flex-1', id: 'user-rank-date-form') do %>
|
||||||
|
<div class="form-group mr-2">
|
||||||
|
<label for="status">日期:</label>
|
||||||
|
<% dates_array = (0..30).to_a.map { |item| [(Date.today-item.days).to_s, (Date.today-item.days).to_s] } %>
|
||||||
|
<%= select_tag(:date, options_for_select(dates_array, params[:date]), class:"form-control",id: "user-rank-date-select")%>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container project-language-list-container">
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="20%">排名</th>
|
||||||
|
<th width="20%">用户</th>
|
||||||
|
<th width="20%">得分</th>
|
||||||
|
<th width="20%">影响力</th>
|
||||||
|
<th width="20%">贡献度</th>
|
||||||
|
<th width="20%">活跃度</th>
|
||||||
|
<th width="20%">项目经验</th>
|
||||||
|
<th width="20%">语言能力</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% @date_rank.each_with_index do |item, index| %>
|
||||||
|
<tr class="">
|
||||||
|
<td><%= index + 1%></td>
|
||||||
|
<% owner_common = $redis_cache.hgetall("v2-owner-common:#{item[0]}")%>
|
||||||
|
<td>
|
||||||
|
<a href="/<%= owner_common["login"] %>">
|
||||||
|
<%= owner_common["name"] %>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<% user_date_statistic_key = "v2-user-statistic:#{item[0]}-#{@rank_date}"%>
|
||||||
|
<% follow_count = $redis_cache.hget(user_date_statistic_key, "follow-count") || 0 %>
|
||||||
|
<% pullrequest_count = $redis_cache.hget(user_date_statistic_key, "pullrequest-count") || 0 %>
|
||||||
|
<% issues_count = $redis_cache.hget(user_date_statistic_key, "issue-count") || 0 %>
|
||||||
|
<% project_count = $redis_cache.hget(user_date_statistic_key, "project-count") || 0 %>
|
||||||
|
<% fork_count = $redis_cache.hget(user_date_statistic_key, "fork-count") || 0 %>
|
||||||
|
<% project_watchers_count = $redis_cache.hget(user_date_statistic_key, "project-watcher-count") || 0 %>
|
||||||
|
<% project_praises_count = $redis_cache.hget(user_date_statistic_key, "project-praise-count") || 0 %>
|
||||||
|
<% project_language = $redis_cache.hget(user_date_statistic_key, "project-language") %>
|
||||||
|
<% project_languages_count = project_language.nil? || project_language == "{}" ? 0 : JSON.parse(project_language).length %>
|
||||||
|
|
||||||
|
<% influence = (60.0 + follow_count.to_i / (follow_count.to_i + 20.0) * 40.0).to_i %>
|
||||||
|
<% contribution = (60.0 + pullrequest_count.to_i / (pullrequest_count.to_i + 20.0) * 40.0).to_i %>
|
||||||
|
<% activity = (60.0 + issues_count.to_i / (issues_count.to_i + 80.0) * 40.0).to_i %>
|
||||||
|
<% experience = 10 * project_count.to_i + 5 * fork_count.to_i + project_watchers_count.to_i + project_praises_count.to_i %>
|
||||||
|
<% experience = (60.0 + experience / (experience + 100.0) * 40.0).to_i %>
|
||||||
|
<% language = (60.0 + project_languages_count.to_i / (project_languages_count.to_i + 5.0) * 40.0).to_i %>
|
||||||
|
<% score = influence+ contribution + activity + experience + language%>
|
||||||
|
<td><%= score %></td>
|
||||||
|
<td><%= influence%></td>
|
||||||
|
<td><%= contribution%></td>
|
||||||
|
<td><%= activity%></td>
|
||||||
|
<td><%= experience%></td>
|
||||||
|
<td><%= language%></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$("#user-rank-date-select").on('change', function() {
|
||||||
|
$("#user-rank-date-form").submit()
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -18,7 +18,7 @@ json.protected branch['protected']
|
||||||
json.user_can_push branch['user_can_push']
|
json.user_can_push branch['user_can_push']
|
||||||
json.user_can_merge branch['user_can_merge']
|
json.user_can_merge branch['user_can_merge']
|
||||||
json.commit_id branch['commit_id']
|
json.commit_id branch['commit_id']
|
||||||
json.commit_time_from_now time_from_now(branch['commit_time'].to_time)
|
json.commit_time_from_now time_from_now(branch['commit']['timestamp'].to_time)
|
||||||
json.commit_time branch['commit_time']
|
json.commit_time branch['commit_time']
|
||||||
json.default_branch branch['default_branch']
|
json.default_branch branch['default_branch']
|
||||||
json.http_url render_http_url(@project)
|
json.http_url render_http_url(@project)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
json.total_count @result_object[:total_data].to_i
|
||||||
|
json.branches @result_object[:data].each do |branch|
|
||||||
|
json.partial! "api/v1/projects/branches/simple_gitea_detail", branch: branch
|
||||||
|
end
|
|
@ -0,0 +1,26 @@
|
||||||
|
if tag.present? && tag.is_a?(Hash)
|
||||||
|
json.name tag['name']
|
||||||
|
json.id tag['id']
|
||||||
|
json.zipball_url render_zip_url(@owner, @repository, tag['name'])
|
||||||
|
json.tarball_url render_tar_url(@owner, @repository, tag['name'])
|
||||||
|
json.tagger do
|
||||||
|
json.partial! 'api/v1/users/commit_user', user: render_cache_commit_author(tag['tagger']), name: tag['tagger']['name']
|
||||||
|
end
|
||||||
|
json.time_ago time_from_now(tag['tagger']['date'].to_time)
|
||||||
|
json.created_at_unix tag['tagger']['date'].to_time.to_i
|
||||||
|
json.message tag['message']
|
||||||
|
json.commit do
|
||||||
|
json.sha tag['commit']['sha']
|
||||||
|
json.message tag['commit']['message']
|
||||||
|
json.time_ago time_from_now(tag['commit']['commiter']['date'].to_time)
|
||||||
|
json.created_at_unix tag['commit']['commiter']['date'].to_time.to_i
|
||||||
|
json.committer do
|
||||||
|
json.partial! 'api/v1/users/commit_user', user: render_cache_commit_author(tag['commit']['commiter']), name: tag['commit']['commiter']['name']
|
||||||
|
end
|
||||||
|
json.author do
|
||||||
|
json.partial! 'api/v1/users/commit_user', user: render_cache_commit_author(tag['commit']['author']), name: tag['commit']['author']['name']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
json.name tag
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
json.total_count @result_object[:total_data].to_i
|
||||||
|
json.tags @result_object[:data].each do |tag|
|
||||||
|
json.partial! "api/v1/projects/tags/simple_gitea_index_detail", tag: tag
|
||||||
|
json.has_release @release_tags.blank? ? false : @release_tags.include?(tag['name'])
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
json.status 0
|
||||||
|
json.message "success"
|
||||||
|
json.data do
|
||||||
|
json.array! @install_bots do |install_bot|
|
||||||
|
json.extract! install_bot.bot, :id, :name
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,13 +1,14 @@
|
||||||
if @project.forge?
|
if @project.forge?
|
||||||
is_dir = @sub_entries.is_a?(Array)
|
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_name.starts_with?('.') ? file_name[1..-1] : File.extname(file_name.to_s)[1..-1]
|
||||||
direct_download = file_name.to_s.downcase != "Makefile".downcase && download_type(file_type)
|
direct_download = file_name.to_s.downcase != "Makefile".downcase && download_type(file_type)
|
||||||
image_type = image_type?(file_type)
|
image_type = image_type?(file_type)
|
||||||
json.name file_name
|
json.name file_name
|
||||||
json.sha entry['sha']
|
json.sha entry['sha']
|
||||||
json.path entry['path']
|
json.path entry['path']
|
||||||
json.type entry['type']
|
json.type entry['type']
|
||||||
|
json.submodule_git_url entry['submodule_git_url'].nil? ? nil : repo_git_submodule_url(@owner, @repository, entry['submodule_git_url'])
|
||||||
json.size entry['size']
|
json.size entry['size']
|
||||||
is_readme = is_readme?(entry['type'], entry['name'])
|
is_readme = is_readme?(entry['type'], entry['name'])
|
||||||
if is_readme
|
if is_readme
|
||||||
|
|
|
@ -51,6 +51,7 @@ if @project.forge?
|
||||||
json.path entry['path']
|
json.path entry['path']
|
||||||
json.sha entry['sha']
|
json.sha entry['sha']
|
||||||
json.type entry['type']
|
json.type entry['type']
|
||||||
|
json.submodule_git_url entry['submodule_git_url'].nil? ? nil : repo_git_submodule_url(@owner, @repository, entry['submodule_git_url'])
|
||||||
json.size entry['size']
|
json.size entry['size']
|
||||||
json.is_readme_file is_readme?(entry['type'], entry['name'])
|
json.is_readme_file is_readme?(entry['type'], entry['name'])
|
||||||
json.content decode64_content(entry, @owner, @repository, @ref, @path)
|
json.content decode64_content(entry, @owner, @repository, @ref, @path)
|
||||||
|
|
|
@ -45,8 +45,8 @@ default: &default
|
||||||
callback_url: 'callback_url'
|
callback_url: 'callback_url'
|
||||||
signature_key: 'test12345678'
|
signature_key: 'test12345678'
|
||||||
educoder:
|
educoder:
|
||||||
client_id: 'e9ce4d5ba1698d6f7d01d8ee2959776c7a6d743ebe94da2341e288fd2fbf60aa'
|
client_id: 'test'
|
||||||
client_secret: '6ff84dd75eddd859c5bd0e7a791b58bc5ad1ba4fbb30bc9db37cb0baf9f33012'
|
client_secret: 'test'
|
||||||
base_url: 'https://test-data.educoder.net'
|
base_url: 'https://test-data.educoder.net'
|
||||||
redirect_uri: 'https://testforgeplus.trustie.net/api/auth/educoder/callback'
|
redirect_uri: 'https://testforgeplus.trustie.net/api/auth/educoder/callback'
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ Doorkeeper.configure do
|
||||||
User.authenticate!(params[:username], params[:password])
|
User.authenticate!(params[:username], params[:password])
|
||||||
end
|
end
|
||||||
|
|
||||||
access_token_generator '::Doorkeeper::JWT'
|
# access_token_generator '::Doorkeeper::JWT'
|
||||||
|
|
||||||
admin_authenticator do
|
admin_authenticator do
|
||||||
user = current_user
|
user = current_user
|
||||||
|
|
|
@ -761,6 +761,8 @@ Rails.application.routes.draw do
|
||||||
get :visits_static
|
get :visits_static
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
resources :users_rank, only: [:index]
|
||||||
|
resources :projects_rank, only: [:index]
|
||||||
resources :sites
|
resources :sites
|
||||||
resources :edu_settings
|
resources :edu_settings
|
||||||
resources :project_languages
|
resources :project_languages
|
||||||
|
@ -1045,6 +1047,19 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resources :commit_logs, :only => [:create]
|
resources :commit_logs, :only => [:create]
|
||||||
|
|
||||||
|
scope '/app' do
|
||||||
|
post ':id/auth_active', to: 'installations#auth_active'
|
||||||
|
post ':id/update_private_key', to: 'installations#update_private_key'
|
||||||
|
post ':id/update_secret', to: 'installations#update_secret'
|
||||||
|
resources :installations do
|
||||||
|
get :repositories, on: :collection
|
||||||
|
member do
|
||||||
|
post :access_tokens
|
||||||
|
put :suspended
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
root 'main#index'
|
root 'main#index'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,17 @@ defaults format: :json do
|
||||||
get :hooktasks
|
get :hooktasks
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :branches, only:[:index, :create] do
|
resources :branches, param: :name, only:[:index, :create, :destroy] do
|
||||||
collection do
|
collection do
|
||||||
get :all
|
get :all
|
||||||
|
patch :update_default_branch
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
match 'branches/*name', to: "branches#destroy", via: :all
|
||||||
|
|
||||||
|
resources :tags, param: :name, only: [:index, :destroy]
|
||||||
|
match 'tags/*name', to: "tags#destroy", via: :all
|
||||||
|
|
||||||
resources :commits, only: [:index]
|
resources :commits, only: [:index]
|
||||||
resources :code_stats, only: [:index]
|
resources :code_stats, only: [:index]
|
||||||
get '/commits/:sha/diff', to: 'commits#diff'
|
get '/commits/:sha/diff', to: 'commits#diff'
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class AddBotInfo < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
if table_exists? :bot
|
||||||
|
add_column :bot, :private_key, :text, comment: "私钥"
|
||||||
|
add_column :bot, :owner_id, :integer, comment: "所有者ID"
|
||||||
|
add_column :bot, :uid, :integer, comment: "Bot机器人用户ID"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,7 +13,7 @@ services:
|
||||||
MYSQL_DATABASE: educoder
|
MYSQL_DATABASE: educoder
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:3.2
|
image: redis:6.2.5
|
||||||
container_name: redis
|
container_name: redis
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
|
@ -22,14 +22,17 @@ services:
|
||||||
- ./redis_data:/data
|
- ./redis_data:/data
|
||||||
|
|
||||||
web:
|
web:
|
||||||
image: guange/educoder:latest
|
image: gitlink-ubuntu18.04:latest
|
||||||
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 4000 -b '0.0.0.0'"
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
# command: bash -c "rm -f tmp/pids/server.pid && rails s -p 4000 -b '0.0.0.0'"
|
||||||
stdin_open: true
|
stdin_open: true
|
||||||
tty: true
|
tty: true
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/home/app/gitlink
|
||||||
ports:
|
ports:
|
||||||
- "4000:4000"
|
- "4000:4000"
|
||||||
depends_on:
|
depends_on:
|
||||||
- mysql
|
- mysql
|
||||||
- redis
|
- redis
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
require 'openssl'
|
||||||
|
require 'jwt' # https://rubygems.org/gems/jwt
|
||||||
|
|
||||||
|
# Private key contents
|
||||||
|
private_pem = File.read("/Users/xxq/Documents/gitlink-webhook.2022-06-09.private-key.pem")
|
||||||
|
|
||||||
|
private_key22="-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEApOebWmRV/ooNq5Ks04YnDU7pEezGShGvaiF0cIvn9jvmYHu0\nFialojvJV3VpB6xE6QBPXZ0Pi1lokZ9dMx8F5UWNx9WA7wf7xK3hAJLNml+GeewF\nou8vk/Ry7n6diLxETNVd7YzPvztn5qaMp/DXa+65i11H8a/XXqR7kCVnCevVlufh\nNr/Dp6dW31W8TInnDQasJFMZ8GY7f+tCwLXNc0M8p+TeDp9xmXHOrEB+S/mgbUOF\nXgRr6icbMmlT9bsAxYHrrDkcVxJhs0hq5vD3BaoK06gcZEnN7/HVNzgVSOYNsVNh\n9006cMgDSOwc9F8aulP7cr8k74INq1xswoGs9wIDAQABAoIBAHayc2NkF3YJXv+h\nqx7yUEfHBgKuAKiuBCqLfCnKuqPFx/So9h5/oPeeuzVlwL0SJePlIjuK4vZ128v9\n/vLeILtADmbJ6m2jvHh8hBmKkc3Ndplp50C5k/CWoufCYZhbk3oOlvZ3Rc4rb4VZ\nWqNDu3voMMv8z91KqeZo1LwUAA/l9mU++zLkRA6qOuWGBJFsM8YpshzxL5lzRUb3\n7y+YJDyUZztfzKwr6pqm1n9B2e6e+znCw1vMZXp2TbUrpvrrXSxlgdNuK68SkZX6\nTdZUD8y0viwaioRVf3vR+e/Bf7yZannGdvcmVGs0A7dq9QgHkakqNHiRkQgwviSq\nbjBo7dECgYEAzekeP5j/dAPkv9X4qnmZ4du/+ZgrQrJckDD/JuNIBmQT9m286l4P\nmb2TBcWkswVOZaS5Qy2bN/69rwIbcdvbaROGBCabn3ATK4fSzmUk31M2rRKYZqaU\nMi0W2g2YtSRg+bV6S7aFXa98j5+JlqJeDZQoRuvL68ooq5WzFWmfYnkCgYEAzQTi\n4USqz2z66BfU+v2rchzK8URxnv7EW/CG3XFRsG+1UXCyEIct2L7rzvC7r7+jjS4s\ngmV3Civ1sckGMwikLzxFtUZ1LUBakZp/mmipIzxcHOeBsRdHei8BFvMNqveg1JpO\ncY/Fp+wEkSNLhfkb/IXRw0iwFalBRnyo4BJbLu8CgYBrQ7E6OB169jxHotNzGv2K\npssO3rJKgFev1ZZVT7jJe4Dasrfi7zT5RcQ9EYSGrZD1aiYIVM2zEcUGUfayDXHy\n/vSlXOdc2ylhV9P9KLtYiyTEbBdwAf7ZVJu+465VTqol6t/WaTJ4Z15gAx/NlK+i\nKzgAGf2Uyy78k3NDCE67IQKBgFwM0pUUEKEbLDhi4uRiWsTcep4C/gTGHIGvJ85r\nH6NZNI7BS6GyH/qOFjAO1CYfpB4yWhed2Om/PQw61sa5HYZ7yEyQuvG7UC7JsHsy\nfKZuZmkv5IIPkq8gRZv5OuzFS/fI5GmGhNdVV+OWdkVLyK4Do1/L1guTt9QfCm+4\nrioPAoGBALGr8aUAbz/A611M/bLnk04UYfV+M34/hCf6/rKiBHdQoIHOriSC9Nv7\nyhE5axTdmIWMxfbyb3vHJ5MizZkD/Qj0VDuMkyS2+3TepI6tySQE3YQeWnCMJI9i\nuoCZ31GBui4+W5udbx8NOVsJfXUQn/OAoOn6WuMNPdgB45KXcktj\n-----END RSA PRIVATE KEY-----\n"
|
||||||
|
private_key33= "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAq/wUH8N+5fzj3hArKY7ChC591R/uKyeNM/BbsR2OGxO5F1CE\nozy6thtPult96Gm9oK3sMpLdYCze2YgozgteFO1Ft0o1GEJ1A4SinOKzeixLpFy0\n5N9t+iz7Xa7jC/1E3uy/s2WvSYCS9NnK2Uj3DQOH8BUWfkvyTtt91a2pplbPCV3T\nw1PykAcDWIFXVJJCMtYd2x+DukSWKHRsYbBCMtVZhEVuKmTE3FBTDVu9sN3b7uLL\n5RzHUg13QZZr9OvMNR3nUZl6yDxw+wD4anDrtpL9C+tFjhMyqsyYpYWwcJm65YiD\ny7Ps24IdcLB4iOxJE91fu+MnicvyBrtEjoBP/wIDAQABAoIBAAcKc9x1CW3q8300\n1j+GS6pTqO0fuIVlwh8dOPPATQAIx6wPrM5t/wrThWkQs8/e/Fdmp2POpWd5jsoD\nDACbcIeUyyTc0d2jYtz5AhtAIK7gv1wEO5efGgaC7ut/7GWiQb6KnLKAeDOfIuUJ\nQYexuAN9YIRQqLIU89+MltM3n9liZTMuPWRFJcitaDytXa10TCe5RUqHGZf49pi7\njCgk0x7jDYqbIzsqOu741P8My/gkAjKPkRnjaj3o6MrwHzIlc4t/6mKbaPnywywk\n6roYMqmytgueA9wxFcj74ekBQAaXsu4xRkbZXxjcBtIvTId5IHHK5Z/r3fgE9K3J\nOuzzJ1kCgYEA3uu/pUjJbKegOsgSdu3cO/NvRV2YsRD4NUgtiMCEakE4VQXRK5pf\nV8xqQeH/rLjZf5aP5xe8n25krh/c+m0ezOMyu5MmhoxaWCPWIezsaKJXOcvsOxIu\n2sJ9GRMXabyuDuSdL7ZGYMpLhRclXYLyPCz7wzN445IluTHuD3lJ2qUCgYEAxYFh\ncVD73yNZn9BN1DSGWpfPtLqOKIdG+xi/ypCSGpJG0QCJRFi7R1qJOxFtJNI8DRiD\nZapPEGLVd/KY5NzBGZBfNQt4DQH9qR4l43c6NNkisWA9rvXvCDqXKmBq7wfpnkYr\n4Ul2hXYmsPJjP8e0BfG54PaSu3BDBMJMtcgDktMCgYBvzyDdnwdgVyc3tHgGbMFk\n1HHAAfT/ArrrxpsIFz+TJ8lAY92JGDGwENhO2TLrCAAXTYY5657w/GbFKzgj5y1m\nqKIekOzm2WjLApZ5h6L/zEUhuRVwf2s+0AP82qWIpFlNIP9yGeNs0qpUQ8q6/13O\nLuXL/3on8nq3S8LSwgv3/QKBgDfM+g7d5ouAnU29uH9/54Wo5pIVMxzYO4Gt2GIO\nvnirYz6hfCbHOwJJ3gPGRKPmkfjROC59E6F5iv48mF3w0M28MGn4N47VRSmGzwWZ\nJeTQhDDBFCxeZ45Xn2Xln9Cw15xUDwmzi7zhSMUtdkUK0x3q0a1xfLtgWE775lhl\njjzpAoGAdUXFW1elfjXpfIYZf7vUV7MPquKL7qAcopd96XBszhOn7g+ibzem+wgt\n1UTSeOBESYANHeJk2MuWPSRXk/FlQETVIcPAEp0kxbwQE+7YEdrMVeDcIe5lPwGD\n+WuS3kg0MPgUrXZXn74gcwWmSIOyHfqXULqOxWE25uU2icdV+2w=\n-----END RSA PRIVATE KEY-----\n"
|
||||||
|
private_key = OpenSSL::PKey::RSA.new(private_key33)
|
||||||
|
# puts private_key.to_json
|
||||||
|
|
||||||
|
# Generate the JWT
|
||||||
|
payload = {
|
||||||
|
# issued at time, 60 seconds in the past to allow for clock drift
|
||||||
|
iat: Time.now.to_i - 60,
|
||||||
|
# JWT expiration time (10 minute maximum)
|
||||||
|
exp: Time.now.to_i + (10 * 60),
|
||||||
|
# GitHub App's identifier
|
||||||
|
iss: "782"
|
||||||
|
}
|
||||||
|
|
||||||
|
jwt = JWT.encode(payload, private_key, "RS256")
|
||||||
|
puts jwt
|
||||||
|
# puts OpenSSL::PKey::RSA.new(private_key33).public_key.to_s
|
||||||
|
#
|
||||||
|
rsa_private = OpenSSL::PKey::RSA.new(private_key33)
|
||||||
|
rsa_public = rsa_private.public_key
|
||||||
|
|
||||||
|
# decoded_token = JWT.decode jwt, nil, false
|
||||||
|
begin
|
||||||
|
decoded_token = JWT.decode jwt, rsa_private, true, { algorithm: 'RS256' }
|
||||||
|
rescue JWT::DecodeError
|
||||||
|
puts "jwt is not mmmmmm"
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
puts decoded_token[0]
|
||||||
|
puts decoded_token[0]["iss"]
|
||||||
|
|
||||||
|
# serialized_private_key = OpenSSL::PKey::RSA::generate(2048).to_s
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue