Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Team#time_zone now defaults to UTC and is updated when we know the first user's time zone #958

Merged
merged 8 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bullet_train/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ GEM
parallel (1.22.1)
parser (3.1.3.0)
ast (~> 2.4.1)
pg (1.5.9)
phonelib (0.8.4)
possessive (1.0.1)
premailer (1.21.0)
Expand Down Expand Up @@ -503,6 +504,7 @@ DEPENDENCIES
bullet_train-themes!
bullet_train-themes-light!
minitest-reporters
pg (~> 1.3)
pry
pry-stack_explorer
sprockets-rails
Expand Down
10 changes: 10 additions & 0 deletions bullet_train/app/models/concerns/memberships/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ module Memberships::Base

after_commit :publish_changed_quantity

after_create :set_team_time_zone, if: :is_first_membership?

after_validation :remove_user_profile_photo, if: :user_profile_photo_removal?

scope :excluding_platform_agents, -> { where(platform_agent_of: nil) }
Expand Down Expand Up @@ -157,5 +159,13 @@ def publish_changed_quantity
ActiveSupport::Notifications.instrument("memberships.quantity-changed", {team:})
end

def set_team_time_zone
team.set_time_zone_from_user(user)
end

def is_first_membership?
team.memberships.count == 1 && team.memberships.first.id == id
end

ActiveSupport.run_load_hooks :bullet_train_memberships_base, self
end
12 changes: 12 additions & 0 deletions bullet_train/app/models/concerns/teams/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ module Teams::Base
validates :time_zone, inclusion: {in: ActiveSupport::TimeZone.all.map(&:name)}, allow_nil: true
end

def initialize(attributes = nil)
super
self.time_zone = "UTC" if time_zone.blank?
end

def set_time_zone_from_user(user)
if time_zone.blank? || time_zone == "UTC"
self.time_zone = user.time_zone if user.time_zone.present?
save
end
end

def platform_agent_access_tokens
Platform::AccessToken.joins(:application).where(resource_owner_id: users.where.not(platform_agent_of_id: nil), application: {team: nil})
end
Expand Down
2 changes: 1 addition & 1 deletion bullet_train/app/models/concerns/users/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def developer?
end

def set_teams_time_zone
teams.where(time_zone: nil).each do |team|
teams.where(time_zone: [nil, "UTC"]).each do |team|
team.update(time_zone: time_zone) if team.users.count == 1
end
end
Expand Down
1 change: 1 addition & 0 deletions bullet_train/bullet_train.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Gem::Specification.new do |spec|
# We don't want to develop in a world where we don't have `binding.pry` or `object.pry` for debugging.
spec.add_development_dependency "pry"
spec.add_development_dependency "pry-stack_explorer"
spec.add_development_dependency "pg", "~> 1.3"

# Password strength.
spec.add_dependency "devise-pwned_password"
Expand Down
37 changes: 37 additions & 0 deletions bullet_train/config/models/roles.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
default:
models:
Team: read
Document: read
Membership:
- read
- search

crud_role:
models:
Team: crud

editor:
models:
Scaffolding::AbsolutelyAbstract::CreativeConcept:
- read
- update

manager:
includes:
- editor

supervisor:
includes:
- manager

admin:
includes:
- editor
manageable_roles:
- admin
- editor
models:
Team: manage
Membership: manage
Document: manage
Scaffolding::AbsolutelyAbstract::CreativeConcept: manage
21 changes: 4 additions & 17 deletions bullet_train/test/dummy/config/database.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
# SQLite. Versions 3.8.0 and up are supported.
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem "sqlite3"
#
default: &default
adapter: sqlite3
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000

development:
<<: *default
database: db/development.sqlite3
database: bullet_train-core_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: db/test.sqlite3

production:
<<: *default
database: db/production.sqlite3
database: bullet_train-core_test
120 changes: 120 additions & 0 deletions bullet_train/test/dummy/db/schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2022_03_02_235728) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

create_table "documents", force: :cascade do |t|
t.bigint "membership_id", null: false
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["membership_id"], name: "index_documents_on_membership_id"
end

create_table "memberships", id: :serial, force: :cascade do |t|
t.integer "user_id"
t.integer "team_id"
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.bigint "invitation_id"
t.string "user_first_name"
t.string "user_last_name"
t.string "user_profile_photo_id"
t.string "user_email"
t.bigint "added_by_id"
t.bigint "platform_agent_of_id"
t.jsonb "role_ids", default: []
t.boolean "platform_agent", default: false
t.index ["added_by_id"], name: "index_memberships_on_added_by_id"
t.index ["invitation_id"], name: "index_memberships_on_invitation_id"
t.index ["platform_agent_of_id"], name: "index_memberships_on_platform_agent_of_id"
t.index ["team_id"], name: "index_memberships_on_team_id"
t.index ["user_id"], name: "index_memberships_on_user_id"
end

create_table "scaffolding_absolutely_abstract_creative_concepts", force: :cascade do |t|
t.string "name"
t.text "description"
t.bigint "team_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["team_id"], name: "index_scaffold_absolutely_abstract_creative_concept_on_team_id"
end

create_table "scaffolding_absolutely_abstract_creative_concepts_collaborators", force: :cascade do |t|
t.jsonb "role_ids"
t.bigint "creative_concept_id", null: false
t.bigint "membership_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["creative_concept_id"], name: "index_creative_concepts_collaborators_on_creative_concept_id"
t.index ["membership_id"], name: "index_creative_concepts_collaborators_on_membership_id"
end

create_table "teams", force: :cascade do |t|
t.string "name"
t.string "slug"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "being_destroyed"
t.string "time_zone"
t.string "locale"
end

create_table "users", id: :serial, force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at", precision: nil
t.datetime "remember_created_at", precision: nil
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at", precision: nil
t.datetime "last_sign_in_at", precision: nil
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.integer "current_team_id"
t.string "first_name"
t.string "last_name"
t.string "time_zone"
t.datetime "last_seen_at", precision: nil
t.string "profile_photo_id"
t.jsonb "ability_cache"
t.datetime "last_notification_email_sent_at", precision: nil
t.boolean "former_user", default: false, null: false
t.string "encrypted_otp_secret"
t.string "encrypted_otp_secret_iv"
t.string "encrypted_otp_secret_salt"
t.integer "consumed_timestep"
t.boolean "otp_required_for_login"
t.string "otp_backup_codes", array: true
t.string "locale"
t.bigint "platform_agent_of_id"
t.string "otp_secret"
t.integer "failed_attempts", default: 0, null: false
t.string "unlock_token"
t.datetime "locked_at"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["platform_agent_of_id"], name: "index_users_on_platform_agent_of_id"
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
end

add_foreign_key "documents", "memberships"
add_foreign_key "memberships", "teams"
add_foreign_key "memberships", "users"
add_foreign_key "scaffolding_absolutely_abstract_creative_concepts", "teams"
add_foreign_key "scaffolding_absolutely_abstract_creative_concepts_collaborators", "scaffolding_absolutely_abstract_creative_concepts", column: "creative_concept_id"
end
75 changes: 75 additions & 0 deletions bullet_train/test/models/team_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
require "test_helper"

class TeamTest < ActiveSupport::TestCase
test "a new team defaults time_zone to UTC" do
team = Team.new
assert_equal "UTC", team.time_zone
end

test "explicitly set time_zone is not clobbered by first user" do
team = Team.create!(name: "new test team", time_zone: "Eastern Time (US & Canada)")
user = User.create!(email: "[email protected]", password: "password", password_confirmation: "password", time_zone: "Central Time (US & Canada)")
Membership.create!(team: team, user: user)
team.reload
assert_equal "Eastern Time (US & Canada)", team.time_zone
end

test "a new team gets the time_zone of the first user when they join" do
team = Team.create!(name: "new test team")
user = User.create!(email: "[email protected]", password: "password", password_confirmation: "password", time_zone: "Central Time (US & Canada)")
Membership.create!(team: team, user: user)
team.reload
assert_equal "Central Time (US & Canada)", team.time_zone
end

test "a team with a nil time_zone gets the time_zone of the first user when they join" do
team = Team.create!(name: "new test team")
team.time_zone = nil
team.save
team.reload
assert_equal nil, team.time_zone

user = User.create!(email: "[email protected]", password: "password", password_confirmation: "password", time_zone: "Central Time (US & Canada)")
Membership.create!(team: team, user: user)
team.reload
assert_equal "Central Time (US & Canada)", team.time_zone
end

test "default UTC time_zone is not clobbered if first user doesn't have a time zone set" do
team = Team.create!(name: "new test team")
user = User.create!(email: "[email protected]", password: "password", password_confirmation: "password", time_zone: nil)
Membership.create!(team: team, user: user)
team.reload
assert_equal "UTC", team.time_zone
end

test "default UTC time_zone is overwritten once the first user sets a time zone" do
team = Team.create!(name: "new test team")
user = User.create!(email: "[email protected]", password: "password", password_confirmation: "password", time_zone: nil)
Membership.create!(team: team, user: user)
team.reload
assert_equal "UTC", team.time_zone

user.time_zone = "Central Time (US & Canada)"
user.save

team.reload
assert_equal "Central Time (US & Canada)", team.time_zone
end

test "nil time_zone is overwritten once the first user sets a time zone" do
team = Team.create!(name: "new test team", time_zone: nil)
user = User.create!(email: "[email protected]", password: "password", password_confirmation: "password", time_zone: nil)
Membership.create!(team: team, user: user)
team.time_zone = nil
team.save
team.reload
assert_equal nil, team.time_zone

user.time_zone = "Central Time (US & Canada)"
user.save

team.reload
assert_equal "Central Time (US & Canada)", team.time_zone
end
end
Loading