16349: Set time zone to UTC at db connection level.
authorTom Clegg <tom@tomclegg.ca>
Wed, 29 Apr 2020 19:37:32 +0000 (15:37 -0400)
committerTom Clegg <tom@tomclegg.ca>
Wed, 29 Apr 2020 19:37:32 +0000 (15:37 -0400)
This covers the trash time comparisons in materialized_permission_view
as well as explicit uses of CURRENT_TIMESTAMP in Rails queries.

Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@tomclegg.ca>

services/api/app/controllers/application_controller.rb
services/api/app/models/api_client_authorization.rb
services/api/config/initializers/time_zone.rb [new file with mode: 0644]
services/api/lib/create_superuser_token.rb
services/api/test/unit/container_test.rb
services/api/test/unit/time_zone_test.rb [new file with mode: 0644]

index c7d7ad8148246f883d87b37840da5ed3610946d1..83a233cd54681b18b9fb6bb12c72642a2e95cae4 100644 (file)
@@ -386,8 +386,8 @@ class ApplicationController < ActionController::Base
       @read_auths += ApiClientAuthorization
         .includes(:user)
         .where('api_token IN (?) AND
-                (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP AT TIME ZONE ?)',
-               secrets, 'UTC')
+                (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)',
+               secrets)
         .to_a
     end
     @read_auths.select! { |auth| auth.scopes_allow_request? request }
index a80865348089a324095c4a692c96f207cfeed274..5386cb119a0c9cadbcc2cc0d8edfc5cadd8a1e76 100644 (file)
@@ -158,7 +158,7 @@ class ApiClientAuthorization < ArvadosModel
       # fast path: look up the token in the local database
       auth = ApiClientAuthorization.
              includes(:user, :api_client).
-             where('uuid=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP AT TIME ZONE ?)', token_uuid, 'UTC').
+             where('uuid=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP)', token_uuid).
              first
       if auth && auth.user &&
          (secret == auth.api_token ||
@@ -280,7 +280,7 @@ class ApiClientAuthorization < ArvadosModel
       # token is not a 'v2' token
       auth = ApiClientAuthorization.
                includes(:user, :api_client).
-               where('api_token=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP AT TIME ZONE ?)', token, 'UTC').
+               where('api_token=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP)', token).
                first
       if auth && auth.user
         return auth
diff --git a/services/api/config/initializers/time_zone.rb b/services/api/config/initializers/time_zone.rb
new file mode 100644 (file)
index 0000000..cedd8f3
--- /dev/null
@@ -0,0 +1,15 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+ActiveRecord::Base.connection.class.set_callback :checkout, :after do
+  # If the database connection is in a time zone other than UTC,
+  # "timestamp" values don't behave as desired.
+  #
+  # For example, ['select now() > ?', Time.now] returns true in time
+  # zones +0100 and UTC (which makes sense since Time.now is evaluated
+  # before now()), but false in time zone -0100 (now() returns an
+  # earlier clock time, and its time zone is dropped when comparing to
+  # a "timestamp without time zone").
+  raw_connection.sync_exec("SET TIME ZONE 'UTC'")
+end
index c1530162e958d2c8e59b2e8283ef073f33ca54e8..57eac048a9595b6d2bb5e139d7a191caa3e70017 100755 (executable)
@@ -40,7 +40,7 @@ module CreateSuperUserToken
           where(user_id: system_user.id).
           where(api_client_id: apiClient.id).
           where_serialized(:scopes, ['all']).
-          where('(expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP AT TIME ZONE ?)', 'UTC').
+          where('(expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)').
           first
 
         # none exist; create one with the supplied token
index 0bbbc17b0cc14fd07d8c4b072f18cbc8bded3e18..98e60e057910f034194ad9f47289627a245f97e4 100644 (file)
@@ -605,10 +605,6 @@ class ContainerTest < ActiveSupport::TestCase
   end
 
   test "Lock and unlock" do
-    # The "token is expired" check (at the end of this test case)
-    # requires a west-of-UTC time zone in order to be effective.
-    ActiveRecord::Base.connection.select_value("SET TIME ZONE '-4'")
-
     set_user_from_auth :active
     c, cr = minimal_new priority: 0
 
diff --git a/services/api/test/unit/time_zone_test.rb b/services/api/test/unit/time_zone_test.rb
new file mode 100644 (file)
index 0000000..60ca6b5
--- /dev/null
@@ -0,0 +1,15 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+require 'test_helper'
+
+class TimeZoneTest < ActiveSupport::TestCase
+  test "Database connection time zone" do
+    # This is pointless if the testing host is already using the UTC
+    # time zone.  But if not, the test confirms that
+    # config/initializers/time_zone.rb has successfully changed the
+    # database connection time zone to UTC.
+    assert_equal('UTC', ActiveRecord::Base.connection.select_value("show timezone"))
+  end
+end