return errors.add :auth_uuid, 'is readonly'
end
if not [Locked, Running].include? self.state
- # don't need one
- self.auth.andand.update_attributes(expires_at: db_current_time)
+ # Don't need one. If auth already exists, expire it.
+ #
+ # We use db_transaction_time here (not db_current_time) to
+ # ensure the token doesn't validate later in the same
+ # transaction (e.g., in a test case) by satisfying expires_at >
+ # transaction timestamp.
+ self.auth.andand.update_attributes(expires_at: db_transaction_time)
self.auth = nil
return
elsif self.auth
def db_current_time
Time.parse(ActiveRecord::Base.connection.select_value(CURRENT_TIME_SQL)).to_time
end
+
+ def db_transaction_time
+ Time.parse(ActiveRecord::Base.connection.select_value('SELECT current_timestamp')).to_time
+ end
end
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
auth_exp = ApiClientAuthorization.find_by_uuid(auth_uuid_was).expires_at
assert_operator auth_exp, :<, db_current_time
+
+ assert_nil ApiClientAuthorization.validate(token: ApiClientAuthorization.find_by_uuid(auth_uuid_was).token)
end
test "Exceed maximum lock-unlock cycles" do