| @@ -531,17 +531,18 @@ curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror | jq | |||||
| #### 项目详情 | #### 项目详情 | ||||
| ``` | ``` | ||||
| GET api/projects/:id | |||||
| GET /api/:namespace_id/:id | |||||
| ``` | ``` | ||||
| *示例* | *示例* | ||||
| ``` | ``` | ||||
| curl -X GET http://localhost:3000/api/projects/3263 | jq | |||||
| curl -X GET http://localhost:3000/api/jasder/jasder_test | jq | |||||
| ``` | ``` | ||||
| *请求参数说明:* | *请求参数说明:* | ||||
| |参数名|必选|类型|说明| | |参数名|必选|类型|说明| | ||||
| |-|-|-|-| | |-|-|-|-| | ||||
| |id |是|int |项目id | | |||||
| |namespace_id |是|string |用户登录名 | | |||||
| |id |是|string |项目标识identifier | | |||||
| *返回参数说明:* | *返回参数说明:* | ||||
| @@ -570,6 +571,50 @@ curl -X GET http://localhost:3000/api/projects/3263 | jq | |||||
| ``` | ``` | ||||
| --- | --- | ||||
| #### 项目详情(简版) | |||||
| ``` | |||||
| GET /api/:namespace_id/:id/simple | |||||
| ``` | |||||
| *示例* | |||||
| ``` | |||||
| curl -X GET http://localhost:3000/api/jasder/jasder_test/simple | jq | |||||
| ``` | |||||
| *请求参数说明:* | |||||
| |参数名|必选|类型|说明| | |||||
| |-|-|-|-| | |||||
| |id |是|int |项目id | | |||||
| *返回参数说明:* | |||||
| |参数名|类型|说明| | |||||
| |-|-|-| | |||||
| |id |int |id | | |||||
| |name |string|项目名称| | |||||
| |identifier |string|项目标识| | |||||
| |is_public |boolean|项目是否公开, true:公开,false:私有| | |||||
| |description |string|项目简介| | |||||
| |repo_id |int|仓库id| | |||||
| |repo_identifier|string|仓库标识| | |||||
| 返回值 | |||||
| ``` | |||||
| { | |||||
| "identifier": "jasder_test", | |||||
| "name": "jasder的测试项目", | |||||
| "id": 4967, | |||||
| "type": 0, | |||||
| "author": { | |||||
| "login": "jasder", | |||||
| "name": "姓名", | |||||
| "image_url": "avatars/User/b" | |||||
| } | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| #### 编辑仓库信息 | #### 编辑仓库信息 | ||||
| ``` | ``` | ||||
| GET /api/repositories/:id/edit.json | GET /api/repositories/:id/edit.json | ||||
| @@ -897,13 +942,13 @@ curl -X POST http://localhost:3000/api/projects/3297/forks | jq | |||||
| #### 获取代码目录列表 | #### 获取代码目录列表 | ||||
| ``` | ``` | ||||
| POST /api/repositories/:id/entries.json | |||||
| POST /api/:namespace_id/:project_id/repository/entries | |||||
| ``` | ``` | ||||
| *示例* | *示例* | ||||
| ``` | ``` | ||||
| curl -X GET \ | curl -X GET \ | ||||
| -d "ref=develop" \ | -d "ref=develop" \ | ||||
| http://localhost:3000//api/repositories/3687/entries.json | jq | |||||
| http://localhost:3000//api/jasder/jasder_test/repository/entries | jq | |||||
| ``` | ``` | ||||
| *请求参数说明:* | *请求参数说明:* | ||||
| @@ -1320,11 +1365,11 @@ http://localhost:3000/api/projects | jq | |||||
| ### 获取分支列表 | ### 获取分支列表 | ||||
| ``` | ``` | ||||
| GET /api/projects/:id/branches | |||||
| GET /api/:namespace_id/:id/branches | |||||
| ``` | ``` | ||||
| *示例* | *示例* | ||||
| ``` | ``` | ||||
| curl -X GET http://localhost:3000/api/projects/4797/branches | jq | |||||
| curl -X GET http://localhost:3000/api/jasder/jasder_test/branches | jq | |||||
| ``` | ``` | ||||
| *请求参数说明:* | *请求参数说明:* | ||||
| @@ -1487,18 +1532,19 @@ http://localhost:3000/api/repositories/5836/tags.json | jq | |||||
| ## 仓库详情 | ## 仓库详情 | ||||
| ``` | ``` | ||||
| GET /api/repositories/:id | |||||
| GET /api/:namespace_id/:project_id/repository | |||||
| ``` | ``` | ||||
| *示例* | *示例* | ||||
| ``` | ``` | ||||
| curl -X GET \ | curl -X GET \ | ||||
| http://localhost:3000/api/repositories/23.json | jq | |||||
| http://192.168.2.230:3000/api/jasder/forgeplus/repository | jq | |||||
| ``` | ``` | ||||
| *请求参数说明:* | *请求参数说明:* | ||||
| |参数名|必选|类型|说明| | |参数名|必选|类型|说明| | ||||
| |-|-|-|-| | |-|-|-|-| | ||||
| |id |是|string |项目id | | |||||
| |namespace_id |是|string |用户登录名 | | |||||
| |project_id |是|string |项目标识identifier | | |||||
| *返回参数说明:* | *返回参数说明:* | ||||
| @@ -2357,6 +2403,51 @@ http://localhost:3000/api//api/repositories/3868/delete_file | jq | |||||
| ### DevOps相关api | ### DevOps相关api | ||||
| --- | --- | ||||
| #### 获取devops流程步骤(判断devops是否初始化) | |||||
| ``` | |||||
| GET /api/users/devops | |||||
| ``` | |||||
| *示例* | |||||
| ``` | |||||
| curl -X GET \ | |||||
| -d "project_id=5988" \ | |||||
| https://localhost:3000/api/users/devops.json | jq | |||||
| ``` | |||||
| *请求参数说明:* | |||||
| |参数名|必选|类型|说明| | |||||
| |-|-|-|-| | |||||
| |project_id |是|string |项目id或者项目的标识identifier| | |||||
| *返回参数说明:* | |||||
| |参数名|类型|说明| | |||||
| |-|-|-| | |||||
| |step |int|初始化devops流程步骤; 0: 标识未开启devops,1: 标识用户已填写了云服务器相关信息,但并未开启认证, 2: 标识用户已开启了CI服务端的认证, 3: 标识用户已经授权并获取了CI服务的token| | |||||
| |account |string|你的云服务器帐号| | |||||
| |ip |string|你的云服务器帐号ip| | |||||
| |secret |string|你的云服务器登录密码| | |||||
| |authenticate_url |string|devops授权认证地址, 只有填写了服务器相关信息后才会有该地址| | |||||
| |get_drone_token_url |string|获取CI服务端token地址, 只有认证成功后才会有该地址| | |||||
| 返回值 | |||||
| ```json | |||||
| { | |||||
| "step": 0, | |||||
| "cloud_account": { | |||||
| "id": 1, | |||||
| "account": "xxx", | |||||
| "ip": "xxx.xxx.xxx.x", | |||||
| "secret": "11111", | |||||
| "authenticate_url": "http://localhost:3000/login", | |||||
| "get_drone_token_url": "http://localhost:3000/account" | |||||
| } | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| #### 初始化DevOps流程 | #### 初始化DevOps流程 | ||||
| ``` | ``` | ||||
| POST /api/dev_ops/cloud_accounts | POST /api/dev_ops/cloud_accounts | ||||
| @@ -2399,6 +2490,72 @@ https://localhost:3000/api/dev_ops/cloud_accounts.json | jq | |||||
| ``` | ``` | ||||
| --- | --- | ||||
| #### 用户认证CI服务端后,需要调用该接口进行更新devlops流程状态 | |||||
| ``` | |||||
| PUT /api/users/devops_authenticate | |||||
| ``` | |||||
| *示例* | |||||
| ``` | |||||
| curl -X PUT \ | |||||
| -d "project_id=5988" \ | |||||
| http://localhost:3000/api/users/devops_authenticate.json | jq | |||||
| ``` | |||||
| *请求参数说明:* | |||||
| |参数名|必选|类型|说明| | |||||
| |-|-|-|-| | |||||
| |project_id |是|string |项目id或者项目的标识identifier| | |||||
| *返回参数说明:* | |||||
| |参数名|类型|说明| | |||||
| |-|-|-| | |||||
| |status |int|0:成功, -1: 失败| | |||||
| ``` | |||||
| { | |||||
| "status": 0, | |||||
| "message": "success" | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| #### 激活项目 | |||||
| ``` | |||||
| POST /api/dev_ops/cloud_accounts/:id/activate | |||||
| ``` | |||||
| *示例* | |||||
| ``` | |||||
| curl -X POST \ | |||||
| -d "id=1" \ | |||||
| -d "project_id=4844" \ | |||||
| -d "drone_token=xxxxxxxxxx" \ | |||||
| http://localhost:3000/api/dev_ops/cloud_accounts/1/activate.json | jq | |||||
| ``` | |||||
| *请求参数说明:* | |||||
| |参数名|必选|类型|说明| | |||||
| |-|-|-|-| | |||||
| |project_id |是|int |project's id or identifier | | |||||
| |id |是|int |cloud_account's id | | |||||
| |drone_token |否|string |CI端用户的token值,只有当用户第一次激活时,才需要填写该值 | | |||||
| *返回参数说明:* | |||||
| |参数名|类型|说明| | |||||
| |-|-|-| | |||||
| |status |int|0:成功, -1: 失败| | |||||
| ``` | |||||
| { | |||||
| "status": 0, | |||||
| "message": "success" | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| #### 获取仓库的.trustie-pipeline.yml | #### 获取仓库的.trustie-pipeline.yml | ||||
| ``` | ``` | ||||
| GET /api/dev_ops/builds/get_trustie_pipeline | GET /api/dev_ops/builds/get_trustie_pipeline | ||||
| @@ -2429,9 +2586,11 @@ http://localhost:3000/api/dev_ops/builds/get_trustie_pipeline.json | jq | |||||
| { | { | ||||
| "name": ".trustie-pipeline.yml", | "name": ".trustie-pipeline.yml", | ||||
| "path": ".trustie-pipeline.yml", | "path": ".trustie-pipeline.yml", | ||||
| "sha": "548sfefsafef48sf485s4f", | |||||
| "content": "..jsaf" | "content": "..jsaf" | ||||
| } | } | ||||
| ``` | ``` | ||||
| --- | |||||
| #### 获取语言列表 | #### 获取语言列表 | ||||
| ``` | ``` | ||||
| @@ -0,0 +1,78 @@ | |||||
| html{margin:0px;padding: 0px;font-size: 14px;font-family: "微软雅黑","宋体";} | |||||
| body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td { | |||||
| margin: 0; | |||||
| padding: 0; | |||||
| } | |||||
| .IndexContent{ | |||||
| height: 100vh; | |||||
| width: 100%; | |||||
| position: relative; | |||||
| background-image: url('/images/oauth/backImg.png'); | |||||
| background-repeat: no-repeat; | |||||
| background-size: cover; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| flex-direction: column; | |||||
| } | |||||
| .indexLogo{ | |||||
| width:80px; | |||||
| margin-bottom: 35px; | |||||
| } | |||||
| .indexPanel{ | |||||
| width: 580px; | |||||
| min-height: 400px; | |||||
| background-color: #fff; | |||||
| box-shadow: 0px 2px 10px 5px rgba(0,0,0,0.05); | |||||
| border-radius: 5px; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .indexTitle{ | |||||
| height: 75px; | |||||
| line-height: 75px; | |||||
| font-size: 18px; | |||||
| color:#333; | |||||
| text-align: center; | |||||
| border-bottom: 1px solid #eee; | |||||
| } | |||||
| .indexInfo{ | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: flex-start; | |||||
| } | |||||
| .indexInfos{ | |||||
| padding:40px 60px; | |||||
| } | |||||
| .indexInfo > span{ | |||||
| color: #333; | |||||
| font-size: 16px; | |||||
| margin-top: 5px; | |||||
| } | |||||
| .indexInfo input{ | |||||
| width: 100%; | |||||
| height:40px; | |||||
| border-radius: 2px; | |||||
| border:1px solid #eee; | |||||
| margin-top: 5px; | |||||
| padding:0px 0px 0px 8px; | |||||
| outline: none; | |||||
| } | |||||
| .indexInfo .checkInfo{ | |||||
| height: 15px; | |||||
| color: red; | |||||
| } | |||||
| .indexBtn{ | |||||
| text-align: center; | |||||
| margin-top: 20px; | |||||
| } | |||||
| .indexSubmit{ | |||||
| width: 50%; | |||||
| height: 32px; | |||||
| line-height: 32px; | |||||
| background-color: #1890FF; | |||||
| border:none; | |||||
| color: #fff; | |||||
| border-radius: 2px; | |||||
| cursor: pointer; | |||||
| outline: none; | |||||
| } | |||||
| @@ -13,24 +13,12 @@ class AccountsController < ApplicationController | |||||
| password = params[:password] | password = params[:password] | ||||
| platform = (params[:platform] || 'forge')&.gsub(/\s+/, "") | platform = (params[:platform] || 'forge')&.gsub(/\s+/, "") | ||||
| @user = User.new(admin: false, login: username, mail: email, type: "User") | |||||
| @user.password = password | |||||
| @user.platform = platform | |||||
| @user.activate | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) | |||||
| if interactor.success? | |||||
| gitea_user = interactor.result | |||||
| result = Gitea::User::GenerateTokenService.new(username, password).call | |||||
| @user.gitea_token = result['sha1'] | |||||
| @user.gitea_uid = gitea_user['id'] | |||||
| if @user.save! | |||||
| UserExtension.create!(user_id: @user.id) | |||||
| render_ok({user: {id: @user.id, token: @user.gitea_token}}) | |||||
| end | |||||
| result = autologin_register(username, email, password, platform) | |||||
| if result[:message].blank? | |||||
| render_ok({user: result[:user]}) | |||||
| else | else | ||||
| render_error(interactor.error) | |||||
| render_error(result[:message]) | |||||
| end | end | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -9,7 +9,8 @@ class ApplicationController < ActionController::Base | |||||
| include GitHelper | include GitHelper | ||||
| include LoggerHelper | include LoggerHelper | ||||
| include LoginHelper | include LoginHelper | ||||
| include RegisterHelper | |||||
| protect_from_forgery prepend: true, unless: -> { request.format.json? } | protect_from_forgery prepend: true, unless: -> { request.format.json? } | ||||
| before_action :check_sign | before_action :check_sign | ||||
| @@ -728,11 +729,6 @@ class ApplicationController < ActionController::Base | |||||
| render_not_found("未找到’#{project}’相关的项目") unless @project | render_not_found("未找到’#{project}’相关的项目") unless @project | ||||
| end | end | ||||
| def find_project_with_identifier | |||||
| @project = Project.find_by_identifier! params[:id] | |||||
| render_not_found("未找到’#{params[:id]}’相关的项目") unless @project | |||||
| end | |||||
| def find_project_with_id | def find_project_with_id | ||||
| @project = Project.find(params[:project_id] || params[:id]) | @project = Project.find(params[:project_id] || params[:id]) | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -744,9 +740,30 @@ class ApplicationController < ActionController::Base | |||||
| interactor.success? ? render_ok : render_error(interactor.error) | interactor.success? ? render_ok : render_error(interactor.error) | ||||
| end | end | ||||
| # devops 权限验证 | |||||
| def devops_authorize! | |||||
| render_forbidden unless @project.owner?(current_user) | |||||
| # projects | |||||
| def load_project | |||||
| namespace = params[:owner] | |||||
| id = params[:repo] || params[:id] | |||||
| @project = Project.find_with_namespace(namespace, id) | |||||
| if @project and current_user.can_read_project?(@project) | |||||
| logger.info "###########: has project and can read project" | |||||
| @project | |||||
| elsif current_user.is_a?(AnonymousUser) | |||||
| logger.info "###########:This is AnonymousUser" | |||||
| @project = nil if !@project.is_public? | |||||
| render_forbidden and return | |||||
| else | |||||
| logger.info "###########:project not found" | |||||
| @project = nil | |||||
| render_not_found and return | |||||
| end | |||||
| @project | |||||
| end | |||||
| def load_repository | |||||
| @repository ||= load_project.repository | |||||
| end | end | ||||
| private | private | ||||
| @@ -0,0 +1,3 @@ | |||||
| class Ci::BaseController < ApplicationController | |||||
| before_action :require_login | |||||
| end | |||||
| @@ -0,0 +1,58 @@ | |||||
| class Ci::BuildsController < Ci::BaseController | |||||
| include RepositoriesHelper | |||||
| before_action :find_project, :find_cloud_account | |||||
| before_action :find_cloud_account, except: :get_trustie_pipeline | |||||
| before_action :ci_authorize! | |||||
| def index | |||||
| result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier).builds | |||||
| render json: result | |||||
| end | |||||
| def detail | |||||
| result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).build | |||||
| render json: result | |||||
| end | |||||
| def restart | |||||
| result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).restart | |||||
| render json: result | |||||
| end | |||||
| def delete | |||||
| result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).stop | |||||
| render json: result | |||||
| end | |||||
| def logs | |||||
| result = Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier, build: params[:number], stage: params[:stage], step: params[:step]).logs | |||||
| render json: result | |||||
| end | |||||
| # get .trustie-pipeline.yml file | |||||
| def get_trustie_pipeline | |||||
| file_path_uri = URI.parse('.trustie-pipeline.yml') | |||||
| interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: params[:ref] || "master") | |||||
| if interactor.success? | |||||
| file = interactor.result | |||||
| return render json: {} if file[:status] | |||||
| json = {name: file['name'], path: file['path'], sha: file['sha'], content: render_decode64_content(file['content'])} | |||||
| render json: json | |||||
| end | |||||
| end | |||||
| private | |||||
| def find_project | |||||
| @project = Project.find params[:project_id] | |||||
| end | |||||
| def find_cloud_account | |||||
| @cloud_account = @project.ci_cloud_account | |||||
| end | |||||
| end | |||||
| @@ -1,21 +1,21 @@ | |||||
| class DevOps::CloudAccountsController < ApplicationController | |||||
| before_action :require_login | |||||
| before_action :find_project | |||||
| before_action :devops_authorize! | |||||
| class Ci::CloudAccountsController < Ci::BaseController | |||||
| include Devopsable | |||||
| before_action :auto_load_project | |||||
| before_action :ci_authorize! | |||||
| before_action :find_cloud_account, only: %i[activate] | |||||
| def create | def create | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| DevOps::CreateCloudAccountForm.new(devops_params).validate! | |||||
| Ci::CreateCloudAccountForm.new(devops_params).validate! | |||||
| # 1. 保存华为云服务器帐号 | # 1. 保存华为云服务器帐号 | ||||
| create_params = devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num]).to_i, secret: DevOps::CloudAccount.encrypted_secret(devops_params[:secret])) | |||||
| create_params = devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num]).to_i, secret: Ci::CloudAccount.encrypted_secret(devops_params[:secret])) | |||||
| if cloud_account = @project.dev_ops_cloud_account | if cloud_account = @project.dev_ops_cloud_account | ||||
| return render_error('该仓库已绑定了云帐号.') | return render_error('该仓库已绑定了云帐号.') | ||||
| else | else | ||||
| cloud_account = DevOps::CloudAccount.new(create_params) | |||||
| cloud_account = Ci::CloudAccount.new(create_params) | |||||
| cloud_account.user = current_user | cloud_account.user = current_user | ||||
| cloud_account.repo_id = @project.repository.id | |||||
| cloud_account.project_id = @project.id | |||||
| cloud_account.save! | cloud_account.save! | ||||
| end | end | ||||
| @@ -34,15 +34,15 @@ class DevOps::CloudAccountsController < ApplicationController | |||||
| logger.info "######### rpc_secret: #{rpc_secret}" | logger.info "######### rpc_secret: #{rpc_secret}" | ||||
| # 3. 创建drone server | # 3. 创建drone server | ||||
| drone_server_cmd = DevOps::Drone::Server.new(oauth.client_id, oauth.client_secret, cloud_account.drone_host, rpc_secret).generate_cmd | |||||
| drone_server_cmd = Ci::Drone::Server.new(oauth.client_id, oauth.client_secret, cloud_account.drone_host, rpc_secret).generate_cmd | |||||
| logger.info "######### drone_server_cmd: #{drone_server_cmd}" | logger.info "######### drone_server_cmd: #{drone_server_cmd}" | ||||
| # 4. 创建drone client | # 4. 创建drone client | ||||
| drone_client_cmd = DevOps::Drone::Client.new(oauth.client_id, cloud_account.drone_ip, rpc_secret).generate_cmd | |||||
| drone_client_cmd = Ci::Drone::Client.new(oauth.client_id, cloud_account.drone_ip, rpc_secret).generate_cmd | |||||
| logger.info "######### drone_client_cmd: #{drone_client_cmd}" | logger.info "######### drone_client_cmd: #{drone_client_cmd}" | ||||
| # 5. 登录远程服务器,启动drone服务 | # 5. 登录远程服务器,启动drone服务 | ||||
| result = DevOps::Drone::Start.new(cloud_account.account, cloud_account.visible_secret, cloud_account.drone_ip, drone_server_cmd, drone_client_cmd).run | |||||
| result = Ci::Drone::Start.new(cloud_account.account, cloud_account.visible_secret, cloud_account.drone_ip, drone_server_cmd, drone_client_cmd).run | |||||
| logger.info "######### result: #{result}" | logger.info "######### result: #{result}" | ||||
| @@ -50,6 +50,7 @@ class DevOps::CloudAccountsController < ApplicationController | |||||
| logger.info "######### redirect_url: #{redirect_url}" | logger.info "######### redirect_url: #{redirect_url}" | ||||
| if result && !result.blank? | if result && !result.blank? | ||||
| current_user.set_drone_step!(User::DEVOPS_UNVERIFIED) | |||||
| render_ok(redirect_url: redirect_url) | render_ok(redirect_url: redirect_url) | ||||
| else | else | ||||
| render_error('激活失败, 请检查你的云服务器信息是否正确.') | render_error('激活失败, 请检查你的云服务器信息是否正确.') | ||||
| @@ -60,12 +61,28 @@ class DevOps::CloudAccountsController < ApplicationController | |||||
| render_error(ex.message) | render_error(ex.message) | ||||
| end | end | ||||
| def activate | |||||
| result = | |||||
| if current_user.devops_has_token? | |||||
| # 已有drone_token的,直接激活项目 | |||||
| Ci::Drone::API.new(@cloud_account.drone_token, @cloud_account.drone_url, @project.owner.login, @project.identifier).activate | |||||
| else | |||||
| # 没有token,说明是第一次激活devops, 需要用户填写token值 | |||||
| return render_error('请先在CI服务端做用户认证.') if !current_user.devops_verified? | |||||
| Ci::Drone::API.new(params[:drone_token], @cloud_account.drone_url, @project.owner.login, @project.identifier).activate | |||||
| end | |||||
| if result | |||||
| set_drone_token!(current_user, @cloud_account, params[:drone_token]) | |||||
| @project.update_column(:open_devops, true) | |||||
| render_ok | |||||
| else | |||||
| render_error("激活失败,请检查你的token值是否正确.") | |||||
| end | |||||
| end | |||||
| private | private | ||||
| def devops_params | def devops_params | ||||
| params.permit(:account, :secret, :ip_num, :project_id) | params.permit(:account, :secret, :ip_num, :project_id) | ||||
| end | end | ||||
| def find_project | |||||
| @project = Project.find params[:project_id] | |||||
| end | |||||
| end | end | ||||
| @@ -0,0 +1,20 @@ | |||||
| class Ci::LanguagesController < Ci::BaseController | |||||
| # TODO 需要开启权限认证,只有该项目devops初始化成功后才能获取语言列表 | |||||
| before_action :find_langugae, only: :show | |||||
| def index | |||||
| @languages = Ci::Language.by_usage_amount_desc | |||||
| end | |||||
| def show | |||||
| end | |||||
| def common | |||||
| @languages = Ci::Language.six_common | |||||
| end | |||||
| private | |||||
| def find_langugae | |||||
| @language = Ci::Language.find params[:id] | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,32 @@ | |||||
| module Devopsable | |||||
| extend ActiveSupport::Concern | |||||
| included do | |||||
| end | |||||
| # ci 权限验证 | |||||
| def ci_authorize! | |||||
| render_forbidden unless @project.owner?(current_user) | |||||
| end | |||||
| def auto_load_project | |||||
| @project = Project.find_by(id: params[:project_id]) || Project.find_by(identifier: params[:project_id]) | |||||
| render_not_found('未找到相关的项目') if @project.blank? | |||||
| end | |||||
| # TODO 暂时限制项目拥有者才有权限操作 | |||||
| def limit_owner_can_devops!(user) | |||||
| return if @project.owner? user | |||||
| render_forbidden | |||||
| end | |||||
| def find_cloud_account | |||||
| @cloud_account = Ci::CloudAccount.find params[:id] | |||||
| end | |||||
| def set_drone_token!(user, cloud_account, drone_token) | |||||
| return if user.devops_has_token? | |||||
| cloud_account.update_column(:drone_token, drone_token) | |||||
| user.set_drone_step!(User::DEVOPS_HAS_TOKEN) | |||||
| end | |||||
| end | |||||
| @@ -10,7 +10,7 @@ module OperateProjectAbilityAble | |||||
| end | end | ||||
| def authorizate_user_can_edit_repo! | def authorizate_user_can_edit_repo! | ||||
| return if @repo.project.manager?(current_user) || current_user.admin? | |||||
| return if @repository.project.manager?(current_user) || current_user.admin? | |||||
| render_forbidden('你没有权限操作.') | render_forbidden('你没有权限操作.') | ||||
| end | end | ||||
| @@ -0,0 +1,28 @@ | |||||
| module RegisterHelper | |||||
| extend ActiveSupport::Concern | |||||
| def autologin_register(username, email, password, platform= '') | |||||
| result = {message: nil, user: nil} | |||||
| user = User.new(admin: false, login: username, mail: email, type: "User") | |||||
| user.password = password | |||||
| user.platform = platform | |||||
| user.activate | |||||
| interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) | |||||
| if interactor.success? | |||||
| gitea_user = interactor.result | |||||
| result = Gitea::User::GenerateTokenService.new(username, password).call | |||||
| user.gitea_token = result['sha1'] | |||||
| user.gitea_uid = gitea_user['id'] | |||||
| if user.save! | |||||
| UserExtension.create!(user_id: user.id) | |||||
| result[:user] = {id: user.id, token: user.gitea_token} | |||||
| end | |||||
| else | |||||
| result[:message] = interactor.error | |||||
| end | |||||
| result | |||||
| end | |||||
| end | |||||
| @@ -1,59 +0,0 @@ | |||||
| class DevOps::BuildsController < ApplicationController | |||||
| include RepositoriesHelper | |||||
| before_action :require_login | |||||
| before_action :find_project | |||||
| before_action :devops_authorize! | |||||
| def index | |||||
| cloud_account = @project.dev_ops_cloud_account | |||||
| result = DevOps::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @project.owner.login, @project.identifier).builds | |||||
| render json: result | |||||
| end | |||||
| def detail | |||||
| cloud_account = @project.dev_ops_cloud_account | |||||
| result = DevOps::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).build | |||||
| render json: result | |||||
| end | |||||
| def restart | |||||
| cloud_account = @project.dev_ops_cloud_account | |||||
| result = DevOps::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).restart | |||||
| render json: result | |||||
| end | |||||
| def delete | |||||
| cloud_account = @project.dev_ops_cloud_account | |||||
| result = DevOps::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @project.owner.login, @project.identifier, number: params[:number]).stop | |||||
| render json: result | |||||
| end | |||||
| def logs | |||||
| cloud_account = @project.dev_ops_cloud_account | |||||
| result = DevOps::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @project.owner.login, @project.identifier, build: params[:number], stage: params[:stage], step: params[:step]).logs | |||||
| render json: result | |||||
| end | |||||
| # get .trustie-pipeline.yml file | |||||
| def get_trustie_pipeline | |||||
| file_path_uri = URI.parse('.trustie-pipeline.yml') | |||||
| interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: params[:ref] || "master") | |||||
| if interactor.success? | |||||
| file = interactor.result | |||||
| return render json: {} if file[:status] | |||||
| json = {name: file['name'], path: file['path'], content: render_decode64_content(file['content'])} | |||||
| render json: json | |||||
| end | |||||
| end | |||||
| private | |||||
| def find_project | |||||
| @project = Project.find params[:project_id] | |||||
| end | |||||
| end | |||||
| @@ -1,20 +0,0 @@ | |||||
| class DevOps::LanguagesController < ApplicationController | |||||
| before_action :require_login | |||||
| before_action :find_langugae, only: :show | |||||
| def index | |||||
| @languages = DevOps::Language.by_usage_amount_desc | |||||
| end | |||||
| def show | |||||
| end | |||||
| def common | |||||
| @languages = DevOps::Language.six_common | |||||
| end | |||||
| private | |||||
| def find_langugae | |||||
| @language = DevOps::Language.find params[:id] | |||||
| end | |||||
| end | |||||
| @@ -1,5 +1,6 @@ | |||||
| class ForksController < ApplicationController | class ForksController < ApplicationController | ||||
| before_action :require_login, :find_project_with_id | |||||
| before_action :require_login | |||||
| before_action :load_project | |||||
| before_action :authenticate_project!, :authenticate_user! | before_action :authenticate_project!, :authenticate_user! | ||||
| def create | def create | ||||
| @@ -1,7 +1,7 @@ | |||||
| class IssueTagsController < ApplicationController | class IssueTagsController < ApplicationController | ||||
| before_action :require_login, except: [:index] | before_action :require_login, except: [:index] | ||||
| before_action :find_project_with_id | |||||
| before_action :set_project | |||||
| before_action :load_repository | |||||
| before_action :set_user | |||||
| before_action :check_issue_permission, except: :index | before_action :check_issue_permission, except: :index | ||||
| before_action :set_issue_tag, only: [:edit, :update, :destroy] | before_action :set_issue_tag, only: [:edit, :update, :destroy] | ||||
| @@ -38,12 +38,12 @@ class IssueTagsController < ApplicationController | |||||
| begin | begin | ||||
| issue_tag = IssueTag.new(tag_params.merge(project_id: @project.id, user_id: current_user.id)) | issue_tag = IssueTag.new(tag_params.merge(project_id: @project.id, user_id: current_user.id)) | ||||
| if issue_tag.save | if issue_tag.save | ||||
| gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call | |||||
| if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"]) | |||||
| normal_status(0, "标签创建成功") | |||||
| else | |||||
| normal_status(-1, "标签创建失败") | |||||
| end | |||||
| # gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call | |||||
| # if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"]) | |||||
| # normal_status(0, "标签创建成功") | |||||
| # else | |||||
| # normal_status(-1, "标签创建失败") | |||||
| # end | |||||
| else | else | ||||
| normal_status(-1, "标签创建失败") | normal_status(-1, "标签创建失败") | ||||
| end | end | ||||
| @@ -79,12 +79,12 @@ class IssueTagsController < ApplicationController | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| if @issue_tag.update_attributes(tag_params) | if @issue_tag.update_attributes(tag_params) | ||||
| gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call | |||||
| if gitea_tag | |||||
| normal_status(0, "标签更新成功") | |||||
| else | |||||
| normal_status(-1, "标签更新失败") | |||||
| end | |||||
| # gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call | |||||
| # if gitea_tag | |||||
| # normal_status(0, "标签更新成功") | |||||
| # else | |||||
| # normal_status(-1, "标签更新失败") | |||||
| # end | |||||
| else | else | ||||
| normal_status(-1, "标签更新失败") | normal_status(-1, "标签更新失败") | ||||
| end | end | ||||
| @@ -103,12 +103,12 @@ class IssueTagsController < ApplicationController | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| if @issue_tag.destroy | if @issue_tag.destroy | ||||
| issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call | |||||
| if issue_tag | |||||
| normal_status(0, "标签删除成功") | |||||
| else | |||||
| normal_status(-1, "标签删除失败") | |||||
| end | |||||
| # issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call | |||||
| # if issue_tag | |||||
| # normal_status(0, "标签删除成功") | |||||
| # else | |||||
| # normal_status(-1, "标签删除失败") | |||||
| # end | |||||
| else | else | ||||
| normal_status(-1, "标签删除失败") | normal_status(-1, "标签删除失败") | ||||
| end | end | ||||
| @@ -121,13 +121,8 @@ class IssueTagsController < ApplicationController | |||||
| private | private | ||||
| def set_project | |||||
| # @project = Project.find_by_identifier! params[:project_id] | |||||
| @repository = @project.repository | |||||
| def set_user | |||||
| @user = @project.owner | @user = @project.owner | ||||
| normal_status(-1, "项目不存在") unless @project.present? | |||||
| normal_status(-1, "仓库不存在") unless @repository.present? | |||||
| normal_status(-1, "用户不存在") unless @user.present? | |||||
| end | end | ||||
| def check_issue_permission | def check_issue_permission | ||||
| @@ -143,4 +138,4 @@ class IssueTagsController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -1,7 +1,7 @@ | |||||
| class IssuesController < ApplicationController | class IssuesController < ApplicationController | ||||
| before_action :require_login, except: [:index, :show, :index_chosen] | before_action :require_login, except: [:index, :show, :index_chosen] | ||||
| before_action :find_project_with_id | |||||
| before_action :set_project_and_user | |||||
| before_action :load_project | |||||
| before_action :set_user | |||||
| before_action :check_issue_permission | before_action :check_issue_permission | ||||
| before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue] | before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue] | ||||
| @@ -16,7 +16,7 @@ class IssuesController < ApplicationController | |||||
| @user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user)) | @user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user)) | ||||
| issues = @project.issues.issue_issue.issue_index_includes | issues = @project.issues.issue_issue.issue_index_includes | ||||
| issues = issues.where(is_private: false) unless @user_admin_or_member | issues = issues.where(is_private: false) unless @user_admin_or_member | ||||
| @all_issues_size = issues.size | @all_issues_size = issues.size | ||||
| @open_issues_size = issues.where.not(status_id: 5).size | @open_issues_size = issues.where.not(status_id: 5).size | ||||
| @close_issues_size = issues.where(status_id: 5).size | @close_issues_size = issues.where(status_id: 5).size | ||||
| @@ -383,11 +383,8 @@ class IssuesController < ApplicationController | |||||
| end | end | ||||
| private | private | ||||
| def set_project_and_user | |||||
| # @project = Project.find_by_identifier(params[:project_id]) || (Project.find params[:project_id]) || (Project.find params[:id]) | |||||
| def set_user | |||||
| @user = @project&.owner | @user = @project&.owner | ||||
| # normal_status(-1, "项目不存在") unless @project.present? | |||||
| normal_status(-1, "用户不存在") unless @user.present? | |||||
| end | end | ||||
| def check_project_public | def check_project_public | ||||
| @@ -1,6 +1,6 @@ | |||||
| class MembersController < ApplicationController | class MembersController < ApplicationController | ||||
| before_action :require_login | before_action :require_login | ||||
| before_action :find_project_with_id | |||||
| before_action :load_project | |||||
| before_action :find_user_with_id, only: %i[create remove change_role] | before_action :find_user_with_id, only: %i[create remove change_role] | ||||
| before_action :operate!, except: %i[index] | before_action :operate!, except: %i[index] | ||||
| before_action :check_member_exists!, only: %i[create] | before_action :check_member_exists!, only: %i[create] | ||||
| @@ -0,0 +1,39 @@ | |||||
| class Oauth::EducoderController < Oauth::BaseController | |||||
| def bind | |||||
| begin | |||||
| login = params[:login] | |||||
| callback_url = params[:callback_url] | |||||
| token = params[:token] | |||||
| ::OauthEducoderForm.new({login: login, token: token, callback_url: callback_url}).validate! | |||||
| open_user= OpenUsers::Educoder.find_by(uid: login) | |||||
| if open_user.present? && open_user.user.present? && open_user.user.email_binded? | |||||
| if current_user != open_user.user | |||||
| logout_user | |||||
| successful_authentication(open_user.user) | |||||
| end | |||||
| redirect_to callback_url | |||||
| else | |||||
| if current_user.blank? || !current_user.logged? | |||||
| user = User.find_by(login: login) | |||||
| if user | |||||
| successful_authentication(user) | |||||
| OpenUsers::Educoder.create!(user: user, uid: user.login) | |||||
| redirect_to callback_url | |||||
| else | |||||
| redirect_to oauth_register_path(login: login, callback_url: callback_url) | |||||
| end | |||||
| else | |||||
| # forge平台已登录 | |||||
| OpenUsers::Educoder.create!(user: current_user, uid: login) | |||||
| redirect_to callback_url | |||||
| end | |||||
| end | |||||
| rescue WechatOauth::Error => ex | |||||
| render_error(ex.message) | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,4 +1,6 @@ | |||||
| class OauthController < ApplicationController | class OauthController < ApplicationController | ||||
| layout "oauth_register", only: [:register] | |||||
| DEFAULT_PASSWORD = "a12345678" | DEFAULT_PASSWORD = "a12345678" | ||||
| TOKEN_CALL_BACK = "/oauth/get_token_callback" | TOKEN_CALL_BACK = "/oauth/get_token_callback" | ||||
| USER_INFO = "/oauth/userinfo" | USER_INFO = "/oauth/userinfo" | ||||
| @@ -51,4 +53,35 @@ class OauthController < ApplicationController | |||||
| def get_token_callback | def get_token_callback | ||||
| end | end | ||||
| def register | |||||
| end | |||||
| def auto_register | |||||
| login = params[:login] | |||||
| email = params[:mail] | |||||
| password = params[:password] | |||||
| callback_url = params[:callback_url] | |||||
| platform = params[:plathform] || 'educoder' | |||||
| if User.where(mail: email).exists? | |||||
| render_error("该邮箱已使用过.") and return | |||||
| end | |||||
| result = autologin_register(login, email, password, platform) | |||||
| logger.info "[Oauth educoer] =====#{result}" | |||||
| if result[:message].blank? | |||||
| logger.info "[Oauth educoer] ====auto_register success" | |||||
| user = User.find result[:user][:id] | |||||
| successful_authentication(user) | |||||
| OpenUsers::Educoder.create!(user: user, uid: user.login) | |||||
| render_ok({callback_url: callback_url}) | |||||
| # redirect_to callback_url | |||||
| else | |||||
| logger.info "[Oauth educoer] ====auto_register failed." | |||||
| render :action => "auto_register" | |||||
| end | |||||
| end | |||||
| end | end | ||||
| @@ -1,5 +1,5 @@ | |||||
| class ProjectTrendsController < ApplicationController | class ProjectTrendsController < ApplicationController | ||||
| before_action :find_project_with_id | |||||
| before_action :load_repository | |||||
| before_action :check_project_public | before_action :check_project_public | ||||
| def index | def index | ||||
| @@ -44,4 +44,4 @@ class ProjectTrendsController < ApplicationController | |||||
| normal_status(-1, "您没有权限") | normal_status(-1, "您没有权限") | ||||
| end | end | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -1,5 +1,7 @@ | |||||
| class Projects::BaseController < ApplicationController | class Projects::BaseController < ApplicationController | ||||
| include PaginateHelper | include PaginateHelper | ||||
| before_action :require_login, :check_auth | |||||
| before_action :load_project | |||||
| before_action :load_repository | |||||
| end | end | ||||
| @@ -2,8 +2,8 @@ class ProjectsController < ApplicationController | |||||
| include ApplicationHelper | include ApplicationHelper | ||||
| include OperateProjectAbilityAble | include OperateProjectAbilityAble | ||||
| include ProjectsHelper | include ProjectsHelper | ||||
| before_action :require_login, except: %i[index branches group_type_list simple] | |||||
| before_action :find_project_with_id, only: %i[show branches update destroy fork_users praise_users watch_users] | |||||
| before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users] | |||||
| before_action :load_project, except: %i[index group_type_list migrate create] | |||||
| before_action :authorizate_user_can_edit_project!, only: %i[update] | before_action :authorizate_user_can_edit_project!, only: %i[update] | ||||
| before_action :project_public?, only: %i[fork_users praise_users watch_users] | before_action :project_public?, only: %i[fork_users praise_users watch_users] | ||||
| @@ -100,8 +100,7 @@ class ProjectsController < ApplicationController | |||||
| end | end | ||||
| def simple | def simple | ||||
| project = Project.includes(:owner, :repository).select(:id, :name, :identifier, :user_id, :project_type, :open_devops).find params[:id] | |||||
| json_response(project) | |||||
| json_response(@project) | |||||
| end | end | ||||
| @@ -1,7 +1,7 @@ | |||||
| class PullRequestsController < ApplicationController | class PullRequestsController < ApplicationController | ||||
| before_action :require_login, except: [:index, :show] | before_action :require_login, except: [:index, :show] | ||||
| before_action :find_project_with_id | |||||
| before_action :set_repository | |||||
| before_action :load_repository | |||||
| before_action :set_user, only: [:new, :get_branches] | |||||
| before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos] | before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos] | ||||
| # before_action :get_relatived, only: [:edit] | # before_action :get_relatived, only: [:edit] | ||||
| include TagChosenHelper | include TagChosenHelper | ||||
| @@ -238,12 +238,8 @@ class PullRequestsController < ApplicationController | |||||
| private | private | ||||
| def set_repository | |||||
| @repository = @project.repository | |||||
| def set_user | |||||
| @user = @project.owner | @user = @project.owner | ||||
| normal_status(-1, "仓库不存在") unless @repository.present? | |||||
| normal_status(-1, "用户不存在") unless @user.present? | |||||
| end | end | ||||
| def find_pull_request | def find_pull_request | ||||
| @@ -1,11 +1,10 @@ | |||||
| class RepositoriesController < ApplicationController | class RepositoriesController < ApplicationController | ||||
| include ApplicationHelper | include ApplicationHelper | ||||
| include OperateProjectAbilityAble | include OperateProjectAbilityAble | ||||
| before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror] | before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror] | ||||
| before_action :find_project_with_includes, only: :show | |||||
| before_action :find_project, except: [:tags, :commit, :sync_mirror, :show] | |||||
| before_action :load_repository | |||||
| before_action :authorizate!, except: [:sync_mirror, :tags, :commit] | before_action :authorizate!, except: [:sync_mirror, :tags, :commit] | ||||
| before_action :find_repository_by_id, only: %i[commit sync_mirror tags] | |||||
| before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror] | before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror] | ||||
| before_action :get_ref, only: %i[entries sub_entries top_counts] | before_action :get_ref, only: %i[entries sub_entries top_counts] | ||||
| before_action :get_latest_commit, only: %i[entries sub_entries top_counts] | before_action :get_latest_commit, only: %i[entries sub_entries top_counts] | ||||
| @@ -56,18 +55,18 @@ class RepositoriesController < ApplicationController | |||||
| end | end | ||||
| def commit | def commit | ||||
| @commit = Gitea::Repository::Commits::GetService.new(@repo.user.login, @repo.identifier, params[:sha], current_user.gitea_token).call | |||||
| @commit = Gitea::Repository::Commits::GetService.new(@repository.user.login, @repository.identifier, params[:sha], current_user.gitea_token).call | |||||
| end | end | ||||
| def tags | def tags | ||||
| @tags = Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @repo.user.login, @repo.identifier, {page: params[:page], limit: params[:limit]}).call | |||||
| @tags = Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}).call | |||||
| end | end | ||||
| def edit | def edit | ||||
| end | end | ||||
| def create_file | def create_file | ||||
| interactor = Gitea::CreateFileInteractor.call(current_user, content_params) | |||||
| interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @project.owner.login, content_params) | |||||
| if interactor.success? | if interactor.success? | ||||
| @file = interactor.result | @file = interactor.result | ||||
| create_new_pr(params) | create_new_pr(params) | ||||
| @@ -77,7 +76,7 @@ class RepositoriesController < ApplicationController | |||||
| end | end | ||||
| def update_file | def update_file | ||||
| interactor = Gitea::UpdateFileInteractor.call(current_user, params.merge(identifier: @project.identifier)) | |||||
| interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @project.owner.login, params.merge(identifier: @project.identifier)) | |||||
| if interactor.success? | if interactor.success? | ||||
| @file = interactor.result | @file = interactor.result | ||||
| create_new_pr(params) | create_new_pr(params) | ||||
| @@ -88,7 +87,7 @@ class RepositoriesController < ApplicationController | |||||
| end | end | ||||
| def delete_file | def delete_file | ||||
| interactor = Gitea::DeleteFileInteractor.call(current_user, params.merge(identifier: @project.identifier)) | |||||
| interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @project.owner.login, params.merge(identifier: @project.identifier)) | |||||
| if interactor.success? | if interactor.success? | ||||
| @file = interactor.result | @file = interactor.result | ||||
| render_result(1, "文件删除成功") | render_result(1, "文件删除成功") | ||||
| @@ -102,10 +101,10 @@ class RepositoriesController < ApplicationController | |||||
| end | end | ||||
| def sync_mirror | def sync_mirror | ||||
| return render_error("正在镜像中..") if @repo.mirror.waiting? | |||||
| return render_error("正在镜像中..") if @repository.mirror.waiting? | |||||
| @repo.sync_mirror! | |||||
| SyncMirroredRepositoryJob.perform_later(@repo.id, current_user.id) | |||||
| @repository.sync_mirror! | |||||
| SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id) | |||||
| render_ok | render_ok | ||||
| end | end | ||||
| @@ -12,11 +12,11 @@ class SyncForgeController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| # def create | |||||
| # def create | |||||
| # ActiveRecord::Base.transaction do | # ActiveRecord::Base.transaction do | ||||
| # params.permit! | # params.permit! | ||||
| # sync_params = params[:sync_params] | # sync_params = params[:sync_params] | ||||
| # project_user = User.where(login: sync_params[:owner_login])&.first | |||||
| # project_user = User.where(login: sync_params[:owner_login])&.first | |||||
| # #以前已同步的项目,那么肯定存在仓库 | # #以前已同步的项目,那么肯定存在仓库 | ||||
| # SyncLog.sync_log("=================begin_to_sync_forge: project_identifier: #{sync_params[:identifier]}========") | # SyncLog.sync_log("=================begin_to_sync_forge: project_identifier: #{sync_params[:identifier]}========") | ||||
| # user_projects = Project.where(user_id: project_user.id) | # user_projects = Project.where(user_id: project_user.id) | ||||
| @@ -38,7 +38,7 @@ class SyncForgeController < ApplicationController | |||||
| # check_sync_project(project, sync_params) | # check_sync_project(project, sync_params) | ||||
| # else #新建项目 | # else #新建项目 | ||||
| # SyncLog.sync_log("=================begin_to_create_new_project========") | # SyncLog.sync_log("=================begin_to_create_new_project========") | ||||
| # project_params = { | # project_params = { | ||||
| # repository_name: sync_params[:identifier], | # repository_name: sync_params[:identifier], | ||||
| # user_id: project_user.id, | # user_id: project_user.id, | ||||
| @@ -53,7 +53,7 @@ class SyncForgeController < ApplicationController | |||||
| # new_project_score = ProjectScore.create(score_params) | # new_project_score = ProjectScore.create(score_params) | ||||
| # SyncLog.sync_log("=================new_project_score:#{new_project_score.try(:id)}========") | # SyncLog.sync_log("=================new_project_score:#{new_project_score.try(:id)}========") | ||||
| # end | # end | ||||
| # SyncRepositoryJob.perform_later(sync_params[:owner_login], sync_params[:identifier], sync_params[:repository], get_sudomain) if sync_params[:repository].present? | # SyncRepositoryJob.perform_later(sync_params[:owner_login], sync_params[:identifier], sync_params[:repository], get_sudomain) if sync_params[:repository].present? | ||||
| # check_new_project(project, sync_params) | # check_new_project(project, sync_params) | ||||
| # else | # else | ||||
| @@ -115,7 +115,7 @@ class SyncForgeController < ApplicationController | |||||
| # SyncLog.sync_log("=================sync_user_failed====#{e}") | # SyncLog.sync_log("=================sync_user_failed====#{e}") | ||||
| # end | # end | ||||
| # private | |||||
| # private | |||||
| # def check_sync_project(project,sync_params) | # def check_sync_project(project,sync_params) | ||||
| # begin | # begin | ||||
| @@ -125,8 +125,8 @@ class SyncForgeController < ApplicationController | |||||
| # # end | # # end | ||||
| # SyncLog.sync_log("----begin_to_check_sync_project----project_id:#{project.id}---------------") | # SyncLog.sync_log("----begin_to_check_sync_project----project_id:#{project.id}---------------") | ||||
| # change_project_score(project, sync_params[:project_score], sync_params[:repository]) if sync_params[:repository].present? #更新project_score | |||||
| # change_project_issues(project, sync_params[:issues],project.id, gitea_main) | |||||
| # change_project_score(project, sync_params[:project_score], sync_params[:repository]) if sync_params[:repository].present? #更新project_score | |||||
| # change_project_issues(project, sync_params[:issues],project.id, gitea_main) | |||||
| # change_project_members(project, sync_params[:members],gitea_main) | # change_project_members(project, sync_params[:members],gitea_main) | ||||
| # change_project_versions(project, sync_params[:project_versions],gitea_main) | # change_project_versions(project, sync_params[:project_versions],gitea_main) | ||||
| # change_project_watchers(project, sync_params[:project_watchers],gitea_main) | # change_project_watchers(project, sync_params[:project_watchers],gitea_main) | ||||
| @@ -134,7 +134,7 @@ class SyncForgeController < ApplicationController | |||||
| # rescue => e | # rescue => e | ||||
| # SyncLog.sync_log("=========check_sync_project_errors:#{e}===================") | # SyncLog.sync_log("=========check_sync_project_errors:#{e}===================") | ||||
| # end | # end | ||||
| # end | # end | ||||
| # def check_new_project(project,sync_params) | # def check_new_project(project,sync_params) | ||||
| @@ -167,7 +167,7 @@ class SyncForgeController < ApplicationController | |||||
| # parent_id: project.id | # parent_id: project.id | ||||
| # } | # } | ||||
| # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | ||||
| # SyncLog.sync_log("***6. end_to_sync_parises---------------") | # SyncLog.sync_log("***6. end_to_sync_parises---------------") | ||||
| # end | # end | ||||
| # end | # end | ||||
| @@ -189,7 +189,7 @@ class SyncForgeController < ApplicationController | |||||
| # end | # end | ||||
| # end | # end | ||||
| # pre_project_score.save! if change_num > 0 #如果 project_score有变化则更新 | # pre_project_score.save! if change_num > 0 #如果 project_score有变化则更新 | ||||
| # else | |||||
| # else | |||||
| # ProjectScore.create!(project_scores.merge(project_id: project.id)) | # ProjectScore.create!(project_scores.merge(project_id: project.id)) | ||||
| # end | # end | ||||
| # SyncLog.sync_log("***1. end_to_sync_project_score---------------") | # SyncLog.sync_log("***1. end_to_sync_project_score---------------") | ||||
| @@ -206,7 +206,7 @@ class SyncForgeController < ApplicationController | |||||
| # SyncLog.sync_log("***2--01. forge_issue_ids-#{forge_issue_ids.size.to_i}--------------") | # SyncLog.sync_log("***2--01. forge_issue_ids-#{forge_issue_ids.size.to_i}--------------") | ||||
| # if forge_issue_ids.size.to_i <= old_issues_params[:count].to_i | # if forge_issue_ids.size.to_i <= old_issues_params[:count].to_i | ||||
| # diff_issue_ids = old_issues_params[:ids] - forge_issue_ids | # diff_issue_ids = old_issues_params[:ids] - forge_issue_ids | ||||
| # if diff_issue_ids.size == 0 #issue数量一样,判断评论是否有增减 | # if diff_issue_ids.size == 0 #issue数量一样,判断评论是否有增减 | ||||
| # forge_journal_ids = Journal.select([:id, :journalized_id, :journalized_type]).where(journalized_id: forge_issue_ids).pluck(:id) | # forge_journal_ids = Journal.select([:id, :journalized_id, :journalized_type]).where(journalized_id: forge_issue_ids).pluck(:id) | ||||
| # diff_journal_ids = old_issues_params[:journals][:ids] - forge_journal_ids | # diff_journal_ids = old_issues_params[:journals][:ids] - forge_journal_ids | ||||
| @@ -241,10 +241,10 @@ class SyncForgeController < ApplicationController | |||||
| # # } | # # } | ||||
| # # SyncLog.sync_log("***2--03. sync_projects_params_groups-#{sync_projects_params}--------------") | # # SyncLog.sync_log("***2--03. sync_projects_params_groups-#{sync_projects_params}--------------") | ||||
| # # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) | # # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) | ||||
| # end | # end | ||||
| # end | # end | ||||
| # # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) if sync_projects_params.present? | # # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) if sync_projects_params.present? | ||||
| # SyncLog.sync_log("***2. end_to_syncissues---------------") | # SyncLog.sync_log("***2. end_to_syncissues---------------") | ||||
| # rescue Exception => e | # rescue Exception => e | ||||
| @@ -265,7 +265,7 @@ class SyncForgeController < ApplicationController | |||||
| # parent_id: project.id | # parent_id: project.id | ||||
| # } | # } | ||||
| # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | ||||
| # end | # end | ||||
| # end | # end | ||||
| # SyncLog.sync_log("***5. begin_to_sync_watchers---------------") | # SyncLog.sync_log("***5. begin_to_sync_watchers---------------") | ||||
| @@ -285,7 +285,7 @@ class SyncForgeController < ApplicationController | |||||
| # } | # } | ||||
| # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | ||||
| # end | # end | ||||
| # SyncLog.sync_log("***4. end_to_sync_versions---------------") | # SyncLog.sync_log("***4. end_to_sync_versions---------------") | ||||
| # end | # end | ||||
| # end | # end | ||||
| @@ -304,7 +304,7 @@ class SyncForgeController < ApplicationController | |||||
| # } | # } | ||||
| # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | # SyncProjectsJob.perform_later(sync_projects_params,gitea_main) | ||||
| # end | # end | ||||
| # SyncLog.sync_log("***3. end_to_sync_members---------------") | # SyncLog.sync_log("***3. end_to_sync_members---------------") | ||||
| # end | # end | ||||
| # end | # end | ||||
| @@ -1,8 +1,10 @@ | |||||
| class UsersController < ApplicationController | class UsersController < ApplicationController | ||||
| include Devopsable | |||||
| before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users] | before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users] | ||||
| before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users] | before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users] | ||||
| before_action :require_login, only: %i[me list] | |||||
| before_action :require_login, only: %i[me list devops_authenticate devops] | |||||
| before_action :auto_load_project, only: %i[devops devops_authenticate] | |||||
| skip_before_action :check_sign, only: [:attachment_show] | skip_before_action :check_sign, only: [:attachment_show] | ||||
| def list | def list | ||||
| @@ -177,7 +179,7 @@ class UsersController < ApplicationController | |||||
| def trustie_projects | def trustie_projects | ||||
| user_id = User.select(:id, :login).where(login: params[:login])&.first&.id | user_id = User.select(:id, :login).where(login: params[:login])&.first&.id | ||||
| projects = Project.visible | projects = Project.visible | ||||
| projects = projects.joins(:members).where(members: { user_id: user_id }) | projects = projects.joins(:members).where(members: { user_id: user_id }) | ||||
| search = params[:search].to_s.strip | search = params[:search].to_s.strip | ||||
| @@ -212,6 +214,19 @@ class UsersController < ApplicationController | |||||
| render_ok | render_ok | ||||
| end | end | ||||
| def devops | |||||
| @user = current_user | |||||
| limit_owner_can_devops!(user) | |||||
| @cloud_account = @user.dev_ops_cloud_account | |||||
| end | |||||
| # devops 认证 | |||||
| def devops_authenticate | |||||
| limit_owner_can_devops!(current_user) | |||||
| current_user.set_drone_step!(User::DEVOPS_VERIFIED) | |||||
| render_ok | |||||
| end | |||||
| private | private | ||||
| def load_user | def load_user | ||||
| @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id]) | @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id]) | ||||
| @@ -1,6 +1,6 @@ | |||||
| class VersionReleasesController < ApplicationController | class VersionReleasesController < ApplicationController | ||||
| before_action :find_project_with_id | |||||
| before_action :set_user_and_project | |||||
| before_action :load_repository | |||||
| before_action :set_user | |||||
| before_action :require_login, except: [:index] | before_action :require_login, except: [:index] | ||||
| before_action :find_version , only: [:edit, :update, :destroy] | before_action :find_version , only: [:edit, :update, :destroy] | ||||
| @@ -78,14 +78,14 @@ class VersionReleasesController < ApplicationController | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| begin | begin | ||||
| version_params = releases_params | version_params = releases_params | ||||
| if @version.update_attributes!(version_params) | if @version.update_attributes!(version_params) | ||||
| create_attachments(params[:attachment_ids], @version) if params[:attachment_ids].present? | create_attachments(params[:attachment_ids], @version) if params[:attachment_ids].present? | ||||
| git_version_release = Gitea::Versions::UpdateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call | git_version_release = Gitea::Versions::UpdateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call | ||||
| unless git_version_release | unless git_version_release | ||||
| raise Error, "更新失败" | raise Error, "更新失败" | ||||
| end | end | ||||
| normal_status(0, "更新成功") | normal_status(0, "更新成功") | ||||
| else | else | ||||
| normal_status(-1, "更新失败") | normal_status(-1, "更新失败") | ||||
| @@ -123,14 +123,8 @@ class VersionReleasesController < ApplicationController | |||||
| private | private | ||||
| def set_user_and_project | |||||
| # @project = Project.find_by_id(params[:project_id]) | |||||
| @repository = @project.repository #项目的仓库 | |||||
| @user = @project.owner | |||||
| unless @user.present? && @project.present? && @repository.present? | |||||
| normal_status(-1, "仓库不存在") | |||||
| end | |||||
| def set_user | |||||
| @user = @repository.user | |||||
| end | end | ||||
| def find_version | def find_version | ||||
| @@ -140,7 +134,7 @@ class VersionReleasesController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| def releases_params | |||||
| def releases_params | |||||
| { | { | ||||
| body: params[:body], | body: params[:body], | ||||
| draft: params[:draft] || false, | draft: params[:draft] || false, | ||||
| @@ -151,7 +145,7 @@ class VersionReleasesController < ApplicationController | |||||
| } | } | ||||
| end | end | ||||
| def create_attachments(attachment_ids, target) | |||||
| def create_attachments(attachment_ids, target) | |||||
| attachment_ids.each do |id| | attachment_ids.each do |id| | ||||
| attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | ||||
| unless attachment.blank? | unless attachment.blank? | ||||
| @@ -1,6 +1,6 @@ | |||||
| class VersionsController < ApplicationController | class VersionsController < ApplicationController | ||||
| before_action :require_login, except: [:index, :show] | before_action :require_login, except: [:index, :show] | ||||
| before_action :find_project_with_id | |||||
| before_action :load_repository | |||||
| before_action :check_issue_permission, except: [:show, :index] | before_action :check_issue_permission, except: [:show, :index] | ||||
| before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status] | before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status] | ||||
| @@ -166,4 +166,4 @@ class VersionsController < ApplicationController | |||||
| end | end | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::CreateCloudAccountForm | |||||
| class Ci::CreateCloudAccountForm | |||||
| include ActiveModel::Model | include ActiveModel::Model | ||||
| attr_accessor :project_id, :ip_num, :account, :secret | attr_accessor :project_id, :ip_num, :account, :secret | ||||
| @@ -0,0 +1,36 @@ | |||||
| class OauthEducoderForm | |||||
| include ActiveModel::Model | |||||
| attr_accessor :login, :token, :callback_url | |||||
| validates :login, presence: true | |||||
| validates :token, presence: true | |||||
| validates :callback_url, presence: true | |||||
| validate :check_callback_url! | |||||
| validate :check_auth! | |||||
| def check_auth! | |||||
| Rails.logger.info "====login: #{login} ====token: #{token} ==== callback_url: #{callback_url}" | |||||
| secret = OauthEducoder.config[:access_key_secret] | |||||
| Rails.logger.info "==== secret: #{secret}" | |||||
| before_raw_pay_load = Digest::SHA1.hexdigest("#{login}#{secret}#{Time.now.to_i/60-1}") | |||||
| now_raw_pay_load = Digest::SHA1.hexdigest("#{login}#{secret}#{Time.now.to_i/60}") | |||||
| Rails.logger.info "==== before_raw_pay_load: #{before_raw_pay_load}" | |||||
| Rails.logger.info "==== now_raw_pay_load: #{now_raw_pay_load}" | |||||
| Rails.logger.info "==== token: #{token}" | |||||
| if token != now_raw_pay_load && token != before_raw_pay_load | |||||
| raise '你的请求无效值无效.' | |||||
| end | |||||
| end | |||||
| def check_callback_url! | |||||
| request_host = URI.parse(callback_url).host | |||||
| callback_url = OauthEducoder.config[:callback_url_host] | |||||
| raise 'callback_url参数无效.' if request_host != callback_url | |||||
| end | |||||
| end | |||||
| @@ -1,15 +1,15 @@ | |||||
| module Gitea | module Gitea | ||||
| class CreateFileInteractor | class CreateFileInteractor | ||||
| def self.call(user, params={}) | |||||
| interactor = new(user, params) | |||||
| def self.call(token, owner, params={}) | |||||
| interactor = new(token, owner, params) | |||||
| interactor.run | interactor.run | ||||
| interactor | interactor | ||||
| end | end | ||||
| attr_reader :error, :result | attr_reader :error, :result | ||||
| def initialize(user, params) | |||||
| @user = user | |||||
| def initialize(token, owner, params) | |||||
| @owner = owner | |||||
| @params = params | @params = params | ||||
| end | end | ||||
| @@ -23,7 +23,7 @@ module Gitea | |||||
| def run | def run | ||||
| Contents::CreateForm.new(valid_params).validate! | Contents::CreateForm.new(valid_params).validate! | ||||
| response = Gitea::Repository::Entries::CreateService.new(user, @params[:identifier], @params[:filepath], file_params).call | |||||
| response = Gitea::Repository::Entries::CreateService.new(token, owner, @params[:identifier], @params[:filepath], file_params).call | |||||
| render_result(response) | render_result(response) | ||||
| rescue Exception => exception | rescue Exception => exception | ||||
| Rails.logger.info "Exception ===========> #{exception.message}" | Rails.logger.info "Exception ===========> #{exception.message}" | ||||
| @@ -33,7 +33,7 @@ module Gitea | |||||
| private | private | ||||
| attr_reader :params, :user | |||||
| attr_reader :params, :owner, :token | |||||
| def fail!(error) | def fail!(error) | ||||
| @error = error | @error = error | ||||
| @@ -1,15 +1,16 @@ | |||||
| module Gitea | module Gitea | ||||
| class DeleteFileInteractor | class DeleteFileInteractor | ||||
| def self.call(user, params={}) | |||||
| interactor = new(user, params) | |||||
| def self.call(token, owner, params={}) | |||||
| interactor = new(token, owner, params) | |||||
| interactor.run | interactor.run | ||||
| interactor | interactor | ||||
| end | end | ||||
| attr_reader :error, :result | attr_reader :error, :result | ||||
| def initialize(user, params) | |||||
| @user = user | |||||
| def initialize(token, owner, params) | |||||
| @token = token | |||||
| @owner = owner | |||||
| @params = params | @params = params | ||||
| end | end | ||||
| @@ -23,7 +24,7 @@ module Gitea | |||||
| def run | def run | ||||
| Contents::DeleteForm.new(valid_params).validate! | Contents::DeleteForm.new(valid_params).validate! | ||||
| response = Gitea::Repository::Entries::DeleteService.new(user, @params[:identifier], @params[:filepath], file_params).call | |||||
| response = Gitea::Repository::Entries::DeleteService.new(token, owner, @params[:identifier], @params[:filepath], file_params).call | |||||
| render_result(response) | render_result(response) | ||||
| rescue Exception => exception | rescue Exception => exception | ||||
| fail!(exception.message) | fail!(exception.message) | ||||
| @@ -31,7 +32,7 @@ module Gitea | |||||
| private | private | ||||
| attr_reader :params, :user | |||||
| attr_reader :params, :owner, :token | |||||
| def fail!(error) | def fail!(error) | ||||
| puts "[exception]: error" | puts "[exception]: error" | ||||
| @@ -1,15 +1,16 @@ | |||||
| module Gitea | module Gitea | ||||
| class UpdateFileInteractor | class UpdateFileInteractor | ||||
| def self.call(user, params={}) | |||||
| interactor = new(user, params) | |||||
| def self.call(token, owner, params={}) | |||||
| interactor = new(token, owner, params) | |||||
| interactor.run | interactor.run | ||||
| interactor | interactor | ||||
| end | end | ||||
| attr_reader :error, :result | attr_reader :error, :result | ||||
| def initialize(user, params) | |||||
| @user = user | |||||
| def initialize(token, owner, params) | |||||
| @owner = owner | |||||
| @token = token | |||||
| @params = params | @params = params | ||||
| end | end | ||||
| @@ -23,7 +24,7 @@ module Gitea | |||||
| def run | def run | ||||
| Contents::UpdateForm.new(valid_params).validate! | Contents::UpdateForm.new(valid_params).validate! | ||||
| response = Gitea::Repository::Entries::UpdateService.new(user, @params[:identifier], @params[:filepath], file_params).call | |||||
| response = Gitea::Repository::Entries::UpdateService.new(token, owner, @params[:identifier], @params[:filepath], file_params).call | |||||
| render_result(response) | render_result(response) | ||||
| rescue Exception => exception | rescue Exception => exception | ||||
| fail!(exception.message) | fail!(exception.message) | ||||
| @@ -31,7 +32,7 @@ module Gitea | |||||
| private | private | ||||
| attr_reader :params, :user | |||||
| attr_reader :params, :owner, :token | |||||
| def fail!(error) | def fail!(error) | ||||
| puts "[exception]: error" | puts "[exception]: error" | ||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::Drone::API < DevOps::Drone::Request | |||||
| class Ci::Drone::API < Ci::Drone::Request | |||||
| attr_reader :drone_token, :endpoint, :owner, :repo, :options | attr_reader :drone_token, :endpoint, :owner, :repo, :options | ||||
| # drone_token: | # drone_token: | ||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::Drone::Ci | |||||
| class Ci::Drone::Ci | |||||
| attr_reader :host, :username, :password, :gitea_username | attr_reader :host, :username, :password, :gitea_username | ||||
| # host: drone server's ip | # host: drone server's ip | ||||
| @@ -20,6 +20,6 @@ class DevOps::Drone::Ci | |||||
| private | private | ||||
| def cmd | def cmd | ||||
| "cd ..; cd var/lib/drone/; sqlite3 database.sqlite; .dump; select user_hash from users where user_login=#{gitea_username} " | |||||
| "cd ..; cd var/lib/drone/; sqlite3 database.sqlite; .dump; select user_hash from users where user_login=#{gitea_username};" | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::Drone::Client | |||||
| class Ci::Drone::Client | |||||
| attr_reader :client_id, :drone_ip, :rpc_secret | attr_reader :client_id, :drone_ip, :rpc_secret | ||||
| # client_id: user's client_id from oauth | # client_id: user's client_id from oauth | ||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::Drone::Error < StandardError | |||||
| class Ci::Drone::Error < StandardError | |||||
| attr_reader :code | attr_reader :code | ||||
| def initialize(code, message) | def initialize(code, message) | ||||
| @@ -0,0 +1,108 @@ | |||||
| class Ci::Drone::Request | |||||
| # Converts the response body to an ObjectifiedHash. | |||||
| def self.parse(body) | |||||
| body = decode(body) | |||||
| if body.is_a? Hash | |||||
| ObjectifiedHash.new body | |||||
| elsif body.is_a? Array | |||||
| body.collect! { |e| ObjectifiedHash.new(e) } | |||||
| elsif body == true | |||||
| body | |||||
| else | |||||
| raise Error::Parsing.new "Couldn't parse a response body" | |||||
| end | |||||
| end | |||||
| # Decodes a JSON response into Ruby object. | |||||
| def self.decode(response) | |||||
| begin | |||||
| JSON.load response | |||||
| rescue JSON::ParserError | |||||
| raise Error::Parsing.new "The response is not a valid JSON" | |||||
| end | |||||
| end | |||||
| def get(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:get, endpoint, path, options) | |||||
| end | |||||
| def post(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:post, endpoint, path, options) | |||||
| end | |||||
| def put(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:put, endpoint, path, options) | |||||
| end | |||||
| def patch(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:patch, endpoint, path, options) | |||||
| end | |||||
| def delete(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:delete, endpoint, path, options) | |||||
| end | |||||
| private | |||||
| def request(method, endpoint, path, **params) | |||||
| Rails.logger.info("[drone] request: #{method} #{path} #{params.except(:drone_token).inspect}") | |||||
| client ||= begin | |||||
| Faraday.new(url: endpoint) do |req| | |||||
| req.request :url_encoded | |||||
| req.headers['Content-Type'] = 'application/json' | |||||
| req.response :logger # 显示日志 | |||||
| req.adapter Faraday.default_adapter | |||||
| req.authorization :Bearer, params[:drone_token] | |||||
| req.headers['Authorization'] | |||||
| end | |||||
| end | |||||
| response = client.public_send(method, path) do |req| | |||||
| req.body = params.except(:drone_token).to_json | |||||
| end | |||||
| json_response(response) | |||||
| end | |||||
| # Checks the response code for common errors. | |||||
| # Returns parsed response for successful requests. | |||||
| def validate(response) | |||||
| # case response.code | |||||
| # when 400; raise Error::BadRequest.new error_message(response) | |||||
| # when 401; raise Error::Unauthorized.new error_message(response) | |||||
| # when 403; raise Error::Forbidden.new error_message(response) | |||||
| # when 404; raise Error::NotFound.new error_message(response) | |||||
| # when 405; raise Error::MethodNotAllowed.new error_message(response) | |||||
| # when 406; raise Error::DataNotAccepted.new error_message(response) | |||||
| # when 409; raise Error::Conflict.new error_message(response) | |||||
| # when 500; raise Error::InternalServerError.new error_message(response) | |||||
| # when 502; raise Error::BadGateway.new error_message(response) | |||||
| # when 503; raise Error::ServiceUnavailable.new error_message(response) | |||||
| # end | |||||
| response.parsed_response | |||||
| end | |||||
| # Checks a base_uri and params for requests. | |||||
| def validate_request_params!(endpoint) | |||||
| raise "Please set an endpoint to API" unless endpoint | |||||
| end | |||||
| def error_message(response) | |||||
| "Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \ | |||||
| "Request URI: #{response.request.base_uri}#{response.request.path}" | |||||
| end | |||||
| def json_response(response) | |||||
| result = JSON.parse(response.body) | |||||
| status = response.status | |||||
| Rails.logger.info("[drone] response:#{status} #{result.inspect}") | |||||
| response.status != 200 ? result.merge!(status: response.status) : result | |||||
| end | |||||
| end | |||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::Drone::Server | |||||
| class Ci::Drone::Server | |||||
| attr_reader :client_id, :client_secret, :drone_host, :rpc_secret | attr_reader :client_id, :client_secret, :drone_host, :rpc_secret | ||||
| # client_id: user's client_id from oauth | # client_id: user's client_id from oauth | ||||
| @@ -18,7 +18,8 @@ class DevOps::Drone::Server | |||||
| def generate_cmd | def generate_cmd | ||||
| "service docker start; docker rm -f `docker ps -qa`; docker run \ | "service docker start; docker rm -f `docker ps -qa`; docker run \ | ||||
| -v /var/run/docker.sock:/var/run/docker.sock \ | -v /var/run/docker.sock:/var/run/docker.sock \ | ||||
| -v /var/lib/drone:/data \ | |||||
| -e DRONE_DATABASE_DRIVER=mysql \ | |||||
| -e DRONE_DATABASE_DATASOURCE=#{database_username}:#{database_password}@#{database_host}:3306/drone?parseTime=true \ | |||||
| -e DRONE_GITEA_SERVER=#{gitea_url} \ | -e DRONE_GITEA_SERVER=#{gitea_url} \ | ||||
| -e DRONE_GITEA_CLIENT_ID=#{client_id} \ | -e DRONE_GITEA_CLIENT_ID=#{client_id} \ | ||||
| -e DRONE_GITEA_CLIENT_SECRET=#{client_secret} \ | -e DRONE_GITEA_CLIENT_SECRET=#{client_secret} \ | ||||
| @@ -37,4 +38,24 @@ class DevOps::Drone::Server | |||||
| def gitea_url | def gitea_url | ||||
| Gitea.gitea_config[:domain] | Gitea.gitea_config[:domain] | ||||
| end | end | ||||
| def database_username | |||||
| database_config[Rails.env]["username"] | |||||
| end | |||||
| def database_password | |||||
| database_config[Rails.env]["password"] | |||||
| end | |||||
| def database_host | |||||
| database_config[Rails.env]["host"] | |||||
| end | |||||
| def database | |||||
| database_config[Rails.env]["database"] | |||||
| end | |||||
| def database_config | |||||
| Rails.configuration.database_configuration | |||||
| end | |||||
| end | end | ||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::Drone::Start | |||||
| class Ci::Drone::Start | |||||
| attr_reader :drone_username, :drone_password, :drone_host, :drone_server_cmd, :drone_client_cmd | attr_reader :drone_username, :drone_password, :drone_host, :drone_server_cmd, :drone_client_cmd | ||||
| # drone_username="XXXX" 云服务器登录用户名 | # drone_username="XXXX" 云服务器登录用户名 | ||||
| @@ -1,108 +0,0 @@ | |||||
| class DevOps::Drone::Request | |||||
| # Converts the response body to an ObjectifiedHash. | |||||
| def self.parse(body) | |||||
| body = decode(body) | |||||
| if body.is_a? Hash | |||||
| ObjectifiedHash.new body | |||||
| elsif body.is_a? Array | |||||
| body.collect! { |e| ObjectifiedHash.new(e) } | |||||
| elsif body == true | |||||
| body | |||||
| else | |||||
| raise Error::Parsing.new "Couldn't parse a response body" | |||||
| end | |||||
| end | |||||
| # Decodes a JSON response into Ruby object. | |||||
| def self.decode(response) | |||||
| begin | |||||
| JSON.load response | |||||
| rescue JSON::ParserError | |||||
| raise Error::Parsing.new "The response is not a valid JSON" | |||||
| end | |||||
| end | |||||
| def get(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:get, endpoint, path, options) | |||||
| end | |||||
| def post(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:post, endpoint, path, options) | |||||
| end | |||||
| def put(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:put, endpoint, path, options) | |||||
| end | |||||
| def patch(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:patch, endpoint, path, options) | |||||
| end | |||||
| def delete(endpoint, path, options={}) | |||||
| validate_request_params!(endpoint) | |||||
| request(:delete, endpoint, path, options) | |||||
| end | |||||
| private | |||||
| def request(method, endpoint, path, **params) | |||||
| Rails.logger.info("[drone] request: #{method} #{path} #{params.except(:drone_token).inspect}") | |||||
| client ||= begin | |||||
| Faraday.new(url: endpoint) do |req| | |||||
| req.request :url_encoded | |||||
| req.headers['Content-Type'] = 'application/json' | |||||
| req.response :logger # 显示日志 | |||||
| req.adapter Faraday.default_adapter | |||||
| req.authorization :Bearer, params[:drone_token] | |||||
| req.headers['Authorization'] | |||||
| end | |||||
| end | |||||
| response = client.public_send(method, path) do |req| | |||||
| req.body = params.except(:drone_token).to_json | |||||
| end | |||||
| json_response(response) | |||||
| end | |||||
| # Checks the response code for common errors. | |||||
| # Returns parsed response for successful requests. | |||||
| def validate(response) | |||||
| # case response.code | |||||
| # when 400; raise Error::BadRequest.new error_message(response) | |||||
| # when 401; raise Error::Unauthorized.new error_message(response) | |||||
| # when 403; raise Error::Forbidden.new error_message(response) | |||||
| # when 404; raise Error::NotFound.new error_message(response) | |||||
| # when 405; raise Error::MethodNotAllowed.new error_message(response) | |||||
| # when 406; raise Error::DataNotAccepted.new error_message(response) | |||||
| # when 409; raise Error::Conflict.new error_message(response) | |||||
| # when 500; raise Error::InternalServerError.new error_message(response) | |||||
| # when 502; raise Error::BadGateway.new error_message(response) | |||||
| # when 503; raise Error::ServiceUnavailable.new error_message(response) | |||||
| # end | |||||
| response.parsed_response | |||||
| end | |||||
| # Checks a base_uri and params for requests. | |||||
| def validate_request_params!(endpoint) | |||||
| raise "Please set an endpoint to API" unless endpoint | |||||
| end | |||||
| def error_message(response) | |||||
| "Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \ | |||||
| "Request URI: #{response.request.base_uri}#{response.request.path}" | |||||
| end | |||||
| def json_response(response) | |||||
| result = JSON.parse(response.body) | |||||
| status = response.status | |||||
| Rails.logger.info("[drone] response:#{status} #{result.inspect}") | |||||
| response.status != 200 ? result.merge!(status: response.status) : result | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,20 @@ | |||||
| module OauthEducoder | |||||
| class << self | |||||
| def config | |||||
| educoder_config = {} | |||||
| begin | |||||
| config = Rails.application.config_for(:configuration).symbolize_keys! | |||||
| educoder_config = config[:oauth_educoder].symbolize_keys! | |||||
| raise 'oauth educoder config missing' if educoder_config.blank? | |||||
| rescue => ex | |||||
| raise ex if Rails.env.production? | |||||
| puts %Q{\033[33m [warning] educoder config or configuration.yml missing, | |||||
| please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m} | |||||
| educoder_config = {} | |||||
| end | |||||
| educoder_config | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::CloudAccount < ApplicationRecord | |||||
| class Ci::CloudAccount < ApplicationRecord | |||||
| belongs_to :project | belongs_to :project | ||||
| belongs_to :user | belongs_to :user | ||||
| belongs_to :repository, foreign_key: :repo_id | belongs_to :repository, foreign_key: :repo_id | ||||
| @@ -1,4 +1,4 @@ | |||||
| class DevOps::Language < ApplicationRecord | |||||
| class Ci::Language < ApplicationRecord | |||||
| # before_save :encode_content | # before_save :encode_content | ||||
| belongs_to :cover, class_name: "Attachment", foreign_key: :cover_id, optional: true | belongs_to :cover, class_name: "Attachment", foreign_key: :cover_id, optional: true | ||||
| @@ -0,0 +1,29 @@ | |||||
| module Droneable | |||||
| extend ActiveSupport::Concern | |||||
| included do | |||||
| end | |||||
| def devops_uninit? | |||||
| self.devops_step === User::DEVOPS_UNINIT | |||||
| end | |||||
| def devops_unverified? | |||||
| self.devops_step === User::DEVOPS_UNVERIFIED | |||||
| end | |||||
| def devops_verified? | |||||
| self.devops_step === User::DEVOPS_VERIFIED | |||||
| end | |||||
| def devops_has_token? | |||||
| self.devops_step === User::DEVOPS_HAS_TOKEN | |||||
| end | |||||
| def set_drone_step!(step) | |||||
| self.update_column(:devops_step, step) | |||||
| end | |||||
| module ClassMethods | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,14 @@ | |||||
| module ProjectAbility | |||||
| extend ActiveSupport::Concern | |||||
| included do | |||||
| end | |||||
| def can_read_project?(project) | |||||
| return true if self.admin? | |||||
| return false if !project.is_public? && !project.member?(self.id) | |||||
| true | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,9 @@ | |||||
| class OpenUsers::Educoder < OpenUser | |||||
| def nickname | |||||
| extra&.[]('nickname') | |||||
| end | |||||
| def en_type | |||||
| 'educoder' | |||||
| end | |||||
| end | |||||
| @@ -20,7 +20,7 @@ class Project < ApplicationRecord | |||||
| has_many :fork_users, dependent: :destroy | has_many :fork_users, dependent: :destroy | ||||
| # has_many :commits, dependent: :destroy | # has_many :commits, dependent: :destroy | ||||
| has_one :dev_ops_cloud_account, class_name: 'DevOps::CloudAccount', dependent: :destroy | |||||
| has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', dependent: :destroy | |||||
| has_one :project_score, dependent: :destroy | has_one :project_score, dependent: :destroy | ||||
| has_one :repository, dependent: :destroy | has_one :repository, dependent: :destroy | ||||
| has_many :pull_requests, dependent: :destroy | has_many :pull_requests, dependent: :destroy | ||||
| @@ -169,4 +169,15 @@ class Project < ApplicationRecord | |||||
| joins(:members).where(members: { user_id: member_user_id}) | joins(:members).where(members: { user_id: member_user_id}) | ||||
| end | end | ||||
| def self.find_with_namespace(namespace_path, identifier) | |||||
| logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} " | |||||
| user = User.find_by_login namespace_path | |||||
| return nil if user.blank? | |||||
| project = user.projects.find_by(identifier: identifier) | |||||
| return nil if project.blank? | |||||
| project | |||||
| end | |||||
| end | end | ||||
| @@ -3,7 +3,7 @@ class Repository < ApplicationRecord | |||||
| belongs_to :project, :touch => true | belongs_to :project, :touch => true | ||||
| belongs_to :user | belongs_to :user | ||||
| has_one :mirror, foreign_key: :repo_id | has_one :mirror, foreign_key: :repo_id | ||||
| has_one :dev_ops_cloud_account, class_name: 'DevOps::CloudAccount', foreign_key: :repo_id | |||||
| has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', foreign_key: :repo_id | |||||
| has_many :version_releases, dependent: :destroy | has_many :version_releases, dependent: :destroy | ||||
| validates :identifier, presence: true | validates :identifier, presence: true | ||||
| @@ -5,8 +5,17 @@ class User < ApplicationRecord | |||||
| include Likeable | include Likeable | ||||
| include BaseModel | include BaseModel | ||||
| include ProjectOperable | include ProjectOperable | ||||
| include ProjectAbility | |||||
| include Droneable | |||||
| # include Searchable::Dependents::User | # include Searchable::Dependents::User | ||||
| # devops step | |||||
| # devops_step column: 0: 未填写服务器信息;1: 已填写服务器信息(未认证); 2: 已认证, 3: 已填写token值 | |||||
| DEVOPS_UNINIT = 0 | |||||
| DEVOPS_UNVERIFIED = 1 | |||||
| DEVOPS_VERIFIED = 2 | |||||
| DEVOPS_HAS_TOKEN = 3 | |||||
| # Account statuses | # Account statuses | ||||
| STATUS_ANONYMOUS = 0 | STATUS_ANONYMOUS = 0 | ||||
| STATUS_ACTIVE = 1 | STATUS_ACTIVE = 1 | ||||
| @@ -70,8 +79,9 @@ class User < ApplicationRecord | |||||
| # 关注 | # 关注 | ||||
| has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注 | has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注 | ||||
| has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户 | has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户 | ||||
| has_many :watchers, as: :watchable, dependent: :destroy | |||||
| has_many :watchers, as: :watchable, dependent: :destroy | |||||
| has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', dependent: :destroy | |||||
| # 认证 | # 认证 | ||||
| has_many :apply_user_authentication | has_many :apply_user_authentication | ||||
| @@ -1,5 +1,5 @@ | |||||
| class Gitea::Repository::Entries::CreateService < Gitea::ClientService | class Gitea::Repository::Entries::CreateService < Gitea::ClientService | ||||
| attr_reader :user, :repo_name, :filepath, :body | |||||
| attr_reader :token, :owner, :repo_name, :filepath, :body | |||||
| # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) | # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) | ||||
| # filepath: path of the dir, file, symlink or submodule in the repo | # filepath: path of the dir, file, symlink or submodule in the repo | ||||
| @@ -20,8 +20,9 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService | |||||
| # "new_branch": "string" | # "new_branch": "string" | ||||
| # } | # } | ||||
| # | # | ||||
| def initialize(user, repo_name, filepath, body) | |||||
| @user = user | |||||
| def initialize(token, owner, repo_name, filepath, body) | |||||
| @token = token | |||||
| @owner = owner | |||||
| @repo_name = repo_name | @repo_name = repo_name | ||||
| @filepath = filepath | @filepath = filepath | ||||
| @body = body | @body = body | ||||
| @@ -33,11 +34,11 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService | |||||
| private | private | ||||
| def params | def params | ||||
| Hash.new.merge(token: user.gitea_token, data: body) | |||||
| Hash.new.merge(token: token, data: body) | |||||
| end | end | ||||
| def url | def url | ||||
| "/repos/#{user.login}/#{repo_name}/contents/#{filepath}".freeze | |||||
| "/repos/#{owner}/#{repo_name}/contents/#{filepath}".freeze | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,5 +1,5 @@ | |||||
| class Gitea::Repository::Entries::DeleteService < Gitea::ClientService | class Gitea::Repository::Entries::DeleteService < Gitea::ClientService | ||||
| attr_reader :user, :repo_name, :filepath, :body | |||||
| attr_reader :token, :owner, :repo_name, :filepath, :body | |||||
| # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) | # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) | ||||
| # filepath: path of the dir, file, symlink or submodule in the repo | # filepath: path of the dir, file, symlink or submodule in the repo | ||||
| @@ -19,8 +19,9 @@ class Gitea::Repository::Entries::DeleteService < Gitea::ClientService | |||||
| # "new_branch": "string", | # "new_branch": "string", | ||||
| # "sha": "string", #require | # "sha": "string", #require | ||||
| # } | # } | ||||
| def initialize(user, repo_name, filepath, body) | |||||
| @user = user | |||||
| def initialize(token, owner, repo_name, filepath, body) | |||||
| @token = token | |||||
| @owner = owner | |||||
| @repo_name = repo_name | @repo_name = repo_name | ||||
| @filepath = filepath | @filepath = filepath | ||||
| @body = body | @body = body | ||||
| @@ -32,11 +33,11 @@ class Gitea::Repository::Entries::DeleteService < Gitea::ClientService | |||||
| private | private | ||||
| def params | def params | ||||
| Hash.new.merge(token: user.gitea_token, data: body) | |||||
| Hash.new.merge(token: token, data: body) | |||||
| end | end | ||||
| def url | def url | ||||
| "/repos/#{user.login}/#{repo_name}/contents/#{filepath}".freeze | |||||
| "/repos/#{owner}/#{repo_name}/contents/#{filepath}".freeze | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,5 +1,5 @@ | |||||
| class Gitea::Repository::Entries::UpdateService < Gitea::ClientService | class Gitea::Repository::Entries::UpdateService < Gitea::ClientService | ||||
| attr_reader :user, :repo_name, :filepath, :body | |||||
| attr_reader :token, :owner, :repo_name, :filepath, :body | |||||
| # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) | # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) | ||||
| # filepath: path of the dir, file, symlink or submodule in the repo | # filepath: path of the dir, file, symlink or submodule in the repo | ||||
| @@ -20,8 +20,9 @@ class Gitea::Repository::Entries::UpdateService < Gitea::ClientService | |||||
| # "new_branch": "string" | # "new_branch": "string" | ||||
| # } | # } | ||||
| # | # | ||||
| def initialize(user, repo_name, filepath, body) | |||||
| @user = user | |||||
| def initialize(token, owner, repo_name, filepath, body) | |||||
| @token = token | |||||
| @owner = owner | |||||
| @repo_name = repo_name | @repo_name = repo_name | ||||
| @filepath = filepath | @filepath = filepath | ||||
| @body = body | @body = body | ||||
| @@ -33,11 +34,11 @@ class Gitea::Repository::Entries::UpdateService < Gitea::ClientService | |||||
| private | private | ||||
| def params | def params | ||||
| Hash.new.merge(token: user.gitea_token, data: body) | |||||
| Hash.new.merge(token: token, data: body) | |||||
| end | end | ||||
| def url | def url | ||||
| "/repos/#{user.login}/#{repo_name}/contents/#{filepath}".freeze | |||||
| "/repos/#{owner}/#{repo_name}/contents/#{filepath}".freeze | |||||
| end | end | ||||
| end | end | ||||
| @@ -0,0 +1,14 @@ | |||||
| <html> | |||||
| <head> | |||||
| <%= csrf_meta_tags %> | |||||
| <%= csp_meta_tag %> | |||||
| <%= javascript_include_tag '/javascripts/jquery-1.8.3-ui-1.9.2-ujs-2.0.3', '': '' %> | |||||
| <%= stylesheet_link_tag '/stylesheets/css/oauth', '', :media => 'all' %> | |||||
| </head> | |||||
| <body> | |||||
| <div class="IndexContent"> | |||||
| <%= image_tag('/images/oauth/logo.png') %> | |||||
| <%= yield %> | |||||
| </div> | |||||
| </body> | |||||
| </html> | |||||
| @@ -0,0 +1,78 @@ | |||||
| <div class="indexPanel"> | |||||
| <p class="indexTitle">完善信息,进入比赛</p> | |||||
| <div class="indexInfos"> | |||||
| <%= form_tag('', method: :post, id: 'oauth_form', class: 'form-inline search-form flex-1', remote: true) do %> | |||||
| <%= hidden_field_tag 'callback_url', params[:callback_url] %> | |||||
| <div class="indexInfo"> | |||||
| <span>用户名:</span> | |||||
| <%= text_field_tag :login, params[:login], placeholder: '请输入用户名', readonly: true, id: 'login' %> | |||||
| <p class="checkInfo loginCheck"><span></span></p> | |||||
| </div> | |||||
| <div class="indexInfo"> | |||||
| <span>邮箱:</span> | |||||
| <%= text_field_tag :mail, '', placeholder: '请输入绑定邮箱', maxlength: 40, id: 'email' %> | |||||
| <p class="checkInfo emailCheck"><span></span></p> | |||||
| </div> | |||||
| <div class="indexInfo"> | |||||
| <span>密码:</span> | |||||
| <%= password_field_tag :password, '', placeholder: '请输入账号密码', id: 'password' %> | |||||
| <p class="checkInfo passwordCheck"><span></span></p> | |||||
| </div> | |||||
| <div class="indexBtn"> | |||||
| <button type="button" class="indexSubmit" id="indexSubmit" onclick="submitdata();">确定</button> | |||||
| </div> | |||||
| <% end %> | |||||
| </div> | |||||
| </div> | |||||
| <script type="text/javascript"> | |||||
| function submitdata(){ | |||||
| var login = $("#login").val(); | |||||
| var email = $("#email").val(); | |||||
| var password = $("#password").val(); | |||||
| if(!login){ | |||||
| $(".loginCheck span").html("请输入账号"); | |||||
| return; | |||||
| }else{ | |||||
| $(".loginCheck span").html(""); | |||||
| } | |||||
| if(!email){ | |||||
| $(".emailCheck span").html("请输入绑定的邮箱"); | |||||
| return; | |||||
| }else{ | |||||
| $(".emailCheck span").html(""); | |||||
| } | |||||
| if(!password){ | |||||
| $(".passwordCheck span").html("请输入账号密码"); | |||||
| return; | |||||
| }else if(password.length < 8){ | |||||
| $(".passwordCheck span").html("密码最少为8位数"); | |||||
| return; | |||||
| }else{ | |||||
| $(".passwordCheck span").html(""); | |||||
| } | |||||
| $.ajax({ | |||||
| url: "<%= oauth_auto_register_path %>", | |||||
| data: $("#oauth_form").serialize(), | |||||
| type: 'post', | |||||
| dataType: "json", | |||||
| success: function(data) { | |||||
| console.log(data) | |||||
| if (data) { | |||||
| if(data.message){ | |||||
| $(".emailCheck span").html("该邮箱已存在."); | |||||
| return; | |||||
| } | |||||
| // data.redirect contains the string URL to redirect to | |||||
| // window.location.href = "<%#= params[:callback_url] %>"; | |||||
| window.location.href = data.callback_url; | |||||
| } | |||||
| }, | |||||
| error: function (data) { | |||||
| console.log('ajax error handling',data); | |||||
| } | |||||
| }); | |||||
| } | |||||
| </script> | |||||
| @@ -1,12 +1,13 @@ | |||||
| json.count @forks_count | json.count @forks_count | ||||
| json.users do | |||||
| json.users do | |||||
| json.array! @fork_users.each do |f| | json.array! @fork_users.each do |f| | ||||
| user = f.user | |||||
| fork_project = Project.select(:id,:name).find_by(id: f.fork_project_id) | |||||
| user = f.user | |||||
| fork_project = Project.select(:id,:name, :identifier).find_by(id: f.fork_project_id) | |||||
| json.id f.fork_project_id | json.id f.fork_project_id | ||||
| json.identifier fork_project.identifier | |||||
| json.name "#{user.try(:show_real_name)}/#{fork_project.try(:name)}" | json.name "#{user.try(:show_real_name)}/#{fork_project.try(:name)}" | ||||
| json.login user.try(:login) | json.login user.try(:login) | ||||
| json.image_url url_to_avatar(user) | json.image_url url_to_avatar(user) | ||||
| json.format_time f.created_at.strftime("%Y-%m-%d") | json.format_time f.created_at.strftime("%Y-%m-%d") | ||||
| end | end | ||||
| end | |||||
| end | |||||
| @@ -1,6 +1,6 @@ | |||||
| json.commit do | json.commit do | ||||
| json.sha commit['sha'] | json.sha commit['sha'] | ||||
| json.url EduSetting.get('host_name') + commit_repository_path(project.repository, commit['sha']) | |||||
| # json.url EduSetting.get('host_name') + commit_repository_path(project.repository, commit['sha']) | |||||
| json.message commit['commit']['message'] | json.message commit['commit']['message'] | ||||
| json.author commit['commit']['author'] | json.author commit['commit']['author'] | ||||
| json.committer commit['commit']['committer'] | json.committer commit['commit']['committer'] | ||||
| @@ -31,6 +31,7 @@ json.fork_info do | |||||
| if @fork_project.present? | if @fork_project.present? | ||||
| json.fork_form_name @fork_project.try(:name) | json.fork_form_name @fork_project.try(:name) | ||||
| json.fork_project_user_login @fork_project_user.try(:login) | json.fork_project_user_login @fork_project_user.try(:login) | ||||
| json.fork_project_identifier @fork_project.identifier | |||||
| json.fork_project_user_name @fork_project_user.try(:show_real_name) | json.fork_project_user_name @fork_project_user.try(:show_real_name) | ||||
| end | end | ||||
| end | end | ||||
| @@ -0,0 +1,12 @@ | |||||
| json.step @user.devops_step | |||||
| json.cloud_account do | |||||
| if @cloud_account && !@user.devops_uninit? | |||||
| json.account @cloud_account.account | |||||
| json.ip @cloud_account.drone_ip | |||||
| json.secret @cloud_account.visible_secret | |||||
| json.authenticate_url "#{@cloud_account.drone_url}/login" if @user.devops_unverified? | |||||
| json.get_drone_token_url "#{@cloud_account.drone_url}/account" if @user.devops_verified? | |||||
| else | |||||
| json.nil! | |||||
| end | |||||
| end | |||||
| @@ -12,5 +12,4 @@ json.user_phone_binded @user.phone.present? | |||||
| # json.email @user.mail | # json.email @user.mail | ||||
| json.profile_completed @user.profile_completed? | json.profile_completed @user.profile_completed? | ||||
| json.professional_certification @user.professional_certification | json.professional_certification @user.professional_certification | ||||
| json.devops_step @user.devops_step | |||||
| @@ -5,8 +5,8 @@ json.members_count project.members.count | |||||
| json.issues_count project.issues.count | json.issues_count project.issues.count | ||||
| json.changesets_count project.project_score&.changeset_num.to_i | json.changesets_count project.project_score&.changeset_num.to_i | ||||
| json.is_public project&.is_public | |||||
| json.can_visited project&.can_visited? | |||||
| json.is_public project.is_public? | |||||
| json.can_visited project.can_visited? | |||||
| json.owner do | json.owner do | ||||
| json.partial! 'users/shared/real_user', user: project.owner | json.partial! 'users/shared/real_user', user: project.owner | ||||
| @@ -5,4 +5,4 @@ json.image_url url_to_avatar(subject) | |||||
| json.owner_id subject.user.id | json.owner_id subject.user.id | ||||
| json.owner_name subject.user.full_name | json.owner_name subject.user.full_name | ||||
| json.visits_count subject.visits | json.visits_count subject.visits | ||||
| json.can_visited subject&.can_visited? | |||||
| json.can_visited subject.can_visited? | |||||
| @@ -12,5 +12,4 @@ Rails.application.config.assets.paths << Rails.root.join('vendor/assets') | |||||
| # Precompile additional assets. | # Precompile additional assets. | ||||
| # application.js, application.css, and all non-JS/CSS in the app/assets | # application.js, application.css, and all non-JS/CSS in the app/assets | ||||
| # folder are already added. | # folder are already added. | ||||
| Rails.application.config.assets.precompile += %w( admin.js admin.css college.js college.css cooperative.js cooperative.css ) | |||||
| Rails.application.config.assets.precompile += %w( admin.js admin.css college.js college.css cooperative.js cooperative.css oauth.css ) | |||||
| @@ -13,10 +13,19 @@ Rails.application.routes.draw do | |||||
| get 'auth/qq/callback', to: 'oauth/qq#create' | get 'auth/qq/callback', to: 'oauth/qq#create' | ||||
| get 'auth/failure', to: 'oauth/base#auth_failure' | get 'auth/failure', to: 'oauth/base#auth_failure' | ||||
| get 'auth/cas/callback', to: 'oauth/cas#create' | get 'auth/cas/callback', to: 'oauth/cas#create' | ||||
| get 'oauth/bind', to: 'oauth/educoder#bind' | |||||
| get 'oauth/register', to: 'oauth#register' | |||||
| post 'oauth/auto_register', to: 'oauth#auto_register' | |||||
| resources :edu_settings | resources :edu_settings | ||||
| scope '/api' do | scope '/api' do | ||||
| namespace :dev_ops do | |||||
| resources :cloud_accounts, only: [:create] | |||||
| namespace :ci do | |||||
| resources :cloud_accounts, only: [:create] do | |||||
| member do | |||||
| post :activate | |||||
| end | |||||
| end | |||||
| resources :languages, only: [:index, :show] do | resources :languages, only: [:index, :show] do | ||||
| collection do | collection do | ||||
| get :common | get :common | ||||
| @@ -85,41 +94,6 @@ Rails.application.routes.draw do | |||||
| end | end | ||||
| end | end | ||||
| resources :projects do | resources :projects do | ||||
| resources :hooks | |||||
| resources :pull_requests, except: [:destroy] do | |||||
| member do | |||||
| post :pr_merge | |||||
| # post :check_merge | |||||
| post :refuse_merge | |||||
| end | |||||
| collection do | |||||
| post :check_can_merge | |||||
| get :create_merge_infos | |||||
| get :get_branches | |||||
| end | |||||
| end | |||||
| resources :version_releases, only: [:index,:new, :create, :edit, :update, :destroy] | |||||
| resources :project_trends, only: [:index, :create] | |||||
| resources :issues do | |||||
| collection do | |||||
| get :commit_issues | |||||
| get :index_chosen | |||||
| post :clean | |||||
| post :series_update | |||||
| end | |||||
| member do | |||||
| post :copy | |||||
| post :close_issue | |||||
| post :lock_issue | |||||
| end | |||||
| end | |||||
| resources :issue_tags, only: [:create, :edit, :update, :destroy, :index] | |||||
| resources :versions do | |||||
| member do | |||||
| post :update_status | |||||
| end | |||||
| end | |||||
| resources :praise_tread, only: [:index] do | resources :praise_tread, only: [:index] do | ||||
| collection do | collection do | ||||
| post :like | post :like | ||||
| @@ -127,25 +101,10 @@ Rails.application.routes.draw do | |||||
| get :check_like | get :check_like | ||||
| end | end | ||||
| end | end | ||||
| resources :members, only: [:index, :create] do | |||||
| collection do | |||||
| delete :remove | |||||
| put :change_role | |||||
| end | |||||
| end | |||||
| resources :forks, only: [:create] | |||||
| collection do | collection do | ||||
| post :migrate | post :migrate | ||||
| get :group_type_list | get :group_type_list | ||||
| post :watch | |||||
| end | |||||
| member do | |||||
| get :branches | |||||
| post :watch | |||||
| get :watch_users | |||||
| get :praise_users | |||||
| get :fork_users | |||||
| get :simple | |||||
| end | end | ||||
| end | end | ||||
| @@ -190,11 +149,12 @@ Rails.application.routes.draw do | |||||
| post :sync_salt | post :sync_salt | ||||
| get :trustie_projects | get :trustie_projects | ||||
| get :trustie_related_projects | get :trustie_related_projects | ||||
| get :devops | |||||
| put :devops_authenticate | |||||
| end | end | ||||
| scope module: :users do | scope module: :users do | ||||
| # resources :courses, only: [:index] | |||||
| resources :projects, only: [:index] | |||||
| # resources :projects, only: [:index] | |||||
| # resources :subjects, only: [:index] | # resources :subjects, only: [:index] | ||||
| resources :project_packages, only: [:index] | resources :project_packages, only: [:index] | ||||
| # 私信 | # 私信 | ||||
| @@ -204,11 +164,6 @@ Rails.application.routes.draw do | |||||
| # resource :unread_message_info, only: [:show] | # resource :unread_message_info, only: [:show] | ||||
| end | end | ||||
| resources :projects, module: :users, only: [] do | |||||
| get :search, on: :collection | |||||
| end | |||||
| resources :tidings, only: [:index] | resources :tidings, only: [:index] | ||||
| scope module: :users do | scope module: :users do | ||||
| @@ -227,23 +182,6 @@ Rails.application.routes.draw do | |||||
| end | end | ||||
| end | end | ||||
| resources :repositories, only: [:index, :show, :edit] do | |||||
| member do | |||||
| get :entries | |||||
| match :sub_entries, :via => [:get, :put] | |||||
| get :commits | |||||
| post :files | |||||
| get :tags | |||||
| post :create_file | |||||
| put :update_file | |||||
| delete :delete_file | |||||
| post :repo_hook | |||||
| post :sync_mirror | |||||
| get :top_counts | |||||
| get 'commits/:sha', to: 'repositories#commit', as: 'commit' | |||||
| end | |||||
| end | |||||
| resources :users_for_private_messages, only: [:index] | resources :users_for_private_messages, only: [:index] | ||||
| resources :files, only: [:index, :show, :update] do | resources :files, only: [:index, :show, :update] do | ||||
| @@ -263,119 +201,6 @@ Rails.application.routes.draw do | |||||
| end | end | ||||
| end | end | ||||
| resources :courses do | |||||
| member do | |||||
| get 'settings', :action => 'settings', :as => 'settings' | |||||
| post 'set_invite_code_halt' | |||||
| post 'set_public_or_private' | |||||
| post 'search_teacher_candidate' | |||||
| post 'add_teacher' | |||||
| post 'create_graduation_group' | |||||
| post 'join_graduation_group' | |||||
| post 'set_course_group' | |||||
| post 'change_course_admin' | |||||
| post 'change_member_role' | |||||
| post 'change_course_teacher' | |||||
| post 'delete_course_teacher' | |||||
| post 'teacher_application_review' | |||||
| post 'transfer_to_course_group' | |||||
| post 'delete_from_course' | |||||
| post 'add_students_by_search' | |||||
| post 'create_group_by_importing_file' | |||||
| post 'duplicate_course' | |||||
| post 'visits_plus_one' | |||||
| get 'get_historical_courses' | |||||
| get 'get_historical_course_students' | |||||
| get 'course_group_list' | |||||
| get 'add_teacher_popup' | |||||
| get 'teachers' | |||||
| get 'apply_teachers' | |||||
| get 'graduation_group_list' | |||||
| get 'top_banner' | |||||
| get 'left_banner' | |||||
| get 'students' | |||||
| get 'all_course_groups' | |||||
| get 'search_users' | |||||
| get 'base_info' | |||||
| get 'attahcment_category_list' | |||||
| get 'export_member_scores_excel' #导出课堂信息 | |||||
| get 'export_couser_info' | |||||
| get 'export_member_act_score' | |||||
| post 'switch_to_teacher' | |||||
| post 'switch_to_assistant' | |||||
| post 'switch_to_student' | |||||
| post 'exit_course' | |||||
| get 'informs' | |||||
| post 'update_informs' | |||||
| post 'new_informs' | |||||
| delete 'delete_informs' | |||||
| get 'online_learning' | |||||
| post 'join_excellent_course' | |||||
| get 'tasks_list' | |||||
| post 'update_task_position' | |||||
| get 'course_groups' | |||||
| post 'join_course_group' | |||||
| get 'work_score' | |||||
| get 'act_score' | |||||
| get 'statistics' | |||||
| get 'course_videos' | |||||
| delete 'delete_course_video' | |||||
| post :inform_up | |||||
| post :inform_down | |||||
| end | |||||
| collection do | |||||
| post 'apply_to_join_course' | |||||
| post 'search_course_list' | |||||
| get 'board_list' | |||||
| get 'mine' | |||||
| get 'search_slim' | |||||
| end | |||||
| resources :course_stages, shallow: true do | |||||
| member do | |||||
| post :up_position | |||||
| post :down_position | |||||
| end | |||||
| end | |||||
| resources :course_groups, shallow: true do | |||||
| member do | |||||
| post 'rename_group' | |||||
| post 'move_category' | |||||
| post 'set_invite_code_halt' | |||||
| end | |||||
| end | |||||
| end | |||||
| resources :course_modules, shallow: true do | |||||
| member do | |||||
| get 'sticky_module' | |||||
| get 'hidden_module' | |||||
| post 'rename_module' | |||||
| post 'add_second_category' | |||||
| end | |||||
| collection do | |||||
| post 'unhidden_modules' | |||||
| end | |||||
| end | |||||
| resources :course_second_categories, shallow: true do | |||||
| member do | |||||
| post 'rename_category' | |||||
| post 'move_category' | |||||
| end | |||||
| end | |||||
| resources :repertoires, only: [:index] | |||||
| scope module: :projects do | |||||
| resources :project_applies, only: [:create] | |||||
| end | |||||
| namespace :wechats do | namespace :wechats do | ||||
| resource :js_sdk_signature, only: [:create] | resource :js_sdk_signature, only: [:create] | ||||
| end | end | ||||
| @@ -428,6 +253,151 @@ Rails.application.routes.draw do | |||||
| end | end | ||||
| end | end | ||||
| end | end | ||||
| # Project Area START | |||||
| scope "/:owner/:repo" do | |||||
| scope do | |||||
| get( | |||||
| '/activity', | |||||
| to: 'project_trends#index', | |||||
| as: :project_activity | |||||
| ) | |||||
| end | |||||
| resource :projects, path: '/', except: [:show, :edit] do | |||||
| member do | |||||
| get :branches | |||||
| get :simple | |||||
| get :watchers, to: 'projects#watch_users' | |||||
| get :stargazers, to: 'projects#praise_users' | |||||
| get :members, to: 'projects#fork_users' | |||||
| end | |||||
| end | |||||
| resource :repositories, path: '/', only: [:show, :create, :edit] do | |||||
| member do | |||||
| get :archive | |||||
| get :top_counts | |||||
| get :entries | |||||
| match :sub_entries, :via => [:get, :put] | |||||
| get :commits | |||||
| get :tags | |||||
| post :create_file | |||||
| put :update_file | |||||
| delete :delete_file | |||||
| post :repo_hook | |||||
| post :sync_mirror | |||||
| get :top_counts | |||||
| get 'commits/:sha', to: 'repositories#commit', as: 'commit' | |||||
| end | |||||
| end | |||||
| resources :issues do | |||||
| collection do | |||||
| get :commit_issues | |||||
| get :index_chosen | |||||
| post :clean | |||||
| post :series_update | |||||
| end | |||||
| member do | |||||
| post :copy | |||||
| post :close_issue | |||||
| post :lock_issue | |||||
| end | |||||
| end | |||||
| resources :pull_requests, :path => :pulls, except: [:destroy] do | |||||
| member do | |||||
| post :pr_merge | |||||
| # post :check_merge | |||||
| post :refuse_merge | |||||
| end | |||||
| collection do | |||||
| post :check_can_merge | |||||
| get :create_merge_infos | |||||
| get :get_branches | |||||
| end | |||||
| end | |||||
| resources :versions, :path => :milestones do | |||||
| member do | |||||
| post :update_status | |||||
| end | |||||
| end | |||||
| resources :members, :path => :collaborators, only: [:index, :create] do | |||||
| collection do | |||||
| delete :remove | |||||
| put :change_role | |||||
| end | |||||
| end | |||||
| resources :hooks | |||||
| resources :forks, only: [:create] | |||||
| resources :project_trends, :path => :activity, only: [:index, :create] | |||||
| resources :issue_tags, :path => :labels, only: [:create, :edit, :update, :destroy, :index] | |||||
| resources :version_releases, :path => :releases, only: [:index,:new, :create, :edit, :update, :destroy] | |||||
| scope module: :projects do | |||||
| scope do | |||||
| get( | |||||
| '/blob/*id/diff', | |||||
| to: 'blob#diff', | |||||
| constraints: { id: /.+/, format: false }, | |||||
| as: :blob_diff | |||||
| ) | |||||
| get( | |||||
| '/blob/*id', | |||||
| to: 'blob#show', | |||||
| constraints: { id: /.+/, format: false }, | |||||
| as: :blob | |||||
| ) | |||||
| delete( | |||||
| '/blob/*id', | |||||
| to: 'blob#destroy', | |||||
| constraints: { id: /.+/, format: false } | |||||
| ) | |||||
| put( | |||||
| '/blob/*id', | |||||
| to: 'blob#update', | |||||
| constraints: { id: /.+/, format: false } | |||||
| ) | |||||
| post( | |||||
| '/blob/*id', | |||||
| to: 'blob#create', | |||||
| constraints: { id: /.+/, format: false } | |||||
| ) | |||||
| end | |||||
| scope do | |||||
| get( | |||||
| '/raw/*id', | |||||
| to: 'raw#show', | |||||
| constraints: { id: /.+/, format: /(html|js)/ }, | |||||
| as: :raw | |||||
| ) | |||||
| end | |||||
| scope do | |||||
| get( | |||||
| '/blame/*id', | |||||
| to: 'blame#show', | |||||
| constraints: { id: /.+/, format: /(html|js)/ }, | |||||
| as: :blame | |||||
| ) | |||||
| end | |||||
| scope do | |||||
| get( | |||||
| '/tree/*id', | |||||
| to: 'tree#show', | |||||
| constraints: { id: /.+/, format: /(html|js)/ }, | |||||
| as: :tree | |||||
| ) | |||||
| end | |||||
| end | |||||
| end | |||||
| # Project Area END | |||||
| end | end | ||||
| namespace :admins do | namespace :admins do | ||||
| @@ -704,4 +674,6 @@ Rails.application.routes.draw do | |||||
| ## react用 | ## react用 | ||||
| get '*path', to: 'main#index', constraints: ReactConstraint.new | get '*path', to: 'main#index', constraints: ReactConstraint.new | ||||
| end | end | ||||
| @@ -0,0 +1,5 @@ | |||||
| class AddDevopsStepToUsers < ActiveRecord::Migration[5.2] | |||||
| def change | |||||
| add_column :users, :devops_step, :integer, default: 0, comment: '0: uninit devops; 1: unverified; 2: verified' | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| class RenameDevOpsCloudAccountToCiCloudAccount < ActiveRecord::Migration[5.2] | |||||
| def change | |||||
| rename_table :dev_ops_cloud_accounts, :ci_cloud_accounts | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| class RenameDevOpsLanguageToCiLanguage < ActiveRecord::Migration[5.2] | |||||
| def change | |||||
| rename_table :dev_ops_languages, :ci_languages | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,78 @@ | |||||
| html{margin:0px;padding: 0px;font-size: 14px;font-family: "微软雅黑","宋体";} | |||||
| body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td { | |||||
| margin: 0; | |||||
| padding: 0; | |||||
| } | |||||
| .IndexContent{ | |||||
| height: 100vh; | |||||
| width: 100%; | |||||
| position: relative; | |||||
| background-image: url('/images/oauth/backImg.png'); | |||||
| background-repeat: no-repeat; | |||||
| background-size: cover; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| flex-direction: column; | |||||
| } | |||||
| .indexLogo{ | |||||
| width:80px; | |||||
| margin-bottom: 35px; | |||||
| } | |||||
| .indexPanel{ | |||||
| width: 580px; | |||||
| min-height: 400px; | |||||
| background-color: #fff; | |||||
| box-shadow: 0px 2px 10px 5px rgba(0,0,0,0.05); | |||||
| border-radius: 5px; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .indexTitle{ | |||||
| height: 75px; | |||||
| line-height: 75px; | |||||
| font-size: 18px; | |||||
| color:#333; | |||||
| text-align: center; | |||||
| border-bottom: 1px solid #eee; | |||||
| } | |||||
| .indexInfo{ | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: flex-start; | |||||
| } | |||||
| .indexInfos{ | |||||
| padding:40px 60px; | |||||
| } | |||||
| .indexInfo > span{ | |||||
| color: #333; | |||||
| font-size: 16px; | |||||
| margin-top: 5px; | |||||
| } | |||||
| .indexInfo input{ | |||||
| width: 100%; | |||||
| height:40px; | |||||
| border-radius: 2px; | |||||
| border:1px solid #eee; | |||||
| margin-top: 5px; | |||||
| padding:0px 0px 0px 8px; | |||||
| outline: none; | |||||
| } | |||||
| .indexInfo .checkInfo{ | |||||
| height: 15px; | |||||
| color: red; | |||||
| } | |||||
| .indexBtn{ | |||||
| text-align: center; | |||||
| margin-top: 20px; | |||||
| } | |||||
| .indexSubmit{ | |||||
| width: 50%; | |||||
| height: 32px; | |||||
| line-height: 32px; | |||||
| background-color: #1890FF; | |||||
| border:none; | |||||
| color: #fff; | |||||
| border-radius: 2px; | |||||
| cursor: pointer; | |||||
| outline: none; | |||||
| } | |||||