atomic_admin 2.1.0 → 2.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a60af477fc58d9334de687508e1eb0ef56f2bef8ec96e5fabd726133e0934b2
4
- data.tar.gz: f17e627608ebc01b5b9281cff0af01ebf17d10d06cd4db62744d833fc4b790e9
3
+ metadata.gz: 9fcb9d4217719b4cf883630148626b1a212bdd1512bec4c3aa7a6584abc1a253
4
+ data.tar.gz: db0ae794f2c1f4ff8de5e896ab806193d2c7ce1e0f3c5d1e24c920f35b8cd9d2
5
5
  SHA512:
6
- metadata.gz: 1ca007af30664fd22c363cff5a2e76b8bf818928d9100a9b43af07dcf1ac18a93034d0ec3f89107226ac9e1755e0ec055167f0680d607b0f4bc0eadbeaaa96fb
7
- data.tar.gz: f15c1ea152ef5869f3465a1a47bb36dfa7685808cffad13989c42b34d1e8368a984116cf00d5d703202ee4c671a73bd80afbe4fd526a1925b4b78cc57e5237c3
6
+ metadata.gz: 2a262801ae054590fd97e3335604ccec397537bd04c04474b2d73ae39a5311c28bff4ef8f72e6b3eddda20801b9b3a97f5eebdc46c7c1ce30d48ecf2f3d9e8cf
7
+ data.tar.gz: 03ce10d91f332d48af7bf3686baed86b8bcbdce48d9127c4c8b50716dd9fbb4bd48c22284f1c387296c68ba0f59404c4cf4de0cee54d52407545051be068173d
@@ -61,8 +61,12 @@ module AtomicAdmin::V1
61
61
 
62
62
  def destroy
63
63
  instance = ApplicationInstance.find(params[:id])
64
- instance.destroy
65
- render json: { success: true }
64
+
65
+ if destroy_instance(instance)
66
+ render json: { success: true }
67
+ else
68
+ render json: { errors: instance.errors }, status: 422
69
+ end
66
70
  end
67
71
 
68
72
  def interactions
@@ -71,8 +75,21 @@ module AtomicAdmin::V1
71
75
  render json: { interactions: interactions }
72
76
  end
73
77
 
78
+ # Host apps store the tenant on an application instance in one of two ways:
79
+ # older schemas have a `tenant` string column, newer ones have `tenant_key`
80
+ # plus a `tenant` association. Returns nil if the app has neither, in which
81
+ # case we skip stats rather than raising.
82
+ def tenant_column
83
+ return @tenant_column if defined?(@tenant_column)
84
+
85
+ columns = ApplicationInstance.column_names
86
+ @tenant_column = ["tenant", "tenant_key"].find { |column| columns.include?(column) }&.to_sym
87
+ end
88
+
74
89
  def get_stats_for_instances(instances)
75
- tenants = instances.pluck(:tenant)
90
+ return {} if tenant_column.nil?
91
+
92
+ tenants = instances.pluck(tenant_column)
76
93
  stats = {}
77
94
  stats[:errors] = RequestStatistic.total_errors_grouped(tenants) if defined?(RequestStatistic)
78
95
  stats[:unique_users] = CachedUniqueUsersByContractDate.unique_users_by_contract_date(instances) if defined?(CachedUniqueUsersByContractDate)
@@ -82,12 +99,15 @@ module AtomicAdmin::V1
82
99
  end
83
100
 
84
101
  def request_stats(instance)
85
- tenant = instance.tenant
102
+ tenant = instance[tenant_column] if tenant_column
86
103
 
87
104
  {
88
105
  unique_users_in_contract: @stats.dig(:unique_users, tenant) || 0,
106
+ # total_errors_grouped returns one tenant => count hash per window,
107
+ # ordered [today, 7 days, 30 days, 365 days]. These are array indexes,
108
+ # not day counts.
89
109
  day_1_errors: @stats.dig(:errors, 0, tenant) || 0,
90
- day_7_errors: @stats.dig(:errors, 7, tenant) || 0,
110
+ day_7_errors: @stats.dig(:errors, 1, tenant) || 0,
91
111
  max_users_month: @stats.dig(:max_users_month, tenant) || 0,
92
112
  }
93
113
  end
@@ -109,6 +129,33 @@ module AtomicAdmin::V1
109
129
 
110
130
  protected
111
131
 
132
+ # Deletes an application instance.
133
+ #
134
+ # Host apps whose ApplicationInstance implements soft-delete semantics get
135
+ # them automatically. This matters because a hard destroy strands the
136
+ # Apartment tenant schema along with any tenant-keyed data (request
137
+ # statistics and the like), and removes the only row naming that tenant --
138
+ # which hides it from reapers that discover tenants by grouping
139
+ # ApplicationInstance rows, making the orphan permanent rather than delayed.
140
+ #
141
+ # Override this method for anything more involved, such as notifying an
142
+ # external service before deleting.
143
+ #
144
+ # Returns truthy on success. Note that #soft_delete is typically implemented
145
+ # with #update, so it runs validations: an instance that is invalid for
146
+ # unrelated reasons will return false here rather than being deleted.
147
+ def destroy_instance(instance)
148
+ return instance.soft_delete if instance.respond_to?(:soft_delete)
149
+
150
+ Rails.logger.warn(
151
+ "AtomicAdmin: #{instance.class} does not respond to #soft_delete, falling back to a hard " \
152
+ "destroy. This may orphan the tenant schema and tenant-keyed data. Define " \
153
+ "#soft_delete on #{instance.class} to opt into soft deletion.",
154
+ )
155
+
156
+ instance.destroy
157
+ end
158
+
112
159
  def sortable_columns
113
160
  [
114
161
  "created_at",
@@ -140,7 +187,7 @@ module AtomicAdmin::V1
140
187
  end
141
188
 
142
189
  def create_params
143
- params.require(:application_instance).except(:is_paid, :lti_config_xml, :site, :application).permit!
190
+ params.require(:application_instance).except(:is_paid, :lti_config_xml, :site, :application, :request_stats).permit!
144
191
  end
145
192
 
146
193
  def update_params
@@ -21,8 +21,12 @@ module AtomicAdmin::V1
21
21
 
22
22
  def destroy
23
23
  install = find_install
24
- install.destroy
25
- render json: install
24
+
25
+ if install.destroy
26
+ render json: install
27
+ else
28
+ render json: { errors: install.errors }, status: 422
29
+ end
26
30
  end
27
31
 
28
32
  protected
@@ -29,8 +29,12 @@ module AtomicAdmin::V1
29
29
 
30
30
  def destroy
31
31
  platform = find_platform
32
- platform.destroy
33
- render json: platform
32
+
33
+ if platform.destroy
34
+ render json: platform
35
+ else
36
+ render json: { errors: platform.errors }, status: 422
37
+ end
34
38
  end
35
39
 
36
40
  protected
@@ -24,8 +24,12 @@ module AtomicAdmin::V1
24
24
 
25
25
  def destroy
26
26
  @site = Site.find(params[:id])
27
- @site.destroy!
28
- render json: { site: json_for(@site) }
27
+
28
+ if @site.destroy
29
+ render json: { site: json_for(@site) }
30
+ else
31
+ render json: { errors: @site.errors }, status: 422
32
+ end
29
33
  end
30
34
 
31
35
  protected
@@ -29,8 +29,12 @@ module AtomicAdmin::V1
29
29
 
30
30
  def destroy
31
31
  pinned_client_id = find_pinned_client_id
32
- pinned_client_id.destroy
33
- render json: { pinned_client_id: pinned_client_id }
32
+
33
+ if pinned_client_id.destroy
34
+ render json: { pinned_client_id: pinned_client_id }
35
+ else
36
+ render json: { errors: pinned_client_id.errors }, status: 422
37
+ end
34
38
  end
35
39
 
36
40
  protected
@@ -26,8 +26,12 @@ module AtomicAdmin::V1
26
26
 
27
27
  def destroy
28
28
  deployment = find_deployment
29
- deployment.destroy
30
- render json: { deployment: deployment }
29
+
30
+ if deployment.destroy
31
+ render json: { deployment: deployment }
32
+ else
33
+ render json: { errors: deployment.errors }, status: 422
34
+ end
31
35
  end
32
36
 
33
37
  protected
@@ -34,8 +34,12 @@ module AtomicAdmin::V1
34
34
 
35
35
  def destroy
36
36
  pinned_platform_guid = find_pinned_platform_guid
37
- pinned_platform_guid.destroy
38
- render json: { pinned_platform_guid: pinned_platform_guid }
37
+
38
+ if pinned_platform_guid.destroy
39
+ render json: { pinned_platform_guid: pinned_platform_guid }
40
+ else
41
+ render json: { errors: pinned_platform_guid.errors }, status: 422
42
+ end
39
43
  end
40
44
 
41
45
  protected
@@ -1,3 +1,3 @@
1
1
  module AtomicAdmin
2
- VERSION = "2.1.0".freeze
2
+ VERSION = "2.1.2".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atomic_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Benoit
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-06-16 00:00:00.000000000 Z
12
+ date: 2026-07-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -180,7 +180,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
180
  - !ruby/object:Gem::Version
181
181
  version: '0'
182
182
  requirements: []
183
- rubygems_version: 3.4.10
183
+ rubygems_version: 3.5.22
184
184
  signing_key:
185
185
  specification_version: 4
186
186
  summary: Engine to provide apis that power the Atomic Jolt admin app