mirror of
https://github.com/czhu12/canine.git
synced 2025-12-21 10:49:49 -06:00
jumpstart
This commit is contained in:
13
Gemfile
13
Gemfile
@@ -71,3 +71,16 @@ gem "sidekiq", "~> 6.2"
|
||||
gem "sitemap_generator", "~> 6.1"
|
||||
gem "whenever", require: false
|
||||
gem "responders", github: "heartcombo/responders", branch: "main"
|
||||
gem "dotenv", "~> 3.1"
|
||||
gem "image_processing", "~> 1.13"
|
||||
gem "k8s-ruby", "~> 0.16.0"
|
||||
gem "kubeclient", "~> 4.12"
|
||||
gem "light-service", "~> 0.19.0"
|
||||
gem "octokit", "~> 9.1"
|
||||
gem "omniauth-digitalocean", "~> 0.3.2"
|
||||
gem "redis", "~> 4.8"
|
||||
gem "pagy", "~> 9.0"
|
||||
gem "rqrcode", "~> 2.2"
|
||||
gem "oj", "~> 3.16"
|
||||
gem "omniauth", "~> 2.1"
|
||||
gem "omniauth-rails_csrf_protection", "~> 1.0"
|
||||
|
||||
123
Gemfile.lock
123
Gemfile.lock
@@ -109,6 +109,7 @@ GEM
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
chronic (0.10.2)
|
||||
chunky_png (1.4.0)
|
||||
concurrent-ruby (1.3.4)
|
||||
connection_pool (2.4.1)
|
||||
crass (1.0.6)
|
||||
@@ -124,21 +125,71 @@ GEM
|
||||
railties (>= 4.1.0)
|
||||
responders
|
||||
warden (~> 1.2.3)
|
||||
domain_name (0.6.20240107)
|
||||
dotenv (3.1.4)
|
||||
drb (2.2.1)
|
||||
dry-configurable (1.2.0)
|
||||
dry-core (~> 1.0, < 2)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-core (1.0.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-inflector (1.1.0)
|
||||
dry-logic (1.5.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-core (~> 1.0, < 2)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-struct (1.6.0)
|
||||
dry-core (~> 1.0, < 2)
|
||||
dry-types (>= 1.7, < 2)
|
||||
ice_nine (~> 0.11)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-types (1.7.2)
|
||||
bigdecimal (~> 3.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-core (~> 1.0)
|
||||
dry-inflector (~> 1.0)
|
||||
dry-logic (~> 1.4)
|
||||
zeitwerk (~> 2.6)
|
||||
erubi (1.13.0)
|
||||
excon (0.111.0)
|
||||
faraday (2.12.0)
|
||||
faraday-net_http (>= 2.0, < 3.4)
|
||||
json
|
||||
logger
|
||||
faraday-net_http (3.3.0)
|
||||
net-http
|
||||
ffi (1.17.0-aarch64-linux-gnu)
|
||||
ffi (1.17.0-arm-linux-gnu)
|
||||
ffi (1.17.0-arm64-darwin)
|
||||
ffi (1.17.0-x86-linux-gnu)
|
||||
ffi (1.17.0-x86_64-darwin)
|
||||
ffi (1.17.0-x86_64-linux-gnu)
|
||||
ffi-compiler (1.3.2)
|
||||
ffi (>= 1.15.5)
|
||||
rake
|
||||
friendly_id (5.5.1)
|
||||
activerecord (>= 4.0.0)
|
||||
globalid (1.2.1)
|
||||
activesupport (>= 6.1)
|
||||
hashdiff (1.0.1)
|
||||
hashie (5.0.0)
|
||||
http (5.2.0)
|
||||
addressable (~> 2.8)
|
||||
base64 (~> 0.1)
|
||||
http-cookie (~> 1.0)
|
||||
http-form_data (~> 2.2)
|
||||
llhttp-ffi (~> 0.5.0)
|
||||
http-accept (1.7.0)
|
||||
http-cookie (1.0.7)
|
||||
domain_name (~> 0.5)
|
||||
http-form_data (2.3.0)
|
||||
i18n (1.14.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
ice_nine (0.11.2)
|
||||
image_processing (1.13.0)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
importmap-rails (2.0.1)
|
||||
actionpack (>= 6.0.0)
|
||||
activesupport (>= 6.0.0)
|
||||
@@ -153,9 +204,30 @@ GEM
|
||||
jsbundling-rails (1.3.1)
|
||||
railties (>= 6.0.0)
|
||||
json (2.7.2)
|
||||
jsonpath (1.1.5)
|
||||
multi_json
|
||||
jwt (2.9.1)
|
||||
base64
|
||||
k8s-ruby (0.16.0)
|
||||
dry-configurable
|
||||
dry-struct
|
||||
dry-types
|
||||
excon (~> 0.71)
|
||||
hashdiff (~> 1.0.0)
|
||||
jsonpath (~> 1.1)
|
||||
recursive-open-struct (~> 1.1.3)
|
||||
yajl-ruby (~> 1.4.0)
|
||||
yaml-safe_load_stream3
|
||||
kubeclient (4.12.0)
|
||||
http (>= 3.0, < 6.0)
|
||||
jsonpath (~> 1.0)
|
||||
recursive-open-struct (~> 1.1, >= 1.1.1)
|
||||
rest-client (~> 2.0)
|
||||
language_server-protocol (3.17.0.3)
|
||||
light-service (0.19.0)
|
||||
llhttp-ffi (0.5.0)
|
||||
ffi-compiler (~> 1.0)
|
||||
rake (~> 13.0)
|
||||
logger (1.6.1)
|
||||
loofah (2.22.0)
|
||||
crass (~> 1.0.2)
|
||||
@@ -170,9 +242,14 @@ GEM
|
||||
net-smtp
|
||||
marcel (1.0.4)
|
||||
matrix (0.4.2)
|
||||
mime-types (3.5.2)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2024.0903)
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
minitest (5.25.1)
|
||||
msgpack (1.7.2)
|
||||
multi_json (1.15.0)
|
||||
multi_xml (0.7.1)
|
||||
bigdecimal (~> 3.1)
|
||||
net-http (0.4.1)
|
||||
@@ -186,6 +263,7 @@ GEM
|
||||
timeout
|
||||
net-smtp (0.5.0)
|
||||
net-protocol
|
||||
netrc (0.11.0)
|
||||
nio4r (2.7.3)
|
||||
nokogiri (1.16.7-aarch64-linux)
|
||||
racc (~> 1.4)
|
||||
@@ -214,10 +292,20 @@ GEM
|
||||
rack (>= 1.2, < 4)
|
||||
snaky_hash (~> 2.0)
|
||||
version_gem (~> 1.1)
|
||||
octokit (9.1.0)
|
||||
faraday (>= 1, < 3)
|
||||
sawyer (~> 0.9)
|
||||
oj (3.16.6)
|
||||
bigdecimal (>= 3.0)
|
||||
ostruct (>= 0.2)
|
||||
omniauth (2.1.2)
|
||||
hashie (>= 3.4.6)
|
||||
rack (>= 2.2.3)
|
||||
rack-protection
|
||||
omniauth-digitalocean (0.3.2)
|
||||
multi_json (~> 1.15)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-oauth2 (~> 1.0)
|
||||
omniauth-facebook (8.0.0)
|
||||
omniauth-oauth2 (~> 1.2)
|
||||
omniauth-github (2.0.1)
|
||||
@@ -230,10 +318,14 @@ GEM
|
||||
omniauth-oauth2 (1.8.0)
|
||||
oauth2 (>= 1.4, < 3)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-rails_csrf_protection (1.0.2)
|
||||
actionpack (>= 4.2)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-twitter (1.4.0)
|
||||
omniauth-oauth (~> 1.1)
|
||||
rack
|
||||
orm_adapter (0.5.0)
|
||||
ostruct (0.6.0)
|
||||
pagy (9.0.9)
|
||||
parallel (1.26.3)
|
||||
parser (3.3.5.0)
|
||||
@@ -294,11 +386,21 @@ GEM
|
||||
rake (13.2.1)
|
||||
rdoc (6.7.0)
|
||||
psych (>= 4.0.0)
|
||||
recursive-open-struct (1.1.3)
|
||||
redis (4.8.1)
|
||||
regexp_parser (2.9.2)
|
||||
reline (0.5.10)
|
||||
io-console (~> 0.5)
|
||||
rest-client (2.1.0)
|
||||
http-accept (>= 1.7.0, < 2.0)
|
||||
http-cookie (>= 1.0.2, < 2.0)
|
||||
mime-types (>= 1.16, < 4.0)
|
||||
netrc (~> 0.8)
|
||||
rexml (3.3.7)
|
||||
rqrcode (2.2.0)
|
||||
chunky_png (~> 1.0)
|
||||
rqrcode_core (~> 1.0)
|
||||
rqrcode_core (1.2.0)
|
||||
rubocop (1.66.1)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (>= 3.17.0)
|
||||
@@ -328,7 +430,13 @@ GEM
|
||||
rubocop-performance
|
||||
rubocop-rails
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby-vips (2.2.2)
|
||||
ffi (~> 1.12)
|
||||
logger
|
||||
rubyzip (2.3.2)
|
||||
sawyer (0.9.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (>= 0.17.3, < 3)
|
||||
securerandom (0.3.1)
|
||||
selenium-webdriver (4.25.0)
|
||||
base64 (~> 0.2)
|
||||
@@ -382,6 +490,8 @@ GEM
|
||||
chronic (>= 0.6.3)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
yajl-ruby (1.4.3)
|
||||
yaml-safe_load_stream3 (0.1.2)
|
||||
zeitwerk (2.6.18)
|
||||
|
||||
PLATFORMS
|
||||
@@ -399,22 +509,35 @@ DEPENDENCIES
|
||||
cssbundling-rails
|
||||
debug
|
||||
devise (~> 4.9)
|
||||
dotenv (~> 3.1)
|
||||
friendly_id (~> 5.4)
|
||||
image_processing (~> 1.13)
|
||||
importmap-rails
|
||||
jbuilder
|
||||
jsbundling-rails
|
||||
k8s-ruby (~> 0.16.0)
|
||||
kubeclient (~> 4.12)
|
||||
light-service (~> 0.19.0)
|
||||
madmin
|
||||
name_of_person!
|
||||
noticed (~> 2.0)
|
||||
octokit (~> 9.1)
|
||||
oj (~> 3.16)
|
||||
omniauth (~> 2.1)
|
||||
omniauth-digitalocean (~> 0.3.2)
|
||||
omniauth-facebook (~> 8.0)
|
||||
omniauth-github (~> 2.0)
|
||||
omniauth-rails_csrf_protection (~> 1.0)
|
||||
omniauth-twitter (~> 1.4)
|
||||
pagy (~> 9.0)
|
||||
pg (~> 1.1)
|
||||
pretender (~> 0.3.4)
|
||||
puma (>= 5.0)
|
||||
pundit (~> 2.1)
|
||||
rails (~> 7.2.1)
|
||||
redis (~> 4.8)
|
||||
responders!
|
||||
rqrcode (~> 2.2)
|
||||
rubocop-rails-omakase
|
||||
selenium-webdriver
|
||||
sidekiq (~> 6.2)
|
||||
|
||||
31
app/actions/add_ons/install_helm_chart.rb
Normal file
31
app/actions/add_ons/install_helm_chart.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
class AddOns::InstallHelmChart
|
||||
extend LightService::Action
|
||||
expects :add_on
|
||||
|
||||
executed do |context|
|
||||
add_on = context.add_on
|
||||
add_on.installing!
|
||||
charts = YAML.load_file(Rails.root.join('resources', 'helm', 'charts.yml'))['helm']['charts']
|
||||
chart = charts.find { |chart| chart['name'] == add_on.chart_type }
|
||||
# First, check if the chart is already installed & running
|
||||
|
||||
client = K8::Helm::Client.new(add_on.cluster.kubeconfig, Cli::RunAndLog.new(add_on))
|
||||
charts = client.ls
|
||||
unless charts.any? { |chart| chart.name == add_on.name }
|
||||
charts = client.install(add_on.name, add_on.helm_chart_url, values: get_values(add_on))
|
||||
end
|
||||
add_on.installed!
|
||||
end
|
||||
|
||||
def self.get_values(add_on)
|
||||
values = add_on.metadata['template'].keys.each_with_object({}) do |key, values|
|
||||
template = add_on.metadata['template'][key]
|
||||
if template.is_a?(Hash) && template['type'] == 'size'
|
||||
values[key] = "#{template['value']}#{template['unit']}"
|
||||
else
|
||||
values[key] = template['value']
|
||||
end
|
||||
end
|
||||
values
|
||||
end
|
||||
end
|
||||
14
app/actions/add_ons/uninstall_helm_chart.rb
Normal file
14
app/actions/add_ons/uninstall_helm_chart.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class AddOns::UninstallHelmChart
|
||||
extend LightService::Action
|
||||
expects :add_on
|
||||
|
||||
executed do |context|
|
||||
add_on = context.add_on
|
||||
client = K8::Helm::Client.new(add_on.cluster.kubeconfig, Cli::RunAndLog.new(add_on))
|
||||
charts = client.ls
|
||||
if charts.any? { |chart| chart.name == add_on.name }
|
||||
client.uninstall(add_on.name)
|
||||
end
|
||||
add_on.uninstalled!
|
||||
end
|
||||
end
|
||||
18
app/actions/clusters/install.rb
Normal file
18
app/actions/clusters/install.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
class Clusters::Install
|
||||
extend LightService::Organizer
|
||||
|
||||
def self.call(cluster)
|
||||
cluster.installing!
|
||||
result = with(cluster:).reduce(
|
||||
Clusters::IsReady,
|
||||
Clusters::InstallNginxIngress,
|
||||
Clusters::InstallAcmeIssuer,
|
||||
Clusters::InstallMetricServer,
|
||||
)
|
||||
cluster.running! if result.success?
|
||||
cluster.failed! if result.failure?
|
||||
rescue StandardError => e
|
||||
cluster.failed!
|
||||
raise e
|
||||
end
|
||||
end
|
||||
25
app/actions/clusters/install_acme_issuer.rb
Normal file
25
app/actions/clusters/install_acme_issuer.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
class Clusters::InstallAcmeIssuer
|
||||
extend LightService::Action
|
||||
|
||||
expects :cluster
|
||||
|
||||
executed do |context|
|
||||
cluster = context.cluster
|
||||
cluster.info("Checking if acme issuer is already installed")
|
||||
runner = Cli::RunAndLog.new(cluster)
|
||||
kubectl = K8::Kubectl.new(cluster.kubeconfig, runner)
|
||||
begin
|
||||
kubectl.("get clusterissuer letsencryptasdf")
|
||||
cluster.info("Acme issuer is already installed")
|
||||
rescue Cli::CommandFailedError => e
|
||||
cluster.info("Acme issuer not detected, installing...")
|
||||
ingress_yaml = K8::Shared::AcmeIssuer.new(cluster.user.email).to_yaml
|
||||
kubectl.apply_yaml(ingress_yaml)
|
||||
cluster.info("Acme issuer installed")
|
||||
end
|
||||
rescue StandardError => e
|
||||
cluster.failed!
|
||||
cluster.info("Acme issuer failed to install")
|
||||
context.fail!("Script failed with exit code #{exit_status.exitstatus}")
|
||||
end
|
||||
end
|
||||
20
app/actions/clusters/install_metric_server.rb
Normal file
20
app/actions/clusters/install_metric_server.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
class Clusters::InstallMetricServer
|
||||
extend LightService::Action
|
||||
|
||||
expects :cluster
|
||||
|
||||
executed do |context|
|
||||
cluster = context.cluster
|
||||
runner = Cli::RunAndLog.new(cluster)
|
||||
kubectl = K8::Kubectl.new(cluster.kubeconfig, runner)
|
||||
cluster.info("Checking if metric server is already installed...")
|
||||
|
||||
begin
|
||||
kubectl.("get deployment metrics-server -n kube-system")
|
||||
cluster.info("Nginx ingress controller is already installed")
|
||||
rescue Cli::CommandFailedError => e
|
||||
cluster.info("Metric server not detected, installing...")
|
||||
kubectl.apply_yaml(Rails.root.join("resources", "k8", "shared", "metrics_server.yaml"))
|
||||
end
|
||||
end
|
||||
end
|
||||
30
app/actions/clusters/install_nginx_ingress.rb
Normal file
30
app/actions/clusters/install_nginx_ingress.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
class Clusters::InstallNginxIngress
|
||||
extend LightService::Action
|
||||
|
||||
expects :cluster
|
||||
|
||||
executed do |context|
|
||||
cluster = context.cluster
|
||||
runner = Cli::RunAndLog.new(cluster)
|
||||
kubectl = K8::Kubectl.new(cluster.kubeconfig, runner)
|
||||
cluster.info("Checking if Nginx ingress controller is already installed...")
|
||||
|
||||
begin
|
||||
kubectl.("get deployment ingress-nginx-controller")
|
||||
cluster.info("Nginx ingress controller is already installed")
|
||||
rescue Cli::CommandFailedError => e
|
||||
cluster.info("Nginx ingress controller not detected, installing...")
|
||||
command = "bash #{Rails.root.join("resources", "k8", "scripts", "install_cert_manager.sh")}"
|
||||
kubectl.with_kube_config do |kubeconfig_file|
|
||||
begin
|
||||
runner.(command, envs: { "KUBECONFIG" => kubeconfig_file.path })
|
||||
cluster.info("Nginx ingress controller installed successfully")
|
||||
rescue Cli::CommandFailedError => e
|
||||
cluster.failed!
|
||||
cluster.info("Cert manager failed to install")
|
||||
context.fail!("Script failed with exit code #{exit_status.exitstatus}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
17
app/actions/clusters/is_ready.rb
Normal file
17
app/actions/clusters/is_ready.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
class Clusters::IsReady
|
||||
extend LightService::Action
|
||||
|
||||
expects :cluster
|
||||
|
||||
executed do |context|
|
||||
cluster = context.cluster
|
||||
client = K8::Client.new(cluster.kubeconfig)
|
||||
if client.can_connect?
|
||||
cluster.installing!
|
||||
cluster.info("Cluster is ready")
|
||||
else
|
||||
cluster.info("Cluster is not ready, retrying in 60 seconds...")
|
||||
context.fail!("Cluster is not ready")
|
||||
end
|
||||
end
|
||||
end
|
||||
19
app/actions/environment_variables/bulk_update.rb
Normal file
19
app/actions/environment_variables/bulk_update.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
class EnvironmentVariables::BulkUpdate
|
||||
extend LightService::Action
|
||||
|
||||
expects :project, :params
|
||||
|
||||
executed do |context|
|
||||
project = context.project
|
||||
# Delete all environment variables and create new ones
|
||||
|
||||
project.environment_variables.destroy_all
|
||||
|
||||
(context.params[:environment_variables] || []).each do |environment_variable_params|
|
||||
next if environment_variable_params[:name].blank?
|
||||
name = environment_variable_params[:name].strip.upcase
|
||||
value = environment_variable_params[:value].strip
|
||||
project.environment_variables.create!(name:, value:)
|
||||
end
|
||||
end
|
||||
end
|
||||
17
app/actions/projects/create.rb
Normal file
17
app/actions/projects/create.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Projects
|
||||
class Create
|
||||
extend LightService::Organizer
|
||||
|
||||
def self.call(project, params)
|
||||
with(project:, params:).reduce(
|
||||
Projects::CreateAssociations,
|
||||
Projects::ValidateGithubRepository,
|
||||
Projects::Save,
|
||||
Projects::RegisterGithubWebhook,
|
||||
Projects::DeployLatestCommit
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
11
app/actions/projects/create_associations.rb
Normal file
11
app/actions/projects/create_associations.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class Projects::CreateAssociations
|
||||
extend LightService::Action
|
||||
|
||||
expects :project, :params
|
||||
|
||||
executed do |context|
|
||||
if context.params[:cron_schedule].present?
|
||||
CronSchedule.create(schedule: context.params[:cron_schedule], project: context.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
20
app/actions/projects/deploy_latest_commit.rb
Normal file
20
app/actions/projects/deploy_latest_commit.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
class Projects::DeployLatestCommit
|
||||
extend LightService::Action
|
||||
|
||||
expects :project
|
||||
promises :project
|
||||
|
||||
executed do |context|
|
||||
# Fetch the latest commit from the default branch
|
||||
project = context.project
|
||||
client = Octokit::Client.new(access_token: project.user.github_access_token)
|
||||
commit = client.commits(project.repository_url).first
|
||||
|
||||
build = Build.create!(
|
||||
project: context.project,
|
||||
commit_sha: commit.sha,
|
||||
commit_message: commit.commit[:message]
|
||||
)
|
||||
Projects::BuildJob.perform_later(build)
|
||||
end
|
||||
end
|
||||
24
app/actions/projects/register_github_webhook.rb
Normal file
24
app/actions/projects/register_github_webhook.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
class Projects::RegisterGithubWebhook
|
||||
extend LightService::Action
|
||||
|
||||
expects :project
|
||||
promises :project
|
||||
|
||||
executed do |context|
|
||||
client = Octokit::Client.new(access_token: context.project.user.github_access_token)
|
||||
client.create_hook(
|
||||
context.project.repository_url,
|
||||
'web',
|
||||
{
|
||||
url: Rails.application.routes.url_helpers.inbound_webhooks_github_index_url,
|
||||
content_type: 'json',
|
||||
secret: ENV.fetch('OMNIAUTH_GITHUB_WEBHOOK_SECRET',
|
||||
Jumpstart::Omniauth.credentials_for(:github)[:webhook_secret])
|
||||
},
|
||||
{
|
||||
events: ['push'],
|
||||
active: true
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
10
app/actions/projects/save.rb
Normal file
10
app/actions/projects/save.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
class Projects::Save
|
||||
extend LightService::Action
|
||||
|
||||
expects :project
|
||||
promises :project
|
||||
|
||||
executed do |context|
|
||||
context.project.save!
|
||||
end
|
||||
end
|
||||
14
app/actions/projects/validate_github_repository.rb
Normal file
14
app/actions/projects/validate_github_repository.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class Projects::ValidateGithubRepository
|
||||
extend LightService::Action
|
||||
|
||||
expects :project
|
||||
promises :project
|
||||
|
||||
executed do |context|
|
||||
client = Octokit::Client.new(access_token: context.project.user.github_access_token)
|
||||
unless client.repository?(context.project.repository_url)
|
||||
context.project.errors.add(:repository_url, 'does not exist')
|
||||
context.fail_and_return!('Repository does not exist')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class ActionText::EncryptedRichTextsController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class ActionText::RichTextsController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class ActiveStorage::AttachmentsController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
module Madmin
|
||||
class ActiveStorage::BlobsController < Madmin::ResourceController
|
||||
def new
|
||||
super
|
||||
@record.assign_attributes(filename: "")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class ActiveStorage::VariantRecordsController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
4
app/controllers/madmin/announcements_controller.rb
Normal file
4
app/controllers/madmin/announcements_controller.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class AnnouncementsController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
22
app/controllers/madmin/application_controller.rb
Normal file
22
app/controllers/madmin/application_controller.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
module Madmin
|
||||
class ApplicationController < Madmin::BaseController
|
||||
before_action :authenticate_admin_user
|
||||
|
||||
def authenticate_admin_user
|
||||
# TODO: Add your authentication logic here
|
||||
|
||||
# For example, we could redirect if the user isn't an admin
|
||||
# redirect_to "/", alert: "Not authorized." unless user_signed_in? && current_user.admin?
|
||||
end
|
||||
|
||||
# Authenticate with Clearance
|
||||
# include Clearance::Controller
|
||||
# before_action :require_login
|
||||
|
||||
# Authenticate with Devise
|
||||
# before_action :authenticate_user!
|
||||
|
||||
# Authenticate with Basic Auth
|
||||
# http_basic_authenticate_with(name: Rails.application.credentials.admin_username, password: Rails.application.credentials.admin_password)
|
||||
end
|
||||
end
|
||||
4
app/controllers/madmin/noticed/events_controller.rb
Normal file
4
app/controllers/madmin/noticed/events_controller.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class Noticed::EventsController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class Noticed::NotificationsController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
4
app/controllers/madmin/services_controller.rb
Normal file
4
app/controllers/madmin/services_controller.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class ServicesController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
4
app/controllers/madmin/users_controller.rb
Normal file
4
app/controllers/madmin/users_controller.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
module Madmin
|
||||
class UsersController < Madmin::ResourceController
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,26 @@
|
||||
class ActionText::EncryptedRichTextResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :name
|
||||
attribute :body
|
||||
attribute :created_at, form: false
|
||||
attribute :updated_at, form: false
|
||||
attribute :embeds, index: false
|
||||
|
||||
# Associations
|
||||
attribute :record
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
26
app/madmin/resources/action_text/rich_text_resource.rb
Normal file
26
app/madmin/resources/action_text/rich_text_resource.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
class ActionText::RichTextResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :name
|
||||
attribute :body
|
||||
attribute :created_at, form: false
|
||||
attribute :updated_at, form: false
|
||||
attribute :embeds, index: false
|
||||
|
||||
# Associations
|
||||
attribute :record
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
24
app/madmin/resources/active_storage/attachment_resource.rb
Normal file
24
app/madmin/resources/active_storage/attachment_resource.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
class ActiveStorage::AttachmentResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :name
|
||||
attribute :created_at, form: false
|
||||
|
||||
# Associations
|
||||
attribute :record
|
||||
attribute :blob
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
33
app/madmin/resources/active_storage/blob_resource.rb
Normal file
33
app/madmin/resources/active_storage/blob_resource.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
class ActiveStorage::BlobResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :key
|
||||
attribute :filename
|
||||
attribute :content_type
|
||||
attribute :byte_size
|
||||
attribute :checksum
|
||||
attribute :created_at, form: false
|
||||
attribute :service_name
|
||||
attribute :analyzed
|
||||
attribute :identified
|
||||
attribute :composed
|
||||
attribute :preview_image, index: false
|
||||
|
||||
# Associations
|
||||
attribute :attachments
|
||||
attribute :variant_records
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
class ActiveStorage::VariantRecordResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :variation, index: false, show: false
|
||||
attribute :variation_confirmation, index: false, show: false
|
||||
attribute :image, index: false
|
||||
|
||||
# Associations
|
||||
attribute :blob
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
25
app/madmin/resources/announcement_resource.rb
Normal file
25
app/madmin/resources/announcement_resource.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
class AnnouncementResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :kind
|
||||
attribute :title
|
||||
attribute :published_at
|
||||
attribute :created_at, form: false
|
||||
attribute :updated_at, form: false
|
||||
|
||||
# Associations
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
28
app/madmin/resources/noticed/event_resource.rb
Normal file
28
app/madmin/resources/noticed/event_resource.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
class Noticed::EventResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :account_id
|
||||
attribute :type
|
||||
attribute :params
|
||||
attribute :created_at, form: false
|
||||
attribute :updated_at, form: false
|
||||
attribute :notifications_count, form: false
|
||||
|
||||
# Associations
|
||||
attribute :record
|
||||
attribute :notifications
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
28
app/madmin/resources/noticed/notification_resource.rb
Normal file
28
app/madmin/resources/noticed/notification_resource.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
class Noticed::NotificationResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :account_id
|
||||
attribute :type
|
||||
attribute :read_at
|
||||
attribute :seen_at
|
||||
attribute :created_at, form: false
|
||||
attribute :updated_at, form: false
|
||||
|
||||
# Associations
|
||||
attribute :event
|
||||
attribute :recipient
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
27
app/madmin/resources/service_resource.rb
Normal file
27
app/madmin/resources/service_resource.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
class ServiceResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :project_id
|
||||
attribute :service_type
|
||||
attribute :command
|
||||
attribute :name
|
||||
attribute :created_at, form: false
|
||||
attribute :updated_at, form: false
|
||||
|
||||
# Associations
|
||||
attribute :user
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
57
app/madmin/resources/user_resource.rb
Normal file
57
app/madmin/resources/user_resource.rb
Normal file
@@ -0,0 +1,57 @@
|
||||
class UserResource < Madmin::Resource
|
||||
# Attributes
|
||||
attribute :id, form: false
|
||||
attribute :email
|
||||
attribute :encrypted_password
|
||||
attribute :reset_password_token
|
||||
attribute :reset_password_sent_at
|
||||
attribute :remember_created_at
|
||||
attribute :confirmation_token
|
||||
attribute :confirmed_at
|
||||
attribute :confirmation_sent_at
|
||||
attribute :unconfirmed_email
|
||||
attribute :first_name
|
||||
attribute :last_name
|
||||
attribute :time_zone
|
||||
attribute :accepted_terms_at
|
||||
attribute :accepted_privacy_at
|
||||
attribute :announcements_read_at
|
||||
attribute :admin
|
||||
attribute :created_at, form: false
|
||||
attribute :updated_at, form: false
|
||||
attribute :invitation_token
|
||||
attribute :invitation_created_at
|
||||
attribute :invitation_sent_at
|
||||
attribute :invitation_accepted_at
|
||||
attribute :invitation_limit
|
||||
attribute :invited_by_type
|
||||
attribute :invited_by_id
|
||||
attribute :invitations_count, form: false
|
||||
attribute :preferred_language
|
||||
attribute :otp_required_for_login
|
||||
attribute :otp_secret
|
||||
attribute :last_otp_timestep
|
||||
attribute :otp_backup_codes
|
||||
attribute :preferences
|
||||
attribute :name
|
||||
attribute :avatar, index: false
|
||||
|
||||
# Associations
|
||||
attribute :notifications
|
||||
attribute :notification_mentions
|
||||
attribute :services
|
||||
|
||||
# Uncomment this to customize the display name of records in the admin area.
|
||||
# def self.display_name(record)
|
||||
# record.name
|
||||
# end
|
||||
|
||||
# Uncomment this to customize the default sort column and direction.
|
||||
# def self.default_sort_column
|
||||
# "created_at"
|
||||
# end
|
||||
#
|
||||
# def self.default_sort_direction
|
||||
# "desc"
|
||||
# end
|
||||
end
|
||||
@@ -1,6 +1,7 @@
|
||||
require 'sidekiq/web'
|
||||
|
||||
Rails.application.routes.draw do
|
||||
draw :madmin
|
||||
get '/privacy', to: 'home#privacy'
|
||||
get '/terms', to: 'home#terms'
|
||||
authenticate :user, lambda { |u| u.admin? } do
|
||||
|
||||
28
config/routes/madmin.rb
Normal file
28
config/routes/madmin.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
# Below are the routes for madmin
|
||||
namespace :madmin do
|
||||
namespace :action_text do
|
||||
resources :encrypted_rich_texts
|
||||
end
|
||||
namespace :action_text do
|
||||
resources :rich_texts
|
||||
end
|
||||
resources :announcements
|
||||
resources :services
|
||||
resources :users
|
||||
namespace :active_storage do
|
||||
resources :blobs
|
||||
end
|
||||
namespace :active_storage do
|
||||
resources :attachments
|
||||
end
|
||||
namespace :active_storage do
|
||||
resources :variant_records
|
||||
end
|
||||
namespace :noticed do
|
||||
resources :events
|
||||
end
|
||||
namespace :noticed do
|
||||
resources :notifications
|
||||
end
|
||||
root to: "dashboard#show"
|
||||
end
|
||||
122
db/schema.rb
generated
Normal file
122
db/schema.rb
generated
Normal file
@@ -0,0 +1,122 @@
|
||||
# This file is auto-generated from the current state of the database. Instead
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# This file is the source Rails uses to define your schema when running `bin/rails
|
||||
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
||||
# be faster and is potentially less error prone than running all of your
|
||||
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||
# migrations use external dependencies or application code.
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.2].define(version: 2024_09_25_205204) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
create_table "active_storage_attachments", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.string "record_type", null: false
|
||||
t.bigint "record_id", null: false
|
||||
t.bigint "blob_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
|
||||
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
|
||||
end
|
||||
|
||||
create_table "active_storage_blobs", force: :cascade do |t|
|
||||
t.string "key", null: false
|
||||
t.string "filename", null: false
|
||||
t.string "content_type"
|
||||
t.text "metadata"
|
||||
t.string "service_name", null: false
|
||||
t.bigint "byte_size", null: false
|
||||
t.string "checksum"
|
||||
t.datetime "created_at", null: false
|
||||
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
|
||||
end
|
||||
|
||||
create_table "active_storage_variant_records", force: :cascade do |t|
|
||||
t.bigint "blob_id", null: false
|
||||
t.string "variation_digest", null: false
|
||||
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
|
||||
end
|
||||
|
||||
create_table "announcements", force: :cascade do |t|
|
||||
t.datetime "published_at"
|
||||
t.string "announcement_type"
|
||||
t.string "name"
|
||||
t.text "description"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "friendly_id_slugs", force: :cascade do |t|
|
||||
t.string "slug", null: false
|
||||
t.integer "sluggable_id", null: false
|
||||
t.string "sluggable_type", limit: 50
|
||||
t.string "scope"
|
||||
t.datetime "created_at"
|
||||
t.index ["slug", "sluggable_type", "scope"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_scope", unique: true
|
||||
t.index ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type"
|
||||
t.index ["sluggable_type", "sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_type_and_sluggable_id"
|
||||
end
|
||||
|
||||
create_table "noticed_events", force: :cascade do |t|
|
||||
t.string "type"
|
||||
t.string "record_type"
|
||||
t.bigint "record_id"
|
||||
t.jsonb "params"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "notifications_count"
|
||||
t.index ["record_type", "record_id"], name: "index_noticed_events_on_record"
|
||||
end
|
||||
|
||||
create_table "noticed_notifications", force: :cascade do |t|
|
||||
t.string "type"
|
||||
t.bigint "event_id", null: false
|
||||
t.string "recipient_type", null: false
|
||||
t.bigint "recipient_id", null: false
|
||||
t.datetime "read_at", precision: nil
|
||||
t.datetime "seen_at", precision: nil
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["event_id"], name: "index_noticed_notifications_on_event_id"
|
||||
t.index ["recipient_type", "recipient_id"], name: "index_noticed_notifications_on_recipient"
|
||||
end
|
||||
|
||||
create_table "services", force: :cascade do |t|
|
||||
t.bigint "user_id", null: false
|
||||
t.string "provider"
|
||||
t.string "uid"
|
||||
t.string "access_token"
|
||||
t.string "access_token_secret"
|
||||
t.string "refresh_token"
|
||||
t.datetime "expires_at"
|
||||
t.text "auth"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["user_id"], name: "index_services_on_user_id"
|
||||
end
|
||||
|
||||
create_table "users", force: :cascade do |t|
|
||||
t.string "email", default: "", null: false
|
||||
t.string "encrypted_password", default: "", null: false
|
||||
t.string "reset_password_token"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.string "first_name"
|
||||
t.string "last_name"
|
||||
t.datetime "announcements_last_read_at"
|
||||
t.boolean "admin", default: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["email"], name: "index_users_on_email", unique: true
|
||||
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||
end
|
||||
|
||||
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "services", "users"
|
||||
end
|
||||
Reference in New Issue
Block a user