├── .browserslistrc
├── .dockerignore
├── .gitattributes
├── .gitignore
├── .rubocop.yml
├── .ruby-version
├── Capfile
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── Procfile
├── README.md
├── Rakefile
├── app
├── assets
│ ├── config
│ │ └── manifest.js
│ ├── images
│ │ └── .keep
│ └── stylesheets
│ │ ├── api
│ │ └── v1
│ │ │ ├── check_domains.scss
│ │ │ ├── msg_channels.scss
│ │ │ └── projects.scss
│ │ ├── application.css
│ │ └── home.scss
├── channels
│ └── application_cable
│ │ ├── channel.rb
│ │ └── connection.rb
├── controllers
│ ├── api
│ │ └── v1
│ │ │ ├── api_tokens_controller.rb
│ │ │ ├── check_domains_controller.rb
│ │ │ ├── msg_channels_controller.rb
│ │ │ ├── projects_controller.rb
│ │ │ └── users_controller.rb
│ ├── api_controller.rb
│ ├── application_controller.rb
│ ├── concerns
│ │ └── .keep
│ ├── home_controller.rb
│ ├── madmin
│ │ ├── application_controller.rb
│ │ ├── check_domains_controller.rb
│ │ ├── dashboard_controller.rb
│ │ ├── msg_channels_controller.rb
│ │ ├── projects_controller.rb
│ │ ├── user_omniauths_controller.rb
│ │ └── users_controller.rb
│ └── users
│ │ ├── confirmations_controller.rb
│ │ ├── omniauth_callbacks_controller.rb
│ │ ├── passwords_controller.rb
│ │ ├── registrations_controller.rb
│ │ ├── sessions_controller.rb
│ │ └── unlocks_controller.rb
├── helpers
│ ├── api
│ │ └── v1
│ │ │ ├── check_domains_helper.rb
│ │ │ ├── msg_channels_helper.rb
│ │ │ └── projects_helper.rb
│ ├── application_helper.rb
│ └── home_helper.rb
├── javascript
│ ├── channels
│ │ ├── consumer.js
│ │ └── index.js
│ └── packs
│ │ ├── admin.js
│ │ └── application.js
├── jobs
│ └── application_job.rb
├── madmin
│ └── resources
│ │ ├── check_domain_resource.rb
│ │ ├── msg_channel_resource.rb
│ │ ├── project_resource.rb
│ │ ├── user_omniauth_resource.rb
│ │ └── user_resource.rb
├── mailers
│ └── application_mailer.rb
├── models
│ ├── application_record.rb
│ ├── check_domain.rb
│ ├── concerns
│ │ ├── .keep
│ │ ├── check_domain_notification.rb
│ │ ├── check_domain_ssl.rb
│ │ └── omni_authable.rb
│ ├── domain_msg_channel.rb
│ ├── msg_channel.rb
│ ├── msg_channel
│ │ ├── bark.rb
│ │ ├── dingtalk.rb
│ │ ├── email.rb
│ │ ├── lark.rb
│ │ ├── webhook.rb
│ │ └── wecom.rb
│ ├── project.rb
│ ├── user.rb
│ └── user_omniauth.rb
├── services
│ └── email_service.rb
├── views
│ ├── api
│ │ └── v1
│ │ │ ├── check_domains
│ │ │ ├── _check_domain.json.jbuilder
│ │ │ ├── create.html.erb
│ │ │ ├── create.json.jbuilder
│ │ │ ├── destroy.html.erb
│ │ │ ├── index.html.erb
│ │ │ ├── index.json.jbuilder
│ │ │ ├── show.html.erb
│ │ │ ├── show.json.jbuilder
│ │ │ └── update.json.jbuilder
│ │ │ ├── msg_channels
│ │ │ ├── _msg_channel.json.jbuilder
│ │ │ ├── create.html.erb
│ │ │ ├── destroy.html.erb
│ │ │ ├── index.html.erb
│ │ │ ├── index.json.jbuilder
│ │ │ ├── show.html.erb
│ │ │ ├── show.json.jbuilder
│ │ │ └── update.html.erb
│ │ │ ├── projects
│ │ │ ├── _project.json.jbuilder
│ │ │ ├── create.html.erb
│ │ │ ├── create.json.jbuilder
│ │ │ ├── destroy.html.erb
│ │ │ ├── index.html.erb
│ │ │ ├── index.json.jbuilder
│ │ │ ├── show.html.erb
│ │ │ ├── show.json.jbuilder
│ │ │ ├── update.html.erb
│ │ │ └── update.json.jbuilder
│ │ │ └── users
│ │ │ └── info.json.jbuilder
│ ├── home
│ │ ├── index.html.erb
│ │ └── policy.html.erb
│ ├── layouts
│ │ ├── application.html.erb
│ │ ├── madmin
│ │ │ └── application.html.erb
│ │ ├── mailer.html.erb
│ │ └── mailer.text.erb
│ ├── madmin
│ │ ├── application
│ │ │ ├── _form.html.erb
│ │ │ ├── _javascript.html.erb
│ │ │ ├── _navigation.html.erb
│ │ │ ├── dashboard.html.erb
│ │ │ ├── edit.html.erb
│ │ │ ├── index.html.erb
│ │ │ ├── new.html.erb
│ │ │ └── show.html.erb
│ │ └── dashboard
│ │ │ └── index.html.erb
│ └── users
│ │ ├── confirmations
│ │ └── new.html.erb
│ │ ├── mailer
│ │ ├── confirmation_instructions.html.erb
│ │ ├── email_changed.html.erb
│ │ ├── password_change.html.erb
│ │ ├── reset_password_instructions.html.erb
│ │ └── unlock_instructions.html.erb
│ │ ├── passwords
│ │ ├── edit.html.erb
│ │ └── new.html.erb
│ │ ├── registrations
│ │ ├── edit.html.erb
│ │ └── new.html.erb
│ │ ├── sessions
│ │ └── new.html.erb
│ │ ├── shared
│ │ ├── _error_messages.html.erb
│ │ └── _links.html.erb
│ │ └── unlocks
│ │ └── new.html.erb
└── workers
│ ├── domain_dead_check_schedule_worker.rb
│ └── domain_schedule_worker.rb
├── babel.config.js
├── bin
├── bundle
├── rails
├── rake
├── setup
├── spring
├── webpack
├── webpack-dev-server
└── yarn
├── config.ru
├── config
├── application.rb
├── application.yml.example
├── boot.rb
├── cable.yml
├── credentials.yml.enc
├── database.yml
├── deploy.rb
├── deploy
│ ├── production.rb
│ └── staging.rb
├── environment.rb
├── environments
│ ├── development.rb
│ ├── production.rb
│ └── test.rb
├── initializers
│ ├── application_controller_renderer.rb
│ ├── assets.rb
│ ├── backtrace_silencers.rb
│ ├── content_security_policy.rb
│ ├── cookies_serializer.rb
│ ├── devise.rb
│ ├── filter_parameter_logging.rb
│ ├── inflections.rb
│ ├── mime_types.rb
│ ├── omniauth.rb
│ ├── pagy.rb
│ ├── permissions_policy.rb
│ ├── sentry.rb
│ ├── sidekiq.rb
│ ├── url_error.rb
│ └── wrap_parameters.rb
├── locales
│ ├── devise.en.yml
│ └── en.yml
├── newrelic.yml
├── puma.rb
├── routes.rb
├── sidekiq.yml
├── spring.rb
├── storage.yml
├── webpack
│ ├── development.js
│ ├── environment.js
│ ├── production.js
│ └── test.js
└── webpacker.yml
├── db
├── migrate
│ ├── 20210621053408_devise_create_users.rb
│ ├── 20210621084517_create_check_domains.rb
│ ├── 20210621084536_create_projects.rb
│ ├── 20210621095602_create_user_omniauths.rb
│ ├── 20210621100331_add_check_expire_time_to_check_domains.rb
│ ├── 20210622032920_add_status_to_check_domains.rb
│ ├── 20210622053718_add_check_domains_count_to_projects.rb
│ ├── 20210622080840_create_msg_channels.rb
│ ├── 20210622083843_add_attributes_to_msg_channels.rb
│ ├── 20210622101007_create_domain_msg_channels.rb
│ ├── 20210623055035_add_notifier_to_check_domains.rb
│ ├── 20210624034532_add_api_token_to_user.rb
│ ├── 20210624083614_add_error_info_to_msg_channel.rb
│ └── 20210624091715_add_is_default_to_msg_channel.rb
├── schema.rb
└── seeds.rb
├── lib
├── assets
│ └── .keep
├── omniauth
│ └── strategies
│ │ └── wechat.rb
└── tasks
│ ├── .keep
│ └── auto_annotate_models.rake
├── log
└── .keep
├── package.json
├── postcss.config.js
├── public
├── 404.html
├── 422.html
├── 500.html
├── apple-touch-icon-precomposed.png
├── apple-touch-icon.png
├── favicon.ico
├── images
│ ├── types-of-ssl-certificates.jpg
│ └── what-is-a-ssl-certificate-1.png
├── robots.txt
├── secure.png
└── ssl-secure.png
├── sidekiq
├── storage
└── .keep
├── test
├── application_system_test_case.rb
├── channels
│ └── application_cable
│ │ └── connection_test.rb
├── controllers
│ ├── .keep
│ ├── api
│ │ └── v1
│ │ │ ├── check_domains_controller_test.rb
│ │ │ ├── msg_channels_controller_test.rb
│ │ │ └── projects_controller_test.rb
│ └── home_controller_test.rb
├── fixtures
│ ├── check_domains.yml
│ ├── domain_msg_channels.yml
│ ├── files
│ │ └── .keep
│ ├── msg_channels.yml
│ ├── projects.yml
│ ├── user_omniauths.yml
│ └── users.yml
├── helpers
│ └── .keep
├── integration
│ └── .keep
├── mailers
│ └── .keep
├── models
│ ├── .keep
│ ├── check_domain_test.rb
│ ├── domain_msg_channel_test.rb
│ ├── msg_channel_test.rb
│ ├── project_test.rb
│ ├── user_omniauth_test.rb
│ └── user_test.rb
├── system
│ └── .keep
└── test_helper.rb
├── tmp
├── .keep
└── pids
│ └── .keep
├── vendor
└── .keep
└── yarn.lock
/.browserslistrc:
--------------------------------------------------------------------------------
1 | defaults
2 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | data/
2 | log/
3 | tmp/
4 | public/uploads/
5 | spec/
6 | plugins/*
7 | test/
8 | doc/
9 | coverage/
10 |
11 | Dockerfile
12 | .env.*
13 | *.md
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # See https://git-scm.com/docs/gitattributes for more about git attribute files.
2 |
3 | # Mark the database schema as having been generated.
4 | db/schema.rb linguist-generated
5 |
6 | # Mark the yarn lockfile as having been generated.
7 | yarn.lock linguist-generated
8 |
9 | # Mark any vendored files as having been vendored.
10 | vendor/* linguist-vendored
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile '~/.gitignore_global'
6 |
7 | # Ignore bundler config.
8 | /.bundle
9 |
10 | # Ignore all logfiles and tempfiles.
11 | /log/*
12 | /tmp/*
13 | !/log/.keep
14 | !/tmp/.keep
15 |
16 | # Ignore pidfiles, but keep the directory.
17 | /tmp/pids/*
18 | !/tmp/pids/
19 | !/tmp/pids/.keep
20 |
21 | # Ignore uploaded files in development.
22 | /storage/*
23 | !/storage/.keep
24 |
25 | /public/assets
26 | .byebug_history
27 |
28 | # Ignore master key for decrypting credentials and more.
29 | /config/master.key
30 | /config/application.yml
31 |
32 | /public/packs
33 | /public/packs-test
34 | /node_modules
35 | /yarn-error.log
36 | yarn-debug.log*
37 | .yarn-integrity
38 | TAGS
39 |
40 | /datadir
41 | # Ignore application configuration
42 | # /config/application.yml
43 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | Style/ClassAndModuleChildren:
2 | Enable: false
3 |
4 | AllCops:
5 | TargetRubyVersion: 2.7
6 |
7 | Style/AsciiComments:
8 | Enable: false
9 |
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | ruby-2.7.3
2 |
--------------------------------------------------------------------------------
/Capfile:
--------------------------------------------------------------------------------
1 | # Load DSL and set up stages
2 | require "capistrano/setup"
3 |
4 | # Include default deployment tasks
5 | require "capistrano/deploy"
6 | require 'capistrano/puma'
7 | require 'capistrano/sidekiq'
8 |
9 |
10 | # Load the SCM plugin appropriate to your project:
11 | #
12 | # require "capistrano/scm/hg"
13 | # install_plugin Capistrano::SCM::Hg
14 | # or
15 | # require "capistrano/scm/svn"
16 | # install_plugin Capistrano::SCM::Svn
17 | # or
18 | require "capistrano/scm/git"
19 | install_plugin Capistrano::SCM::Git
20 |
21 | # Include tasks from other gems included in your Gemfile
22 | #
23 | # For documentation on these, see for example:
24 | #
25 | # https://github.com/capistrano/rvm
26 | # https://github.com/capistrano/rbenv
27 | # https://github.com/capistrano/chruby
28 | # https://github.com/capistrano/bundler
29 | # https://github.com/capistrano/rails
30 | # https://github.com/capistrano/passenger
31 | #
32 | require "capistrano/rvm"
33 | # require "capistrano/rbenv"
34 | # require "capistrano/chruby"
35 | require "capistrano/bundler"
36 | require "capistrano/rails/assets"
37 | # require 'capistrano/local_precompile'
38 |
39 | require "capistrano/rails/migrations"
40 | # require "capistrano/passenger"
41 | install_plugin Capistrano::Puma
42 | install_plugin Capistrano::Puma::Workers
43 | install_plugin Capistrano::Puma::Nginx
44 | install_plugin Capistrano::Puma::Systemd
45 |
46 | install_plugin Capistrano::Sidekiq
47 | install_plugin Capistrano::Sidekiq::Systemd
48 |
49 | # Load custom tasks from `lib/capistrano/tasks` if you have any defined
50 | Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
51 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ruby:2.7.3
2 | RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list
3 |
4 | RUN apt-get update
5 |
6 | RUN apt-get install -y imagemagick build-essential libpq-dev &&\
7 | apt-get install -y git curl htop postgresql-client vim
8 |
9 | RUN sed -i 's#http://deb.debian.org#https://mirrors.163.com#g' /etc/apt/sources.list && \
10 | apt update && apt install -y curl gnupg && \
11 | curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
12 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
13 | echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
14 | apt update && apt-get install -y nodejs yarn
15 |
16 | RUN gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
17 | RUN gem install bundler rake
18 |
19 | ENV APP_HOME /sslguala-ce
20 | RUN mkdir -p $APP_HOME
21 |
22 | WORKDIR $APP_HOME
23 |
24 | ADD Gemfile Gemfile.lock $APP_HOME/
25 | RUN bundle config set without 'development test'
26 | RUN bundle install --jobs=20
27 | RUN bundle exec rails assets:precompile RAILS_PRECOMPILE=1 RAILS_ENV=production SECRET_KEY_BASE=fake_secure_for_compile
28 |
29 | COPY . $APP_HOME
30 | # CMD ["foreman", "start"]
31 | # docker build -t firhq/sslguala-ce:1.0 .
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3 |
4 | ruby '2.7.3'
5 |
6 |
7 | gem 'rails', '~> 6.1.3', '>= 6.1.3.2'
8 |
9 | gem 'pg', '~> 1.1'
10 | gem 'puma', '~> 5.0'
11 | gem 'redis-namespace'
12 | gem 'sass-rails', '>= 6'
13 | gem 'webpacker', '~> 5.0'
14 | gem 'turbolinks', '~> 5'
15 | gem 'jbuilder', '~> 2.7'
16 | gem 'redis', '~> 4.0'
17 | gem 'api_tools'
18 | gem 'sentry-raven'
19 | gem 'public_suffix'
20 | gem 'foreman'
21 | # Use Active Storage variant
22 | gem 'image_processing', '~> 1.2'
23 | gem 'newrelic_rpm'
24 | # Reduces boot times through caching; required in config/boot.rb
25 | gem 'bootsnap', '>= 1.4.4', require: false
26 |
27 | group :development, :test do
28 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console
29 | gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
30 | end
31 |
32 | group :development do
33 | gem 'capistrano', '~> 3.10', require: false
34 | gem 'capistrano3-puma'
35 | gem 'capistrano-rails', '~> 1.6', require: false
36 | gem 'capistrano-rvm'
37 | gem 'capistrano-sidekiq'
38 | gem 'annotate'
39 | gem 'rubocop'
40 |
41 | # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
42 | gem 'web-console', '>= 4.1.0'
43 | # Display performance information such as SQL time and flame graphs for each request in your browser.
44 | # Can be configured to work on production as well see: https://github.com/MiniProfiler/rack-mini-profiler/blob/master/README.md
45 | gem 'rack-mini-profiler', '~> 2.0'
46 | gem 'listen', '~> 3.3'
47 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
48 | gem 'spring'
49 | end
50 |
51 | group :test do
52 | # Adds support for Capybara system testing and selenium driver
53 | gem 'capybara', '>= 3.26'
54 | gem 'selenium-webdriver'
55 | # Easy installation and use of web drivers to run system tests with browsers
56 | gem 'webdrivers'
57 | end
58 |
59 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
60 | # gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
61 | gem 'devise', '~> 4.7', '>= 4.7.3'
62 | gem 'friendly_id', '~> 5.4', '>= 5.4.1'
63 | gem 'sidekiq', '~> 6.1', '>= 6.1.2'
64 | gem 'sidekiq-scheduler'
65 | gem 'name_of_person', '~> 1.1', '>= 1.1.1'
66 | gem 'devise-jwt'
67 | gem 'omniauth-wechat-oauth2'
68 | gem 'pagy'
69 | gem 'madmin'
70 | gem 'figaro'
71 | gem 'ransack'
72 | gem 'rack-cors'
73 | gem 'omniauth-rails_csrf_protection'
74 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: bundle exec rails s -p 3000
2 | sidekiq: bundle exec sidekiq -C config/sidekiq.yml
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SSLGUALA
2 |
3 | sslguala是一款实时监测网站https过期时间以及提醒通知
4 |
5 | ## 官网
6 | 访问官网[https://www.sslguala.com](https://www.sslguala.com)
7 |
8 | ## 前端
9 | [sslguala-ui-ce](https://github.com/firhq/sslguala-ui-ce)
10 |
11 | ## 部署
12 | 请使用docker的形式部署
13 |
14 | [sslguala-ce-docker](https://github.com/FIRHQ/sslguala-ce-docker)
15 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require_relative "config/application"
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/app/assets/config/manifest.js:
--------------------------------------------------------------------------------
1 | //= link_tree ../images
2 | //= link_directory ../stylesheets .css
3 |
--------------------------------------------------------------------------------
/app/assets/images/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/app/assets/images/.keep
--------------------------------------------------------------------------------
/app/assets/stylesheets/api/v1/check_domains.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the api/v1/check_domains controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: https://sass-lang.com/
4 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/api/v1/msg_channels.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the api/v1/msg_channels controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: https://sass-lang.com/
4 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/api/v1/projects.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the api/v1/projects controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: https://sass-lang.com/
4 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/app/assets/stylesheets/application.css
--------------------------------------------------------------------------------
/app/assets/stylesheets/home.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the home controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: https://sass-lang.com/
4 |
--------------------------------------------------------------------------------
/app/channels/application_cable/channel.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Channel < ActionCable::Channel::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/channels/application_cable/connection.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Connection < ActionCable::Connection::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/api_tokens_controller.rb:
--------------------------------------------------------------------------------
1 | class Api::V1::ApiTokensController < ApiController
2 | skip_before_action :auth_user!
3 | before_action :auth_api_token!
4 | before_action :valid, only: [:create_domain]
5 |
6 | def check_domains
7 | @check_domains = current_user.check_domains.includes(:msg_channels)
8 | render "api/v1/check_domains/index"
9 | end
10 |
11 | def create_domain
12 | @project = current_user.projects.find_by(id: check_domain_params[:project_id])
13 | @channel = current_user.msg_channels.find_by(id: params[:channel_id])
14 | @check_domain = current_user.check_domains.new(check_domain_params)
15 | @check_domain.project_id = @project&.id
16 | if @check_domain.save
17 | @channel.bind_domain(@check_domain.id) if @channel.present?
18 | render "api/v1/check_domains/show"
19 | else
20 | render json: @check_domain.errors, status: 422
21 | end
22 | rescue => e
23 | render json: { error: e }, status: 422
24 | end
25 |
26 | def destroy_domain
27 | @check_domain = current_user.check_domains.find_by(id: params[:id])
28 | if @check_domain.destroy
29 | render json: {status: 'ok'}
30 | else
31 | render json: {error: @check_domain.errors}, status: 422
32 | end
33 | end
34 |
35 | def valid
36 | domain = params[:domain]
37 | domain = CheckDomain.parse_domain(domain)
38 |
39 | return render json: {error: "请填写正确的域名地址" }, status: 422 if domain.blank?
40 |
41 | answer = CheckDomain.ask_expire_time(domain)
42 | render json: { expire_at: answer}
43 | rescue StandardError => e
44 | render json: { error: e }, status: 422
45 | end
46 |
47 | def msg_channels
48 | @msg_channels = current_user.msg_channels
49 | render "api/v1/msg_channels/index"
50 | end
51 |
52 | def projects
53 | @projects = current_user.projects
54 | render "api/v1/projects/index"
55 | end
56 |
57 | protected
58 |
59 | def set_check_domain
60 | @check_domain = current_user.check_domains.find params[:id]
61 | end
62 |
63 | def check_domain_params
64 | params.permit(:domain, :markup, :project_id)
65 | end
66 |
67 | def auth_api_token!
68 | api_token = params[:api_token]
69 | if api_token.present? && user = User.find_by(api_token: api_token)
70 | @current_user = user
71 | else
72 | render json: { error: 'please check your api token'}, status: 401
73 | end
74 | end
75 |
76 | def valid
77 | domain = params[:domain]
78 | domain = CheckDomain.parse_domain(domain)
79 |
80 | return render json: {error: "请填写正确的域名地址"}, status: 422 if domain.blank?
81 |
82 | answer = CheckDomain.ask_expire_time(domain)
83 | rescue StandardError => e
84 | render json: { error: e }, status: 422
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/check_domains_controller.rb:
--------------------------------------------------------------------------------
1 | class Api::V1::CheckDomainsController < ApiController
2 | before_action :set_check_domain, only: %i[show destroy check_now update]
3 | skip_before_action :auth_user!, only: [:welcome]
4 | def index
5 | @check_domains = current_user.check_domains.ransack(params.permit(:project_id_eq, :expire_at_gteq, :expire_at_lt,
6 | :domain_cont, :project_id_null)).result
7 | @check_domains = @check_domains.includes(:msg_channels)
8 |
9 | order_dict = if params[:order_name].blank?
10 | { 'created_at' => 'desc' }
11 | else
12 | { params[:order_name] => params[:order_desc].to_s == 'true' ? 'desc' : 'asc' }
13 | end
14 |
15 | Rails.logger.info order_dict
16 | Rails.logger.info @check_domains.order(order_dict).to_sql
17 | pagy, @check_domains = pagy(@check_domains.order(order_dict))
18 | pagy_headers_merge(pagy)
19 | end
20 |
21 | def welcome
22 | render json: { msg: 'ok' }
23 | end
24 |
25 | def batch_create
26 | info = CheckDomain.batch_create(current_user, params[:domains], params[:project_id], params[:markup])
27 |
28 | render json: {
29 | new_domains: info[:new_domains].map { |domain| { id: domain.id, domain: domain.domain } }
30 | }
31 | end
32 |
33 | def create
34 | @check_domain = current_user.check_domains.new(check_domain_params)
35 | if @check_domain.save
36 | render
37 | else
38 | render json: @check_domain.errors, status: 422
39 | end
40 | rescue StandardError => e
41 | render json: { error: e }, status: 422
42 | end
43 |
44 | def show
45 | render
46 | end
47 |
48 | def check_now
49 | @check_domain.update_check_expire_time
50 | render :show
51 | end
52 |
53 | def update
54 | if @check_domain.update(check_domain_params)
55 | render
56 | else
57 | render json: @check_domain.errors, status: 422
58 | end
59 | end
60 |
61 | def destroy
62 | @check_domain.destroy
63 | head 200
64 | end
65 |
66 | def valid
67 | domain = params[:domain]
68 | domain = CheckDomain.parse_domain(domain)
69 |
70 | return render json: { error: '请填写正确的域名地址' }, status: 422 if domain.blank?
71 |
72 | answer = CheckDomain.ask_expire_time(domain)
73 | render json: { expire_at: answer }
74 | rescue StandardError => e
75 | render json: { error: e }, status: 422
76 | end
77 |
78 | protected
79 |
80 | def set_check_domain
81 | @check_domain = current_user.check_domains.find params[:id]
82 | end
83 |
84 | def check_domain_params
85 | params.permit(:domain, :markup, :project_id)
86 | end
87 | end
88 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/msg_channels_controller.rb:
--------------------------------------------------------------------------------
1 | class Api::V1::MsgChannelsController < ApiController
2 | before_action :set_channel, only: %i[update show destroy bind unbind try_send_message multiple_bind]
3 | def index
4 | @msg_channels = current_user.msg_channels
5 | if params[:domain_id]
6 | domain = current_user.check_domains.find_by_id params[:domain_id]
7 | return if domain.nil?
8 |
9 | @msg_channels = domain.msg_channels
10 | end
11 |
12 | @msg_channels = @msg_channels.where(is_common: true) if params[:is_common].to_s == 'true'
13 | end
14 |
15 | def multiple_bind
16 | domain_ids = current_user.check_domains.where(id: params[:domain_ids]).pluck(:id)
17 | domain_ids.each do |domain_id|
18 | @msg_channel.bind_domain(domain_id)
19 | end
20 | render json: {msg: 'ok'}
21 | end
22 |
23 | def bind
24 | if @msg_channel.bind_domain(params[:domain_id])
25 | render :show
26 | else
27 | render json: { msg: 'domain_id not found' }, status: 400
28 | end
29 | end
30 |
31 | def unbind
32 | if @msg_channel.unbind_domain(params[:domain_id])
33 | render :show
34 | else
35 | render json: { msg: 'domain_id not found' }, status: 400
36 | end
37 | end
38 |
39 | def create
40 | @msg_channel = current_user.msg_channels.new(msg_channel_params)
41 | if @msg_channel.save
42 | @msg_channel.bind_domain(params[:domain_id]) if params[:domain_id]
43 | render :show
44 | else
45 | render json: @msg_channel.errors, status: 422
46 | end
47 | end
48 |
49 | def try_send_message
50 | domain_id = params[:domain_id]
51 | if domain_id.present? && check_domain = current_user.check_domains.find_by(id: domain_id)
52 | title = "sslguala通知-#{check_domain.domain}"
53 | body = "#{check_domain.domain} 的SSL证书的过期时间为 #{check_domain.expire_at}."
54 | answer = @msg_channel.send_msg(title, body)
55 | else
56 | title = "sslguala通知"
57 | body = "感谢使用sslguala,您能正常接收到通知"
58 | answer = @msg_channel.send_msg(title, body)
59 | end
60 | render json: answer
61 | end
62 |
63 | def show
64 | render
65 | end
66 |
67 | def update
68 | if @msg_channel.update(msg_channel_params)
69 | render :show
70 | else
71 | render json: @msg_channel.errors, status: 422
72 | end
73 | end
74 |
75 | def destroy
76 | if @msg_channel.domain_msg_channels.map{ |x| x.destroy } && @msg_channel.destroy
77 | render json: {status: "success" }
78 | else
79 | render json: @msg_channel.errors, status: 422
80 | end
81 | end
82 |
83 | private
84 |
85 | def msg_channel_params
86 | params.permit(:title, :url, :type, :is_default, :markup, :is_common, :config_secret, :config_custom_string, :config_email)
87 | end
88 |
89 | def set_channel
90 | @msg_channel = current_user.msg_channels.find params[:id]
91 | end
92 | end
93 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/projects_controller.rb:
--------------------------------------------------------------------------------
1 | class Api::V1::ProjectsController < ApiController
2 | before_action :set_project, only: %i[update show destroy add_domains]
3 | def index
4 | @projects = current_user.projects.order("created_at desc")
5 | end
6 |
7 | def add_domains
8 | domain_ids = params[:domain_ids]
9 | current_user.check_domains.where(id: domain_ids).each do |domain|
10 | domain.update(project_id: @project.id)
11 | end
12 | render :show
13 |
14 | end
15 |
16 | def create
17 | @project = current_user.projects.new(project_params)
18 | if @project.save
19 | render
20 | else
21 | render json: @project.errors, status: 422
22 | end
23 | end
24 |
25 | def show
26 | end
27 |
28 | def update
29 | if @project.update(project_params)
30 | render
31 | else
32 | render json: @project.errors, status: 422
33 | end
34 | end
35 |
36 | def destroy
37 | if @project.destroy
38 | head 200
39 | else
40 | render json: @project.errors, status: 422
41 | end
42 | end
43 |
44 | protected
45 |
46 | def project_params
47 | params.permit(:name, :description)
48 |
49 | end
50 |
51 | def set_project
52 | @project = current_user.projects.find params[:id]
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/users_controller.rb:
--------------------------------------------------------------------------------
1 | class Api::V1::UsersController < ApiController
2 | def info
3 | @user = current_user
4 | end
5 |
6 | def reset_token
7 | current_user.reset_api_token
8 | render json: { api_token: current_user.reload.api_token }
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/controllers/api_controller.rb:
--------------------------------------------------------------------------------
1 | class ApiController < ActionController::Base
2 | protect_from_forgery unless: -> { request.format.json? || request.format.xml? }
3 | before_action :check_user
4 | before_action :auth_user!, unless: -> { Rails.env.development? }
5 | # before_action :authenticate_user!, unless: -> { Rails.env.development? }
6 |
7 | include Pagy::Backend
8 |
9 | def check_user
10 | @current_user = User.first if Rails.env.development?
11 | end
12 |
13 | def auth_user!
14 | # api_token = params[:api_token]
15 | # if api_token.present? && user = User.find_by(api_token: api_token)
16 | # return @current_user = user
17 | # end
18 | authenticate_user!
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | before_action :set_raven_context
3 | before_action :check_user
4 |
5 | def check_user
6 | # @current_user = User.first if Rails.env.development?
7 |
8 |
9 | end
10 |
11 |
12 |
13 | private
14 |
15 | def set_raven_context
16 | Raven.user_context(id: session[:current_user_id]) # or anything else in session
17 | Raven.extra_context(params: params.to_unsafe_h, url: request.url)
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/app/controllers/home_controller.rb:
--------------------------------------------------------------------------------
1 | class HomeController < ApplicationController
2 | def index
3 | end
4 |
5 | def policy
6 |
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/controllers/madmin/application_controller.rb:
--------------------------------------------------------------------------------
1 | module Madmin
2 | class ApplicationController < Madmin::BaseController
3 | before_action :authenticate_user!
4 | before_action :authenticate_admin_user
5 |
6 | def authenticate_admin_user
7 | unless current_user.admin?
8 | sign_out
9 | redirect_to new_user_session_path, notice: '您账号没有管理员权限'
10 | end
11 | end
12 |
13 | # Authenticate with Clearance
14 | # include Clearance::Controller
15 | # before_action :require_login
16 |
17 | # Authenticate with Devise
18 | # before_action :authenticate_user!
19 |
20 | # Authenticate with Basic Auth
21 | # http_basic_authenticate_with(name: Rails.application.credentials.admin_username, password: Rails.application.credentials.admin_password)
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/controllers/madmin/check_domains_controller.rb:
--------------------------------------------------------------------------------
1 | module Madmin
2 | class CheckDomainsController < Madmin::ResourceController
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/controllers/madmin/dashboard_controller.rb:
--------------------------------------------------------------------------------
1 | module Madmin
2 | class DashboardController < ApplicationController
3 | def index
4 | end
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/app/controllers/madmin/msg_channels_controller.rb:
--------------------------------------------------------------------------------
1 | module Madmin
2 | class MsgChannelsController < Madmin::ResourceController
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/controllers/madmin/projects_controller.rb:
--------------------------------------------------------------------------------
1 | module Madmin
2 | class ProjectsController < Madmin::ResourceController
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/controllers/madmin/user_omniauths_controller.rb:
--------------------------------------------------------------------------------
1 | module Madmin
2 | class UserOmniauthsController < Madmin::ResourceController
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/controllers/madmin/users_controller.rb:
--------------------------------------------------------------------------------
1 | module Madmin
2 | class UsersController < Madmin::ResourceController
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/controllers/users/confirmations_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Users::ConfirmationsController < Devise::ConfirmationsController
4 | # GET /resource/confirmation/new
5 | # def new
6 | # super
7 | # end
8 |
9 | # POST /resource/confirmation
10 | # def create
11 | # super
12 | # end
13 |
14 | # GET /resource/confirmation?confirmation_token=abcdef
15 | # def show
16 | # super
17 | # end
18 |
19 | # protected
20 |
21 | # The path used after resending confirmation instructions.
22 | # def after_resending_confirmation_instructions_path_for(resource_name)
23 | # super(resource_name)
24 | # end
25 |
26 | # The path used after confirmation.
27 | # def after_confirmation_path_for(resource_name, resource)
28 | # super(resource_name, resource)
29 | # end
30 | end
31 |
--------------------------------------------------------------------------------
/app/controllers/users/omniauth_callbacks_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'devise/jwt/test_helpers'
3 |
4 | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
5 | skip_before_action :verify_authenticity_token#, only: :wechat
6 |
7 | def wechat
8 | auth = request.env['omniauth.auth']
9 | Rails.logger.info("====> wechat #{auth}")
10 | unionid = auth['info']['unionid']
11 | user = bind_omniauth('wechat', auth['uid'])
12 | info = auth['info']
13 | @user = user || User.from_omniauth('wechat', auth['uid'], nil, info['nickname'], avatar: info['headimgurl'], unionid: info['unionid'])
14 |
15 | redirect_oauth(@user)
16 | end
17 |
18 | def redirect_oauth(user)
19 | url = "#{ENV['WEB_DOMAIN']}/auth/callback"
20 | url = if user&.persisted?
21 | sign_in(resource_name, user)
22 | headers = auth_headers(user)
23 | "#{url}?server_token=#{headers['Authorization']}"
24 | else
25 | "#{url}?error=#{user.errors.messages}"
26 | end
27 | redirect_to url
28 | end
29 |
30 | def failure
31 | redirect_to "#{ENV['WEB_DOMAIN']}"
32 | end
33 |
34 | def bind_omniauth(provider, uid)
35 | return current_user if current_user.present? && current_user.bind_service(provider, uid)
36 | end
37 |
38 | # 生成新的token
39 | def auth_headers(user)
40 | headers = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
41 | auth_headers = Devise::JWT::TestHelpers.auth_headers(headers, user)
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/app/controllers/users/passwords_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Users::PasswordsController < Devise::PasswordsController
4 | protect_from_forgery with: :null_session, prepend: true
5 | respond_to :html, :json
6 | # GET /resource/password/new
7 | # def new
8 | # super
9 | # end
10 |
11 | # POST /resource/password
12 | # def create
13 | # super
14 | # end
15 |
16 | # GET /resource/password/edit?reset_password_token=abcdef
17 | # def edit
18 | # super
19 | # end
20 |
21 | # PUT /resource/password
22 | # def update
23 | # super
24 | # end
25 |
26 | # protected
27 |
28 | # def after_resetting_password_path_for(resource)
29 | # super(resource)
30 | # end
31 |
32 | # The path used after sending reset password instructions
33 | # def after_sending_reset_password_instructions_path_for(resource_name)
34 | # super(resource_name)
35 | # end
36 | end
37 |
--------------------------------------------------------------------------------
/app/controllers/users/registrations_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Users::RegistrationsController < Devise::RegistrationsController
4 | protect_from_forgery with: :null_session, prepend: true
5 | respond_to :html, :json
6 | before_action :configure_sign_up_params, only: [:create]
7 | # before_action :configure_account_update_params, only: [:update]
8 |
9 | # GET /resource/sign_up
10 | # def new
11 | # super
12 | # end
13 |
14 | # POST /resource
15 | def create
16 | super do |user|
17 | if user.errors.present?
18 | return render json: { error: user.errors.full_messages }, status: 422
19 | end
20 | end
21 | end
22 |
23 |
24 | # GET /resource/edit
25 | # def edit
26 | # super
27 | # end
28 |
29 | # PUT /resource
30 | def update
31 | super do |user|
32 | if user.errors.present?
33 | return render json: { error: user.errors }, status: 422
34 | end
35 | end
36 | end
37 |
38 | # DELETE /resource
39 | # def destroy
40 | # super
41 | # end
42 |
43 | # GET /resource/cancel
44 | # Forces the session data which is usually expired after sign
45 | # in to be expired now. This is useful if the user wants to
46 | # cancel oauth signing in/up in the middle of the process,
47 | # removing all OAuth session data.
48 | # def cancel
49 | # super
50 | # end
51 |
52 | # protected
53 |
54 | # If you have extra params to permit, append them to the sanitizer.
55 | def configure_sign_up_params
56 | devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :login, :password, :password_confirmation])
57 | end
58 |
59 | # If you have extra params to permit, append them to the sanitizer.
60 | def configure_account_update_params
61 | devise_parameter_sanitizer.permit(:account_update, keys: [:current_password, :password, :password_confirmation])
62 | end
63 |
64 | # The path used after sign up.
65 | # def after_sign_up_path_for(resource)
66 | # super(resource)
67 | # end
68 |
69 | # The path used after sign up for inactive accounts.
70 | # def after_inactive_sign_up_path_for(resource)
71 | # super(resource)
72 | # end
73 |
74 | # def respond_with(resource, _opts = {})
75 | # render json: resource
76 | # end
77 | end
78 |
--------------------------------------------------------------------------------
/app/controllers/users/sessions_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Users::SessionsController < Devise::SessionsController
4 | before_action :configure_permitted_parameters, if: :devise_controller?
5 | respond_to :html, :json
6 |
7 | def configure_permitted_parameters
8 | devise_parameter_sanitizer.permit(:sign_in, keys: [:login, :email, :password, :password_confirmation])
9 | end
10 |
11 | protect_from_forgery with: :null_session, prepend: true
12 | before_action :configure_sign_in_params, only: [:create]
13 |
14 | # GET /resource/sign_in
15 | def new
16 | super
17 | end
18 |
19 | # POST /resource/sign_in
20 | def create
21 | super
22 | end
23 |
24 | # DELETE /resource/sign_out
25 | def destroy
26 | super
27 | end
28 |
29 | # protected
30 |
31 | # def respond_with(resource, _opts = {})
32 | # render json: resource
33 | # end
34 |
35 | # If you have extra params to permit, append them to the sanitizer.
36 | def configure_sign_in_params
37 | devise_parameter_sanitizer.permit(:sign_in, keys: [:login, :email, :password])
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/app/controllers/users/unlocks_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Users::UnlocksController < Devise::UnlocksController
4 | # GET /resource/unlock/new
5 | # def new
6 | # super
7 | # end
8 |
9 | # POST /resource/unlock
10 | # def create
11 | # super
12 | # end
13 |
14 | # GET /resource/unlock?unlock_token=abcdef
15 | # def show
16 | # super
17 | # end
18 |
19 | # protected
20 |
21 | # The path used after sending unlock password instructions
22 | # def after_sending_unlock_instructions_path_for(resource)
23 | # super(resource)
24 | # end
25 |
26 | # The path used after unlocking the resource
27 | # def after_unlock_path_for(resource)
28 | # super(resource)
29 | # end
30 | end
31 |
--------------------------------------------------------------------------------
/app/helpers/api/v1/check_domains_helper.rb:
--------------------------------------------------------------------------------
1 | module Api::V1::CheckDomainsHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/api/v1/msg_channels_helper.rb:
--------------------------------------------------------------------------------
1 | module Api::V1::MsgChannelsHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/api/v1/projects_helper.rb:
--------------------------------------------------------------------------------
1 | module Api::V1::ProjectsHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/home_helper.rb:
--------------------------------------------------------------------------------
1 | module HomeHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/javascript/channels/consumer.js:
--------------------------------------------------------------------------------
1 | // Action Cable provides the framework to deal with WebSockets in Rails.
2 | // You can generate new channels where WebSocket features live using the `bin/rails generate channel` command.
3 |
4 | import { createConsumer } from "@rails/actioncable"
5 |
6 | export default createConsumer()
7 |
--------------------------------------------------------------------------------
/app/javascript/channels/index.js:
--------------------------------------------------------------------------------
1 | // Load all the channels within this directory and all subdirectories.
2 | // Channel files must be named *_channel.js.
3 |
4 | const channels = require.context('.', true, /_channel\.js$/)
5 | channels.keys().forEach(channels)
6 |
--------------------------------------------------------------------------------
/app/javascript/packs/admin.js:
--------------------------------------------------------------------------------
1 | // This file is automatically compiled by Webpack, along with any other files
2 | // present in this directory. You're encouraged to place your actual application logic in
3 | // a relevant structure within app/javascript and only use these pack files to reference
4 | // that code so it'll be compiled.
5 |
6 | import Rails from "@rails/ujs"
7 | import Turbolinks from "turbolinks"
8 | import * as ActiveStorage from "@rails/activestorage"
9 | import "channels"
10 | import { Application, Controller } from 'stimulus';
11 |
12 | Rails.start()
13 | Turbolinks.start()
14 | ActiveStorage.start()
15 |
16 | document.addEventListener("turbolinks:load", function () {
17 | // $(".search_form select").addClass('form-control');
18 |
19 | (() => {
20 | const application = Application.start()
21 | application.register('nested-form', class extends Controller {
22 | static get targets() {
23 | return [ "links", "template" ]
24 | }
25 |
26 | connect() {
27 | this.wrapperClass = this.data.get("wrapperClass") || "nested-fields"
28 | }
29 |
30 | add_association(event) {
31 | event.preventDefault()
32 |
33 | var content = this.templateTarget.innerHTML.replace(/NEW_RECORD/g, new Date().getTime())
34 | this.linksTarget.insertAdjacentHTML('beforebegin', content)
35 | }
36 |
37 | remove_association(event) {
38 | event.preventDefault()
39 |
40 | let wrapper = event.target.closest("." + this.wrapperClass)
41 |
42 | // New records are simply removed from the page
43 | if (wrapper.dataset.newRecord == "true") {
44 | wrapper.remove()
45 |
46 | // Existing records are hidden and flagged for deletion
47 | } else {
48 | wrapper.querySelector("input[name*='_destroy']").value = 1
49 | wrapper.style.display = 'none'
50 | }
51 | }
52 | })
53 | })()
54 |
55 | })
56 |
57 |
--------------------------------------------------------------------------------
/app/javascript/packs/application.js:
--------------------------------------------------------------------------------
1 | // This file is automatically compiled by Webpack, along with any other files
2 | // present in this directory. You're encouraged to place your actual application logic in
3 | // a relevant structure within app/javascript and only use these pack files to reference
4 | // that code so it'll be compiled.
5 |
6 | import Rails from "@rails/ujs"
7 | import Turbolinks from "turbolinks"
8 | import * as ActiveStorage from "@rails/activestorage"
9 | import "channels"
10 |
11 | Rails.start()
12 | Turbolinks.start()
13 | ActiveStorage.start()
14 |
--------------------------------------------------------------------------------
/app/jobs/application_job.rb:
--------------------------------------------------------------------------------
1 | class ApplicationJob < ActiveJob::Base
2 | # Automatically retry jobs that encountered a deadlock
3 | # retry_on ActiveRecord::Deadlocked
4 |
5 | # Most jobs are safe to ignore if the underlying records are no longer available
6 | # discard_on ActiveJob::DeserializationError
7 | end
8 |
--------------------------------------------------------------------------------
/app/madmin/resources/check_domain_resource.rb:
--------------------------------------------------------------------------------
1 | class CheckDomainResource < Madmin::Resource
2 | # Attributes
3 | attribute :id, form: false
4 | attribute :domain
5 | attribute :markup
6 | attribute :expire_at
7 | attribute :status
8 | attribute :created_at, form: false
9 | # attribute :updated_at, form: false
10 | attribute :check_expire_time_at
11 | attribute :project_id
12 |
13 | # Associations
14 | attribute :user
15 |
16 | # Uncomment this to customize the display name of records in the admin area.
17 | # def self.display_name(record)
18 | # record.name
19 | # end
20 |
21 | # Uncomment this to customize the default sort column and direction.
22 | # def self.default_sort_column
23 | # "created_at"
24 | # end
25 | #
26 | # def self.default_sort_direction
27 | # "desc"
28 | # end
29 | end
30 |
--------------------------------------------------------------------------------
/app/madmin/resources/msg_channel_resource.rb:
--------------------------------------------------------------------------------
1 | class MsgChannelResource < Madmin::Resource
2 | # Attributes
3 | attribute :id, form: false
4 | attribute :title
5 | attribute :url
6 | attribute :type
7 | attribute :markup
8 | attribute :config
9 | attribute :created_at, form: false
10 | attribute :updated_at, form: false
11 | attribute :is_common
12 | attribute :error_info
13 | attribute :is_default
14 |
15 | # Associations
16 | attribute :user
17 | attribute :domain_msg_channels
18 | attribute :check_domains
19 |
20 | # Uncomment this to customize the display name of records in the admin area.
21 | # def self.display_name(record)
22 | # record.name
23 | # end
24 |
25 | # Uncomment this to customize the default sort column and direction.
26 | # def self.default_sort_column
27 | # "created_at"
28 | # end
29 | #
30 | # def self.default_sort_direction
31 | # "desc"
32 | # end
33 | end
34 |
--------------------------------------------------------------------------------
/app/madmin/resources/project_resource.rb:
--------------------------------------------------------------------------------
1 | class ProjectResource < Madmin::Resource
2 | # Attributes
3 | attribute :id, form: false
4 | attribute :name
5 | attribute :description
6 | attribute :created_at, form: false
7 | attribute :updated_at, form: false
8 |
9 | # Associations
10 | attribute :check_domains
11 | attribute :user
12 |
13 | # Uncomment this to customize the display name of records in the admin area.
14 | # def self.display_name(record)
15 | # record.name
16 | # end
17 |
18 | # Uncomment this to customize the default sort column and direction.
19 | # def self.default_sort_column
20 | # "created_at"
21 | # end
22 | #
23 | # def self.default_sort_direction
24 | # "desc"
25 | # end
26 | end
27 |
--------------------------------------------------------------------------------
/app/madmin/resources/user_omniauth_resource.rb:
--------------------------------------------------------------------------------
1 | class UserOmniauthResource < Madmin::Resource
2 | # Attributes
3 | attribute :id, form: false
4 | attribute :nickname
5 | attribute :provider
6 | attribute :uid
7 | attribute :unionid
8 | attribute :user_id
9 | # attribute :created_at, form: false
10 | # attribute :updated_at, form: false
11 |
12 | # Associations
13 |
14 | # Uncomment this to customize the display name of records in the admin area.
15 | # def self.display_name(record)
16 | # record.name
17 | # end
18 |
19 | # Uncomment this to customize the default sort column and direction.
20 | # def self.default_sort_column
21 | # "created_at"
22 | # end
23 | #
24 | # def self.default_sort_direction
25 | # "desc"
26 | # end
27 | end
28 |
--------------------------------------------------------------------------------
/app/madmin/resources/user_resource.rb:
--------------------------------------------------------------------------------
1 | class UserResource < Madmin::Resource
2 | # Attributes
3 | attribute :id, form: false
4 | attribute :email
5 | #attribute :password
6 | # attribute :encrypted_password, form: false
7 | # attribute :reset_password_token, form: false
8 | # attribute :reset_password_sent_at, form: false
9 | # attribute :remember_created_at, form: false
10 | attribute :first_name
11 | attribute :last_name
12 | attribute :admin
13 | attribute :created_at, form: false
14 | # attribute :updated_at, form: false
15 |
16 | # Associations
17 | attribute :check_domains
18 | attribute :projects
19 |
20 | # Uncomment this to customize the display name of records in the admin area.
21 | # def self.display_name(record)
22 | # record.name
23 | # end
24 |
25 | # Uncomment this to customize the default sort column and direction.
26 | # def self.default_sort_column
27 | # "created_at"
28 | # end
29 | #
30 | # def self.default_sort_direction
31 | # "desc"
32 | # end
33 | end
34 |
--------------------------------------------------------------------------------
/app/mailers/application_mailer.rb:
--------------------------------------------------------------------------------
1 | class ApplicationMailer < ActionMailer::Base
2 | default from: 'from@example.com'
3 | layout 'mailer'
4 | end
5 |
--------------------------------------------------------------------------------
/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | class ApplicationRecord < ActiveRecord::Base
2 | self.abstract_class = true
3 | end
4 |
--------------------------------------------------------------------------------
/app/models/check_domain.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: check_domains
4 | #
5 | # id :bigint not null, primary key
6 | # check_expire_time_at :datetime
7 | # domain :string
8 | # expire_at :datetime
9 | # latest_notice_at :datetime
10 | # markup :string
11 | # notice_info :jsonb
12 | # status :string
13 | # created_at :datetime not null
14 | # updated_at :datetime not null
15 | # project_id :integer
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_check_domains_on_user_id (user_id)
21 | #
22 | # Foreign Keys
23 | #
24 | # fk_rails_... (user_id => users.id)
25 | #
26 | class CheckDomain < ApplicationRecord
27 | include CheckDomainSsl
28 | include CheckDomainNotification
29 | enum status: {
30 | enabled: 'enabled',
31 | ignored: 'ignored',
32 | dead: 'dead'
33 | }, _default: 'enabled'
34 |
35 | belongs_to :user
36 | belongs_to :project, optional: true, counter_cache: true
37 | has_many :domain_msg_channels, dependent: :destroy
38 | has_many :msg_channels, through: :domain_msg_channels
39 |
40 | validates :domain, presence: true
41 | validate :check_domain, on: :create
42 |
43 | before_create :check_project
44 | before_create :strip_domain
45 |
46 | after_create :update_check_expire_time
47 | after_update_commit :check_send_msg_channels
48 | after_update_commit :ssl_recover
49 |
50 | def ask_expire_time
51 | self.class.ask_expire_time(domain)
52 | end
53 |
54 | def expired?
55 | expire_at < Time.current
56 | end
57 |
58 | def expire_soon?
59 | expire_time - Time.current < 7.days
60 | end
61 |
62 | def update_check_expire_time
63 | self.expire_at = ask_expire_time
64 | self.check_expire_time_at = Time.current
65 | save!
66 | end
67 |
68 | def async_check_expire_time(random_waiting: false)
69 | if random_waiting
70 | self.class.delay_for(SecureRandom.rand(1..60).seconds, retry: false).check_domain_expire_time(domain)
71 | else
72 | self.class.delay.check_domain_expire_time(domain)
73 | end
74 | end
75 |
76 | def remain_days
77 | (expire_at.to_i - Time.current.to_i ) / (3600 * 24)
78 | end
79 |
80 | # 当expire_at变化,并且过期时间比当前长的话。发送通知为ssl的状态已更新通知
81 | def ssl_recover
82 | if saved_change_to_expire_at? && expire_at > expire_at_before_last_save
83 | send_recover_notification(async: true)
84 | clear_domain_cache
85 | update(status: :enabled) if status == 'dead'
86 | end
87 | end
88 |
89 | def clear_domain_cache
90 | [14, 7, 3, 1, 0].each { |days| Rails.cache.delete("check-domain-#{id}-days-#{days}") }
91 | end
92 |
93 | class << self
94 | def batch_create(user, domains, project_id, markup)
95 | exist_domains = user.check_domains.where(domain: domains.uniq)
96 |
97 | new_domain_objects = (domains.uniq - exist_domains.pluck(:domain)).map do |domain|
98 | user.check_domains.create(project_id: project_id, domain: domain, markup: markup)
99 | end
100 |
101 | {
102 | new_domains: new_domain_objects
103 | }
104 | end
105 |
106 | def parse_domain(domain)
107 | domain = domain.strip.downcase
108 | domain_url = "#{domain}".start_with?(/(http|https):\/\//) ? domain : "https://#{domain}"
109 | host = URI.parse(domain_url).host
110 | return '' unless PublicSuffix.valid?(host)
111 |
112 | clear_domain = PublicSuffix.parse(host).subdomain || PublicSuffix.parse(host).domain
113 | clear_domain
114 | end
115 |
116 | def check_domain_expire_time(domain)
117 | expire_time = ask_expire_time(domain)
118 | now = Time.current
119 |
120 | CheckDomain.where(domain: domain).each do |check_domain|
121 | check_domain.update(expire_at: expire_time, check_expire_time_at: now) unless check_domain.dead?
122 | end
123 | end
124 |
125 | def ask_expire_time(url)
126 | info = ssl_cert(url)
127 | info.not_after
128 | end
129 | end
130 |
131 | private
132 |
133 | def check_project
134 | self.project_id = user.projects.first&.id if project_id.nil?
135 | end
136 |
137 | def check_send_msg_channels
138 | # 如果不是检查域名引起的提交, 则直接返回
139 | return unless saved_change_to_check_expire_time_at?
140 |
141 | send_warn_msg
142 | end
143 |
144 | def strip_domain
145 | self.domain = parse_domain.downcase
146 | end
147 |
148 | def check_domain
149 | errors.add(:domain, "请填写合法的域名") if parse_domain.blank?
150 | errors.add(:domain, "您已创建过相同的域名") if CheckDomain.where(domain: parse_domain, user: user).exists?
151 | end
152 |
153 | def parse_domain
154 | self.class.parse_domain(self.domain)
155 | end
156 |
157 | def send_warn_msg
158 | if expired?
159 | # 发送过期通知
160 | try_send_expire_notification
161 | else
162 | # 快要过期, 发送通知
163 | try_send_expire_soon_notification
164 | end
165 | end
166 |
167 | end
168 |
--------------------------------------------------------------------------------
/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/app/models/concerns/.keep
--------------------------------------------------------------------------------
/app/models/concerns/check_domain_notification.rb:
--------------------------------------------------------------------------------
1 | module CheckDomainNotification
2 | extend ActiveSupport::Concern
3 |
4 | class_methods do
5 | def send_channels_msg(id, title, content)
6 | check_domain = find id
7 | return if check_domain.nil?
8 |
9 | # 取关联的channel以及默认的channel
10 | channels = check_domain.msg_channels# + check_domain.user.msg_channels.default_list
11 | channels.uniq.each do |msg_channel|
12 | msg_channel.send_msg(title, content)
13 | end
14 | end
15 | end
16 |
17 |
18 | def try_send_expire_notification(async: true)
19 | return unless expired?
20 | return if latest_notice_at.to_i >= expire_at.to_i # 已经过期, 且通知了一次
21 |
22 | title = "域名 #{domain} 证书已过期, 请立即更新证书"
23 | content = <<-EOF
24 | 域名 #{domain} 证书过期时间为 #{expire_at.localtime}
25 |
26 | 详情请访问 https://www.sslguala.com/projects/#{project_id}/domains/#{id}/details 查看
27 | EOF
28 |
29 | if async
30 | self.class.delay(retry: 1).send_channels_msg(id, title, content)
31 | else
32 | self.class.send_channels_msg(id, title, content)
33 | end
34 | self.class.where(id: id).update_all(latest_notice_at: Time.current)
35 | true
36 | end
37 |
38 | def try_send_expire_soon_notification(async: true, ignore_days_limit: false)
39 | return false if expired?
40 |
41 | days = remain_days
42 | return unless [14, 7, 3, 1, 0].include?(days) || ignore_days_limit
43 |
44 | Rails.cache.fetch("check-domain-#{id}-days-#{days}", expires_in: 25.hours) do
45 | send_expire_soon_notification(days, async: async)
46 | self.class.where(id: id).update_all(latest_notice_at: Time.current)
47 | end
48 | end
49 |
50 | def send_expire_soon_notification(day, async: true)
51 | title = "域名 #{domain} 证书还有#{day}天过期, 请立即更新证书"
52 | content = <<-EOF
53 | 域名 #{domain} 证书过期时间为 #{expire_at.localtime}, 还有#{remain_days}天过期
54 |
55 | 详情请访问 https://www.sslguala.com/# 查看
56 | EOF
57 | if async
58 | self.class.delay(retry: 1).send_channels_msg(id, title, content)
59 | else
60 | self.class.send_channels_msg(id, title, content)
61 | end
62 | true
63 | end
64 |
65 | def send_recover_notification(async: true)
66 | title = "域名 #{domain} 证书已更新成功, 证书还有#{remain_days}天过期。"
67 | Rails.logger.info("notice => #{title}")
68 | content = <<-EOF
69 | 域名 #{domain} 证书过期时间为 #{expire_at.localtime}, 还有#{remain_days}天过期
70 | 详情请访问 https://www.sslguala.com 查看
71 | EOF
72 | if async
73 | self.class.delay(retry: 1).send_channels_msg(id, title, content)
74 | else
75 | self.class.send_channels_msg(id, title, content)
76 | end
77 | true
78 | end
79 | end
--------------------------------------------------------------------------------
/app/models/concerns/check_domain_ssl.rb:
--------------------------------------------------------------------------------
1 | module CheckDomainSsl
2 | extend ActiveSupport::Concern
3 |
4 | class_methods do
5 | def ssl_cert(url)
6 | http = if url.start_with? 'http'
7 | uri = URI.parse(url)
8 | Net::HTTP.new(uri.host, uri.port)
9 | else
10 | Net::HTTP.new(url.split('/')[0], 443)
11 | end
12 |
13 | http.use_ssl = true
14 | # http.ssl_version = :TLSv1
15 | http.verify_mode = OpenSSL::SSL::VERIFY_NONE
16 | http.open_timeout = 20
17 | http.read_timeout = 20
18 | http.ssl_timeout = 20
19 |
20 | http.start do |h|
21 | @cert = h.peer_cert
22 | end
23 | raise UrlError, 'No https found' if @cert.nil?
24 |
25 | @cert
26 | rescue SocketError, SystemCallError
27 | raise UrlError, "Bad URL? #{$!.message}"
28 | rescue Net::OpenTimeout
29 | raise UrlError, "访问链接 #{url} 超时,请确认网站能使用https访问"
30 | rescue OpenSSL::SSL::SSLError
31 | raise UrlError, "#{http.address} SSL config Error"
32 | end
33 | end
34 | end
--------------------------------------------------------------------------------
/app/models/concerns/omni_authable.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module OmniAuthable
4 | extend ActiveSupport::Concern
5 |
6 | def bind?(provider)
7 | user_omniauths.collect(&:provider).include?(provider)
8 | end
9 |
10 | def bind_service(provider, uid)
11 | user_omniauths.find_or_create_by(provider: provider, uid: uid).try(:user)
12 | end
13 |
14 | module ClassMethods
15 | def from_omniauth(provider, uid, email = nil, name = '', opts = {})
16 | user = UserOmniauth.find_by(provider: provider, uid: uid).try(:user)
17 | return user if user
18 | return user if email.present? && user = User.find_by(email: email)
19 |
20 | new_user = User.new do |user|
21 | user.email = email || "#{SecureRandom.uuid}@example-#{provider}.com"
22 | user.password = Devise.friendly_token[0, 20]
23 | user.first_name = name
24 | end
25 |
26 | new_user.save
27 | new_user.user_omniauths.find_or_create_by(provider: provider, uid: uid)
28 | new_user
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/app/models/domain_msg_channel.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: domain_msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # created_at :datetime not null
7 | # updated_at :datetime not null
8 | # check_domain_id :bigint not null
9 | # msg_channel_id :bigint not null
10 | #
11 | # Indexes
12 | #
13 | # index_domain_msg_channels_on_check_domain_id (check_domain_id)
14 | # index_domain_msg_channels_on_msg_channel_id (msg_channel_id)
15 | #
16 | # Foreign Keys
17 | #
18 | # fk_rails_... (check_domain_id => check_domains.id)
19 | # fk_rails_... (msg_channel_id => msg_channels.id)
20 | #
21 | class DomainMsgChannel < ApplicationRecord
22 | belongs_to :check_domain
23 | belongs_to :msg_channel
24 |
25 | end
26 |
--------------------------------------------------------------------------------
/app/models/msg_channel.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # config :jsonb
7 | # error_info :string
8 | # is_common :boolean default(TRUE)
9 | # is_default :boolean default(FALSE)
10 | # markup :string
11 | # title :string
12 | # type :string
13 | # url :string
14 | # created_at :datetime not null
15 | # updated_at :datetime not null
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_msg_channels_on_is_default (is_default)
21 | # index_msg_channels_on_user_id (user_id)
22 | #
23 | # Foreign Keys
24 | #
25 | # fk_rails_... (user_id => users.id)
26 | #
27 | class MsgChannel < ApplicationRecord
28 | store :config, accessors: %i[token secret custom_string email], prefix: :config
29 |
30 | belongs_to :user
31 | has_many :domain_msg_channels
32 | has_many :check_domains, through: :domain_msg_channels
33 |
34 | scope :default_list, -> { where(is_default: true)}
35 |
36 | # 记录发送状态
37 | def send_status_log(answer = {status: true, error: ''})
38 | if answer[:status]
39 | update(error_info: nil)
40 | true
41 | else
42 | update(error_info: answer[:error])
43 | false
44 | end
45 | end
46 |
47 | def bind_domain(domain_id)
48 | domain = user.check_domains.find_by_id domain_id
49 | return if domain.nil?
50 |
51 | DomainMsgChannel.create(msg_channel: self, check_domain: domain)
52 | end
53 |
54 | def unbind_domain(domain_id)
55 | domain = user.check_domains.find_by_id domain_id
56 | return if domain.nil?
57 |
58 | DomainMsgChannel.where(msg_channel: self, check_domain: domain).each(&:destroy)
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/app/models/msg_channel/bark.rb:
--------------------------------------------------------------------------------
1 | class MsgChannel::Bark < MsgChannel
2 | validates_presence_of :url
3 |
4 | def send_msg(title, body)
5 | payload = {
6 | "title": title,
7 | "body": body,
8 | "url": 'https://sslguala.com'
9 | }
10 | DefaultRest.post(url, payload)
11 | rescue
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/models/msg_channel/dingtalk.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # config :jsonb
7 | # error_info :string
8 | # is_common :boolean default(TRUE)
9 | # is_default :boolean default(FALSE)
10 | # markup :string
11 | # title :string
12 | # type :string
13 | # url :string
14 | # created_at :datetime not null
15 | # updated_at :datetime not null
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_msg_channels_on_is_default (is_default)
21 | # index_msg_channels_on_user_id (user_id)
22 | #
23 | # Foreign Keys
24 | #
25 | # fk_rails_... (user_id => users.id)
26 | #
27 | class MsgChannel::Dingtalk < MsgChannel
28 | validates_presence_of :url
29 |
30 | validate :check_url
31 |
32 | def send_msg(title = "ssl", body = 'good')
33 | payload = {
34 | "msgtype": 'markdown',
35 | "markdown": {
36 | "title": title,
37 | "text": body
38 | }
39 | }
40 |
41 | dingtalk_url = url
42 | if config_secret.present?
43 | info = secret_cal(config_secret)
44 | dingtalk_url = "#{dingtalk_url}×tamp=#{info[:timestamp]}&sign=#{info[:sign]}"
45 | end
46 |
47 | answer = DefaultRest.post(dingtalk_url, payload)
48 | send_status_log({status: answer[:errcode] == 0, error: answer})
49 | rescue StandardError => e
50 | Rails.logger.info("url => #{dingtalk_url}, error => #{e}")
51 | send_status_log({status: false, error: e})
52 | { error: e }
53 | end
54 |
55 | def check_url
56 | errors.add(:url, "请填写钉钉的URL") unless url.start_with?('https://oapi.dingtalk.com/robot/send')
57 | end
58 |
59 | private
60 |
61 | def secret_cal(secret)
62 | timestamp = Time.now.to_i * 1000
63 | secret_enc = secret.encode('utf-8')
64 | str = "#{timestamp}\n#{secret}"
65 | string_to_sign_enc = str.encode('utf-8')
66 |
67 | hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret_enc, string_to_sign_enc)
68 | {
69 | timestamp: timestamp,
70 | sign: CGI.escape(Base64.encode64(hmac).strip)
71 | }
72 | end
73 | end
74 |
--------------------------------------------------------------------------------
/app/models/msg_channel/email.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # config :jsonb
7 | # error_info :string
8 | # is_common :boolean default(TRUE)
9 | # is_default :boolean default(FALSE)
10 | # markup :string
11 | # title :string
12 | # type :string
13 | # url :string
14 | # created_at :datetime not null
15 | # updated_at :datetime not null
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_msg_channels_on_is_default (is_default)
21 | # index_msg_channels_on_user_id (user_id)
22 | #
23 | # Foreign Keys
24 | #
25 | # fk_rails_... (user_id => users.id)
26 | #
27 | class MsgChannel::Email < MsgChannel
28 | validates :config_email, presence: true
29 | validates :config_email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
30 |
31 | def send_msg(title, body)
32 | return if config_email.blank?
33 |
34 | answer = EmailService.send!(from: ENV['TUBECENTER_APP_USEREMAIL'], to: config_email, title: title, content: body)
35 | answer = { status: answer}
36 | send_status_log({status: answer, error: answer})
37 | rescue StandardError => e
38 | send_status_log({status: false, error: e})
39 | {error: e}
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/app/models/msg_channel/lark.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # config :jsonb
7 | # error_info :string
8 | # is_common :boolean default(TRUE)
9 | # is_default :boolean default(FALSE)
10 | # markup :string
11 | # title :string
12 | # type :string
13 | # url :string
14 | # created_at :datetime not null
15 | # updated_at :datetime not null
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_msg_channels_on_is_default (is_default)
21 | # index_msg_channels_on_user_id (user_id)
22 | #
23 | # Foreign Keys
24 | #
25 | # fk_rails_... (user_id => users.id)
26 | #
27 | class MsgChannel::Lark < MsgChannel
28 | validates_presence_of :url
29 |
30 | validate :check_url
31 |
32 | def send_msg(title, body)
33 | payload = build_v2_info(title, body)
34 | answer = DefaultRest.post(url, payload, { timeout: ENV['FEISHU_TIMEOUT'] ? ENV['FEISHU_TIMEOUT'].to_i : 30 })
35 | send_status_log({status: answer[:StatusCode] == 0, error: answer})
36 | rescue => e
37 | send_status_log({status: false, error: e})
38 | { error: e}
39 | end
40 |
41 | # https://open.feishu.cn/open-apis/bot/v2/hook/901340c5-39ff-4fe4-a2e6-e151c0a28247
42 | def check_url
43 | errors.add(:url, "请填写的飞书URL") unless url.start_with?('https://open.feishu.cn/')
44 | end
45 |
46 | # private
47 |
48 | def build_v2_info(title, body)
49 | answer = {
50 | msg_type: 'post',
51 | content: {
52 | post: {
53 | zh_cn: {
54 | title: title,
55 | content: [[{ "tag": 'text', "text": body }]]
56 | }
57 | }
58 | }
59 | }
60 | unless config_secret.blank?
61 | secret_info = secret_cal(config_secret)
62 | answer = answer.merge(secret_info)
63 | end
64 | answer
65 | end
66 |
67 | def secret_cal(secret)
68 | timestamp = Time.now.to_i
69 | str = "#{timestamp}\n#{secret}"
70 | string_to_sign_enc = str.encode('utf-8')
71 |
72 | hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), string_to_sign_enc, "")
73 | {
74 | timestamp: timestamp.to_s,
75 | sign: Base64.encode64(hmac).strip
76 | }
77 | end
78 | end
79 |
--------------------------------------------------------------------------------
/app/models/msg_channel/webhook.rb:
--------------------------------------------------------------------------------
1 | class MsgChannel::Webhook < MsgChannel
2 | validates_presence_of :url
3 |
4 |
5 | def send_msg(title, body)
6 | payload = {
7 | "title": title,
8 | "description": body,
9 | "url": 'https://sslguala.com'
10 | }
11 | DefaultRest.post(url, payload)
12 | rescue
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/models/msg_channel/wecom.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # config :jsonb
7 | # error_info :string
8 | # is_common :boolean default(TRUE)
9 | # is_default :boolean default(FALSE)
10 | # markup :string
11 | # title :string
12 | # type :string
13 | # url :string
14 | # created_at :datetime not null
15 | # updated_at :datetime not null
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_msg_channels_on_is_default (is_default)
21 | # index_msg_channels_on_user_id (user_id)
22 | #
23 | # Foreign Keys
24 | #
25 | # fk_rails_... (user_id => users.id)
26 | #
27 | class MsgChannel::Wecom < MsgChannel
28 | validates_presence_of :url
29 |
30 | validate :check_url
31 |
32 | def send_msg(title, body)
33 | payload = {
34 | "msgtype": 'news',
35 | "news": {
36 | "articles": [{
37 | "title": title,
38 | "description": body,
39 | "url": 'https://sslguala.com'
40 | }]
41 | }
42 | }
43 |
44 | answer = DefaultRest.post(url, payload)
45 | send_status_log({status: answer[:errcode] == 0, error: answer})
46 | rescue => e
47 | send_status_log({status: false, error: e})
48 | { error: e}
49 | end
50 |
51 | def check_url
52 | errors.add(:url, "请填写的企业微信的URL") unless url.start_with?('https://qyapi.weixin.qq.com/')
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/app/models/project.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: projects
4 | #
5 | # id :bigint not null, primary key
6 | # check_domains_count :integer
7 | # description :string
8 | # name :string
9 | # created_at :datetime not null
10 | # updated_at :datetime not null
11 | # user_id :bigint
12 | #
13 | # Indexes
14 | #
15 | # index_projects_on_user_id (user_id)
16 | #
17 | class Project < ApplicationRecord
18 | has_many :check_domains
19 | belongs_to :user
20 | before_destroy :check_project_destroy
21 |
22 | private
23 |
24 | def check_project_destroy
25 | if user.projects.order("created_at asc").first.id == id
26 | errors.add("id", "默认项目不能删除")
27 | throw(:abort) if errors.present?
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/app/models/user.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: users
4 | #
5 | # id :bigint not null, primary key
6 | # admin :boolean default(FALSE)
7 | # api_token :string
8 | # email :string default(""), not null
9 | # encrypted_password :string default(""), not null
10 | # first_name :string
11 | # last_name :string
12 | # remember_created_at :datetime
13 | # reset_password_sent_at :datetime
14 | # reset_password_token :string
15 | # created_at :datetime not null
16 | # updated_at :datetime not null
17 | #
18 | # Indexes
19 | #
20 | # index_users_on_api_token (api_token)
21 | # index_users_on_email (email) UNIQUE
22 | # index_users_on_reset_password_token (reset_password_token) UNIQUE
23 | #
24 | class User < ApplicationRecord
25 | include OmniAuthable
26 | attr_accessor :login
27 | has_person_name
28 |
29 | has_many :check_domains
30 | has_many :projects
31 | has_many :user_omniauths
32 | has_many :msg_channels
33 |
34 | before_create :set_init
35 | after_create :create_project
36 |
37 |
38 | def set_init
39 | self.api_token = SecureRandom.uuid
40 | end
41 |
42 | def reset_api_token
43 | Rails.cache.write("user_api_token:#{id}", api_token, expires_in: 7.days)
44 | update(api_token: SecureRandom.uuid)
45 | end
46 |
47 | # Include default devise modules. Others available are:
48 | # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
49 | devise :database_authenticatable, :registerable,
50 | :recoverable, :rememberable, :validatable,
51 | :jwt_authenticatable, :omniauthable, omniauth_providers: %i[wechat], jwt_revocation_strategy: Devise::JWT::RevocationStrategies::Null
52 |
53 |
54 | def self.find_for_database_authentication(warden_conditions)
55 | conditions = warden_conditions.dup
56 | if login = conditions.delete(:login)
57 | return if login.blank?
58 |
59 | where(email: login).first
60 | end
61 | end
62 |
63 | def create_project
64 | projects.create(name: "默认分组")
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/app/models/user_omniauth.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: user_omniauths
4 | #
5 | # id :bigint not null, primary key
6 | # nickname :string
7 | # provider :string not null
8 | # uid :string
9 | # unionid :string
10 | # created_at :datetime not null
11 | # updated_at :datetime not null
12 | # user_id :integer not null
13 | #
14 | # Indexes
15 | #
16 | # index_user_omniauths_on_provider_and_uid (provider,uid)
17 | #
18 | class UserOmniauth < ApplicationRecord
19 | belongs_to :user
20 | end
21 |
--------------------------------------------------------------------------------
/app/services/email_service.rb:
--------------------------------------------------------------------------------
1 | class EmailService
2 |
3 | class << self
4 | def app_authen
5 | ENV['TUBECENTER_APP_TOKEN'].presence
6 | end
7 |
8 | def send!(from:, to:, title:, content: )
9 | data = {
10 | from: from,
11 | to: to,
12 | title: title,
13 | content: content,
14 | app_authen: app_authen
15 | }
16 |
17 | res = DefaultRest.post(ENV['TUBECENTER_APP_URL'], data)
18 | Rails.logger.info("send email status => #{res}")
19 | res[:to] == to
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/_check_domain.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.call(check_domain, :id, :domain, :expire_at, :created_at, :updated_at, :project_id, :check_expire_time_at,
2 | :remain_days)
3 | json.msg_channels do
4 | json.array! check_domain.msg_channels.order('id asc'), :id, :title, :type
5 | end
6 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/create.html.erb:
--------------------------------------------------------------------------------
1 |
Api::V1::CheckDomains#create
2 | Find me in app/views/api/v1/check_domains/create.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/create.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.partial! 'check_domain', check_domain: @check_domain
2 |
3 | json.markup @check_domain.markup
4 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/destroy.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::CheckDomains#destroy
2 | Find me in app/views/api/v1/check_domains/destroy.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/index.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::CheckDomains#index
2 | Find me in app/views/api/v1/check_domains/index.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/index.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.array! @check_domains, partial: 'api/v1/check_domains/check_domain', as: :check_domain
2 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/show.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::CheckDomains#show
2 | Find me in app/views/api/v1/check_domains/show.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/show.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.partial! 'api/v1/check_domains/check_domain', check_domain: @check_domain
2 |
3 | json.markup @check_domain.markup
4 |
--------------------------------------------------------------------------------
/app/views/api/v1/check_domains/update.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.partial! 'check_domain', check_domain: @check_domain
2 |
3 | json.markup @check_domain.markup
4 |
--------------------------------------------------------------------------------
/app/views/api/v1/msg_channels/_msg_channel.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.call(msg_channel, :id, :is_default, :title, :url, :config_email, :type, :markup, :is_common, :config_secret, :config_custom_string)
2 |
3 | json.chechk_domains do
4 | json.array! msg_channel.check_domains, :id, :domain
5 | end
6 |
--------------------------------------------------------------------------------
/app/views/api/v1/msg_channels/create.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::MsgChannels#create
2 | Find me in app/views/api/v1/msg_channels/create.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/msg_channels/destroy.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::MsgChannels#destroy
2 | Find me in app/views/api/v1/msg_channels/destroy.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/msg_channels/index.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::MsgChannels#index
2 | Find me in app/views/api/v1/msg_channels/index.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/msg_channels/index.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.array! @msg_channels, partial: 'api/v1/msg_channels/msg_channel', as: :msg_channel
2 |
--------------------------------------------------------------------------------
/app/views/api/v1/msg_channels/show.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::MsgChannels#show
2 | Find me in app/views/api/v1/msg_channels/show.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/msg_channels/show.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.partial! "msg_channel", msg_channel: @msg_channel
--------------------------------------------------------------------------------
/app/views/api/v1/msg_channels/update.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::MsgChannels#update
2 | Find me in app/views/api/v1/msg_channels/update.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/projects/_project.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.(project, :id, :name, :description, :check_domains_count)
--------------------------------------------------------------------------------
/app/views/api/v1/projects/create.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::Projects#create
2 | Find me in app/views/api/v1/projects/create.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/projects/create.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.partial! "project", project: @project
--------------------------------------------------------------------------------
/app/views/api/v1/projects/destroy.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::Projects#destroy
2 | Find me in app/views/api/v1/projects/destroy.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/projects/index.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::Projects#index
2 | Find me in app/views/api/v1/projects/index.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/projects/index.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.array! @projects, partial: 'api/v1/projects/project', as: :project
2 |
--------------------------------------------------------------------------------
/app/views/api/v1/projects/show.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::Projects#show
2 | Find me in app/views/api/v1/projects/show.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/projects/show.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.partial! "project", project: @project
--------------------------------------------------------------------------------
/app/views/api/v1/projects/update.html.erb:
--------------------------------------------------------------------------------
1 | Api::V1::Projects#update
2 | Find me in app/views/api/v1/projects/update.html.erb
3 |
--------------------------------------------------------------------------------
/app/views/api/v1/projects/update.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.partial! "project", project: @project
--------------------------------------------------------------------------------
/app/views/api/v1/users/info.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.(@user, :id, :email, :api_token, :first_name, :last_name, :created_at, :admin)
--------------------------------------------------------------------------------
/app/views/home/index.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | SSL证书挂啦
8 |
160 |
161 |
162 |
163 |
180 |
181 |
182 | SSL证书状态
183 | 不必每次都打开网页查看,一次查看所有网站的SSL证书
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
196 |
197 |
198 |
--------------------------------------------------------------------------------
/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Sslguala
5 |
6 |
7 | <%= csrf_meta_tags %>
8 | <%= csp_meta_tag %>
9 |
10 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
11 | <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
12 |
13 |
14 |
15 | <%= yield %>
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/views/layouts/madmin/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Madmin: <%= Rails.application.class %>
9 |
10 |
11 |
12 |
13 | <%= csrf_meta_tags %>
14 | <%#= stylesheet_link_tag 'admin', media: 'all', 'data-turbolinks-track': 'reload' %>
15 | <%= javascript_pack_tag 'admin', 'data-turbolinks-track': 'reload' %>
16 |
17 | <%= render "javascript" %>
18 |
19 |
20 |
21 |
24 |
25 | <%#= render "flashes" -%>
26 | <%= yield %>
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/views/layouts/mailer.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/views/layouts/mailer.text.erb:
--------------------------------------------------------------------------------
1 | <%= yield %>
2 |
--------------------------------------------------------------------------------
/app/views/madmin/application/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_with model: [:madmin, record], url: (record.persisted? ? resource.show_path(record) : resource.index_path), local: true do |form| %>
2 | <% if form.object.errors.any? %>
3 |
4 |
There was <%= pluralize form.object.errors.full_messages.count, "error" %> with your submission
5 |
6 | <% form.object.errors.full_messages.each do |message| %>
7 |
<%= message %>
8 | <% end %>
9 |
10 | <% end %>
11 |
12 | <% resource.attributes.each do |attribute| %>
13 | <% next if attribute[:field].nil? %>
14 | <% next unless attribute[:field].visible?(action_name) %>
15 | <% next unless attribute[:field].visible?(:form) %>
16 |
17 | <% field = attribute[:field] %>
18 |
19 |
20 | <%= render partial: field.to_partial_path("form"), locals: { field: field, record: record, form: form, resource: resource } %>
21 |
22 | <% end %>
23 |
24 | <%= form.submit class: "bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow" %>
25 | <% end %>
26 |
--------------------------------------------------------------------------------
/app/views/madmin/application/_javascript.html.erb:
--------------------------------------------------------------------------------
1 | <%= stylesheet_link_tag "https://unpkg.zhimg.com/flatpickr/dist/flatpickr.min.css", "data-turbo-track": "reload" %>
2 | <%= stylesheet_link_tag "https://unpkg.zhimg.com/trix/dist/trix.css", "data-turbo-track": "reload" %>
3 | <%= stylesheet_link_tag "https://unpkg.zhimg.com/slim-select@1.27.0/dist/slimselect.min.css", "data-turbo-track": "reload" %>
4 |
5 |
60 |
--------------------------------------------------------------------------------
/app/views/madmin/application/_navigation.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= link_to "← 回到首页", main_app.root_url, class: "block p-1", data: { turbo: false } if main_app.respond_to?(:root_url) %>
3 |
4 | <%= link_to "Dashboard", '/madmin' %>
5 | <% Madmin.resources.each do |resource| %>
6 | <%= link_to resource.friendly_name.pluralize, resource.index_path, class: "block p-1" %>
7 | <% end %>
8 | <%= link_to "退出", destroy_user_session_path, method: :delete %>
9 |
10 |
--------------------------------------------------------------------------------
/app/views/madmin/application/dashboard.html.erb:
--------------------------------------------------------------------------------
1 | dashboard.html.erb
--------------------------------------------------------------------------------
/app/views/madmin/application/edit.html.erb:
--------------------------------------------------------------------------------
1 | <%= link_to resource.friendly_name.pluralize, resource.index_path %> / Edit <%= resource.friendly_name %> #<%= @record.id %>
2 |
3 | <%= render partial: "form", locals: { record: @record, resource: resource } %>
4 |
--------------------------------------------------------------------------------
/app/views/madmin/application/index.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
<%= resource.friendly_name.pluralize %>
3 | <%= link_to "新建 #{resource.friendly_name}", resource.new_path %>
4 |
5 |
6 |
7 | <% if resource.scopes.any? %>
8 | <%= link_to "全部", resource.index_path %>
9 | <% end %>
10 |
11 | <% resource.scopes.each do |scope| %>
12 | <%= link_to scope.to_s.humanize, resource.index_path(scope: scope) %>
13 | <% end %>
14 |
15 |
16 |
17 |
18 |
19 | <% resource.attributes.each do |attribute| %>
20 | <% next if attribute[:field].nil? %>
21 | <% next unless attribute[:field].visible?(action_name) %>
22 |
23 | <%= sortable attribute[:name], attribute[:name].to_s.titleize %>
24 | <% end %>
25 | Actions
26 |
27 |
28 |
29 |
30 | <% @records.each do |record| %>
31 |
32 | <% resource.attributes.each do |attribute| %>
33 | <% next if attribute[:field].nil? %>
34 | <% next unless attribute[:field].visible?(action_name) %>
35 |
36 | <% field = attribute[:field] %>
37 |
38 | <%= render partial: field.to_partial_path("index"), locals: { field: field, record: record } %>
39 | <% end %>
40 |
41 | <%= link_to "查看", resource.show_path(record) %>
42 |
43 | <% end %>
44 |
45 |
46 |
47 | <%== pagy_nav(@pagy) if @pagy.pages > 1 %>
48 |
--------------------------------------------------------------------------------
/app/views/madmin/application/new.html.erb:
--------------------------------------------------------------------------------
1 | <%= link_to resource.friendly_name.pluralize, resource.index_path %> / New <%= resource.friendly_name %>
2 |
3 | <%= render partial: "form", locals: { record: @record, resource: resource } %>
4 |
--------------------------------------------------------------------------------
/app/views/madmin/application/show.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
<%= link_to resource.friendly_name.pluralize, resource.index_path %> / <%= resource.model.name.singularize %> #<%= @record.id %>
3 |
4 |
5 | <%= link_to "Edit", resource.edit_path(@record), class: "mr-2" %>
6 | <%= button_to "Delete", resource.show_path(@record), method: :delete, data: { confirm: "Are you sure?" }, class: "inline-block" %>
7 |
8 |
9 |
10 | <% resource.attributes.each do |attribute| %>
11 | <% next if attribute[:field].nil? %>
12 | <% next unless attribute[:field].visible?(action_name) %>
13 | <% field = attribute[:field] %>
14 |
15 |
16 |
17 | <%= field.attribute_name.to_s.titleize %>
18 |
19 |
20 |
21 | <%= render partial: field.to_partial_path("show"), locals: { field: field, record: @record } %>
22 |
23 |
24 | <% end %>
25 |
--------------------------------------------------------------------------------
/app/views/madmin/dashboard/index.html.erb:
--------------------------------------------------------------------------------
1 | Dashboard
2 |
3 | Users count <%= User.all.count %>
4 | Project count <%= Project.all.count %>
5 | Checkdomains count <%= CheckDomain.all.count %>
--------------------------------------------------------------------------------
/app/views/users/confirmations/new.html.erb:
--------------------------------------------------------------------------------
1 | Resend confirmation instructions
2 |
3 | <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
4 | <%= render "users/shared/error_messages", resource: resource %>
5 |
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
9 |
10 |
11 |
12 | <%= f.submit "Resend confirmation instructions" %>
13 |
14 | <% end %>
15 |
16 | <%= render "users/shared/links" %>
17 |
--------------------------------------------------------------------------------
/app/views/users/mailer/confirmation_instructions.html.erb:
--------------------------------------------------------------------------------
1 | Welcome <%= @email %>!
2 |
3 | You can confirm your account email through the link below:
4 |
5 | <%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>
6 |
--------------------------------------------------------------------------------
/app/views/users/mailer/email_changed.html.erb:
--------------------------------------------------------------------------------
1 | Hello <%= @email %>!
2 |
3 | <% if @resource.try(:unconfirmed_email?) %>
4 | We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.
5 | <% else %>
6 | We're contacting you to notify you that your email has been changed to <%= @resource.email %>.
7 | <% end %>
8 |
--------------------------------------------------------------------------------
/app/views/users/mailer/password_change.html.erb:
--------------------------------------------------------------------------------
1 | Hello <%= @resource.email %>!
2 |
3 | We're contacting you to notify you that your password has been changed.
4 |
--------------------------------------------------------------------------------
/app/views/users/mailer/reset_password_instructions.html.erb:
--------------------------------------------------------------------------------
1 | Hello <%= @resource.email %>!
2 |
3 | Someone has requested a link to change your password. You can do this through the link below.
4 |
5 | <%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
6 |
7 | If you didn't request this, please ignore this email.
8 | Your password won't change until you access the link above and create a new one.
9 |
--------------------------------------------------------------------------------
/app/views/users/mailer/unlock_instructions.html.erb:
--------------------------------------------------------------------------------
1 | Hello <%= @resource.email %>!
2 |
3 | Your account has been locked due to an excessive number of unsuccessful sign in attempts.
4 |
5 | Click the link below to unlock your account:
6 |
7 | <%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>
8 |
--------------------------------------------------------------------------------
/app/views/users/passwords/edit.html.erb:
--------------------------------------------------------------------------------
1 | Change your password
2 |
3 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
4 | <%= render "users/shared/error_messages", resource: resource %>
5 | <%= f.hidden_field :reset_password_token %>
6 |
7 |
8 | <%= f.label :password, "New password" %>
9 | <% if @minimum_password_length %>
10 | (<%= @minimum_password_length %> characters minimum)
11 | <% end %>
12 | <%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
13 |
14 |
15 |
16 | <%= f.label :password_confirmation, "Confirm new password" %>
17 | <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
18 |
19 |
20 |
21 | <%= f.submit "Change my password" %>
22 |
23 | <% end %>
24 |
25 | <%= render "users/shared/links" %>
26 |
--------------------------------------------------------------------------------
/app/views/users/passwords/new.html.erb:
--------------------------------------------------------------------------------
1 | Forgot your password?
2 |
3 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
4 | <%= render "users/shared/error_messages", resource: resource %>
5 |
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
9 |
10 |
11 |
12 | <%= f.submit "Send me reset password instructions" %>
13 |
14 | <% end %>
15 |
16 | <%= render "users/shared/links" %>
17 |
--------------------------------------------------------------------------------
/app/views/users/registrations/edit.html.erb:
--------------------------------------------------------------------------------
1 | Edit <%= resource_name.to_s.humanize %>
2 |
3 | <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
4 | <%= render "users/shared/error_messages", resource: resource %>
5 |
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
9 |
10 |
11 | <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
12 | Currently waiting confirmation for: <%= resource.unconfirmed_email %>
13 | <% end %>
14 |
15 |
16 | <%= f.label :password %> (leave blank if you don't want to change it)
17 | <%= f.password_field :password, autocomplete: "new-password" %>
18 | <% if @minimum_password_length %>
19 |
20 | <%= @minimum_password_length %> characters minimum
21 | <% end %>
22 |
23 |
24 |
25 | <%= f.label :password_confirmation %>
26 | <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
27 |
28 |
29 |
30 | <%= f.label :current_password %> (we need your current password to confirm your changes)
31 | <%= f.password_field :current_password, autocomplete: "current-password" %>
32 |
33 |
34 |
35 | <%= f.submit "Update" %>
36 |
37 | <% end %>
38 |
39 | Cancel my account
40 |
41 | Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>
42 |
43 | <%= link_to "Back", :back %>
44 |
--------------------------------------------------------------------------------
/app/views/users/registrations/new.html.erb:
--------------------------------------------------------------------------------
1 | Sign up
2 |
3 | <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
4 | <%= render "users/shared/error_messages", resource: resource %>
5 |
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
9 |
10 |
11 |
12 | <%= f.label :password %>
13 | <% if @minimum_password_length %>
14 | (<%= @minimum_password_length %> characters minimum)
15 | <% end %>
16 | <%= f.password_field :password, autocomplete: "new-password" %>
17 |
18 |
19 |
20 | <%= f.label :password_confirmation %>
21 | <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
22 |
23 |
24 |
25 | <%= f.submit "Sign up" %>
26 |
27 | <% end %>
28 |
29 | <%= render "users/shared/links" %>
30 |
--------------------------------------------------------------------------------
/app/views/users/sessions/new.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
管理员登录
3 |
4 | <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
5 | <% if flash[:notice] %>
6 |
7 | <%= flash[:notice] %>
8 |
9 | <% elsif flash[:alert] %>
10 |
11 | <%= flash[:alert] %>
12 |
13 | <% end %>
14 |
15 |
16 | <%= f.label '邮箱' %>
17 | <%= f.text_field :login, autofocus: true, autocomplete: "email" %>
18 |
19 |
20 |
21 | <%= f.label '密码' %>
22 | <%= f.password_field :password, autocomplete: "current-password" %>
23 |
24 |
25 | <% if devise_mapping.rememberable? %>
26 |
27 | <%= f.check_box :remember_me %>
28 | <%= f.label '记住我' %>
29 |
30 | <% end %>
31 |
32 |
33 | <%= f.submit "登录", class: 'login' %>
34 |
35 | <% end %>
36 |
37 | <%= render "users/shared/links" %>
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/views/users/shared/_error_messages.html.erb:
--------------------------------------------------------------------------------
1 | <% if resource.errors.any? %>
2 |
3 |
4 | <%= I18n.t("errors.messages.not_saved",
5 | count: resource.errors.count,
6 | resource: resource.class.model_name.human.downcase)
7 | %>
8 |
9 |
10 | <% resource.errors.full_messages.each do |message| %>
11 | <%= message %>
12 | <% end %>
13 |
14 |
15 | <% end %>
16 |
--------------------------------------------------------------------------------
/app/views/users/shared/_links.html.erb:
--------------------------------------------------------------------------------
1 | <%- if controller_name != 'sessions' %>
2 | <%= link_to "Log in", new_session_path(resource_name) %>
3 | <% end %>
4 |
5 | <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
6 | <%#= link_to "Sign up", new_registration_path(resource_name) %>
7 | <% end %>
8 |
9 | <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
10 | <%#= link_to "Forgot your password?", new_password_path(resource_name) %>
11 | <% end %>
12 |
13 | <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
14 | <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
15 | <% end %>
16 |
17 | <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
18 | <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
19 | <% end %>
20 |
21 | <%- if devise_mapping.omniauthable? %>
22 | <%- resource_class.omniauth_providers.each do |provider| %>
23 | <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), method: :post %>
24 | <% end %>
25 | <% end %>
26 |
--------------------------------------------------------------------------------
/app/views/users/unlocks/new.html.erb:
--------------------------------------------------------------------------------
1 | Resend unlock instructions
2 |
3 | <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
4 | <%= render "users/shared/error_messages", resource: resource %>
5 |
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
9 |
10 |
11 |
12 | <%= f.submit "Resend unlock instructions" %>
13 |
14 | <% end %>
15 |
16 | <%= render "users/shared/links" %>
17 |
--------------------------------------------------------------------------------
/app/workers/domain_dead_check_schedule_worker.rb:
--------------------------------------------------------------------------------
1 | require 'sidekiq-scheduler'
2 |
3 | class DomainDeadCheckScheduleWorker
4 | include Sidekiq::Worker
5 |
6 | def perform
7 | # 当前过期时间超过30天则,不再进行检测,设置状态为dead
8 | time_days = 30.days.ago
9 | need_check_domains = CheckDomain.all.where(status: :enabled).where("expire_at < ?", time_days)
10 | need_check_domains.each do |check_domain|
11 | need_check_domains.update(status: :dead)
12 | end
13 | end
14 | end
--------------------------------------------------------------------------------
/app/workers/domain_schedule_worker.rb:
--------------------------------------------------------------------------------
1 | require 'sidekiq-scheduler'
2 |
3 | class DomainScheduleWorker
4 | include Sidekiq::Worker
5 |
6 | def perform
7 | need_check_domains = CheckDomain.all.where(status: :enabled)
8 | need_check_domains.each do |check_domain|
9 | check_domain.async_check_expire_time(random_waiting: true)
10 | end
11 | end
12 | end
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(api) {
2 | var validEnv = ['development', 'test', 'production']
3 | var currentEnv = api.env()
4 | var isDevelopmentEnv = api.env('development')
5 | var isProductionEnv = api.env('production')
6 | var isTestEnv = api.env('test')
7 |
8 | if (!validEnv.includes(currentEnv)) {
9 | throw new Error(
10 | 'Please specify a valid `NODE_ENV` or ' +
11 | '`BABEL_ENV` environment variables. Valid values are "development", ' +
12 | '"test", and "production". Instead, received: ' +
13 | JSON.stringify(currentEnv) +
14 | '.'
15 | )
16 | }
17 |
18 | return {
19 | presets: [
20 | isTestEnv && [
21 | '@babel/preset-env',
22 | {
23 | targets: {
24 | node: 'current'
25 | }
26 | }
27 | ],
28 | (isProductionEnv || isDevelopmentEnv) && [
29 | '@babel/preset-env',
30 | {
31 | forceAllTransforms: true,
32 | useBuiltIns: 'entry',
33 | corejs: 3,
34 | modules: false,
35 | exclude: ['transform-typeof-symbol']
36 | }
37 | ]
38 | ].filter(Boolean),
39 | plugins: [
40 | 'babel-plugin-macros',
41 | '@babel/plugin-syntax-dynamic-import',
42 | isTestEnv && 'babel-plugin-dynamic-import-node',
43 | '@babel/plugin-transform-destructuring',
44 | [
45 | '@babel/plugin-proposal-class-properties',
46 | {
47 | loose: true
48 | }
49 | ],
50 | [
51 | '@babel/plugin-proposal-object-rest-spread',
52 | {
53 | useBuiltIns: true
54 | }
55 | ],
56 | [
57 | '@babel/plugin-transform-runtime',
58 | {
59 | helpers: false
60 | }
61 | ],
62 | [
63 | '@babel/plugin-transform-regenerator',
64 | {
65 | async: false
66 | }
67 | ]
68 | ].filter(Boolean)
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | #
5 | # This file was generated by Bundler.
6 | #
7 | # The application 'bundle' is installed as part of a gem, and
8 | # this file is here to facilitate running it.
9 | #
10 |
11 | require "rubygems"
12 |
13 | m = Module.new do
14 | module_function
15 |
16 | def invoked_as_script?
17 | File.expand_path($0) == File.expand_path(__FILE__)
18 | end
19 |
20 | def env_var_version
21 | ENV["BUNDLER_VERSION"]
22 | end
23 |
24 | def cli_arg_version
25 | return unless invoked_as_script? # don't want to hijack other binstubs
26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27 | bundler_version = nil
28 | update_index = nil
29 | ARGV.each_with_index do |a, i|
30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31 | bundler_version = a
32 | end
33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34 | bundler_version = $1 || ">= 0.a"
35 | update_index = i
36 | end
37 | bundler_version
38 | end
39 |
40 | def gemfile
41 | gemfile = ENV["BUNDLE_GEMFILE"]
42 | return gemfile if gemfile && !gemfile.empty?
43 |
44 | File.expand_path("../../Gemfile", __FILE__)
45 | end
46 |
47 | def lockfile
48 | lockfile =
49 | case File.basename(gemfile)
50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51 | else "#{gemfile}.lock"
52 | end
53 | File.expand_path(lockfile)
54 | end
55 |
56 | def lockfile_version
57 | return unless File.file?(lockfile)
58 | lockfile_contents = File.read(lockfile)
59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60 | Regexp.last_match(1)
61 | end
62 |
63 | def bundler_version
64 | @bundler_version ||= begin
65 | env_var_version || cli_arg_version ||
66 | lockfile_version || "#{Gem::Requirement.default}.a"
67 | end
68 | end
69 |
70 | def load_bundler!
71 | ENV["BUNDLE_GEMFILE"] ||= gemfile
72 |
73 | # must dup string for RG < 1.8 compatibility
74 | activate_bundler(bundler_version.dup)
75 | end
76 |
77 | def activate_bundler(bundler_version)
78 | if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
79 | bundler_version = "< 2"
80 | end
81 | gem_error = activation_error_handling do
82 | gem "bundler", bundler_version
83 | end
84 | return if gem_error.nil?
85 | require_error = activation_error_handling do
86 | require "bundler/version"
87 | end
88 | return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
89 | warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
90 | exit 42
91 | end
92 |
93 | def activation_error_handling
94 | yield
95 | nil
96 | rescue StandardError, LoadError => e
97 | e
98 | end
99 | end
100 |
101 | m.load_bundler!
102 |
103 | if m.invoked_as_script?
104 | load Gem.bin_path("bundler", "bundle")
105 | end
106 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | load File.expand_path("spring", __dir__)
3 | APP_PATH = File.expand_path('../config/application', __dir__)
4 | require_relative "../config/boot"
5 | require "rails/commands"
6 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | load File.expand_path("spring", __dir__)
3 | require_relative "../config/boot"
4 | require "rake"
5 | Rake.application.run
6 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require "fileutils"
3 |
4 | # path to your application root.
5 | APP_ROOT = File.expand_path('..', __dir__)
6 |
7 | def system!(*args)
8 | system(*args) || abort("\n== Command #{args} failed ==")
9 | end
10 |
11 | FileUtils.chdir APP_ROOT do
12 | # This script is a way to set up or update your development environment automatically.
13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome.
14 | # Add necessary setup steps to this file.
15 |
16 | puts '== Installing dependencies =='
17 | system! 'gem install bundler --conservative'
18 | system('bundle check') || system!('bundle install')
19 |
20 | # Install JavaScript dependencies
21 | system! 'bin/yarn'
22 |
23 | # puts "\n== Copying sample files =="
24 | # unless File.exist?('config/database.yml')
25 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
26 | # end
27 |
28 | puts "\n== Preparing database =="
29 | system! 'bin/rails db:prepare'
30 |
31 | puts "\n== Removing old logs and tempfiles =="
32 | system! 'bin/rails log:clear tmp:clear'
33 |
34 | puts "\n== Restarting application server =="
35 | system! 'bin/rails restart'
36 | end
37 |
--------------------------------------------------------------------------------
/bin/spring:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"])
3 | gem "bundler"
4 | require "bundler"
5 |
6 | # Load Spring without loading other gems in the Gemfile, for speed.
7 | Bundler.locked_gems&.specs&.find { |spec| spec.name == "spring" }&.tap do |spring|
8 | Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
9 | gem "spring", spring.version
10 | require "spring/binstub"
11 | rescue Gem::LoadError
12 | # Ignore when Spring is not installed.
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/bin/webpack:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4 | ENV["NODE_ENV"] ||= "development"
5 |
6 | require "pathname"
7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
8 | Pathname.new(__FILE__).realpath)
9 |
10 | require "bundler/setup"
11 |
12 | require "webpacker"
13 | require "webpacker/webpack_runner"
14 |
15 | APP_ROOT = File.expand_path("..", __dir__)
16 | Dir.chdir(APP_ROOT) do
17 | Webpacker::WebpackRunner.run(ARGV)
18 | end
19 |
--------------------------------------------------------------------------------
/bin/webpack-dev-server:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4 | ENV["NODE_ENV"] ||= "development"
5 |
6 | require "pathname"
7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
8 | Pathname.new(__FILE__).realpath)
9 |
10 | require "bundler/setup"
11 |
12 | require "webpacker"
13 | require "webpacker/dev_server_runner"
14 |
15 | APP_ROOT = File.expand_path("..", __dir__)
16 | Dir.chdir(APP_ROOT) do
17 | Webpacker::DevServerRunner.run(ARGV)
18 | end
19 |
--------------------------------------------------------------------------------
/bin/yarn:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_ROOT = File.expand_path('..', __dir__)
3 | Dir.chdir(APP_ROOT) do
4 | yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
5 | select { |dir| File.expand_path(dir) != __dir__ }.
6 | product(["yarn", "yarn.cmd", "yarn.ps1"]).
7 | map { |dir, file| File.expand_path(file, dir) }.
8 | find { |file| File.executable?(file) }
9 |
10 | if yarn
11 | exec yarn, *ARGV
12 | else
13 | $stderr.puts "Yarn executable was not detected in the system."
14 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
15 | exit 1
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative "config/environment"
4 |
5 | run Rails.application
6 | Rails.application.load_server
7 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative "boot"
2 |
3 | require "rails/all"
4 |
5 | # Require the gems listed in Gemfile, including any gems
6 | # you've limited to :test, :development, or :production.
7 | Bundler.require(*Rails.groups)
8 |
9 | module Sslguala
10 | class Application < Rails::Application
11 | config.active_job.queue_adapter = :sidekiq
12 | # Initialize configuration defaults for originally generated Rails version.
13 | config.load_defaults 6.1
14 |
15 | # Configuration for the application, engines, and railties goes here.
16 | #
17 | # These settings can be overridden in specific environments using the files
18 | # in config/environments, which are processed later.
19 | #
20 | # config.time_zone = "Central Time (US & Canada)"
21 | # config.eager_load_paths << Rails.root.join("extras")
22 | config.cache_store = [:redis_cache_store, {
23 | url: (ENV['REDIS_URL'] || 'redis://127.0.0.1:6379/1'),
24 | namespace: 'ssl_cache',
25 | expire_after: 10.days
26 | }]
27 |
28 | Rails.application.config.middleware.insert_before 0, Rack::Cors do
29 | allow do
30 | origins '*'
31 | resource '*', headers: :any, methods: [:get, :post, :patch, :put, :delete, :options], credentials: false
32 | end
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/config/application.yml.example:
--------------------------------------------------------------------------------
1 | development:
2 | WEB_DOMAIN: ''
3 | WECHAT_APP_ID: ''
4 | WECHAT_APP_SECRET: ''
5 | SENTRY_URL: ''
6 | TUBECENTER_APP_TOKEN: ''
7 | TUBECENTER_APP_URL: ''
8 | NEWRELIC_KEY: ''
9 |
10 | POSTGRES_USERNAME: ''
11 | POSTGRES_PASSWORD: ''
12 | SSLGUALA_DATABASE_POOL: ''
13 | POSTGRES_DATABASE: ''
14 | REDIS_URL: ''
15 |
16 | production:
17 | WEB_DOMAIN: ''
18 | WECHAT_APP_ID: ''
19 | WECHAT_APP_SECRET: ''
20 | SENTRY_URL: ''
21 | TUBECENTER_APP_TOKEN: ''
22 | TUBECENTER_APP_URL: ''
23 | NEWRELIC_KEY: ''
24 |
25 | POSTGRES_USERNAME: ''
26 | POSTGRES_PASSWORD: ''
27 | SSLGUALA_DATABASE_POOL: ''
28 | POSTGRES_DATABASE: ''
29 | REDIS_URL: ''
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
2 |
3 | require "bundler/setup" # Set up gems listed in the Gemfile.
4 | require "bootsnap/setup" # Speed up boot time by caching expensive operations.
5 |
--------------------------------------------------------------------------------
/config/cable.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: async
3 |
4 | test:
5 | adapter: test
6 |
7 | production:
8 | adapter: redis
9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
10 | channel_prefix: sslguala_production
11 |
--------------------------------------------------------------------------------
/config/credentials.yml.enc:
--------------------------------------------------------------------------------
1 | nSTCRepZJzigA8yZ68UfqORHOQwnao5q02ITRcOedtk2B1J5fPxkg4ahqevlypCRRWwjrAaPHxD4PqKum9I1LBsxMTs1eKltEjEIZX3up75EdL8bCFXBbmc7EqLHj7w4U9vleX2b9IYY2NKsvxQwN7wpb3RV/dQvjwxHBlYGPpjzG0GgSSuEOiKhMx7ZxAt2BEOuJQ3zOKxvJfdL4Yde8/fx/IXIkXXTxxwZEFN1WItCA0ckmA8y6elKwFGjyBsK8DZkWUBb6aHZY0nhH3AZAvoipJ/uonFzVdXxsWZP+VMtnzbM1u8S0Z9jqvdxTFQVnjjcmChpLL8b9hBaIKRoy+5xr7xq0PqoZW7wPatpcxbH5u2ozcy2N+HAEFs/y5fOeAk6xySAVKL/rcmgg68ibtZpNYDH3Gj884X9--J91MCVOWEs7D6T35--ddv5//z5pRZ74emIjsHdDw==
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | # PostgreSQL. Versions 9.3 and up are supported.
2 | #
3 | # Install the pg driver:
4 | # gem install pg
5 | # On macOS with Homebrew:
6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config
7 | # On macOS with MacPorts:
8 | # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
9 | # On Windows:
10 | # gem install pg
11 | # Choose the win32 build.
12 | # Install PostgreSQL and put its /bin directory on your path.
13 | #
14 | # Configure Using Gemfile
15 | # gem 'pg'
16 | #
17 | default: &default
18 | adapter: postgresql
19 | encoding: unicode
20 | # For details on connection pooling, see Rails configuration guide
21 | # https://guides.rubyonrails.org/configuring.html#database-pooling
22 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
23 |
24 | development:
25 | <<: *default
26 | database: sslguala_development
27 |
28 | # The specified database role being used to connect to postgres.
29 | # To create additional roles in postgres see `$ createuser --help`.
30 | # When left blank, postgres will use the default role. This is
31 | # the same name as the operating system user running Rails.
32 | #username: sslguala
33 |
34 | # The password associated with the postgres role (username).
35 | #password:
36 |
37 | # Connect on a TCP socket. Omitted by default since the client uses a
38 | # domain socket that doesn't need configuration. Windows does not have
39 | # domain sockets, so uncomment these lines.
40 | #host: localhost
41 |
42 | # The TCP port the server listens on. Defaults to 5432.
43 | # If your server runs on a different port number, change accordingly.
44 | #port: 5432
45 |
46 | # Schema search path. The server defaults to $user,public
47 | #schema_search_path: myapp,sharedapp,public
48 |
49 | # Minimum log levels, in increasing order:
50 | # debug5, debug4, debug3, debug2, debug1,
51 | # log, notice, warning, error, fatal, and panic
52 | # Defaults to warning.
53 | #min_messages: notice
54 |
55 | # Warning: The database defined as "test" will be erased and
56 | # re-generated from your development database when you run "rake".
57 | # Do not set this db to the same as development or production.
58 | test:
59 | <<: *default
60 | database: sslguala_test
61 |
62 | # As with config/credentials.yml, you never want to store sensitive information,
63 | # like your database password, in your source code. If your source code is
64 | # ever seen by anyone, they now have access to your database.
65 | #
66 | # Instead, provide the password or a full connection URL as an environment
67 | # variable when you boot the app. For example:
68 | #
69 | # DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
70 | #
71 | # If the connection URL is provided in the special DATABASE_URL environment
72 | # variable, Rails will automatically merge its configuration values on top of
73 | # the values provided in this file. Alternatively, you can specify a connection
74 | # URL environment variable explicitly:
75 | #
76 | # production:
77 | # url: <%= ENV['MY_APP_DATABASE_URL'] %>
78 | #
79 | # Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
80 | # for a full overview on how database connection configuration can be specified.
81 | #
82 | production:
83 | <<: *default
84 | database: <%= ENV['POSTGRES_DATABASE'] || 'sslguala_production' %>
85 | username: <%= ENV['POSTGRES_USERNAME'] %>
86 | password: <%= ENV['POSTGRES_PASSWORD'] || 'sslguala' %>
87 | pool: <%= ENV['SSLGUALA_DATABASE_POOL'] || 30 %>
88 | host: <%= ENV['POSTGRES_HOST'] %>
--------------------------------------------------------------------------------
/config/deploy.rb:
--------------------------------------------------------------------------------
1 | # config valid for current version and patch releases of Capistrano
2 | lock "~> 3.16.0"
3 |
4 | set :application, "sslguala"
5 | set :repo_url, "git@github.com-repo-sslguala:FIRHQ/sslguala.git"
6 | set :sidekiq_service_unit_name, 'SidekiqSSLGuala'
7 | set :sidekiq_enable_lingering, false
8 | set :puma_service_unit_name, 'PumaSSLGuala'
9 | # Default branch is :master
10 | # ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
11 |
12 | set :deploy_to, "/var/www/sslguala"
13 |
14 | # Default deploy_to directory is /var/www/my_app_name
15 | # set :deploy_to, "/var/www/my_app_name"
16 |
17 | set :rvm_ruby_version, "2.7.3"
18 | set :rvm_custom_path, '/home/deploy/.rvm'
19 |
20 | append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', '.bundle', 'public/assets', 'public/packs', 'storage'
21 |
22 | append :linked_files, "config/database.yml", 'config/application.yml', 'config/storage.yml', 'config/cable.yml'
23 |
24 | # Default value for :format is :airbrussh.
25 | # set :format, :airbrussh
26 |
27 | # You can configure the Airbrussh format using :format_options.
28 | # These are the defaults.
29 | # set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto
30 |
31 | # Default value for :pty is false
32 | # set :pty, true
33 |
34 | # Default value for :linked_files is []
35 | # append :linked_files, "config/database.yml"
36 |
37 | # Default value for linked_dirs is []
38 | # append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"
39 |
40 | # Default value for default_env is {}
41 | # set :default_env, { path: "/opt/ruby/bin:$PATH" }
42 |
43 | # Default value for local_user is ENV['USER']
44 | # set :local_user, -> { `git config user.name`.chomp }
45 |
46 | # Default value for keep_releases is 5
47 | # set :keep_releases, 5
48 |
49 | # Uncomment the following to require manually verifying the host key before first deploy.
50 | # set :ssh_options, verify_host_key: :secure
51 |
--------------------------------------------------------------------------------
/config/deploy/production.rb:
--------------------------------------------------------------------------------
1 | server ENV['production_server'], user: "deploy", roles: %w{app web db}
2 |
3 |
4 | append :linked_files, "config/master.key"
5 |
6 | namespace :deploy do
7 | namespace :check do
8 | before :linked_files, :set_master_key do
9 | on roles(:app), in: :sequence, wait: 10 do
10 | unless test("[ -f #{shared_path}/config/master.key ]")
11 | upload! 'config/master.key', "#{shared_path}/config/master.key"
12 | end
13 | end
14 | end
15 | end
16 | end
17 |
18 | # server-based syntax
19 | # ======================
20 | # Defines a single server with a list of roles and multiple properties.
21 | # You can define all roles on a single server, or split them:
22 |
23 | # server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value
24 | # server "example.com", user: "deploy", roles: %w{app web}, other_property: :other_value
25 | # server "db.example.com", user: "deploy", roles: %w{db}
26 |
27 |
28 |
29 | # role-based syntax
30 | # ==================
31 |
32 | # Defines a role with one or multiple servers. The primary server in each
33 | # group is considered to be the first unless any hosts have the primary
34 | # property set. Specify the username and a domain or IP for the server.
35 | # Don't use `:all`, it's a meta role.
36 |
37 | # role :app, %w{deploy@example.com}, my_property: :my_value
38 | # role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value
39 | # role :db, %w{deploy@example.com}
40 |
41 |
42 |
43 | # Configuration
44 | # =============
45 | # You can set any configuration variable like in config/deploy.rb
46 | # These variables are then only loaded and set in this stage.
47 | # For available Capistrano configuration variables see the documentation page.
48 | # http://capistranorb.com/documentation/getting-started/configuration/
49 | # Feel free to add new variables to customise your setup.
50 |
51 |
52 |
53 | # Custom SSH Options
54 | # ==================
55 | # You may pass any option but keep in mind that net/ssh understands a
56 | # limited set of options, consult the Net::SSH documentation.
57 | # http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start
58 | #
59 | # Global options
60 | # --------------
61 | # set :ssh_options, {
62 | # keys: %w(/home/user_name/.ssh/id_rsa),
63 | # forward_agent: false,
64 | # auth_methods: %w(password)
65 | # }
66 | #
67 | # The server-based syntax can be used to override options:
68 | # ------------------------------------
69 | # server "example.com",
70 | # user: "user_name",
71 | # roles: %w{web app},
72 | # ssh_options: {
73 | # user: "user_name", # overrides user setting above
74 | # keys: %w(/home/user_name/.ssh/id_rsa),
75 | # forward_agent: false,
76 | # auth_methods: %w(publickey password)
77 | # # password: "please use keys"
78 | # }
79 |
--------------------------------------------------------------------------------
/config/deploy/staging.rb:
--------------------------------------------------------------------------------
1 | # server-based syntax
2 | # ======================
3 | # Defines a single server with a list of roles and multiple properties.
4 | # You can define all roles on a single server, or split them:
5 |
6 | # server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value
7 | # server "example.com", user: "deploy", roles: %w{app web}, other_property: :other_value
8 | # server "db.example.com", user: "deploy", roles: %w{db}
9 |
10 |
11 |
12 | # role-based syntax
13 | # ==================
14 |
15 | # Defines a role with one or multiple servers. The primary server in each
16 | # group is considered to be the first unless any hosts have the primary
17 | # property set. Specify the username and a domain or IP for the server.
18 | # Don't use `:all`, it's a meta role.
19 |
20 | # role :app, %w{deploy@example.com}, my_property: :my_value
21 | # role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value
22 | # role :db, %w{deploy@example.com}
23 |
24 |
25 |
26 | # Configuration
27 | # =============
28 | # You can set any configuration variable like in config/deploy.rb
29 | # These variables are then only loaded and set in this stage.
30 | # For available Capistrano configuration variables see the documentation page.
31 | # http://capistranorb.com/documentation/getting-started/configuration/
32 | # Feel free to add new variables to customise your setup.
33 |
34 |
35 |
36 | # Custom SSH Options
37 | # ==================
38 | # You may pass any option but keep in mind that net/ssh understands a
39 | # limited set of options, consult the Net::SSH documentation.
40 | # http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start
41 | #
42 | # Global options
43 | # --------------
44 | # set :ssh_options, {
45 | # keys: %w(/home/user_name/.ssh/id_rsa),
46 | # forward_agent: false,
47 | # auth_methods: %w(password)
48 | # }
49 | #
50 | # The server-based syntax can be used to override options:
51 | # ------------------------------------
52 | # server "example.com",
53 | # user: "user_name",
54 | # roles: %w{web app},
55 | # ssh_options: {
56 | # user: "user_name", # overrides user setting above
57 | # keys: %w(/home/user_name/.ssh/id_rsa),
58 | # forward_agent: false,
59 | # auth_methods: %w(publickey password)
60 | # # password: "please use keys"
61 | # }
62 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative "application"
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | Rails.application.configure do
4 | config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
5 | # Settings specified here will take precedence over those in config/application.rb.
6 |
7 | # In the development environment your application's code is reloaded any time
8 | # it changes. This slows down response time but is perfect for development
9 | # since you don't have to restart the web server when you make code changes.
10 | config.cache_classes = false
11 |
12 | # Do not eager load code on boot.
13 | config.eager_load = false
14 |
15 | # Show full error reports.
16 | config.consider_all_requests_local = true
17 |
18 | # Enable/disable caching. By default caching is disabled.
19 | # Run rails dev:cache to toggle caching.
20 | if Rails.root.join('tmp', 'caching-dev.txt').exist?
21 | config.action_controller.perform_caching = true
22 | config.action_controller.enable_fragment_cache_logging = true
23 |
24 | # config.cache_store = :memory_store
25 | config.public_file_server.headers = {
26 | 'Cache-Control' => "public, max-age=#{2.days.to_i}"
27 | }
28 | else
29 | config.action_controller.perform_caching = false
30 |
31 | config.cache_store = :null_store
32 | end
33 |
34 | # Store uploaded files on the local file system (see config/storage.yml for options).
35 | config.active_storage.service = :local
36 |
37 | # Don't care if the mailer can't send.
38 | config.action_mailer.raise_delivery_errors = false
39 |
40 | config.action_mailer.perform_caching = false
41 |
42 | # Print deprecation notices to the Rails logger.
43 | config.active_support.deprecation = :log
44 |
45 | # Raise exceptions for disallowed deprecations.
46 | config.active_support.disallowed_deprecation = :raise
47 |
48 | # Tell Active Support which deprecation messages to disallow.
49 | config.active_support.disallowed_deprecation_warnings = []
50 |
51 | # Raise an error on page load if there are pending migrations.
52 | config.active_record.migration_error = :page_load
53 |
54 | # Highlight code that triggered database queries in logs.
55 | config.active_record.verbose_query_logs = true
56 |
57 | # Debug mode disables concatenation and preprocessing of assets.
58 | # This option may cause significant delays in view rendering with a large
59 | # number of complex assets.
60 | config.assets.debug = true
61 |
62 | # Suppress logger output for asset requests.
63 | config.assets.quiet = true
64 |
65 | # Raises error for missing translations.
66 | # config.i18n.raise_on_missing_translations = true
67 |
68 | # Annotate rendered view with file names.
69 | # config.action_view.annotate_rendered_view_with_filenames = true
70 |
71 | # Use an evented file watcher to asynchronously detect changes in source code,
72 | # routes, locales, etc. This feature depends on the listen gem.
73 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker
74 | config.hosts << "tl-test.ce04.com"
75 |
76 | # Uncomment if you wish to allow Action Cable access from any origin.
77 | # config.action_cable.disable_request_forgery_protection = true
78 | end
79 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | Rails.application.configure do
4 | # Settings specified here will take precedence over those in config/application.rb.
5 |
6 | # Code is not reloaded between requests.
7 | config.cache_classes = true
8 |
9 | # Eager load code on boot. This eager loads most of Rails and
10 | # your application in memory, allowing both threaded web servers
11 | # and those relying on copy on write to perform better.
12 | # Rake tasks automatically ignore this option for performance.
13 | config.eager_load = true
14 |
15 | # Full error reports are disabled and caching is turned on.
16 | config.consider_all_requests_local = false
17 | config.action_controller.perform_caching = true
18 |
19 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
20 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
21 | # config.require_master_key = true
22 |
23 | # Disable serving static files from the `/public` folder by default since
24 | # Apache or NGINX already handles this.
25 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
26 |
27 | # Compress CSS using a preprocessor.
28 | # config.assets.css_compressor = :sass
29 |
30 | # Do not fallback to assets pipeline if a precompiled asset is missed.
31 | config.assets.compile = false
32 |
33 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
34 | # config.asset_host = 'http://assets.example.com'
35 |
36 | # Specifies the header that your server uses for sending files.
37 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
38 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
39 |
40 | # Store uploaded files on the local file system (see config/storage.yml for options).
41 | config.active_storage.service = :local
42 |
43 | # Mount Action Cable outside main process or domain.
44 | # config.action_cable.mount_path = nil
45 | # config.action_cable.url = 'wss://example.com/cable'
46 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
47 |
48 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
49 | # config.force_ssl = true
50 |
51 | # Include generic and useful information about system operation, but avoid logging too much
52 | # information to avoid inadvertent exposure of personally identifiable information (PII).
53 | config.log_level = :info
54 |
55 | # Prepend all log lines with the following tags.
56 | config.log_tags = [ :request_id ]
57 |
58 | # Use a different cache store in production.
59 | # config.cache_store = :mem_cache_store
60 |
61 | # Use a real queuing backend for Active Job (and separate queues per environment).
62 | # config.active_job.queue_adapter = :resque
63 | # config.active_job.queue_name_prefix = "sslguala_production"
64 |
65 | config.action_mailer.perform_caching = false
66 |
67 | # Ignore bad email addresses and do not raise email delivery errors.
68 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
69 | # config.action_mailer.raise_delivery_errors = false
70 |
71 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
72 | # the I18n.default_locale when a translation cannot be found).
73 | config.i18n.fallbacks = true
74 |
75 | # Send deprecation notices to registered listeners.
76 | config.active_support.deprecation = :notify
77 |
78 | # Log disallowed deprecations.
79 | config.active_support.disallowed_deprecation = :log
80 |
81 | # Tell Active Support which deprecation messages to disallow.
82 | config.active_support.disallowed_deprecation_warnings = []
83 |
84 | # Use default logging formatter so that PID and timestamp are not suppressed.
85 | config.log_formatter = ::Logger::Formatter.new
86 |
87 | # Use a different logger for distributed setups.
88 | # require "syslog/logger"
89 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
90 |
91 | if ENV["RAILS_LOG_TO_STDOUT"].present?
92 | logger = ActiveSupport::Logger.new(STDOUT)
93 | logger.formatter = config.log_formatter
94 | config.logger = ActiveSupport::TaggedLogging.new(logger)
95 | end
96 |
97 | # Do not dump schema after migrations.
98 | config.active_record.dump_schema_after_migration = false
99 |
100 | # Rails.application.config.hosts << "sslguala.com"
101 |
102 | # Inserts middleware to perform automatic connection switching.
103 | # The `database_selector` hash is used to pass options to the DatabaseSelector
104 | # middleware. The `delay` is used to determine how long to wait after a write
105 | # to send a subsequent read to the primary.
106 | #
107 | # The `database_resolver` class is used by the middleware to determine which
108 | # database is appropriate to use based on the time delay.
109 | #
110 | # The `database_resolver_context` class is used by the middleware to set
111 | # timestamps for the last write to the primary. The resolver uses the context
112 | # class timestamps to determine how long to wait before reading from the
113 | # replica.
114 | #
115 | # By default Rails will store a last write timestamp in the session. The
116 | # DatabaseSelector middleware is designed as such you can define your own
117 | # strategy for connection switching and pass that into the middleware through
118 | # these configuration options.
119 | # config.active_record.database_selector = { delay: 2.seconds }
120 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
121 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
122 | end
123 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | # The test environment is used exclusively to run your application's
4 | # test suite. You never need to work with it otherwise. Remember that
5 | # your test database is "scratch space" for the test suite and is wiped
6 | # and recreated between test runs. Don't rely on the data there!
7 |
8 | Rails.application.configure do
9 | # Settings specified here will take precedence over those in config/application.rb.
10 |
11 | config.cache_classes = false
12 | config.action_view.cache_template_loading = true
13 |
14 | # Do not eager load code on boot. This avoids loading your whole application
15 | # just for the purpose of running a single test. If you are using a tool that
16 | # preloads Rails for running tests, you may have to set it to true.
17 | config.eager_load = false
18 |
19 | # Configure public file server for tests with Cache-Control for performance.
20 | config.public_file_server.enabled = true
21 | config.public_file_server.headers = {
22 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
23 | }
24 |
25 | # Show full error reports and disable caching.
26 | config.consider_all_requests_local = true
27 | config.action_controller.perform_caching = false
28 | config.cache_store = :null_store
29 |
30 | # Raise exceptions instead of rendering exception templates.
31 | config.action_dispatch.show_exceptions = false
32 |
33 | # Disable request forgery protection in test environment.
34 | config.action_controller.allow_forgery_protection = false
35 |
36 | # Store uploaded files on the local file system in a temporary directory.
37 | config.active_storage.service = :test
38 |
39 | config.action_mailer.perform_caching = false
40 |
41 | # Tell Action Mailer not to deliver emails to the real world.
42 | # The :test delivery method accumulates sent emails in the
43 | # ActionMailer::Base.deliveries array.
44 | config.action_mailer.delivery_method = :test
45 |
46 | # Print deprecation notices to the stderr.
47 | config.active_support.deprecation = :stderr
48 |
49 | # Raise exceptions for disallowed deprecations.
50 | config.active_support.disallowed_deprecation = :raise
51 |
52 | # Tell Active Support which deprecation messages to disallow.
53 | config.active_support.disallowed_deprecation_warnings = []
54 |
55 | # Raises error for missing translations.
56 | # config.i18n.raise_on_missing_translations = true
57 |
58 | # Annotate rendered view with file names.
59 | # config.action_view.annotate_rendered_view_with_filenames = true
60 | end
61 |
--------------------------------------------------------------------------------
/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ActiveSupport::Reloader.to_prepare do
4 | # ApplicationController.renderer.defaults.merge!(
5 | # http_host: 'example.org',
6 | # https: false
7 | # )
8 | # end
9 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = '1.0'
5 |
6 | # Add additional assets to the asset load path.
7 | # Rails.application.config.assets.paths << Emoji.images_path
8 | # Add Yarn node_modules folder to the asset load path.
9 | Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 |
11 | # Precompile additional assets.
12 | # application.js, application.css, and all non-JS/CSS in the app/assets
13 | # folder are already added.
14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css )
15 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
7 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
8 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
9 |
--------------------------------------------------------------------------------
/config/initializers/content_security_policy.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Define an application-wide content security policy
4 | # For further information see the following documentation
5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
6 |
7 | # Rails.application.config.content_security_policy do |policy|
8 | # policy.default_src :self, :https
9 | # policy.font_src :self, :https, :data
10 | # policy.img_src :self, :https, :data
11 | # policy.object_src :none
12 | # policy.script_src :self, :https
13 | # policy.style_src :self, :https
14 | # # If you are using webpack-dev-server then specify webpack-dev-server host
15 | # policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
16 |
17 | # # Specify URI for violation reports
18 | # # policy.report_uri "/csp-violation-report-endpoint"
19 | # end
20 |
21 | # If you are using UJS then enable automatic nonce generation
22 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
23 |
24 | # Set the nonce only to specific directives
25 | # Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
26 |
27 | # Report CSP violations to a specified URI
28 | # For further information see the following documentation:
29 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
30 | # Rails.application.config.content_security_policy_report_only = true
31 |
--------------------------------------------------------------------------------
/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Specify a serializer for the signed and encrypted cookie jars.
4 | # Valid options are :json, :marshal, and :hybrid.
5 | Rails.application.config.action_dispatch.cookies_serializer = :json
6 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [
5 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
6 | ]
7 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/config/initializers/omniauth.rb:
--------------------------------------------------------------------------------
1 | OmniAuth.config.allowed_request_methods = [:get, :post]
--------------------------------------------------------------------------------
/config/initializers/pagy.rb:
--------------------------------------------------------------------------------
1 | require 'pagy/extras/headers'
2 | Pagy::VARS[:items] = 10
3 |
--------------------------------------------------------------------------------
/config/initializers/permissions_policy.rb:
--------------------------------------------------------------------------------
1 | # Define an application-wide HTTP permissions policy. For further
2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy
3 | #
4 | # Rails.application.config.permissions_policy do |f|
5 | # f.camera :none
6 | # f.gyroscope :none
7 | # f.microphone :none
8 | # f.usb :none
9 | # f.fullscreen :self
10 | # f.payment :self, "https://secure.example.com"
11 | # end
12 |
--------------------------------------------------------------------------------
/config/initializers/sentry.rb:
--------------------------------------------------------------------------------
1 | Raven.configure do |config|
2 | config.dsn = ENV['SENTRY_URL']
3 |
4 | # config.async = lambda do |event|
5 | # Raven.send_event(event)
6 | # end
7 | end
--------------------------------------------------------------------------------
/config/initializers/sidekiq.rb:
--------------------------------------------------------------------------------
1 | Sidekiq::Extensions.enable_delay!
2 |
3 | redis_url = ENV['REDIS_URL'] || 'redis://127.0.0.1:6379/1'
4 | Sidekiq.configure_client do |config|
5 | config.redis = { namespace: 'sslguala', url: redis_url }
6 | end
7 |
8 | Sidekiq.configure_server do |config|
9 | config.redis = { namespace: 'sslguala', url: redis_url}
10 | end
--------------------------------------------------------------------------------
/config/initializers/url_error.rb:
--------------------------------------------------------------------------------
1 | class UrlError < StandardError
2 | end
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/config/locales/devise.en.yml:
--------------------------------------------------------------------------------
1 | # Additional translations at https://github.com/heartcombo/devise/wiki/I18n
2 |
3 | en:
4 | devise:
5 | confirmations:
6 | confirmed: "Your email address has been successfully confirmed."
7 | send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
9 | failure:
10 | already_authenticated: "You are already signed in."
11 | inactive: "Your account is not activated yet."
12 | invalid: "Invalid %{authentication_keys} or password."
13 | locked: "Your account is locked."
14 | last_attempt: "You have one more attempt before your account is locked."
15 | not_found_in_database: "Invalid %{authentication_keys} or password."
16 | timeout: "Your session expired. Please sign in again to continue."
17 | unauthenticated: "You need to sign in or sign up before continuing."
18 | unconfirmed: "You have to confirm your email address before continuing."
19 | mailer:
20 | confirmation_instructions:
21 | subject: "Confirmation instructions"
22 | reset_password_instructions:
23 | subject: "Reset password instructions"
24 | unlock_instructions:
25 | subject: "Unlock instructions"
26 | email_changed:
27 | subject: "Email Changed"
28 | password_change:
29 | subject: "Password Changed"
30 | omniauth_callbacks:
31 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
32 | success: "Successfully authenticated from %{kind} account."
33 | passwords:
34 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
35 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
36 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
37 | updated: "Your password has been changed successfully. You are now signed in."
38 | updated_not_active: "Your password has been changed successfully."
39 | registrations:
40 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
41 | signed_up: "Welcome! You have signed up successfully."
42 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
43 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
44 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
45 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
46 | updated: "Your account has been updated successfully."
47 | updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
48 | sessions:
49 | signed_in: "Signed in successfully."
50 | signed_out: "Signed out successfully."
51 | already_signed_out: "Signed out successfully."
52 | unlocks:
53 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
54 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
55 | unlocked: "Your account has been unlocked successfully. Please sign in to continue."
56 | errors:
57 | messages:
58 | already_confirmed: "was already confirmed, please try signing in"
59 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
60 | expired: "has expired, please request a new one"
61 | not_found: "not found"
62 | not_locked: "was not locked"
63 | not_saved:
64 | one: "1 error prohibited this %{resource} from being saved:"
65 | other: "%{count} errors prohibited this %{resource} from being saved:"
66 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # The following keys must be escaped otherwise they will not be retrieved by
20 | # the default I18n backend:
21 | #
22 | # true, false, on, off, yes, no
23 | #
24 | # Instead, surround them with single quotes.
25 | #
26 | # en:
27 | # 'true': 'foo'
28 | #
29 | # To learn more, please read the Rails Internationalization guide
30 | # available at https://guides.rubyonrails.org/i18n.html.
31 |
32 | en:
33 | hello: "Hello world"
34 |
--------------------------------------------------------------------------------
/config/newrelic.yml:
--------------------------------------------------------------------------------
1 | #
2 | # This file configures the New Relic Agent. New Relic monitors Ruby, Java,
3 | # .NET, PHP, Python, Node, and Go applications with deep visibility and low
4 | # overhead. For more information, visit www.newrelic.com.
5 | #
6 | # Generated June 28, 2021
7 | #
8 | # This configuration file is custom generated for NewRelic Administration
9 | #
10 | # For full documentation of agent configuration options, please refer to
11 | # https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration
12 |
13 | common: &default_settings
14 | # Required license key associated with your New Relic account.
15 | license_key: <%= ENV['NEWRELIC_KEY'] %>
16 |
17 | # Your application name. Renaming here affects where data displays in New
18 | # Relic. For more details, see https://docs.newrelic.com/docs/apm/new-relic-apm/maintenance/renaming-applications
19 | app_name: sslguale
20 |
21 | distributed_tracing:
22 | enabled: false
23 |
24 | # To disable the agent regardless of other settings, uncomment the following:
25 | # agent_enabled: false
26 |
27 | # Logging level for log/newrelic_agent.log
28 | log_level: info
29 |
30 |
31 | # Environment-specific settings are in this section.
32 | # RAILS_ENV or RACK_ENV (as appropriate) is used to determine the environment.
33 | # If your application has other named environments, configure them here.
34 | development:
35 | <<: *default_settings
36 | app_name: sslguale (Development)
37 |
38 | test:
39 | <<: *default_settings
40 | # It doesn't make sense to report to New Relic from automated test runs.
41 | monitor_mode: false
42 |
43 | staging:
44 | <<: *default_settings
45 | app_name: sslguale (Staging)
46 |
47 | production:
48 | <<: *default_settings
49 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | # Puma can serve each request in a thread from an internal thread pool.
2 | # The `threads` method setting takes two numbers: a minimum and maximum.
3 | # Any libraries that use thread pools should be configured to match
4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
5 | # and maximum; this matches the default thread size of Active Record.
6 | #
7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
9 | threads min_threads_count, max_threads_count
10 |
11 | # Specifies the `worker_timeout` threshold that Puma will use to wait before
12 | # terminating a worker in development environments.
13 | #
14 | worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
15 |
16 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
17 | #
18 | port ENV.fetch("PORT") { 3000 }
19 |
20 | # Specifies the `environment` that Puma will run in.
21 | #
22 | environment ENV.fetch("RAILS_ENV") { "development" }
23 |
24 | # Specifies the `pidfile` that Puma will use.
25 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
26 |
27 | # Specifies the number of `workers` to boot in clustered mode.
28 | # Workers are forked web server processes. If using threads and workers together
29 | # the concurrency of the application would be max `threads` * `workers`.
30 | # Workers do not work on JRuby or Windows (both of which do not support
31 | # processes).
32 | #
33 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
34 |
35 | # Use the `preload_app!` method when specifying a `workers` number.
36 | # This directive tells Puma to first boot the application and load code
37 | # before forking the application. This takes advantage of Copy On Write
38 | # process behavior so workers use less memory.
39 | #
40 | # preload_app!
41 |
42 | # Allow puma to be restarted by `rails restart` command.
43 | plugin :tmp_restart
44 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | require 'sidekiq/web'
2 | require 'sidekiq-scheduler/web'
3 |
4 | Rails.application.routes.draw do
5 | namespace :api, defaults: { format: :json } do
6 | namespace :v1 do
7 | resources :check_domains, only: %i[show destroy create update index] do
8 | collection do
9 | get :valid
10 | get :welcome
11 | post :batch_create
12 | end
13 | member do
14 | post :check_now
15 | end
16 | end
17 | resources :projects, only: %i[show destroy create update index] do
18 | member do
19 | post :add_domains
20 | end
21 | end
22 | resources :msg_channels, only: %i[show destroy create update index] do
23 | member do
24 | post :bind
25 | post :unbind
26 | post :try_send_message
27 | post :multiple_bind
28 | end
29 | end
30 |
31 | resources :users, only: [] do
32 | collection do
33 | post :reset_token
34 | get :info
35 | end
36 | end
37 |
38 | # API TOKEN
39 | get 'api_tokens/check_domains', to: "api_tokens#check_domains"
40 | get 'api_tokens/valid', to: "api_tokens#valid"
41 | get 'api_tokens/msg_channels', to: "api_tokens#msg_channels"
42 | get 'api_tokens/projects', to: "api_tokens#projects"
43 | post 'api_tokens/create_domain', to: "api_tokens#create_domain"
44 | post 'api_tokens/destroy_domain', to: "api_tokens#destroy_domain"
45 | end
46 | end
47 | get 'home/index'
48 | authenticate :user, ->(u) { u.admin? } do
49 | mount Sidekiq::Web => '/sidekiq'
50 | end
51 |
52 | devise_for :users,
53 | controllers: {
54 | sessions: 'users/sessions',
55 | registrations: 'users/registrations',
56 | passwords: 'users/passwords',
57 | omniauth_callbacks: 'users/omniauth_callbacks'
58 | }
59 | root to: 'home#index'
60 |
61 | get 'policy', to: 'home#policy'
62 |
63 | # admin
64 | namespace :madmin do
65 | resources :msg_channels
66 | root to: "dashboard#index"
67 | resources :user_omniauths
68 | resources :check_domains
69 | resources :users
70 | resources :projects
71 | end
72 | end
73 |
--------------------------------------------------------------------------------
/config/sidekiq.yml:
--------------------------------------------------------------------------------
1 | :schedule:
2 | domain_schedule:
3 | every: 4 hours
4 | class: DomainScheduleWorker
5 | domain_dead_schedule:
6 | every: 1 day
7 | class: DomainDeadCheckScheduleWorker
--------------------------------------------------------------------------------
/config/spring.rb:
--------------------------------------------------------------------------------
1 | Spring.watch(
2 | ".ruby-version",
3 | ".rbenv-vars",
4 | "tmp/restart.txt",
5 | "tmp/caching-dev.txt"
6 | )
7 |
--------------------------------------------------------------------------------
/config/storage.yml:
--------------------------------------------------------------------------------
1 | test:
2 | service: Disk
3 | root: <%= Rails.root.join("tmp/storage") %>
4 |
5 | local:
6 | service: Disk
7 | root: <%= Rails.root.join("storage") %>
8 |
9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
10 | # amazon:
11 | # service: S3
12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
14 | # region: us-east-1
15 | # bucket: your_own_bucket
16 |
17 | # Remember not to checkin your GCS keyfile to a repository
18 | # google:
19 | # service: GCS
20 | # project: your_project
21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
22 | # bucket: your_own_bucket
23 |
24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
25 | # microsoft:
26 | # service: AzureStorage
27 | # storage_account_name: your_account_name
28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
29 | # container: your_container_name
30 |
31 | # mirror:
32 | # service: Mirror
33 | # primary: local
34 | # mirrors: [ amazon, google, microsoft ]
35 |
--------------------------------------------------------------------------------
/config/webpack/development.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2 |
3 | const environment = require('./environment')
4 |
5 | module.exports = environment.toWebpackConfig()
6 |
--------------------------------------------------------------------------------
/config/webpack/environment.js:
--------------------------------------------------------------------------------
1 | const { environment } = require('@rails/webpacker')
2 |
3 | module.exports = environment
4 |
--------------------------------------------------------------------------------
/config/webpack/production.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = process.env.NODE_ENV || 'production'
2 |
3 | const environment = require('./environment')
4 |
5 | module.exports = environment.toWebpackConfig()
6 |
--------------------------------------------------------------------------------
/config/webpack/test.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2 |
3 | const environment = require('./environment')
4 |
5 | module.exports = environment.toWebpackConfig()
6 |
--------------------------------------------------------------------------------
/config/webpacker.yml:
--------------------------------------------------------------------------------
1 | # Note: You must restart bin/webpack-dev-server for changes to take effect
2 |
3 | default: &default
4 | source_path: app/javascript
5 | source_entry_path: packs
6 | public_root_path: public
7 | public_output_path: packs
8 | cache_path: tmp/cache/webpacker
9 | webpack_compile_output: true
10 |
11 | # Additional paths webpack should lookup modules
12 | # ['app/assets', 'engine/foo/app/assets']
13 | additional_paths: []
14 |
15 | # Reload manifest.json on all requests so we reload latest compiled packs
16 | cache_manifest: false
17 |
18 | # Extract and emit a css file
19 | extract_css: false
20 |
21 | static_assets_extensions:
22 | - .jpg
23 | - .jpeg
24 | - .png
25 | - .gif
26 | - .tiff
27 | - .ico
28 | - .svg
29 | - .eot
30 | - .otf
31 | - .ttf
32 | - .woff
33 | - .woff2
34 |
35 | extensions:
36 | - .mjs
37 | - .js
38 | - .sass
39 | - .scss
40 | - .css
41 | - .module.sass
42 | - .module.scss
43 | - .module.css
44 | - .png
45 | - .svg
46 | - .gif
47 | - .jpeg
48 | - .jpg
49 |
50 | development:
51 | <<: *default
52 | compile: true
53 |
54 | # Reference: https://webpack.js.org/configuration/dev-server/
55 | dev_server:
56 | https: false
57 | host: localhost
58 | port: 3035
59 | public: localhost:3035
60 | hmr: false
61 | # Inline should be set to true if using HMR
62 | inline: true
63 | overlay: true
64 | compress: true
65 | disable_host_check: true
66 | use_local_ip: false
67 | quiet: false
68 | pretty: false
69 | headers:
70 | 'Access-Control-Allow-Origin': '*'
71 | watch_options:
72 | ignored: '**/node_modules/**'
73 |
74 |
75 | test:
76 | <<: *default
77 | compile: true
78 |
79 | # Compile test packs to a separate directory
80 | public_output_path: packs-test
81 |
82 | production:
83 | <<: *default
84 |
85 | # Production depends on precompilation of packs prior to booting for performance.
86 | compile: false
87 |
88 | # Extract and emit a css file
89 | extract_css: true
90 |
91 | # Cache manifest.json for performance
92 | cache_manifest: true
93 |
--------------------------------------------------------------------------------
/db/migrate/20210621053408_devise_create_users.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class DeviseCreateUsers < ActiveRecord::Migration[6.1]
4 | def change
5 | create_table :users do |t|
6 | ## Database authenticatable
7 | t.string :email, null: false, default: ""
8 | t.string :encrypted_password, null: false, default: ""
9 |
10 | ## Recoverable
11 | t.string :reset_password_token
12 | t.datetime :reset_password_sent_at
13 |
14 | ## Rememberable
15 | t.datetime :remember_created_at
16 |
17 | ## Trackable
18 | # t.integer :sign_in_count, default: 0, null: false
19 | # t.datetime :current_sign_in_at
20 | # t.datetime :last_sign_in_at
21 | # t.string :current_sign_in_ip
22 | # t.string :last_sign_in_ip
23 |
24 | ## Confirmable
25 | # t.string :confirmation_token
26 | # t.datetime :confirmed_at
27 | # t.datetime :confirmation_sent_at
28 | # t.string :unconfirmed_email # Only if using reconfirmable
29 |
30 | ## Lockable
31 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
32 | # t.string :unlock_token # Only if unlock strategy is :email or :both
33 | # t.datetime :locked_at
34 |
35 | t.string :first_name
36 | t.string :last_name
37 | t.boolean :admin, default: false
38 |
39 | t.timestamps null: false
40 | end
41 |
42 | add_index :users, :email, unique: true
43 | add_index :users, :reset_password_token, unique: true
44 | # add_index :users, :confirmation_token, unique: true
45 | # add_index :users, :unlock_token, unique: true
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/db/migrate/20210621084517_create_check_domains.rb:
--------------------------------------------------------------------------------
1 | class CreateCheckDomains < ActiveRecord::Migration[6.1]
2 | def change
3 | create_table :check_domains do |t|
4 | t.string :domain
5 | t.string :markup
6 | t.datetime :expire_at
7 | t.references :user, null: false, foreign_key: true
8 |
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20210621084536_create_projects.rb:
--------------------------------------------------------------------------------
1 | class CreateProjects < ActiveRecord::Migration[6.1]
2 | def change
3 | create_table :projects do |t|
4 | t.string :name
5 | t.string :description
6 | t.references :user
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20210621095602_create_user_omniauths.rb:
--------------------------------------------------------------------------------
1 | class CreateUserOmniauths < ActiveRecord::Migration[6.1]
2 | def change
3 | create_table :user_omniauths do |t|
4 | t.string :nickname
5 | t.string :provider, null: false
6 | t.string :uid
7 | t.string :unionid
8 | t.integer :user_id, null: false
9 |
10 | t.timestamps
11 | end
12 |
13 | add_index :user_omniauths, [:provider, :uid]
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20210621100331_add_check_expire_time_to_check_domains.rb:
--------------------------------------------------------------------------------
1 | class AddCheckExpireTimeToCheckDomains < ActiveRecord::Migration[6.1]
2 | def change
3 | add_column :check_domains, :check_expire_time_at, :datetime
4 | add_column :check_domains, :project_id, :integer
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20210622032920_add_status_to_check_domains.rb:
--------------------------------------------------------------------------------
1 | class AddStatusToCheckDomains < ActiveRecord::Migration[6.1]
2 | def change
3 | add_column :check_domains, :status, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20210622053718_add_check_domains_count_to_projects.rb:
--------------------------------------------------------------------------------
1 | class AddCheckDomainsCountToProjects < ActiveRecord::Migration[6.1]
2 | def change
3 | add_column :projects, :check_domains_count, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20210622080840_create_msg_channels.rb:
--------------------------------------------------------------------------------
1 | class CreateMsgChannels < ActiveRecord::Migration[6.1]
2 | def change
3 | create_table :msg_channels do |t|
4 | t.string :title
5 | t.string :url
6 | t.string :type
7 | t.string :markup
8 | t.jsonb :config
9 |
10 | t.timestamps
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/db/migrate/20210622083843_add_attributes_to_msg_channels.rb:
--------------------------------------------------------------------------------
1 | class AddAttributesToMsgChannels < ActiveRecord::Migration[6.1]
2 | def change
3 | add_reference :msg_channels, :user, null: false, foreign_key: true
4 | add_column :msg_channels, :is_common, :boolean, default: true
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20210622101007_create_domain_msg_channels.rb:
--------------------------------------------------------------------------------
1 | class CreateDomainMsgChannels < ActiveRecord::Migration[6.1]
2 | def change
3 | create_table :domain_msg_channels do |t|
4 | t.references :check_domain, null: false, foreign_key: true
5 | t.references :msg_channel, null: false, foreign_key: true
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20210623055035_add_notifier_to_check_domains.rb:
--------------------------------------------------------------------------------
1 | class AddNotifierToCheckDomains < ActiveRecord::Migration[6.1]
2 | def change
3 | add_column :check_domains, :latest_notice_at, :datetime
4 | add_column :check_domains, :notice_info, :jsonb
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20210624034532_add_api_token_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddApiTokenToUser < ActiveRecord::Migration[6.1]
2 | def change
3 | add_column :users, :api_token, :string
4 | add_index :users, :api_token
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20210624083614_add_error_info_to_msg_channel.rb:
--------------------------------------------------------------------------------
1 | class AddErrorInfoToMsgChannel < ActiveRecord::Migration[6.1]
2 | def change
3 | add_column :msg_channels, :error_info, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20210624091715_add_is_default_to_msg_channel.rb:
--------------------------------------------------------------------------------
1 | class AddIsDefaultToMsgChannel < ActiveRecord::Migration[6.1]
2 | def change
3 | add_column :msg_channels, :is_default, :boolean, default: false
4 | add_index :msg_channels, :is_default
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/schema.rb:
--------------------------------------------------------------------------------
1 | # This file is auto-generated from the current state of the database. Instead
2 | # of editing this file, please use the migrations feature of Active Record to
3 | # incrementally modify your database, and then regenerate this schema definition.
4 | #
5 | # This file is the source Rails uses to define your schema when running `bin/rails
6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7 | # be faster and is potentially less error prone than running all of your
8 | # migrations from scratch. Old migrations may fail to apply correctly if those
9 | # migrations use external dependencies or application code.
10 | #
11 | # It's strongly recommended that you check this file into your version control system.
12 |
13 | ActiveRecord::Schema.define(version: 2021_06_24_091715) do
14 |
15 | # These are extensions that must be enabled in order to support this database
16 | enable_extension "plpgsql"
17 |
18 | create_table "check_domains", force: :cascade do |t|
19 | t.string "domain"
20 | t.string "markup"
21 | t.datetime "expire_at"
22 | t.bigint "user_id", null: false
23 | t.datetime "created_at", precision: 6, null: false
24 | t.datetime "updated_at", precision: 6, null: false
25 | t.datetime "check_expire_time_at"
26 | t.integer "project_id"
27 | t.string "status"
28 | t.datetime "latest_notice_at"
29 | t.jsonb "notice_info"
30 | t.index ["user_id"], name: "index_check_domains_on_user_id"
31 | end
32 |
33 | create_table "domain_msg_channels", force: :cascade do |t|
34 | t.bigint "check_domain_id", null: false
35 | t.bigint "msg_channel_id", null: false
36 | t.datetime "created_at", precision: 6, null: false
37 | t.datetime "updated_at", precision: 6, null: false
38 | t.index ["check_domain_id"], name: "index_domain_msg_channels_on_check_domain_id"
39 | t.index ["msg_channel_id"], name: "index_domain_msg_channels_on_msg_channel_id"
40 | end
41 |
42 | create_table "msg_channels", force: :cascade do |t|
43 | t.string "title"
44 | t.string "url"
45 | t.string "type"
46 | t.string "markup"
47 | t.jsonb "config"
48 | t.datetime "created_at", precision: 6, null: false
49 | t.datetime "updated_at", precision: 6, null: false
50 | t.bigint "user_id", null: false
51 | t.boolean "is_common", default: true
52 | t.string "error_info"
53 | t.boolean "is_default", default: false
54 | t.index ["is_default"], name: "index_msg_channels_on_is_default"
55 | t.index ["user_id"], name: "index_msg_channels_on_user_id"
56 | end
57 |
58 | create_table "projects", force: :cascade do |t|
59 | t.string "name"
60 | t.string "description"
61 | t.bigint "user_id"
62 | t.datetime "created_at", precision: 6, null: false
63 | t.datetime "updated_at", precision: 6, null: false
64 | t.integer "check_domains_count"
65 | t.index ["user_id"], name: "index_projects_on_user_id"
66 | end
67 |
68 | create_table "user_omniauths", force: :cascade do |t|
69 | t.string "nickname"
70 | t.string "provider", null: false
71 | t.string "uid"
72 | t.string "unionid"
73 | t.integer "user_id", null: false
74 | t.datetime "created_at", precision: 6, null: false
75 | t.datetime "updated_at", precision: 6, null: false
76 | t.index ["provider", "uid"], name: "index_user_omniauths_on_provider_and_uid"
77 | end
78 |
79 | create_table "users", force: :cascade do |t|
80 | t.string "email", default: "", null: false
81 | t.string "encrypted_password", default: "", null: false
82 | t.string "reset_password_token"
83 | t.datetime "reset_password_sent_at"
84 | t.datetime "remember_created_at"
85 | t.string "first_name"
86 | t.string "last_name"
87 | t.boolean "admin", default: false
88 | t.datetime "created_at", precision: 6, null: false
89 | t.datetime "updated_at", precision: 6, null: false
90 | t.string "api_token"
91 | t.index ["api_token"], name: "index_users_on_api_token"
92 | t.index ["email"], name: "index_users_on_email", unique: true
93 | t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
94 | end
95 |
96 | add_foreign_key "check_domains", "users"
97 | add_foreign_key "domain_msg_channels", "check_domains"
98 | add_foreign_key "domain_msg_channels", "msg_channels"
99 | add_foreign_key "msg_channels", "users"
100 | end
101 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7 | # Character.create(name: 'Luke', movie: movies.first)
8 |
--------------------------------------------------------------------------------
/lib/assets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/lib/assets/.keep
--------------------------------------------------------------------------------
/lib/omniauth/strategies/wechat.rb:
--------------------------------------------------------------------------------
1 | require "omniauth-oauth2"
2 |
3 | module OmniAuth
4 | module Strategies
5 | class Wechat < OmniAuth::Strategies::OAuth2
6 | option :name, "wechat"
7 | option :full_host
8 |
9 | option :client_options, {
10 | site: "https://api.weixin.qq.com",
11 | authorize_url: "https://open.weixin.qq.com/connect/qrconnect?#wechat_redirect",
12 | token_url: "/sns/oauth2/access_token",
13 | token_method: :get
14 | }
15 |
16 | option :authorize_params, {scope: "snsapi_login"}
17 |
18 | option :token_params, {parse: :json}
19 |
20 | def callback_url
21 | (options[:full_host].presence || full_host) + script_name + callback_path
22 | end
23 |
24 | uid do
25 | raw_info['openid']
26 | end
27 |
28 | info do
29 | {
30 | nickname: raw_info['nickname'],
31 | sex: raw_info['sex'],
32 | province: raw_info['province'],
33 | city: raw_info['city'],
34 | country: raw_info['country'],
35 | headimgurl: raw_info['headimgurl'],
36 | image: raw_info['headimgurl'],
37 | unionid: raw_info['unionid']
38 | }
39 | end
40 |
41 | extra do
42 | {raw_info: raw_info}
43 | end
44 |
45 | def request_phase
46 | params = client.auth_code.authorize_params.merge(authorize_params)
47 | params["appid"] = params.delete("client_id")
48 | params["redirect_uri"] = callback_url
49 | redirect client.authorize_url(params)
50 | end
51 |
52 | def raw_info
53 | @uid ||= access_token["openid"]
54 | @raw_info ||= begin
55 | access_token.options[:mode] = :query
56 | if access_token["scope"]&.include?("snsapi_login")
57 | access_token.get("/sns/userinfo", :params => { "openid" => @uid, "lang" => "zh_CN" }, parse: :json).parsed
58 | else
59 | { "openid" => @uid }
60 | end
61 | end
62 | @raw_info
63 | end
64 |
65 | protected
66 | def build_access_token
67 | params = {
68 | 'appid' => client.id,
69 | 'secret' => client.secret,
70 | 'code' => request.params['code'],
71 | 'grant_type' => 'authorization_code',
72 | 'redirect_uri' => callback_url
73 | }.merge(token_params.to_hash(symbolize_keys: true))
74 | client.get_token(params, deep_symbolize(options.auth_token_params))
75 | end
76 |
77 | end
78 | end
79 | end
80 |
--------------------------------------------------------------------------------
/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/lib/tasks/.keep
--------------------------------------------------------------------------------
/lib/tasks/auto_annotate_models.rake:
--------------------------------------------------------------------------------
1 | # NOTE: only doing this in development as some production environments (Heroku)
2 | # NOTE: are sensitive to local FS writes, and besides -- it's just not proper
3 | # NOTE: to have a dev-mode tool do its thing in production.
4 | if Rails.env.development?
5 | require 'annotate'
6 | task :set_annotation_options do
7 | # You can override any of these by setting an environment variable of the
8 | # same name.
9 | Annotate.set_defaults(
10 | 'active_admin' => 'false',
11 | 'additional_file_patterns' => [],
12 | 'routes' => 'false',
13 | 'models' => 'true',
14 | 'position_in_routes' => 'before',
15 | 'position_in_class' => 'before',
16 | 'position_in_test' => 'before',
17 | 'position_in_fixture' => 'before',
18 | 'position_in_factory' => 'before',
19 | 'position_in_serializer' => 'before',
20 | 'show_foreign_keys' => 'true',
21 | 'show_complete_foreign_keys' => 'false',
22 | 'show_indexes' => 'true',
23 | 'simple_indexes' => 'false',
24 | 'model_dir' => 'app/models',
25 | 'root_dir' => '',
26 | 'include_version' => 'false',
27 | 'require' => '',
28 | 'exclude_tests' => 'false',
29 | 'exclude_fixtures' => 'false',
30 | 'exclude_factories' => 'false',
31 | 'exclude_serializers' => 'false',
32 | 'exclude_scaffolds' => 'true',
33 | 'exclude_controllers' => 'true',
34 | 'exclude_helpers' => 'true',
35 | 'exclude_sti_subclasses' => 'false',
36 | 'ignore_model_sub_dir' => 'false',
37 | 'ignore_columns' => nil,
38 | 'ignore_routes' => nil,
39 | 'ignore_unknown_models' => 'false',
40 | 'hide_limit_column_types' => 'integer,bigint,boolean',
41 | 'hide_default_column_types' => 'json,jsonb,hstore',
42 | 'skip_on_db_migrate' => 'false',
43 | 'format_bare' => 'true',
44 | 'format_rdoc' => 'false',
45 | 'format_yard' => 'false',
46 | 'format_markdown' => 'false',
47 | 'sort' => 'false',
48 | 'force' => 'false',
49 | 'frozen' => 'false',
50 | 'classified_sort' => 'true',
51 | 'trace' => 'false',
52 | 'wrapper_open' => nil,
53 | 'wrapper_close' => nil,
54 | 'with_comment' => 'true'
55 | )
56 | end
57 |
58 | Annotate.load_tasks
59 | end
60 |
--------------------------------------------------------------------------------
/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/log/.keep
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sslguala",
3 | "private": true,
4 | "dependencies": {
5 | "@rails/actioncable": "^6.0.0",
6 | "@rails/activestorage": "^6.0.0",
7 | "@rails/ujs": "^6.0.0",
8 | "@rails/webpacker": "5.4.0",
9 | "lodash": "^4.17.21",
10 | "stimulus": "^2.0.0",
11 | "turbolinks": "^5.2.0",
12 | "webpack": "^4.46.0",
13 | "webpack-cli": "^3.3.12"
14 | },
15 | "version": "0.1.0",
16 | "devDependencies": {
17 | "webpack-dev-server": "^3.11.2"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('postcss-import'),
4 | require('postcss-flexbugs-fixes'),
5 | require('postcss-preset-env')({
6 | autoprefixer: {
7 | flexbox: 'no-2009'
8 | },
9 | stage: 3
10 | })
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/public/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/public/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/public/favicon.ico
--------------------------------------------------------------------------------
/public/images/types-of-ssl-certificates.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/public/images/types-of-ssl-certificates.jpg
--------------------------------------------------------------------------------
/public/images/what-is-a-ssl-certificate-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/public/images/what-is-a-ssl-certificate-1.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 |
--------------------------------------------------------------------------------
/public/secure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/public/secure.png
--------------------------------------------------------------------------------
/public/ssl-secure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/public/ssl-secure.png
--------------------------------------------------------------------------------
/sidekiq:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=sidekiq for sslguala (production)
3 | After=syslog.target network.target
4 |
5 | [Service]
6 | Type=simple
7 | WorkingDirectory=/var/www/sslguala/current
8 | ExecStart=/home/deploy/.rvm/bin/rvm 2.7.3 do bundle exec sidekiq -e production
9 | ExecReload=/bin/kill -TSTP $MAINPID
10 | ExecStop=/bin/kill -TERM $MAINPID
11 | StandardOutput=append:/var/www/sslguala/shared/log/sidekiq.log
12 | StandardError=append:/var/www/sslguala/shared/log/sidekiq.error.log
13 |
14 |
15 |
16 |
17 |
18 | RestartSec=1
19 | Restart=on-failure
20 |
21 | SyslogIdentifier=sidekiq
22 |
23 | [Install]
24 | WantedBy=default.target
25 |
--------------------------------------------------------------------------------
/storage/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/storage/.keep
--------------------------------------------------------------------------------
/test/application_system_test_case.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
4 | driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
5 | end
6 |
--------------------------------------------------------------------------------
/test/channels/application_cable/connection_test.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase
4 | # test "connects with cookies" do
5 | # cookies.signed[:user_id] = 42
6 | #
7 | # connect
8 | #
9 | # assert_equal connection.user_id, "42"
10 | # end
11 | end
12 |
--------------------------------------------------------------------------------
/test/controllers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/test/controllers/.keep
--------------------------------------------------------------------------------
/test/controllers/api/v1/check_domains_controller_test.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class Api::V1::CheckDomainsControllerTest < ActionDispatch::IntegrationTest
4 | test "should get index" do
5 | get api_v1_check_domains_index_url
6 | assert_response :success
7 | end
8 |
9 | test "should get create" do
10 | get api_v1_check_domains_create_url
11 | assert_response :success
12 | end
13 |
14 | test "should get show" do
15 | get api_v1_check_domains_show_url
16 | assert_response :success
17 | end
18 |
19 | test "should get destroy" do
20 | get api_v1_check_domains_destroy_url
21 | assert_response :success
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/test/controllers/api/v1/msg_channels_controller_test.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class Api::V1::MsgChannelsControllerTest < ActionDispatch::IntegrationTest
4 | test "should get index" do
5 | get api_v1_msg_channels_index_url
6 | assert_response :success
7 | end
8 |
9 | test "should get create" do
10 | get api_v1_msg_channels_create_url
11 | assert_response :success
12 | end
13 |
14 | test "should get show" do
15 | get api_v1_msg_channels_show_url
16 | assert_response :success
17 | end
18 |
19 | test "should get update" do
20 | get api_v1_msg_channels_update_url
21 | assert_response :success
22 | end
23 |
24 | test "should get destroy" do
25 | get api_v1_msg_channels_destroy_url
26 | assert_response :success
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/test/controllers/api/v1/projects_controller_test.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class Api::V1::ProjectsControllerTest < ActionDispatch::IntegrationTest
4 | test "should get index" do
5 | get api_v1_projects_index_url
6 | assert_response :success
7 | end
8 |
9 | test "should get create" do
10 | get api_v1_projects_create_url
11 | assert_response :success
12 | end
13 |
14 | test "should get show" do
15 | get api_v1_projects_show_url
16 | assert_response :success
17 | end
18 |
19 | test "should get update" do
20 | get api_v1_projects_update_url
21 | assert_response :success
22 | end
23 |
24 | test "should get destroy" do
25 | get api_v1_projects_destroy_url
26 | assert_response :success
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/test/controllers/home_controller_test.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class HomeControllerTest < ActionDispatch::IntegrationTest
4 | test "should get index" do
5 | get home_index_url
6 | assert_response :success
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/fixtures/check_domains.yml:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: check_domains
4 | #
5 | # id :bigint not null, primary key
6 | # check_expire_time_at :datetime
7 | # domain :string
8 | # expire_at :datetime
9 | # latest_notice_at :datetime
10 | # markup :string
11 | # notice_info :jsonb
12 | # status :string
13 | # created_at :datetime not null
14 | # updated_at :datetime not null
15 | # project_id :integer
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_check_domains_on_user_id (user_id)
21 | #
22 | # Foreign Keys
23 | #
24 | # fk_rails_... (user_id => users.id)
25 | #
26 |
27 | one:
28 | domain: MyString
29 | markup: MyString
30 | expire_at: 2021-06-21 16:45:17
31 | user: one
32 |
33 | two:
34 | domain: MyString
35 | markup: MyString
36 | expire_at: 2021-06-21 16:45:17
37 | user: two
38 |
--------------------------------------------------------------------------------
/test/fixtures/domain_msg_channels.yml:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: domain_msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # created_at :datetime not null
7 | # updated_at :datetime not null
8 | # check_domain_id :bigint not null
9 | # msg_channel_id :bigint not null
10 | #
11 | # Indexes
12 | #
13 | # index_domain_msg_channels_on_check_domain_id (check_domain_id)
14 | # index_domain_msg_channels_on_msg_channel_id (msg_channel_id)
15 | #
16 | # Foreign Keys
17 | #
18 | # fk_rails_... (check_domain_id => check_domains.id)
19 | # fk_rails_... (msg_channel_id => msg_channels.id)
20 | #
21 |
22 | one:
23 | check_domain: one
24 | msg_channel: one
25 |
26 | two:
27 | check_domain: two
28 | msg_channel: two
29 |
--------------------------------------------------------------------------------
/test/fixtures/files/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/test/fixtures/files/.keep
--------------------------------------------------------------------------------
/test/fixtures/msg_channels.yml:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # config :jsonb
7 | # error_info :string
8 | # is_common :boolean default(TRUE)
9 | # is_default :boolean default(FALSE)
10 | # markup :string
11 | # title :string
12 | # type :string
13 | # url :string
14 | # created_at :datetime not null
15 | # updated_at :datetime not null
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_msg_channels_on_is_default (is_default)
21 | # index_msg_channels_on_user_id (user_id)
22 | #
23 | # Foreign Keys
24 | #
25 | # fk_rails_... (user_id => users.id)
26 | #
27 |
28 | one:
29 | title: MyString
30 | url: MyString
31 | markup: MyString
32 | config:
33 |
34 | two:
35 | title: MyString
36 | url: MyString
37 | markup: MyString
38 | config:
39 |
--------------------------------------------------------------------------------
/test/fixtures/projects.yml:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: projects
4 | #
5 | # id :bigint not null, primary key
6 | # check_domains_count :integer
7 | # description :string
8 | # name :string
9 | # created_at :datetime not null
10 | # updated_at :datetime not null
11 | # user_id :bigint
12 | #
13 | # Indexes
14 | #
15 | # index_projects_on_user_id (user_id)
16 | #
17 |
18 | one:
19 | name: MyString
20 | description: MyString
21 |
22 | two:
23 | name: MyString
24 | description: MyString
25 |
--------------------------------------------------------------------------------
/test/fixtures/user_omniauths.yml:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: user_omniauths
4 | #
5 | # id :bigint not null, primary key
6 | # nickname :string
7 | # provider :string not null
8 | # uid :string
9 | # unionid :string
10 | # created_at :datetime not null
11 | # updated_at :datetime not null
12 | # user_id :integer not null
13 | #
14 | # Indexes
15 | #
16 | # index_user_omniauths_on_provider_and_uid (provider,uid)
17 | #
18 |
19 | one:
20 | nickname: MyString
21 | provider: MyString
22 | uid: MyString
23 | unionid: MyString
24 | user_id: 1
25 |
26 | two:
27 | nickname: MyString
28 | provider: MyString
29 | uid: MyString
30 | unionid: MyString
31 | user_id: 1
32 |
--------------------------------------------------------------------------------
/test/fixtures/users.yml:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: users
4 | #
5 | # id :bigint not null, primary key
6 | # admin :boolean default(FALSE)
7 | # api_token :string
8 | # email :string default(""), not null
9 | # encrypted_password :string default(""), not null
10 | # first_name :string
11 | # last_name :string
12 | # remember_created_at :datetime
13 | # reset_password_sent_at :datetime
14 | # reset_password_token :string
15 | # created_at :datetime not null
16 | # updated_at :datetime not null
17 | #
18 | # Indexes
19 | #
20 | # index_users_on_api_token (api_token)
21 | # index_users_on_email (email) UNIQUE
22 | # index_users_on_reset_password_token (reset_password_token) UNIQUE
23 | #
24 |
25 | # This model initially had no columns defined. If you add columns to the
26 | # model remove the '{}' from the fixture names and add the columns immediately
27 | # below each fixture, per the syntax in the comments below
28 | #
29 | one: {}
30 | # column: value
31 | #
32 | two: {}
33 | # column: value
34 |
--------------------------------------------------------------------------------
/test/helpers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/test/helpers/.keep
--------------------------------------------------------------------------------
/test/integration/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/test/integration/.keep
--------------------------------------------------------------------------------
/test/mailers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/test/mailers/.keep
--------------------------------------------------------------------------------
/test/models/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/test/models/.keep
--------------------------------------------------------------------------------
/test/models/check_domain_test.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: check_domains
4 | #
5 | # id :bigint not null, primary key
6 | # check_expire_time_at :datetime
7 | # domain :string
8 | # expire_at :datetime
9 | # latest_notice_at :datetime
10 | # markup :string
11 | # notice_info :jsonb
12 | # status :string
13 | # created_at :datetime not null
14 | # updated_at :datetime not null
15 | # project_id :integer
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_check_domains_on_user_id (user_id)
21 | #
22 | # Foreign Keys
23 | #
24 | # fk_rails_... (user_id => users.id)
25 | #
26 | require "test_helper"
27 |
28 | class CheckDomainTest < ActiveSupport::TestCase
29 | # test "the truth" do
30 | # assert true
31 | # end
32 | end
33 |
--------------------------------------------------------------------------------
/test/models/domain_msg_channel_test.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: domain_msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # created_at :datetime not null
7 | # updated_at :datetime not null
8 | # check_domain_id :bigint not null
9 | # msg_channel_id :bigint not null
10 | #
11 | # Indexes
12 | #
13 | # index_domain_msg_channels_on_check_domain_id (check_domain_id)
14 | # index_domain_msg_channels_on_msg_channel_id (msg_channel_id)
15 | #
16 | # Foreign Keys
17 | #
18 | # fk_rails_... (check_domain_id => check_domains.id)
19 | # fk_rails_... (msg_channel_id => msg_channels.id)
20 | #
21 | require "test_helper"
22 |
23 | class DomainMsgChannelTest < ActiveSupport::TestCase
24 | # test "the truth" do
25 | # assert true
26 | # end
27 | end
28 |
--------------------------------------------------------------------------------
/test/models/msg_channel_test.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: msg_channels
4 | #
5 | # id :bigint not null, primary key
6 | # config :jsonb
7 | # error_info :string
8 | # is_common :boolean default(TRUE)
9 | # is_default :boolean default(FALSE)
10 | # markup :string
11 | # title :string
12 | # type :string
13 | # url :string
14 | # created_at :datetime not null
15 | # updated_at :datetime not null
16 | # user_id :bigint not null
17 | #
18 | # Indexes
19 | #
20 | # index_msg_channels_on_is_default (is_default)
21 | # index_msg_channels_on_user_id (user_id)
22 | #
23 | # Foreign Keys
24 | #
25 | # fk_rails_... (user_id => users.id)
26 | #
27 | require "test_helper"
28 |
29 | class MsgChannelTest < ActiveSupport::TestCase
30 | # test "the truth" do
31 | # assert true
32 | # end
33 | end
34 |
--------------------------------------------------------------------------------
/test/models/project_test.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: projects
4 | #
5 | # id :bigint not null, primary key
6 | # check_domains_count :integer
7 | # description :string
8 | # name :string
9 | # created_at :datetime not null
10 | # updated_at :datetime not null
11 | # user_id :bigint
12 | #
13 | # Indexes
14 | #
15 | # index_projects_on_user_id (user_id)
16 | #
17 | require "test_helper"
18 |
19 | class ProjectTest < ActiveSupport::TestCase
20 | # test "the truth" do
21 | # assert true
22 | # end
23 | end
24 |
--------------------------------------------------------------------------------
/test/models/user_omniauth_test.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: user_omniauths
4 | #
5 | # id :bigint not null, primary key
6 | # nickname :string
7 | # provider :string not null
8 | # uid :string
9 | # unionid :string
10 | # created_at :datetime not null
11 | # updated_at :datetime not null
12 | # user_id :integer not null
13 | #
14 | # Indexes
15 | #
16 | # index_user_omniauths_on_provider_and_uid (provider,uid)
17 | #
18 | require "test_helper"
19 |
20 | class UserOmniauthTest < ActiveSupport::TestCase
21 | # test "the truth" do
22 | # assert true
23 | # end
24 | end
25 |
--------------------------------------------------------------------------------
/test/models/user_test.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: users
4 | #
5 | # id :bigint not null, primary key
6 | # admin :boolean default(FALSE)
7 | # api_token :string
8 | # email :string default(""), not null
9 | # encrypted_password :string default(""), not null
10 | # first_name :string
11 | # last_name :string
12 | # remember_created_at :datetime
13 | # reset_password_sent_at :datetime
14 | # reset_password_token :string
15 | # created_at :datetime not null
16 | # updated_at :datetime not null
17 | #
18 | # Indexes
19 | #
20 | # index_users_on_api_token (api_token)
21 | # index_users_on_email (email) UNIQUE
22 | # index_users_on_reset_password_token (reset_password_token) UNIQUE
23 | #
24 | require "test_helper"
25 |
26 | class UserTest < ActiveSupport::TestCase
27 | # test "the truth" do
28 | # assert true
29 | # end
30 | end
31 |
--------------------------------------------------------------------------------
/test/system/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/test/system/.keep
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | ENV['RAILS_ENV'] ||= 'test'
2 | require_relative "../config/environment"
3 | require "rails/test_help"
4 |
5 | class ActiveSupport::TestCase
6 | # Run tests in parallel with specified workers
7 | parallelize(workers: :number_of_processors)
8 |
9 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
10 | fixtures :all
11 |
12 | # Add more helper methods to be used by all tests here...
13 | end
14 |
--------------------------------------------------------------------------------
/tmp/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/tmp/.keep
--------------------------------------------------------------------------------
/tmp/pids/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/tmp/pids/.keep
--------------------------------------------------------------------------------
/vendor/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FIRHQ/sslguala-ce/962b8429c8dd53eae8de6c19efd943b141156c31/vendor/.keep
--------------------------------------------------------------------------------