aven 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +35 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/stylesheets/aven/application.css +14 -0
  6. data/app/assets/stylesheets/aven/application.tailwind.css +7 -0
  7. data/app/assets/stylesheets/aven/tailwind.css +224 -0
  8. data/app/components/aven/application_view_component.rb +15 -0
  9. data/app/components/aven/views/admin/dashboard/index/component.html.erb +1 -0
  10. data/app/components/aven/views/admin/dashboard/index/component.rb +5 -0
  11. data/app/components/aven/views/static/index/component.html.erb +17 -0
  12. data/app/components/aven/views/static/index/component.rb +5 -0
  13. data/app/components/aven/views/static/index/controller.js +7 -0
  14. data/app/controllers/aven/admin/base.rb +16 -0
  15. data/app/controllers/aven/admin/dashboard_controller.rb +9 -0
  16. data/app/controllers/aven/application_controller.rb +5 -0
  17. data/app/controllers/aven/auth_controller.rb +64 -0
  18. data/app/controllers/aven/static_controller.rb +7 -0
  19. data/app/helpers/aven/application_helper.rb +20 -0
  20. data/app/javascript/sqema/application.js +3 -0
  21. data/app/javascript/sqema/controllers/application.js +5 -0
  22. data/app/javascript/sqema/controllers/index.js +11 -0
  23. data/app/jobs/aven/application_job.rb +4 -0
  24. data/app/mailers/aven/application_mailer.rb +6 -0
  25. data/app/models/aven/app_record.rb +76 -0
  26. data/app/models/aven/app_record_schema.rb +47 -0
  27. data/app/models/aven/application_record.rb +5 -0
  28. data/app/models/aven/log.rb +67 -0
  29. data/app/models/aven/loggable.rb +21 -0
  30. data/app/models/aven/user.rb +63 -0
  31. data/app/models/aven/workspace.rb +39 -0
  32. data/app/models/aven/workspace_role.rb +47 -0
  33. data/app/models/aven/workspace_user.rb +55 -0
  34. data/app/models/aven/workspace_user_role.rb +39 -0
  35. data/app/views/layouts/aven/admin.html.erb +16 -0
  36. data/app/views/layouts/aven/application.html.erb +18 -0
  37. data/config/importmap.rb +16 -0
  38. data/config/initializers/devise.rb +43 -0
  39. data/config/routes.rb +16 -0
  40. data/db/migrate/20251003090752_create_aven_users.rb +19 -0
  41. data/db/migrate/20251004182000_create_aven_workspaces.rb +14 -0
  42. data/db/migrate/20251004182010_create_aven_workspace_users.rb +12 -0
  43. data/db/migrate/20251004182020_create_aven_workspace_roles.rb +13 -0
  44. data/db/migrate/20251004182030_create_aven_workspace_user_roles.rb +12 -0
  45. data/db/migrate/20251004190000_create_aven_logs.rb +22 -0
  46. data/db/migrate/20251004190100_create_aven_app_record_schemas.rb +12 -0
  47. data/db/migrate/20251004190110_create_aven_app_records.rb +12 -0
  48. data/lib/aven/configuration.rb +35 -0
  49. data/lib/aven/engine.rb +44 -0
  50. data/lib/aven/version.rb +3 -0
  51. data/lib/aven.rb +6 -0
  52. data/lib/tasks/annotate_rb.rake +10 -0
  53. data/lib/tasks/sqema_tasks.rake +21 -0
  54. metadata +321 -0
@@ -0,0 +1,67 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: aven_logs
4
+ #
5
+ # id :bigint not null, primary key
6
+ # level :string default("info"), not null
7
+ # loggable_type :string not null
8
+ # message :text not null
9
+ # metadata :jsonb
10
+ # state :string
11
+ # state_machine :string
12
+ # created_at :datetime not null
13
+ # updated_at :datetime not null
14
+ # loggable_id :bigint not null
15
+ # run_id :string
16
+ # workspace_id :bigint not null
17
+ #
18
+ # Indexes
19
+ #
20
+ # idx_aven_logs_on_loggable_run_state_created_at (loggable_type,loggable_id,run_id,state,created_at)
21
+ # index_aven_logs_on_created_at (created_at)
22
+ # index_aven_logs_on_level (level)
23
+ # index_aven_logs_on_loggable (loggable_type,loggable_id)
24
+ # index_aven_logs_on_workspace_id (workspace_id)
25
+ #
26
+ # Foreign Keys
27
+ #
28
+ # fk_rails_... (workspace_id => aven_workspaces.id)
29
+ #
30
+ module Aven
31
+ class Log < ApplicationRecord
32
+ self.table_name = "aven_logs"
33
+
34
+ LEVELS = %w[debug info warn error fatal].freeze
35
+
36
+ belongs_to :loggable, polymorphic: true
37
+ belongs_to :workspace, class_name: "Aven::Workspace"
38
+
39
+ validates :message, presence: true
40
+ validates :level, inclusion: { in: LEVELS }
41
+
42
+ scope :by_level, ->(level) { where(level:) }
43
+ scope :recent, -> { order(created_at: :desc) }
44
+
45
+ before_validation :apply_loggable_context
46
+
47
+ private
48
+
49
+ def apply_loggable_context
50
+ owner = loggable
51
+ return unless owner
52
+
53
+ if respond_to?(:workspace_id) && workspace_id.blank?
54
+ if owner.is_a?(Aven::Workspace)
55
+ self.workspace = owner
56
+ elsif owner.respond_to?(:workspace)
57
+ self.workspace = owner.workspace
58
+ end
59
+ end
60
+
61
+ if respond_to?(:run_id) && run_id.blank? && owner.respond_to?(:_log_run_id)
62
+ self.run_id = owner._log_run_id
63
+ end
64
+ end
65
+ end
66
+ end
67
+
@@ -0,0 +1,21 @@
1
+ module Aven
2
+ module Loggable
3
+ def log!(message:, level: "info", metadata: nil, **extra)
4
+ attrs = {
5
+ message: message,
6
+ level: level,
7
+ metadata: metadata || {}
8
+ }
9
+
10
+ ws = is_a?(Aven::Workspace) ? self : workspace
11
+ attrs[:workspace] = ws
12
+
13
+ attrs[:run_id] = extra[:run_id] if extra.key?(:run_id)
14
+ attrs[:state] = extra[:state] if extra.key?(:state)
15
+ attrs[:state_machine] = extra[:state_machine] if extra.key?(:state_machine)
16
+
17
+ logs.create!(attrs)
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,63 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: aven_users
4
+ #
5
+ # id :bigint not null, primary key
6
+ # access_token :string
7
+ # admin :boolean default(FALSE), not null
8
+ # auth_tenant :string
9
+ # email :string default(""), not null
10
+ # encrypted_password :string default(""), not null
11
+ # remember_created_at :datetime
12
+ # reset_password_sent_at :datetime
13
+ # reset_password_token :string
14
+ # created_at :datetime not null
15
+ # updated_at :datetime not null
16
+ # remote_id :string
17
+ #
18
+ # Indexes
19
+ #
20
+ # index_aven_users_on_email_and_auth_tenant (email,auth_tenant) UNIQUE
21
+ # index_aven_users_on_reset_password_token (reset_password_token) UNIQUE
22
+ #
23
+ module Aven
24
+ class User < ApplicationRecord
25
+ devise(
26
+ :omniauthable,
27
+ omniauth_providers: Aven.configuration.auth.providers.map { |p| p[:provider] }
28
+ )
29
+
30
+ has_many :workspace_users, dependent: :destroy
31
+ has_many :workspaces, through: :workspace_users
32
+ has_many :workspace_user_roles, through: :workspace_users
33
+ has_many :workspace_roles, through: :workspace_user_roles
34
+
35
+ # has_many(:repos, class_name: UserRepo.name)
36
+ # has_many(:deployments)
37
+ # has_many(:strategies, foreign_key: :author_id, inverse_of: :author)
38
+ # has_many(:credentials, class_name: ProviderCredential.name)
39
+
40
+ validates :email, presence: true, uniqueness: { scope: :auth_tenant, case_sensitive: false }, format: { with: URI::MailTo::EMAIL_REGEXP }
41
+ validates :remote_id, uniqueness: { scope: :auth_tenant, case_sensitive: false }, allow_blank: true
42
+
43
+ encrypts(:access_token)
44
+
45
+ def self.create_from_omniauth!(request_env, auth_tenant)
46
+ user = request_env.dig("omniauth.auth")
47
+ remote_id = user["uid"]
48
+ email = user.dig("info", "email") || "#{SecureRandom.uuid}@aven.dev"
49
+
50
+ u = where(auth_tenant:, remote_id:).or(
51
+ where(auth_tenant:, email:)
52
+ ).first_or_initialize
53
+
54
+ u.auth_tenant = auth_tenant
55
+ u.remote_id = remote_id
56
+ u.email = email
57
+ u.access_token = user.dig("credentials", "token")
58
+ u.save!
59
+
60
+ u
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,39 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: aven_workspaces
4
+ #
5
+ # id :bigint not null, primary key
6
+ # description :text
7
+ # domain :string
8
+ # label :string
9
+ # slug :string
10
+ # created_at :datetime not null
11
+ # updated_at :datetime not null
12
+ #
13
+ # Indexes
14
+ #
15
+ # index_aven_workspaces_on_slug (slug) UNIQUE
16
+ #
17
+ module Aven
18
+ class Workspace < ApplicationRecord
19
+ self.table_name = "aven_workspaces"
20
+
21
+ has_many :workspace_users, class_name: "Aven::WorkspaceUser", dependent: :destroy
22
+ has_many :users, through: :workspace_users, class_name: "Aven::User"
23
+ has_many :workspace_roles, class_name: "Aven::WorkspaceRole", dependent: :destroy
24
+ has_many :workspace_user_roles, through: :workspace_roles, class_name: "Aven::WorkspaceUserRole"
25
+
26
+ validates :slug, uniqueness: true, allow_blank: true
27
+ validates :label, length: { maximum: 255 }, allow_blank: true
28
+ validates :description, length: { maximum: 1000 }, allow_blank: true
29
+
30
+ before_validation :generate_slug, if: -> { slug.blank? && label.present? }
31
+
32
+ private
33
+
34
+ def generate_slug
35
+ self.slug = label.parameterize if label.present?
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,47 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: aven_workspace_roles
4
+ #
5
+ # id :bigint not null, primary key
6
+ # description :string
7
+ # label :string not null
8
+ # created_at :datetime not null
9
+ # updated_at :datetime not null
10
+ # workspace_id :bigint
11
+ #
12
+ # Indexes
13
+ #
14
+ # idx_aven_workspace_roles_on_ws_label (workspace_id,label) UNIQUE
15
+ # index_aven_workspace_roles_on_workspace_id (workspace_id)
16
+ #
17
+ # Foreign Keys
18
+ #
19
+ # fk_rails_... (workspace_id => aven_workspaces.id)
20
+ #
21
+ module Aven
22
+ class WorkspaceRole < ApplicationRecord
23
+ self.table_name = "aven_workspace_roles"
24
+
25
+ belongs_to :workspace, class_name: "Aven::Workspace"
26
+ has_many :workspace_user_roles, class_name: "Aven::WorkspaceUserRole", dependent: :destroy
27
+ has_many :workspace_users, through: :workspace_user_roles, class_name: "Aven::WorkspaceUser"
28
+ has_many :users, through: :workspace_users, class_name: "Aven::User"
29
+
30
+ validates :label, presence: true
31
+ validates :label, uniqueness: { scope: :workspace_id }
32
+
33
+ PREDEFINED_ROLES = %w[owner admin member viewer].freeze
34
+
35
+ scope :predefined, -> { where(label: PREDEFINED_ROLES) }
36
+ scope :custom, -> { where.not(label: PREDEFINED_ROLES) }
37
+
38
+ def predefined?
39
+ PREDEFINED_ROLES.include?(label)
40
+ end
41
+
42
+ def custom?
43
+ !predefined?
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,55 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: aven_workspace_users
4
+ #
5
+ # id :bigint not null, primary key
6
+ # created_at :datetime not null
7
+ # updated_at :datetime not null
8
+ # user_id :bigint not null
9
+ # workspace_id :bigint not null
10
+ #
11
+ # Indexes
12
+ #
13
+ # idx_aven_workspace_users_on_user_workspace (user_id,workspace_id) UNIQUE
14
+ # index_aven_workspace_users_on_user_id (user_id)
15
+ # index_aven_workspace_users_on_workspace_id (workspace_id)
16
+ #
17
+ # Foreign Keys
18
+ #
19
+ # fk_rails_... (user_id => aven_users.id)
20
+ # fk_rails_... (workspace_id => aven_workspaces.id)
21
+ #
22
+ module Aven
23
+ class WorkspaceUser < ApplicationRecord
24
+ self.table_name = "aven_workspace_users"
25
+
26
+ belongs_to :user, class_name: "Aven::User"
27
+ belongs_to :workspace, class_name: "Aven::Workspace"
28
+
29
+ has_many :workspace_user_roles, class_name: "Aven::WorkspaceUserRole", dependent: :destroy
30
+ has_many :workspace_roles, through: :workspace_user_roles, class_name: "Aven::WorkspaceRole"
31
+
32
+ validates :user_id, uniqueness: { scope: :workspace_id }
33
+
34
+ def roles
35
+ workspace_roles.pluck(:label)
36
+ end
37
+
38
+ def has_role?(role_label)
39
+ workspace_roles.exists?(label: role_label)
40
+ end
41
+
42
+ def add_role(role_label)
43
+ role = workspace.workspace_roles.find_or_create_by!(label: role_label)
44
+ workspace_user_roles.find_or_create_by!(workspace_role: role)
45
+ end
46
+
47
+ def remove_role(role_label)
48
+ role = workspace.workspace_roles.find_by(label: role_label)
49
+ return unless role
50
+
51
+ workspace_user_roles.where(workspace_role: role).destroy_all
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,39 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: aven_workspace_user_roles
4
+ #
5
+ # id :bigint not null, primary key
6
+ # created_at :datetime not null
7
+ # updated_at :datetime not null
8
+ # workspace_role_id :bigint
9
+ # workspace_user_id :bigint
10
+ #
11
+ # Indexes
12
+ #
13
+ # idx_aven_ws_user_roles_on_role_user (workspace_role_id,workspace_user_id) UNIQUE
14
+ # index_aven_workspace_user_roles_on_workspace_role_id (workspace_role_id)
15
+ # index_aven_workspace_user_roles_on_workspace_user_id (workspace_user_id)
16
+ #
17
+ # Foreign Keys
18
+ #
19
+ # fk_rails_... (workspace_role_id => aven_workspace_roles.id)
20
+ # fk_rails_... (workspace_user_id => aven_workspace_users.id)
21
+ #
22
+ module Aven
23
+ class WorkspaceUserRole < ApplicationRecord
24
+ self.table_name = "aven_workspace_user_roles"
25
+
26
+ belongs_to :workspace_user, class_name: "Aven::WorkspaceUser"
27
+ belongs_to :workspace_role, class_name: "Aven::WorkspaceRole"
28
+
29
+ validates :workspace_user_id, uniqueness: { scope: :workspace_role_id }
30
+
31
+ delegate :workspace, :label, :description, to: :workspace_role
32
+ delegate :user, to: :workspace_user
33
+ delegate :email, :username, to: :user
34
+
35
+ scope :for_workspace, ->(workspace) { joins(:workspace_role).where(aven_workspace_roles: { workspace_id: workspace.id }) }
36
+ scope :with_role, ->(role_label) { joins(:workspace_role).where(aven_workspace_roles: { label: role_label }) }
37
+ end
38
+ end
39
+
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html class='bg-slate-50'>
3
+ <head>
4
+ <title>Aven</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+ <%= yield :head %>
8
+ <script src="https://cdn.jsdelivr.net/npm/@tailwindplus/elements@1" type="module"></script>
9
+ <%= stylesheet_link_tag "aven/application", media: "all" %>
10
+ <%= stylesheet_link_tag "aven/tailwind", media: "all" %>
11
+ <%= javascript_importmap_tags "aven/application", importmap: Aven.importmap %>
12
+ </head>
13
+ <body class='bg-slate-100'>
14
+ <%= yield %>
15
+ </body>
16
+ </html>
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Aven</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+ <%= yield :head %>
8
+ <script src="https://cdn.jsdelivr.net/npm/@tailwindplus/elements@1" type="module"></script>
9
+ <%= stylesheet_link_tag "aeros/application", media: "all" %>
10
+ <%= stylesheet_link_tag "aeros/tailwind", media: "all" %>
11
+ <%= stylesheet_link_tag "aven/application", media: "all" %>
12
+ <%= stylesheet_link_tag "aven/tailwind", media: "all" %>
13
+ <%= javascript_importmap_tags "aven/application", importmap: Aven.importmap %>
14
+ </head>
15
+ <body>
16
+ <%= yield %>
17
+ </body>
18
+ </html>
@@ -0,0 +1,16 @@
1
+ # Engine's own importmap configuration
2
+ pin "@hotwired/turbo-rails", to: "turbo.min.js"
3
+ pin "aven/application"
4
+ pin "@hotwired/stimulus", to: "stimulus.min.js"
5
+ pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
6
+
7
+ pin_all_from(
8
+ Aven::Engine.root.join("app/javascript/aven/controllers"),
9
+ under: "aven/controllers",
10
+ )
11
+
12
+ pin_all_from(
13
+ Aven::Engine.root.join("app/components/aven"),
14
+ under: "aven/components",
15
+ to: "aven"
16
+ )
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ Devise.setup do |config|
4
+ # The secret key used by Devise will be taken from Rails credentials
5
+ # config.secret_key = Rails.application.credentials.secret_key_base
6
+
7
+ # ==> Mailer Configuration
8
+ config.mailer_sender = "noreply@nvoi.io"
9
+
10
+ # ==> ORM configuration
11
+ require "devise/orm/active_record"
12
+
13
+ # ==> Configuration for any authentication mechanism
14
+ # Configure which keys are used when authenticating a user
15
+ config.authentication_keys = [:email]
16
+
17
+ # ==> OAuth configuration
18
+ # GitHub OAuth will be configured with credentials from the host app
19
+ # The engine will receive credentials via configuration
20
+
21
+ # Configure sign out to use GET request (required for some OAuth providers)
22
+ config.sign_out_via = :get
23
+
24
+ # ==> Scopes configuration
25
+ config.scoped_views = true
26
+
27
+ # ==> Navigation configuration
28
+ config.navigational_formats = ['*/*', :html, :turbo_stream]
29
+
30
+ # The default HTTP method used to sign out a resource. Default is :delete.
31
+ config.sign_out_via = %i[delete get]
32
+
33
+ # ==> Mountable engine configuration
34
+ # Set parent controller for the engine
35
+ config.parent_controller = 'Aven::ApplicationController'
36
+
37
+ # ==> OmniAuth
38
+ # OmniAuth providers are configured dynamically via Aven.configuration
39
+ # in the engine initializer (lib/aven/engine.rb)
40
+
41
+ # Configure OmniAuth to work with the engine's mounted path
42
+ # config.omniauth_path_prefix = '/aven/users/auth'
43
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,16 @@
1
+ Aven::Engine.routes.draw do
2
+ devise_for(
3
+ :users, class_name: "Aven::User", module: :devise, format: false,
4
+ controllers: { omniauth_callbacks: "aven/auth" }
5
+ )
6
+
7
+ # Additional auth routes
8
+ get("/auth/:provider/authenticate", to: "auth#authenticate", as: :authenticate)
9
+ get("/auth/logout", to: "auth#logout", as: :logout)
10
+
11
+ namespace(:admin) do
12
+ root(to: "dashboard#index")
13
+ end
14
+
15
+ root(to: "static#index")
16
+ end
@@ -0,0 +1,19 @@
1
+ class CreateAvenUsers < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :aven_users do |t|
4
+ t.string(:email, default: "", null: false)
5
+ t.string(:encrypted_password, default: "", null: false)
6
+ t.string(:reset_password_token)
7
+ t.datetime(:reset_password_sent_at)
8
+ t.datetime(:remember_created_at)
9
+ t.string(:auth_tenant)
10
+ t.string(:remote_id)
11
+ t.string(:access_token)
12
+ t.boolean(:admin, default: false, null: false)
13
+ t.timestamps
14
+ end
15
+
16
+ add_index(:aven_users, [:email, :auth_tenant], unique: true)
17
+ add_index(:aven_users, :reset_password_token, unique: true)
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ class CreateAvenWorkspaces < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :aven_workspaces do |t|
4
+ t.string :label
5
+ t.string :slug
6
+ t.text :description
7
+ t.string :domain
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :aven_workspaces, :slug, unique: true
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ class CreateAvenWorkspaceUsers < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :aven_workspace_users do |t|
4
+ t.references :user, null: false, foreign_key: { to_table: :aven_users }
5
+ t.references :workspace, null: false, foreign_key: { to_table: :aven_workspaces }
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :aven_workspace_users, [:user_id, :workspace_id], unique: true, name: "idx_aven_workspace_users_on_user_workspace"
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ class CreateAvenWorkspaceRoles < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :aven_workspace_roles do |t|
4
+ t.references :workspace, foreign_key: { to_table: :aven_workspaces }
5
+ t.string :label, null: false
6
+ t.string :description
7
+
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :aven_workspace_roles, [:workspace_id, :label], unique: true, name: "idx_aven_workspace_roles_on_ws_label"
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ class CreateAvenWorkspaceUserRoles < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :aven_workspace_user_roles do |t|
4
+ t.references :workspace_role, foreign_key: { to_table: :aven_workspace_roles }
5
+ t.references :workspace_user, foreign_key: { to_table: :aven_workspace_users }
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :aven_workspace_user_roles, [:workspace_role_id, :workspace_user_id], unique: true, name: "idx_aven_ws_user_roles_on_role_user"
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ class CreateAvenLogs < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :aven_logs do |t|
4
+ t.string :level, null: false, default: "info"
5
+ t.string :loggable_type, null: false
6
+ t.bigint :loggable_id, null: false
7
+ t.text :message, null: false
8
+ t.jsonb :metadata
9
+ t.string :state
10
+ t.string :state_machine
11
+ t.string :run_id
12
+ t.references :workspace, null: false, foreign_key: { to_table: :aven_workspaces }
13
+ t.timestamps
14
+ end
15
+
16
+ add_index :aven_logs, :created_at
17
+ add_index :aven_logs, :level
18
+ add_index :aven_logs, [:loggable_type, :loggable_id], name: "index_aven_logs_on_loggable"
19
+ add_index :aven_logs, [:loggable_type, :loggable_id, :run_id, :state, :created_at], name: "idx_aven_logs_on_loggable_run_state_created_at"
20
+ end
21
+ end
22
+
@@ -0,0 +1,12 @@
1
+ class CreateAvenAppRecordSchemas < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :aven_app_record_schemas do |t|
4
+ t.jsonb :schema, null: false
5
+ t.references :workspace, null: false, foreign_key: { to_table: :aven_workspaces }
6
+ t.timestamps
7
+ end
8
+
9
+ add_index :aven_app_record_schemas, :schema, using: :gin
10
+ end
11
+ end
12
+
@@ -0,0 +1,12 @@
1
+ class CreateAvenAppRecords < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :aven_app_records do |t|
4
+ t.jsonb :data, null: false
5
+ t.references :app_record_schema, null: false, foreign_key: { to_table: :aven_app_record_schemas }
6
+ t.timestamps
7
+ end
8
+
9
+ add_index :aven_app_records, :data, using: :gin
10
+ end
11
+ end
12
+
@@ -0,0 +1,35 @@
1
+ module Aven
2
+ class Configuration
3
+ attr_reader :auth
4
+ attr_accessor :authenticated_root_path
5
+
6
+ def initialize
7
+ @auth = Auth.new
8
+ @authenticated_root_path = nil
9
+ end
10
+
11
+ class Auth
12
+ attr_reader :providers
13
+
14
+ def initialize
15
+ @providers = []
16
+ end
17
+
18
+ def add(provider, *args, **options)
19
+ @providers << { provider: provider, args: args, options: options }
20
+ end
21
+ end
22
+ end
23
+
24
+ class << self
25
+ attr_writer :configuration
26
+
27
+ def configuration
28
+ @configuration ||= Configuration.new
29
+ end
30
+
31
+ def configure
32
+ yield(configuration)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ require "devise"
2
+ require "omniauth"
3
+ require "omniauth/rails_csrf_protection"
4
+ require "repost"
5
+ require "importmap-rails"
6
+ require "view_component-contrib"
7
+ require "dry-effects"
8
+ require "tailwind_merge"
9
+ require "json_skooma"
10
+ require "aeros"
11
+
12
+ module Aven
13
+ class << self
14
+ attr_accessor :importmap
15
+ end
16
+
17
+ class Engine < ::Rails::Engine
18
+ isolate_namespace Aven
19
+
20
+ Aeros::EngineHelpers.setup_assets(self, namespace: Aven)
21
+ Aeros::EngineHelpers.setup_importmap(self, namespace: Aven)
22
+
23
+ # Ensure migrations are available to the host app
24
+ initializer "aven.migrations" do
25
+ unless Rails.env.test? || Rails.application.class.module_parent_name == "Dummy"
26
+ config.paths["db/migrate"].expanded.each do |expanded_path|
27
+ Rails.application.config.paths["db/migrate"] << expanded_path
28
+ end
29
+ end
30
+ end
31
+
32
+ initializer "aven.devise", after: :load_config_initializers do
33
+ # Configure OmniAuth providers from Aven configuration
34
+ providers = Aven.configuration.auth.providers
35
+
36
+ # Add OmniAuth middleware
37
+ Rails.application.config.middleware.use OmniAuth::Builder do
38
+ providers.each do |provider_config|
39
+ provider provider_config[:provider], *provider_config[:args], **provider_config[:options]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module Aven
2
+ VERSION = "0.0.1"
3
+ end
data/lib/aven.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "aven/version"
2
+ require "aven/configuration"
3
+ require "aven/engine"
4
+
5
+ module Aven
6
+ end