| @@ -1,6 +1,78 @@ | |||
| class Api::V1::UsersController < Api::V1::BaseController | |||
| def index | |||
| render_ok | |||
| before_action :load_observe_user | |||
| before_action :check_auth_for_observe_user | |||
| def send_email_vefify_code | |||
| code = %W(0 1 2 3 4 5 6 7 8 9) | |||
| verification_code = code.sample(6).join | |||
| mail = params[:email] | |||
| code_type = params[:code_type] | |||
| sign = Digest::MD5.hexdigest("#{OPENKEY}#{mail}") | |||
| Rails.logger.info sign | |||
| tip_exception(501, "请求不合理") if sign != params[:smscode] | |||
| # 60s内不能重复发送 | |||
| send_email_limit_cache_key = "send_email_60_second_limit:#{mail}" | |||
| tip_exception(-1, '请勿频繁操作') if Rails.cache.exist?(send_email_limit_cache_key) | |||
| send_email_control = LimitForbidControl::SendEmailCode.new(mail) | |||
| tip_exception(-1, '邮件发送太频繁,请稍后再试') if send_email_control.forbid? | |||
| begin | |||
| UserMailer.update_email(mail, verification_code).deliver_now | |||
| Rails.cache.write(send_email_limit_cache_key, 1, expires_in: 1.minute) | |||
| send_email_control.increment! | |||
| rescue Exception => e | |||
| logger_error(e) | |||
| tip_exception(-2,"邮件发送失败,请稍后重试") | |||
| end | |||
| ver_params = {code_type: code_type, code: verification_code, email: mail} | |||
| data = VerificationCode.new(ver_params) | |||
| if data.save! | |||
| render_ok | |||
| else | |||
| tip_exception(-1, "创建数据失败") | |||
| end | |||
| end | |||
| def check_password | |||
| password = params[:password] | |||
| return render_error("8~16位密码,支持字母数字和符号") unless password =~ CustomRegexp::PASSWORD | |||
| return render_error("密码错误") unless @observe_user.check_password?(password) | |||
| render_ok | |||
| end | |||
| def check_email | |||
| mail = strip(params[:email]) | |||
| return render_error("邮件格式有误") unless mail =~ CustomRegexp::EMAIL | |||
| exist_owner = Owner.find_by(mail: mail) | |||
| return render_error('邮箱已被使用') if exist_owner | |||
| render_ok | |||
| end | |||
| def check_email_verify_code | |||
| code = strip(params[:code]) | |||
| mail = strip(params[:email]) | |||
| code_type = params[:code_type] | |||
| return render_error("邮件格式有误") unless mail =~ CustomRegexp::EMAIL | |||
| verifi_code = VerificationCode.where(email: mail, code: code, code_type: code_type).last | |||
| return render_error("验证码不正确") if verifi_code&.code != code | |||
| return render_error("验证码已失效") if !verifi_code&.effective? | |||
| render_ok | |||
| end | |||
| def update_email | |||
| @result_object = Api::V1::Users::UpdateEmailService.call(@observe_user, params, current_user.gitea_token) | |||
| if @result_object | |||
| return render_ok | |||
| else | |||
| return render_error('更改邮箱失败!') | |||
| end | |||
| end | |||
| end | |||
| @@ -31,11 +31,11 @@ class AttachmentsController < ApplicationController | |||
| def get_file | |||
| normal_status(-1, "参数缺失") if params[:download_url].blank? | |||
| url = URI.encode(params[:download_url].to_s.gsub("http:", "https:")) | |||
| url = base_url.starts_with?("https:") ? URI.encode(params[:download_url].to_s.gsub("http:", "https:")) : URI.encode(params[:download_url].to_s) | |||
| if url.starts_with?(base_url) | |||
| domain = GiteaService.gitea_config[:domain] | |||
| api_url = GiteaService.gitea_config[:base_url] | |||
| url = url.split(base_url)[1].gsub("api", "repos").gsub('?filepath=', '/').gsub('&', '?') | |||
| url = ("/repos"+url.split(base_url + "/api")[1]).gsub('?filepath=', '/').gsub('&', '?') | |||
| request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join | |||
| response = Faraday.get(request_url) | |||
| filename = url.to_s.split("/").pop() | |||
| @@ -16,4 +16,13 @@ module Api::UserHelper | |||
| end | |||
| @observe_user | |||
| end | |||
| # 是否具有查看用户或编辑用户的权限 | |||
| def check_auth_for_observe_user | |||
| return render_forbidden unless current_user.admin? || @observe_user.id == current_user.id | |||
| end | |||
| def strip(str) | |||
| str.to_s.strip.presence | |||
| end | |||
| end | |||
| @@ -16,6 +16,7 @@ module RegisterHelper | |||
| return unless user.valid? | |||
| interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) | |||
| result ={} | |||
| if interactor.success? | |||
| gitea_user = interactor.result | |||
| result = Gitea::User::GenerateTokenService.call(username, password) | |||
| @@ -26,7 +27,7 @@ module RegisterHelper | |||
| result[:user] = {id: user.id, token: user.gitea_token} | |||
| end | |||
| else | |||
| result[:message] = interactor.error | |||
| result[:message] = interactor.result[:message] | |||
| end | |||
| result | |||
| end | |||
| @@ -109,6 +109,19 @@ class UsersController < ApplicationController | |||
| @user = current_user | |||
| end | |||
| # cloudIDE saas定制 | |||
| def info | |||
| @code = 1001 | |||
| @message = "用户不存在" | |||
| if params[:token].present? | |||
| @user = User.try_to_autologin(params[:token]) | |||
| if @user.present? | |||
| @code = 1000 | |||
| @message = "success" | |||
| end | |||
| end | |||
| end | |||
| # 贴吧获取用户信接口 | |||
| def get_user_info | |||
| begin | |||
| @@ -2304,4 +2304,189 @@ await octokit.request('GET /api/users/:login/applied_projects/:id/refuse.json') | |||
| "created_at": "2021-06-09 16:41", | |||
| "time_ago": "7分钟前" | |||
| } | |||
| ``` | |||
| ## 用户发送邮件验证码 | |||
| 用户发送邮件验证码 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET http://localhost:3000/api/v1/yystopf/send_email_vefify_code.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/v1/:login/send_email_vefify_code.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/v1/:login/send_email_vefify_code.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |login |string |用户标识 | | |||
| |code_type |int |10: 更新邮箱| | |||
| |email |string |邮箱| | |||
| |smscode |string |邮箱md5加密值| | |||
| ### 返回字段说明: | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| ## 用户验证邮件验证码 | |||
| 用户验证邮件验证码 | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST http://localhost:3000/api/v1/yystopf/check_email_verify_code.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/v1/:login/check_email_verify_code.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST /api/v1/:login/check_email_verify_code.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |login |string |用户标识 | | |||
| |code_type |int |10: 更新邮箱| | |||
| |email |string |邮箱| | |||
| |code |string |邮箱验证码| | |||
| ### 返回字段说明: | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| ## 用户验证密码 | |||
| 用户验证密码,检查是否和用户密码一致 | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST http://localhost:3000/api/v1/yystopf/check_password.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/v1/:login/check_password.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST /api/v1/:login/check_password.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |login |string |用户标识 | | |||
| |password |string |用户密码| | |||
| ### 返回字段说明: | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| ## 用户验证邮箱 | |||
| 用户验证邮箱是否符合规范以及是否已被使用 | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST http://localhost:3000/api/v1/yystopf/check_email.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/v1/:login/check_email.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST /api/v1/:login/check_email.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |login |string |用户标识 | | |||
| |email |string |邮箱地址| | |||
| ### 返回字段说明: | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| ## 用户更改邮箱 | |||
| 用户更改一个新的邮箱 | |||
| > 示例: | |||
| ```shell | |||
| curl -X PATCH http://localhost:3000/api/v1/yystopf/update_email.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('PATCH /api/v1/:login/update_email.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `PATCH /api/v1/:login/update_email.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |login |string |用户标识 | | |||
| |password |string |用户密码| | |||
| |email |string |邮箱地址| | |||
| |code |string |邮箱验证码| | |||
| > 请求的JSON示例: | |||
| ```json | |||
| { | |||
| "password": "Aa19960425.", | |||
| "code": "657134", | |||
| "email": "yystopf@163.com" | |||
| } | |||
| ``` | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| @@ -65,6 +65,7 @@ module ProjectsHelper | |||
| license_id: project.license_id, | |||
| jianmu_devops: jianmu_devops_code(project, user), | |||
| jianmu_devops_url: jianmu_devops_url, | |||
| cloud_ide_saas_url: cloud_ide_saas_url(user), | |||
| ignore_id: project.ignore_id | |||
| }).compact | |||
| @@ -128,6 +129,15 @@ module ProjectsHelper | |||
| EduSetting.get("jianmu_devops_url") || "https://ci-v3.test.jianmuhub.com" | |||
| end | |||
| def cloud_ide_saas_url(user) | |||
| "" unless user.logged? | |||
| token = Token.get_token_from_user(user, "autologin") | |||
| oauth_url = "#{Rails.application.config_for(:configuration)['platform_url']}/api/users/info.json" | |||
| saas_url = EduSetting.get("cloud_ide_saas_url") || "https://saasfactory.test.opentrs.com" | |||
| "#{saas_url}/oauth/login?product_account_id=PA1001218&tenant_code=TI1001383&oauth_url=#{oauth_url}&token=#{token.value}" | |||
| end | |||
| def aes_encrypt(key, des_text) | |||
| # des_text='{"access_key_id":"STS.NTuC9RVmWfJqj3JkcMzPnDf7X","access_key_secret":"E8NxRZWGNxxMfwgt5nFLnBFgg6AzgXCZkSNCyqygLuHM","end_point":"oss-accelerate.aliyuncs.com","security_token":"CAIS8gF1q6Ft5B2yfSjIr5fACIPmu7J20YiaaBX7j2MYdt9Cq6Ocujz2IHhMenVhA+8Wv/02n2hR7PcYlq9IS55VWEqc/VXLaywQo22beIPkl5Gfz95t0e+IewW6Dxr8w7WhAYHQR8/cffGAck3NkjQJr5LxaTSlWS7OU/TL8+kFCO4aRQ6ldzFLKc5LLw950q8gOGDWKOymP2yB4AOSLjIx6lAt2T8vs/7hmZPFukSFtjCglL9J/baWC4O/csxhMK14V9qIx+FsfsLDqnUIs0YWpf0p3P0doGyf54vMWUM05A6dduPS7txkLAJwerjVl1/ADxc0/hqAASXhPeiktbmDjwvnSn4iKcSGQ+xoQB468eHXNdvf13dUlbbE1+JhRi0pZIB2UCtN9oTsLHcwIHt+EJaoMd3+hGwPVmvHSXzECDFHylZ8l/pzTwlE/aCtZyVmI5cZEvmWu2xBa3GRbULo7lLvyeX1cHTVmVWf4Nk6D09PzTU8qlAj","bucket":"edu-bigfiles1","region":"oss-cn-hangzhou","callback_url":"https://data.educoder.net/api/buckets/callback.json","bucket_host":"data.educoder.net"}' | |||
| # des = OpenSSL::Cipher::Cipher.new('aes-256-ctr') | |||
| @@ -1,11 +1,16 @@ | |||
| class UserMailer < ApplicationMailer | |||
| # 注意:这个地方一定要和你的邮箱服务域名一致 | |||
| default from: 'notification@trustie.org' | |||
| # 用户注册验证码 | |||
| def register_email(mail, code) | |||
| @code = code | |||
| mail(to: mail, subject: 'Gitink | 注册验证码') | |||
| end | |||
| end | |||
| class UserMailer < ApplicationMailer | |||
| # 注意:这个地方一定要和你的邮箱服务域名一致 | |||
| # default from: 'notification@trustie.org' | |||
| default from: 'noreply@gitlink.org.cn' | |||
| # 用户注册验证码 | |||
| def register_email(mail, code) | |||
| @code = code | |||
| mail(to: mail, subject: 'Gitink | 注册验证码') | |||
| end | |||
| def update_email(mail, code) | |||
| @code = code | |||
| mail(to: mail, subject: 'Gitink | 更改邮箱验证码') | |||
| end | |||
| end | |||
| @@ -20,7 +20,7 @@ class TimeableVisitRecord < ApplicationRecord | |||
| belongs_to :project | |||
| def self.build(project_id) | |||
| week = TimeableVisitRecord.find_or_create_by!(time: Date.today.cweek, project_id: project_id) | |||
| week = TimeableVisitRecord.find_or_create_by!(time: Date.today.strftime("%Y-%W"), project_id: project_id) | |||
| month = TimeableVisitRecord.find_or_create_by!(time: Date.today.strftime("%Y%m"), project_id: project_id) | |||
| return week, month | |||
| @@ -0,0 +1,68 @@ | |||
| class Api::V1::Users::UpdateEmailService < ApplicationService | |||
| include ActiveModel::Model | |||
| attr_reader :user, :token, :password, :mail, :old_mail, :code, :verify_code | |||
| attr_accessor :gitea_data | |||
| validates :password, :code, presence: true | |||
| validates :mail, presence: true, format: { with: CustomRegexp::EMAIL } | |||
| def initialize(user, params, token =nil) | |||
| @user = user | |||
| @token = token | |||
| @password = params[:password] | |||
| @mail = params[:email] | |||
| @old_mail = user.mail | |||
| @code = params[:code] | |||
| @verify_code = VerificationCode.where(email: @mail, code: @code, code_type: 10).last | |||
| end | |||
| def call | |||
| raise Error, errors.full_messages.join(",") unless valid? | |||
| raise Error, "密码不正确." unless @user.check_password?(@password) | |||
| raise Error, "验证码不正确." if @verify_code&.code != @code | |||
| raise Error, "验证码已失效." if !@verify_code&.effective? | |||
| # begin | |||
| ActiveRecord::Base.transaction do | |||
| change_user_email | |||
| excute_data_to_gitea | |||
| excute_change_email_from_gitea | |||
| end | |||
| return gitea_data | |||
| # rescue | |||
| # raise Error, "服务器错误,请联系系统管理员!" | |||
| # end | |||
| end | |||
| private | |||
| def request_params | |||
| { | |||
| access_token: token | |||
| } | |||
| end | |||
| def request_body | |||
| { | |||
| email: @mail, | |||
| login_name: @user.login, | |||
| source_id: 0 | |||
| } | |||
| end | |||
| def change_user_email | |||
| @user.update_attributes!({mail: @mail}) | |||
| end | |||
| def excute_data_to_gitea | |||
| Rails.logger.info request_body | |||
| @gitea_data = $gitea_client.patch_admin_users_by_username(@user.login, {body: request_body.to_json}) | |||
| end | |||
| def excute_change_email_from_gitea | |||
| $gitea_client.delete_user_emails({body: {emails: [@old_mail]}.to_json, query: request_params}) | |||
| $gitea_client.post_user_emails({body: {emails: [@mail]}.to_json, query: request_params}) | |||
| end | |||
| end | |||
| @@ -133,6 +133,8 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| end | |||
| if @watchers.present? | |||
| $redis_cache.hincrby(project_common_key, watchers_key, @watchers) | |||
| Cache::V2::ProjectRankService.call(@project_id, {watchers: @watchers}) | |||
| Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {watchers: @watchers}) | |||
| end | |||
| if @praises.present? | |||
| $redis_cache.hincrby(project_common_key, praises_key, @praises) | |||
| @@ -7,6 +7,7 @@ class Cache::V2::ProjectDateRankService < ApplicationService | |||
| @project_id = project_id | |||
| @rank_date = rank_date | |||
| @visits = params[:visits] | |||
| @watchers = params[:watchers] | |||
| @praises = params[:praises] | |||
| @forks = params[:forks] | |||
| @issues = params[:issues] | |||
| @@ -35,6 +36,9 @@ class Cache::V2::ProjectDateRankService < ApplicationService | |||
| if @visits.present? | |||
| $redis_cache.zincrby(project_rank_key, @visits.to_i * 1, @project_id) | |||
| end | |||
| if @watchers.present? | |||
| $redis_cache.zincrby(project_rank_key, @watchers.to_i * 5, @project_id) | |||
| end | |||
| if @praises.present? | |||
| $redis_cache.zincrby(project_rank_key, @praises.to_i * 5, @project_id) | |||
| end | |||
| @@ -42,13 +46,13 @@ class Cache::V2::ProjectDateRankService < ApplicationService | |||
| $redis_cache.zincrby(project_rank_key, @forks.to_i * 10, @project_id) | |||
| end | |||
| if @issues.present? | |||
| $redis_cache.zincrby(project_rank_key, @issues.to_i * 10, @project_id) | |||
| $redis_cache.zincrby(project_rank_key, @issues.to_i * 5, @project_id) | |||
| end | |||
| if @pullrequests.present? | |||
| $redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id) | |||
| end | |||
| if @commits.present? | |||
| $redis_cache.zincrby(project_rank_key, @commits.to_i * 1, @project_id) | |||
| $redis_cache.zincrby(project_rank_key, @commits.to_i * 5, @project_id) | |||
| end | |||
| $redis_cache.zscore(project_rank_key, @project_id) | |||
| @@ -5,6 +5,7 @@ class Cache::V2::ProjectRankService < ApplicationService | |||
| def initialize(project_id, params={}) | |||
| @project_id = project_id | |||
| @visits = params[:visits] | |||
| @watchers = params[:watchers] | |||
| @praises = params[:praises] | |||
| @forks = params[:forks] | |||
| @issues = params[:issues] | |||
| @@ -51,6 +52,9 @@ class Cache::V2::ProjectRankService < ApplicationService | |||
| if @visits.present? | |||
| $redis_cache.zincrby(project_rank_key, @visits.to_i * 1, @project_id) | |||
| end | |||
| if @watchers.present? | |||
| $redis_cache.zincrby(project_rank_key, @watchers.to_i * 5, @project_id) | |||
| end | |||
| if @praises.present? | |||
| $redis_cache.zincrby(project_rank_key, @praises.to_i * 5, @project_id) | |||
| end | |||
| @@ -58,13 +62,13 @@ class Cache::V2::ProjectRankService < ApplicationService | |||
| $redis_cache.zincrby(project_rank_key, @forks.to_i * 10, @project_id) | |||
| end | |||
| if @issues.present? | |||
| $redis_cache.zincrby(project_rank_key, @issues.to_i * 10, @project_id) | |||
| $redis_cache.zincrby(project_rank_key, @issues.to_i * 5, @project_id) | |||
| end | |||
| if @pullrequests.present? | |||
| $redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id) | |||
| end | |||
| if @commits.present? | |||
| $redis_cache.zincrby(project_rank_key, @commits.to_i * 1, @project_id) | |||
| $redis_cache.zincrby(project_rank_key, @commits.to_i * 5, @project_id) | |||
| end | |||
| reset_user_project_rank | |||
| end | |||
| @@ -74,7 +78,7 @@ class Cache::V2::ProjectRankService < ApplicationService | |||
| def reset_project_rank | |||
| load_project_common | |||
| score = @project_common["visits"].to_i * 1 + @project_common["praises"].to_i * 5 + @project_common["forks"].to_i * 10 + @project_common["issues"].to_i * 10 + @project_common["pullrequests"].to_i * 10 + @project_common["commits"].to_i * 1 | |||
| score = @project_common["visits"].to_i * 1 + @project_common["watchers"].to_i * 5 + @project_common["praises"].to_i * 5 + @project_common["forks"].to_i * 10 + @project_common["issues"].to_i * 5 + @project_common["pullrequests"].to_i * 10 + @project_common["commits"].to_i * 5 | |||
| $redis_cache.zadd(project_rank_key, score, @project_id) | |||
| reset_user_project_rank | |||
| @@ -35,7 +35,7 @@ | |||
| 期待更加丰富的功能:<span class="text-danger"><%= UserNp.where("memo like '%期待更加丰富的功能%'").count %></span>, | |||
| 希望有新手引导:<span class="text-danger"><%= UserNp.where("memo like '%希望有新手引导%'").count %></span>, | |||
| 提升用户体验:<span class="text-danger"><%= UserNp.where("memo like '%用户体验需进一步提升%'").count %></span>, | |||
| 其他:<span class="text-danger"><%= UserNp.where("action_type !='close'").where("memo is not null").where.not(id: UserNp.where("memo like '%期待更加丰富的功能%' or memo like '%希望有新手引导%' or memo like '%用户体验需进一步提升%' ").ids).count %></span> | |||
| 其他:<span class="text-danger"><%= UserNp.where("action_type !='close'").where("LENGTH(memo) >0").where.not(id: UserNp.where("memo like '%期待更加丰富的功能%' or memo like '%希望有新手引导%' or memo like '%用户体验需进一步提升%' ").ids).count %></span> | |||
| </p> | |||
| </div> | |||
| <div class="box admin-list-container users-list-container"> | |||
| @@ -0,0 +1,61 @@ | |||
| <html> | |||
| <head> | |||
| <meta charset="utf-8"> | |||
| <title>GitLink-验证码发送</title> | |||
| <style type="text/css"> | |||
| /* 验证链接页面 */ | |||
| 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;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto; font-size:14px; "> | |||
| <div style="height:50px; width: 578px; background:#46484c; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.gitlink.org.cn"> | |||
| <%= image_tag("logo.png", alt: "确实开源", width: '100', :style => "float:left; margin-top: 8px;") %> | |||
| </a> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:30px 20px; color:#333; line-height: 1.9;"> | |||
| <p style="color:#333; font-size:16px; margin-bottom:15px;font-weight: bold"> | |||
| 您好! | |||
| </p> | |||
| <p style="color:#333;"> | |||
| 你正在进行GitLink邮箱更改操作,如非本人操作,请忽略。 | |||
| </p> | |||
| <div style="text-align: center;"> | |||
| <div style="display:block; height: 45px; line-height:45px;padding:0 30px; width:100px; font-size: 20px; font-weight: bold; background:#ffd9d9; color:#e72c37; margin:30px auto;"> | |||
| <p><%= @code %></p> | |||
| </div> | |||
| <span style="font-weight: normal;color:#666;"> | |||
| 此邮件为系统所发,请勿直接回复。<br/> | |||
| 要解决问题或了解您的帐户详情,您可以访问 <a href="https:///www.gitlink.org.cn/forums/1168/detail" style="font-weight: normal; color:#ff7500;">帮助中心</a>。 | |||
| </span> | |||
| </div> | |||
| <p style="color:#666; margin-top:30px;"> | |||
| 如果您并未发过此请求,则可能是因为其他用户在注册时误输了您的邮件地址,而使您收到了这封邮件,那么您可以放心的忽略此邮件,无需进一步采取任何操作。 | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background:#46484c;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <a href="https:///www.gitlink.org.cn" style="font-weight: normal; color:#fff;">www.gitlink.org.cn</a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,11 @@ | |||
| json.code @code | |||
| # json.message @message | |||
| json.status @code == 1000 | |||
| if @user.present? | |||
| json.userInfoBO do | |||
| json.name @user.real_name | |||
| json.userEmail @user.mail | |||
| json.phone @user.phone | |||
| # json.tenantCode "TI1001383" | |||
| end | |||
| end | |||
| @@ -6,6 +6,6 @@ gitea_config = config[:gitea].symbolize_keys! | |||
| $gitea_client = Gitea::Api::Client.new({ | |||
| domain: gitea_config[:domain], | |||
| base_url: gitea_config[:base_url], | |||
| username: gitea_config[:username], | |||
| password: gitea_config[:password] | |||
| username: gitea_config[:access_key_id], | |||
| password: gitea_config[:access_key_secret] | |||
| }) | |||
| @@ -258,6 +258,7 @@ Rails.application.routes.draw do | |||
| post :attendance | |||
| get :system_update | |||
| get :me | |||
| get :info | |||
| get :list | |||
| post :sync_token | |||
| post :sync_gitea_pwd | |||
| @@ -2,7 +2,15 @@ defaults format: :json do | |||
| namespace :api do | |||
| namespace :v1 do | |||
| scope ':owner' do | |||
| resource :users, path: '/', only: [:show, :update, :edit, :destroy] | |||
| resource :users, path: '/', only: [:show, :update, :edit, :destroy] do | |||
| collection do | |||
| get :send_email_vefify_code | |||
| post :check_password | |||
| post :check_email | |||
| post :check_email_verify_code | |||
| patch :update_email | |||
| end | |||
| end | |||
| scope module: :users do | |||
| resources :projects, only: [:index] | |||
| end | |||
| @@ -423,6 +423,21 @@ | |||
| <li> | |||
| <a href="#f2ee84ecf7" class="toc-h2 toc-link" data-title="用户拒绝申请">用户拒绝申请</a> | |||
| </li> | |||
| <li> | |||
| <a href="#887583578f" class="toc-h2 toc-link" data-title="用户发送邮件验证码">用户发送邮件验证码</a> | |||
| </li> | |||
| <li> | |||
| <a href="#e60d451c31" class="toc-h2 toc-link" data-title="用户验证邮件验证码">用户验证邮件验证码</a> | |||
| </li> | |||
| <li> | |||
| <a href="#0cea165d49" class="toc-h2 toc-link" data-title="用户验证密码">用户验证密码</a> | |||
| </li> | |||
| <li> | |||
| <a href="#d50324355e" class="toc-h2 toc-link" data-title="用户验证邮箱">用户验证邮箱</a> | |||
| </li> | |||
| <li> | |||
| <a href="#2e8c8a7bae" class="toc-h2 toc-link" data-title="用户更改邮箱">用户更改邮箱</a> | |||
| </li> | |||
| </ul> | |||
| </li> | |||
| <li> | |||
| @@ -4728,6 +4743,230 @@ Success — a happy kitten is an authenticated kitten! | |||
| </span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-06-09 16:41"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"7分钟前"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div><h2 id='887583578f'>用户发送邮件验证码</h2> | |||
| <p>用户发送邮件验证码</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/v1/yystopf/send_email_vefify_code.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/v1/:login/send_email_vefify_code.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-28'>HTTP 请求</h3> | |||
| <p><code>GET /api/v1/:login/send_email_vefify_code.json</code></p> | |||
| <h3 id='aa883f5d52-23'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>login</td> | |||
| <td>string</td> | |||
| <td>用户标识</td> | |||
| </tr> | |||
| <tr> | |||
| <td>code_type</td> | |||
| <td>int</td> | |||
| <td>10: 更新邮箱</td> | |||
| </tr> | |||
| <tr> | |||
| <td>email</td> | |||
| <td>string</td> | |||
| <td>邮箱</td> | |||
| </tr> | |||
| <tr> | |||
| <td>smscode</td> | |||
| <td>string</td> | |||
| <td>邮箱md5加密值</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-21'>返回字段说明:</h3> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div><h2 id='e60d451c31'>用户验证邮件验证码</h2> | |||
| <p>用户验证邮件验证码</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/v1/yystopf/check_email_verify_code.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/v1/:login/check_email_verify_code.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-29'>HTTP 请求</h3> | |||
| <p><code>POST /api/v1/:login/check_email_verify_code.json</code></p> | |||
| <h3 id='aa883f5d52-24'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>login</td> | |||
| <td>string</td> | |||
| <td>用户标识</td> | |||
| </tr> | |||
| <tr> | |||
| <td>code_type</td> | |||
| <td>int</td> | |||
| <td>10: 更新邮箱</td> | |||
| </tr> | |||
| <tr> | |||
| <td>email</td> | |||
| <td>string</td> | |||
| <td>邮箱</td> | |||
| </tr> | |||
| <tr> | |||
| <td>code</td> | |||
| <td>string</td> | |||
| <td>邮箱验证码</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-22'>返回字段说明:</h3> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div><h2 id='0cea165d49'>用户验证密码</h2> | |||
| <p>用户验证密码,检查是否和用户密码一致</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/v1/yystopf/check_password.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/v1/:login/check_password.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-30'>HTTP 请求</h3> | |||
| <p><code>POST /api/v1/:login/check_password.json</code></p> | |||
| <h3 id='aa883f5d52-25'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>login</td> | |||
| <td>string</td> | |||
| <td>用户标识</td> | |||
| </tr> | |||
| <tr> | |||
| <td>password</td> | |||
| <td>string</td> | |||
| <td>用户密码</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-23'>返回字段说明:</h3> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div><h2 id='d50324355e'>用户验证邮箱</h2> | |||
| <p>用户验证邮箱是否符合规范以及是否已被使用</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/v1/yystopf/check_email.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/v1/:login/check_email.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-31'>HTTP 请求</h3> | |||
| <p><code>POST /api/v1/:login/check_email.json</code></p> | |||
| <h3 id='aa883f5d52-26'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>login</td> | |||
| <td>string</td> | |||
| <td>用户标识</td> | |||
| </tr> | |||
| <tr> | |||
| <td>email</td> | |||
| <td>string</td> | |||
| <td>邮箱地址</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-24'>返回字段说明:</h3> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div><h2 id='2e8c8a7bae'>用户更改邮箱</h2> | |||
| <p>用户更改一个新的邮箱</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> PATCH http://localhost:3000/api/v1/yystopf/update_email.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">PATCH /api/v1/:login/update_email.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-32'>HTTP 请求</h3> | |||
| <p><code>PATCH /api/v1/:login/update_email.json</code></p> | |||
| <h3 id='aa883f5d52-27'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>login</td> | |||
| <td>string</td> | |||
| <td>用户标识</td> | |||
| </tr> | |||
| <tr> | |||
| <td>password</td> | |||
| <td>string</td> | |||
| <td>用户密码</td> | |||
| </tr> | |||
| <tr> | |||
| <td>email</td> | |||
| <td>string</td> | |||
| <td>邮箱地址</td> | |||
| </tr> | |||
| <tr> | |||
| <td>code</td> | |||
| <td>string</td> | |||
| <td>邮箱验证码</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <blockquote> | |||
| <p>请求的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"password"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Aa19960425."</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"code"</span><span class="p">:</span><span class="w"> </span><span class="s2">"657134"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"email"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yystopf@163.com"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div><h1 id='projects'>Projects</h1><h2 id='b57112e753'>获取项目邀请链接(项目管理员)</h2> | |||
| <p>当前登录(管理员)用户获取项目邀请链接的接口(第一次请求会默认生成role类型为developer和is_apply为true的链接)</p> | |||