jumpstart

This commit is contained in:
Celina Lopez
2024-09-25 14:18:54 -07:00
parent 67dd26ca9d
commit e59ed8250a
40 changed files with 921 additions and 0 deletions

13
Gemfile
View File

@@ -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"

View File

@@ -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)

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -0,0 +1,10 @@
class Projects::Save
extend LightService::Action
expects :project
promises :project
executed do |context|
context.project.save!
end
end

View 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

View File

@@ -0,0 +1,4 @@
module Madmin
class ActionText::EncryptedRichTextsController < Madmin::ResourceController
end
end

View File

@@ -0,0 +1,4 @@
module Madmin
class ActionText::RichTextsController < Madmin::ResourceController
end
end

View File

@@ -0,0 +1,4 @@
module Madmin
class ActiveStorage::AttachmentsController < Madmin::ResourceController
end
end

View File

@@ -0,0 +1,8 @@
module Madmin
class ActiveStorage::BlobsController < Madmin::ResourceController
def new
super
@record.assign_attributes(filename: "")
end
end
end

View File

@@ -0,0 +1,4 @@
module Madmin
class ActiveStorage::VariantRecordsController < Madmin::ResourceController
end
end

View File

@@ -0,0 +1,4 @@
module Madmin
class AnnouncementsController < Madmin::ResourceController
end
end

View 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

View File

@@ -0,0 +1,4 @@
module Madmin
class Noticed::EventsController < Madmin::ResourceController
end
end

View File

@@ -0,0 +1,4 @@
module Madmin
class Noticed::NotificationsController < Madmin::ResourceController
end
end

View File

@@ -0,0 +1,4 @@
module Madmin
class ServicesController < Madmin::ResourceController
end
end

View File

@@ -0,0 +1,4 @@
module Madmin
class UsersController < Madmin::ResourceController
end
end

View File

@@ -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

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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
View 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
View 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