Class: ActiveCanvas::Setting

Inherits:
ApplicationRecord show all
Defined in:
app/models/active_canvas/setting.rb

Constant Summary collapse

ENCRYPTED_KEYS =

Keys that should be encrypted in the database

%w[
  ai_openai_api_key
  ai_anthropic_api_key
  ai_openrouter_api_key
].freeze
CSS_FRAMEWORKS =
{
  "tailwind" => {
    name: "Tailwind CSS",
    url: "https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4",
    type: :script
  },
  "bootstrap5" => {
    name: "Bootstrap 5",
    url: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css",
    type: :stylesheet
  },
  "custom" => {
    name: "Custom CSS (no framework)",
    url: nil,
    type: nil
  }
}.freeze
DEFAULT_TAILWIND_CONFIG =

Tailwind Configuration

{
  theme: {
    extend: {
      colors: {},
      fontFamily: {}
    }
  }
}.freeze

Class Method Summary collapse

Class Method Details

.ai_anthropic_api_keyObject



177
178
179
# File 'app/models/active_canvas/setting.rb', line 177

def ai_anthropic_api_key
  get("ai_anthropic_api_key")
end

.ai_anthropic_api_key=(key) ⇒ Object



181
182
183
# File 'app/models/active_canvas/setting.rb', line 181

def ai_anthropic_api_key=(key)
  set("ai_anthropic_api_key", key.presence)
end

.ai_connection_modeObject

AI Connection Mode



219
220
221
# File 'app/models/active_canvas/setting.rb', line 219

def ai_connection_mode
  get("ai_connection_mode") || "server"
end

.ai_connection_mode=(value) ⇒ Object



223
224
225
# File 'app/models/active_canvas/setting.rb', line 223

def ai_connection_mode=(value)
  set("ai_connection_mode", value.presence || "server")
end

.ai_default_image_modelObject



202
203
204
# File 'app/models/active_canvas/setting.rb', line 202

def ai_default_image_model
  get("ai_default_image_model") || "dall-e-3"
end

.ai_default_image_model=(model) ⇒ Object



206
207
208
# File 'app/models/active_canvas/setting.rb', line 206

def ai_default_image_model=(model)
  set("ai_default_image_model", model.presence)
end

.ai_default_text_modelObject

AI Default Models



194
195
196
# File 'app/models/active_canvas/setting.rb', line 194

def ai_default_text_model
  get("ai_default_text_model") || "gpt-4o-mini"
end

.ai_default_text_model=(model) ⇒ Object



198
199
200
# File 'app/models/active_canvas/setting.rb', line 198

def ai_default_text_model=(model)
  set("ai_default_text_model", model.presence)
end

.ai_default_vision_modelObject



210
211
212
# File 'app/models/active_canvas/setting.rb', line 210

def ai_default_vision_model
  get("ai_default_vision_model") || "gpt-4o"
end

.ai_default_vision_model=(model) ⇒ Object



214
215
216
# File 'app/models/active_canvas/setting.rb', line 214

def ai_default_vision_model=(model)
  set("ai_default_vision_model", model.presence)
end

.ai_image_enabled=(enabled) ⇒ Object



240
241
242
# File 'app/models/active_canvas/setting.rb', line 240

def ai_image_enabled=(enabled)
  set("ai_image_enabled", enabled.to_s)
end

.ai_image_enabled?Boolean

Returns:

  • (Boolean)


236
237
238
# File 'app/models/active_canvas/setting.rb', line 236

def ai_image_enabled?
  get("ai_image_enabled") != "false"
end

.ai_openai_api_keyObject

AI API Keys



169
170
171
# File 'app/models/active_canvas/setting.rb', line 169

def ai_openai_api_key
  get("ai_openai_api_key")
end

.ai_openai_api_key=(key) ⇒ Object



173
174
175
# File 'app/models/active_canvas/setting.rb', line 173

def ai_openai_api_key=(key)
  set("ai_openai_api_key", key.presence)
end

.ai_openrouter_api_keyObject



185
186
187
# File 'app/models/active_canvas/setting.rb', line 185

def ai_openrouter_api_key
  get("ai_openrouter_api_key")
end

.ai_openrouter_api_key=(key) ⇒ Object



189
190
191
# File 'app/models/active_canvas/setting.rb', line 189

def ai_openrouter_api_key=(key)
  set("ai_openrouter_api_key", key.presence)
end

.ai_screenshot_enabled=(enabled) ⇒ Object



248
249
250
# File 'app/models/active_canvas/setting.rb', line 248

def ai_screenshot_enabled=(enabled)
  set("ai_screenshot_enabled", enabled.to_s)
end

.ai_screenshot_enabled?Boolean

Returns:

  • (Boolean)


244
245
246
# File 'app/models/active_canvas/setting.rb', line 244

def ai_screenshot_enabled?
  get("ai_screenshot_enabled") != "false"
end

.ai_text_enabled=(enabled) ⇒ Object



232
233
234
# File 'app/models/active_canvas/setting.rb', line 232

def ai_text_enabled=(enabled)
  set("ai_text_enabled", enabled.to_s)
end

.ai_text_enabled?Boolean

AI Feature Toggles

Returns:

  • (Boolean)


228
229
230
# File 'app/models/active_canvas/setting.rb', line 228

def ai_text_enabled?
  get("ai_text_enabled") != "false"
end

.api_key_configured?(key) ⇒ Boolean

Check if an API key is configured (without revealing the value)

Returns:

  • (Boolean)


58
59
60
61
62
63
# File 'app/models/active_canvas/setting.rb', line 58

def api_key_configured?(key)
  setting = find_by(key: key)
  return false unless setting

  setting.encrypted_value.present? || setting.value.present?
end

.css_frameworkObject



132
133
134
# File 'app/models/active_canvas/setting.rb', line 132

def css_framework
  get("css_framework") || ActiveCanvas.config.css_framework.to_s
end

.css_framework=(framework) ⇒ Object



136
137
138
# File 'app/models/active_canvas/setting.rb', line 136

def css_framework=(framework)
  set("css_framework", framework.presence)
end

.css_framework_configObject



140
141
142
# File 'app/models/active_canvas/setting.rb', line 140

def css_framework_config
  CSS_FRAMEWORKS[css_framework] || CSS_FRAMEWORKS["custom"]
end

.css_framework_typeObject



148
149
150
# File 'app/models/active_canvas/setting.rb', line 148

def css_framework_type
  css_framework_config[:type]
end

.css_framework_urlObject



144
145
146
# File 'app/models/active_canvas/setting.rb', line 144

def css_framework_url
  css_framework_config[:url]
end

.get(key) ⇒ Object



31
32
33
34
35
36
37
38
39
40
# File 'app/models/active_canvas/setting.rb', line 31

def get(key)
  setting = find_by(key: key)
  return nil unless setting

  if ENCRYPTED_KEYS.include?(key.to_s) && setting.encrypted_value.present?
    decrypt_value(setting.encrypted_value)
  else
    setting.value
  end
end

.global_cssObject



152
153
154
# File 'app/models/active_canvas/setting.rb', line 152

def global_css
  get("global_css") || ""
end

.global_css=(css) ⇒ Object



156
157
158
# File 'app/models/active_canvas/setting.rb', line 156

def global_css=(css)
  set("global_css", css)
end

.global_jsObject



160
161
162
# File 'app/models/active_canvas/setting.rb', line 160

def global_js
  get("global_js") || ""
end

.global_js=(js) ⇒ Object



164
165
166
# File 'app/models/active_canvas/setting.rb', line 164

def global_js=(js)
  set("global_js", js)
end

.homepageObject



125
126
127
128
129
130
# File 'app/models/active_canvas/setting.rb', line 125

def homepage
  page_id = homepage_page_id
  return nil unless page_id&.positive?

  Page.published.find_by(id: page_id)
end

.homepage_page_idObject



117
118
119
# File 'app/models/active_canvas/setting.rb', line 117

def homepage_page_id
  get("homepage_page_id")&.to_i
end

.homepage_page_id=(page_id) ⇒ Object



121
122
123
# File 'app/models/active_canvas/setting.rb', line 121

def homepage_page_id=(page_id)
  set("homepage_page_id", page_id.presence)
end

.masked_api_key(key) ⇒ Object

Get a masked version of the API key for display (last 4 chars only)



66
67
68
69
70
71
# File 'app/models/active_canvas/setting.rb', line 66

def masked_api_key(key)
  value = get(key)
  return nil if value.blank?

  mask_value(value)
end

.set(key, value) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'app/models/active_canvas/setting.rb', line 42

def set(key, value)
  setting = find_or_initialize_by(key: key)

  if ENCRYPTED_KEYS.include?(key.to_s) && value.present?
    setting.encrypted_value = encrypt_value(value)
    setting.value = nil # Clear plain text value
  else
    setting.value = value
    setting.encrypted_value = nil if ENCRYPTED_KEYS.include?(key.to_s)
  end

  setting.save!
  value
end

.tailwind_compiled_mode?Boolean

Returns:

  • (Boolean)


262
263
264
# File 'app/models/active_canvas/setting.rb', line 262

def tailwind_compiled_mode?
  css_framework == "tailwind" && ActiveCanvas::TailwindCompiler.available?
end

.tailwind_configObject



266
267
268
269
270
271
272
273
# File 'app/models/active_canvas/setting.rb', line 266

def tailwind_config
  raw = get("tailwind_config")
  return DEFAULT_TAILWIND_CONFIG.deep_dup if raw.blank?

  JSON.parse(raw).deep_symbolize_keys
rescue JSON::ParserError
  DEFAULT_TAILWIND_CONFIG.deep_dup
end

.tailwind_config=(config) ⇒ Object



275
276
277
278
279
280
281
282
283
284
285
# File 'app/models/active_canvas/setting.rb', line 275

def tailwind_config=(config)
  value = case config
  when String
            config
  when Hash
            config.to_json
  else
            config.to_s
  end
  set("tailwind_config", value)
end

.tailwind_config_jsObject



287
288
289
# File 'app/models/active_canvas/setting.rb', line 287

def tailwind_config_js
  tailwind_config.to_json
end