Module: BetterAuth::Schema

Defined in:
lib/better_auth/schema.rb,
lib/better_auth/schema/sql.rb

Defined Under Namespace

Modules: SQL

Class Method Summary collapse

Class Method Details

.auth_tables(options) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/better_auth/schema.rb', line 9

def auth_tables(options)
  plugin_schema = plugin_tables(options)

  tables = {
    "user" => user_table(options, plugin_schema.delete("user")),
    "session" => session_table(options, plugin_schema.delete("session")),
    "account" => (options, plugin_schema.delete("account")),
    "verification" => verification_table(options, plugin_schema.delete("verification"))
  }

  tables.delete("session") if secondary_storage?(options) && !session_option(options, :store_session_in_database)
  tables.delete("verification") if secondary_storage?(options) && !verification_option(options, :store_in_database)
  tables.merge!(plugin_schema)
  tables["rateLimit"] = rate_limit_table(options) if rate_limit_option(options, :storage) == "database"
  ensure_id_fields!(tables)
  tables.sort_by { |_name, table| table[:order] || Float::INFINITY }.to_h
end

.migration_tables(options) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/better_auth/schema.rb', line 27

def migration_tables(options)
  tables = auth_tables(options)
  grouped = {}

  tables.each_with_index do |(logical_name, table), index|
    table_name = table.fetch(:model_name)
    target = grouped[table_name] ||= {
      model_name: table_name,
      fields: {},
      order: table[:order] || Float::INFINITY,
      source_order: index,
      logical_names: [],
      disable_migration: false
    }
    target[:order] = [target[:order], table[:order] || Float::INFINITY].min
    target[:source_order] = [target[:source_order], index].min
    target[:logical_names] << logical_name
    target[:disable_migration] ||= table[:disable_migration] == true

    table.fetch(:fields).each do |logical_field, attributes|
      column = attributes[:field_name] || physical_name(logical_field)
      physical_attributes = physical_field_attributes(logical_field, attributes, tables)
      merge_physical_field!(target, column, physical_attributes)
    end
  end

  grouped
    .reject { |_name, table| table[:disable_migration] }
    .sort_by { |_name, table| [table[:order], table[:source_order]] }
    .to_h do |name, table|
      [name, table.except(:source_order, :disable_migration)]
    end
end

.parse_output(options, model, data) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/better_auth/schema.rb', line 72

def parse_output(options, model, data)
  return nil unless data

  table = auth_tables(options).fetch(model.to_s)
  table[:fields].each_with_object({}) do |(field, attributes), result|
    next if attributes[:returned] == false && field != "id"
    next unless data.key?(field)

    result[field] = data[field]
  end.tap do |result|
    data.each { |key, value| result[key] = value unless result.key?(key) || table[:fields].key?(key) }
  end
rescue KeyError
  data
end

.parse_provider_profile_user_input(options, profile, action:) ⇒ Object

Raises:

  • (ArgumentError)


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/better_auth/schema.rb', line 88

def parse_provider_profile_user_input(options, profile, action:)
  action = action.to_sym
  raise ArgumentError, "action must be :create or :update" unless [:create, :update].include?(action)

  input = (profile || {}).each_with_object({}) do |(key, value), result|
    result[storage_key(key)] = value
  end
  core_fields = %w[id email emailVerified name image createdAt updatedAt]
  fields = auth_tables(options).fetch("user").fetch(:fields).except(*core_fields)

  fields.each_with_object({}) do |(field, attributes), result|
    provider_value_allowed = attributes[:input] != false && input.key?(field)
    if provider_value_allowed
      value = coerce_provider_profile_value(input[field], attributes)
      transform = attributes[:transform]
      value = transform.call(value) if transform.respond_to?(:call)
      validator = attributes[:validator]
      if validator.respond_to?(:call) && !validator.call(value)
        raise APIError.new("BAD_REQUEST", message: "#{field} is invalid")
      end
      result[field] = value
    elsif action == :create && attributes.key?(:default_value)
      default = attributes[:default_value]
      result[field] = default.respond_to?(:call) ? default.call : default
    elsif action == :create && attributes[:required]
      raise APIError.new("BAD_REQUEST", message: "#{field} is required")
    end
  end
end

.physical_name(value) ⇒ Object



405
406
407
# File 'lib/better_auth/schema.rb', line 405

private_class_method def self.physical_name(value)
  underscore(value.to_s)
end

.storage_field_name(options, model, field) ⇒ Object



66
67
68
69
70
# File 'lib/better_auth/schema.rb', line 66

def storage_field_name(options, model, field)
  table = auth_tables(options).fetch(model.to_s)
  data = table[:fields].fetch(field.to_s)
  data[:field_name] || field.to_s
end

.storage_key(value) ⇒ Object



401
402
403
# File 'lib/better_auth/schema.rb', line 401

private_class_method def self.storage_key(value)
  camelize_lower(value.to_s)
end

.storage_model_name(options, model) ⇒ Object



61
62
63
64
# File 'lib/better_auth/schema.rb', line 61

def storage_model_name(options, model)
  table = auth_tables(options).fetch(model.to_s)
  table[:model_name]
end