Skip to content

Commit dc1febc

Browse files
committed
adds contactable consent field to user model
updates related functionality (filter, strong params) for updated user model adds test cases to users model and users requests updates error handling in lib/gems/baw-app/lib/types.rb autoformat **only** changes: spec/factories/user_factory.rb spec/controllers/user_accounts_controller_spec.rb
1 parent bdf451e commit dc1febc

File tree

10 files changed

+250
-131
lines changed

10 files changed

+250
-131
lines changed

app/controllers/user_accounts_controller.rb

+22-22
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ def projects
105105
do_authorize_instance
106106

107107
@user_projects = Access::ByPermission.projects(@user).includes(:creator).references(:creator)
108-
.order('projects.name ASC')
109-
.page(paging_params[:page].blank? ? 1 : paging_params[:page])
108+
.order('projects.name ASC')
109+
.page((paging_params[:page].presence || 1))
110110
respond_to do |format|
111111
format.html
112112
end
@@ -118,8 +118,8 @@ def sites
118118
do_authorize_instance
119119

120120
@user_sites = Access::ByPermission.sites(@user).includes(:creator, :projects).references(:creator, :project)
121-
.order('sites.name ASC')
122-
.page(paging_params[:page].blank? ? 1 : paging_params[:page])
121+
.order('sites.name ASC')
122+
.page((paging_params[:page].presence || 1))
123123

124124
respond_to do |format|
125125
format.html
@@ -132,8 +132,8 @@ def bookmarks
132132
do_authorize_instance
133133

134134
@user_bookmarks = Access::ByUserModified.bookmarks(@user)
135-
.order('bookmarks.updated_at DESC')
136-
.page(paging_params[:page].blank? ? 1 : paging_params[:page])
135+
.order('bookmarks.updated_at DESC')
136+
.page((paging_params[:page].presence || 1))
137137
respond_to do |format|
138138
format.html
139139
end
@@ -145,8 +145,8 @@ def audio_event_comments
145145
do_authorize_instance
146146

147147
@user_audio_event_comments = Access::ByUserModified.audio_event_comments(@user)
148-
.order('audio_event_comments.updated_at DESC')
149-
.page(paging_params[:page].blank? ? 1 : paging_params[:page])
148+
.order('audio_event_comments.updated_at DESC')
149+
.page((paging_params[:page].presence || 1))
150150
respond_to do |format|
151151
format.html
152152
end
@@ -160,8 +160,8 @@ def audio_events
160160
@user_annotations = Access::ByUserModified.audio_events(@user).includes(audio_recording: [:site]).references(
161161
:audio_recordings, :sites
162162
)
163-
.order('audio_events.updated_at DESC')
164-
.page(paging_params[:page].blank? ? 1 : paging_params[:page])
163+
.order('audio_events.updated_at DESC')
164+
.page((paging_params[:page].presence || 1))
165165
respond_to do |format|
166166
format.html
167167
end
@@ -173,11 +173,11 @@ def saved_searches
173173
do_authorize_instance
174174

175175
@user_saved_searches = Access::ByUserModified.saved_searches(@user)
176-
.order('saved_searches.created_at DESC')
177-
.paginate(
178-
page: paging_params[:page].blank? ? 1 : paging_params[:page],
179-
per_page: 30
180-
)
176+
.order('saved_searches.created_at DESC')
177+
.paginate(
178+
page: paging_params[:page].presence || 1,
179+
per_page: 30
180+
)
181181
respond_to do |format|
182182
format.html
183183
end
@@ -189,11 +189,11 @@ def analysis_jobs
189189
do_authorize_instance
190190

191191
@user_analysis_jobs = Access::ByUserModified.analysis_jobs(@user)
192-
.order('analysis_jobs.updated_at DESC')
193-
.paginate(
194-
page: paging_params[:page].blank? ? 1 : paging_params[:page],
195-
per_page: 30
196-
)
192+
.order('analysis_jobs.updated_at DESC')
193+
.paginate(
194+
page: paging_params[:page].presence || 1,
195+
per_page: 30
196+
)
197197
respond_to do |format|
198198
format.html
199199
end
@@ -223,15 +223,15 @@ def user_params
223223
params.require(:user).permit(
224224
:user_name, :email, :password, :password_confirmation, :remember_me,
225225
:roles, :roles_mask, :preferences,
226-
:image, :login
226+
:image, :login, :contactable
227227
)
228228
end
229229

230230
def user_update_params
231231
params.require(:user).permit(
232232
:id, :user_name, :email, :tzinfo_tz,
233233
:password, :password_confirmation,
234-
:roles_mask, :image
234+
:roles_mask, :image, :contactable
235235
)
236236
end
237237

app/models/ability.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ def to_saved_search(user, is_guest)
667667
can [:index, :filter], SavedSearch
668668
end
669669

670-
def to_provenance(_user, is_guest)
670+
def to_provenance(_user, _is_guest)
671671
# other actions are admin only
672672

673673
# available to any user, including guest
@@ -722,7 +722,7 @@ def to_user(user, is_guest)
722722
# normal users edit their profile using devise/registrations#edit
723723

724724
# users can only view their own:
725-
can [:projects, :sites, :bookmarks, :audio_events, :audio_event_comments], User, id: user.id
725+
can [:projects, :sites, :bookmarks, :audio_events, :audio_event_comments, :update], User, id: user.id
726726

727727
# users get their own account and preferences from these actions
728728
can [:my_account, :modify_preferences], User, id: user.id

app/models/user.rb

+57-36
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,39 @@
44
#
55
# Table name: users
66
#
7-
# id :integer not null, primary key
8-
# authentication_token :string
9-
# confirmation_sent_at :datetime
10-
# confirmation_token :string
11-
# confirmed_at :datetime
12-
# current_sign_in_at :datetime
13-
# current_sign_in_ip :string
14-
# email :string not null
15-
# encrypted_password :string not null
16-
# failed_attempts :integer default(0)
17-
# image_content_type :string
18-
# image_file_name :string
19-
# image_file_size :bigint
20-
# image_updated_at :datetime
21-
# invitation_token :string
22-
# last_seen_at :datetime
23-
# last_sign_in_at :datetime
24-
# last_sign_in_ip :string
25-
# locked_at :datetime
26-
# preferences :text
27-
# rails_tz :string(255)
28-
# remember_created_at :datetime
29-
# reset_password_sent_at :datetime
30-
# reset_password_token :string
31-
# roles_mask :integer
32-
# sign_in_count :integer default(0)
33-
# tzinfo_tz :string(255)
34-
# unconfirmed_email :string
35-
# unlock_token :string
36-
# user_name :string not null
37-
# created_at :datetime
38-
# updated_at :datetime
7+
# id :integer not null, primary key
8+
# authentication_token :string
9+
# confirmation_sent_at :datetime
10+
# confirmation_token :string
11+
# confirmed_at :datetime
12+
# contactable(Is the user contactable - consent status re: email communications ) :enum default("unknown"), not null
13+
# current_sign_in_at :datetime
14+
# current_sign_in_ip :string
15+
# email :string not null
16+
# encrypted_password :string not null
17+
# failed_attempts :integer default(0)
18+
# image_content_type :string
19+
# image_file_name :string
20+
# image_file_size :bigint
21+
# image_updated_at :datetime
22+
# invitation_token :string
23+
# last_seen_at :datetime
24+
# last_sign_in_at :datetime
25+
# last_sign_in_ip :string
26+
# locked_at :datetime
27+
# preferences :text
28+
# rails_tz :string(255)
29+
# remember_created_at :datetime
30+
# reset_password_sent_at :datetime
31+
# reset_password_token :string
32+
# roles_mask :integer
33+
# sign_in_count :integer default(0)
34+
# tzinfo_tz :string(255)
35+
# unconfirmed_email :string
36+
# unlock_token :string
37+
# user_name :string not null
38+
# created_at :datetime
39+
# updated_at :datetime
3940
#
4041
# Indexes
4142
#
@@ -61,6 +62,25 @@ class User < ApplicationRecord
6162
:recoverable, :rememberable, :trackable, :validatable,
6263
:confirmable, :lockable, :timeoutable
6364

65+
# Defines a reusable mapping (CONSENT_ENUM) of consent constants
66+
CONSENT_UNASKED = 'unasked'
67+
CONSENT_CONSENTED = 'consented'
68+
CONSENT_UNCONSENTED = 'unconsented'
69+
70+
CONSENT_ENUM = {
71+
CONSENT_UNASKED => CONSENT_UNASKED,
72+
CONSENT_CONSENTED => CONSENT_CONSENTED,
73+
CONSENT_UNCONSENTED => CONSENT_UNCONSENTED
74+
}.freeze
75+
76+
# enum :consent, {
77+
# CONSENT_UNASKED => CONSENT_UNASKED,
78+
# CONSENT_CONSENTED => CONSENT_CONSENTED,
79+
# CONSENT_UNCONSENTED => CONSENT_UNCONSENTED
80+
# }, prefix: :consent
81+
82+
enum :contactable, CONSENT_ENUM, prefix: :contactable, validate: true
83+
6484
# http://www.phase2technology.com/blog/authentication-permissions-and-roles-in-rails-with-devise-cancan-and-role-model/
6585
include RoleModel
6686

@@ -210,8 +230,8 @@ def login
210230
def excluded_login
211231
reserved_user_names = ['admin', 'harvester', 'analysis_runner', 'root', 'superuser', 'administrator', 'admins',
212232
'administrators']
213-
errors.add(:login, 'is reserved') if reserved_user_names.include?(login.downcase)
214-
errors.add(:user_name, 'is reserved') if reserved_user_names.include?(user_name.downcase)
233+
errors.add(:login, 'is reserved') if reserved_user_names.include?(login&.downcase)
234+
errors.add(:user_name, 'is reserved') if reserved_user_names.include?(user_name&.downcase)
215235
end
216236

217237
# format, uniqueness, and presence are validated by devise
@@ -345,10 +365,11 @@ def admin?
345365
end
346366

347367
# Define filter api settings
368+
# @return [Hash] filter settings
348369
def self.filter_settings
349370
{
350-
valid_fields: [:id, :user_name, :roles_mask, :last_seen_at, :created_at, :updated_at],
351-
render_fields: [:id, :user_name, :roles_mask],
371+
valid_fields: [:id, :user_name, :roles_mask, :last_seen_at, :created_at, :updated_at, :contactable],
372+
render_fields: [:id, :user_name, :roles_mask, :contactable],
352373
text_fields: [:user_name],
353374
custom_fields: lambda { |item, user|
354375
# 'item' is the user being processed, 'user' is the currently logged in user
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# frozen_string_literal: true
2+
3+
class AddContactableToUsers < ActiveRecord::Migration[7.2]
4+
def change
5+
create_enum :consent, ['unasked', 'consented', 'unconsented']
6+
add_column :users, :contactable, :enum, enum_type: :consent, default: 'unasked', null: false,
7+
comment: 'Is the user contactable - consent status re: email communications '
8+
end
9+
end

db/structure.sql

+21-1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ CREATE TYPE public.analysis_jobs_item_transition AS ENUM (
8585
);
8686

8787

88+
--
89+
-- Name: consent; Type: TYPE; Schema: public; Owner: -
90+
--
91+
92+
CREATE TYPE public.consent AS ENUM (
93+
'unasked',
94+
'consented',
95+
'unconsented'
96+
);
97+
98+
8899
--
89100
-- Name: dirname(text); Type: FUNCTION; Schema: public; Owner: -
90101
--
@@ -2004,10 +2015,18 @@ CREATE TABLE public.users (
20042015
preferences text,
20052016
tzinfo_tz character varying(255),
20062017
rails_tz character varying(255),
2007-
last_seen_at timestamp without time zone
2018+
last_seen_at timestamp without time zone,
2019+
contactable public.consent DEFAULT 'unasked'::public.consent NOT NULL
20082020
);
20092021

20102022

2023+
--
2024+
-- Name: COLUMN users.contactable; Type: COMMENT; Schema: public; Owner: -
2025+
--
2026+
2027+
COMMENT ON COLUMN public.users.contactable IS 'Is the user contactable - consent status re: email communications ';
2028+
2029+
20112030
--
20122031
-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: -
20132032
--
@@ -4216,6 +4235,7 @@ ALTER TABLE ONLY public.tags
42164235
SET search_path TO "$user", public;
42174236

42184237
INSERT INTO "schema_migrations" (version) VALUES
4238+
('20250113012304'),
42194239
('20241106015941'),
42204240
('20241004055117'),
42214241
('20240828062256'),

lib/gems/baw-app/lib/types.rb

+8-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,15 @@ module Types
2121
begin
2222
p.mkpath
2323
rescue Errno::EACCES => e
24-
Rails.logger.debug { "ERROR: Could not create directory #{p}, #{e}" }
24+
# These errors happen before the logger is available, don't use rails logger
25+
# rubocop:disable Rails/Output
26+
puts "CreatedDirPathname ERROR: Could not create directory #{p}, #{e}"
27+
# rubocop:enable Rails/Output
2528
raise e if BawApp.dev_or_test?
29+
rescue StandardError => e
30+
# rubocop:disable Rails/Output
31+
puts "CreatedDirPathname ERROR: #{e}"
32+
# rubocop:enable Rails/Output
2633
end
2734
p
2835
}

spec/controllers/user_accounts_controller_spec.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# make sure it can recover from bad input
77
describe 'proper timezones data' do
88
let(:user_bad_tz) {
9-
user = FactoryBot.build(:user, tzinfo_tz: 'Australia - Sydney', rails_tz: 'Sydney')
9+
user = build(:user, tzinfo_tz: 'Australia - Sydney', rails_tz: 'Sydney')
1010
user.save!(validate: false)
1111
user
1212
}
@@ -55,7 +55,7 @@
5555

5656
describe 'bad timezones data' do
5757
let(:user_bad_tz) {
58-
user = FactoryBot.build(:user, tzinfo_tz: '[email protected]', rails_tz: '[email protected]')
58+
user = build(:user, tzinfo_tz: '[email protected]', rails_tz: '[email protected]')
5959
user.save!(validate: false)
6060
user
6161
}
@@ -71,7 +71,7 @@
7171
response = get :my_account, params: { format: :json }
7272
body = JSON.parse(response.body)
7373

74-
expect(body['timezone_information']).to be(nil)
74+
expect(body['timezone_information']).to be_nil
7575

7676
user_good_tz = User.find(user_bad_tz.id)
7777
new_values = [user_good_tz.tzinfo_tz, user_good_tz.rails_tz]

0 commit comments

Comments
 (0)