Skip to content

Commit 1f3fe61

Browse files
committed
Feat: add validation and tests #170
1 parent 74b3015 commit 1f3fe61

File tree

10 files changed

+78
-45
lines changed

10 files changed

+78
-45
lines changed

app/models/person.rb

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class Person < ApplicationRecord
6363
inclusion: { in: ISO3166::Country.all.collect(&:alpha2) },
6464
allow_blank: true
6565

66-
validate :picture_size
66+
validate :picture_size, :validate_url
6767

6868
scope :list, -> { order(:name) }
6969

@@ -111,10 +111,9 @@ def set_default_languages
111111
end
112112
end
113113

114-
115-
def picture_url()
114+
def picture_url
116115
picture_url = read_attribute(:picture_url)
117-
picture_url.presence || super
116+
picture_url.presence
118117
end
119118

120119
private
@@ -124,4 +123,20 @@ def picture_size
124123

125124
errors.add(:picture, :max_size_10MB)
126125
end
126+
127+
def url_valid?(picture_url)
128+
return true if picture_url.nil? || picture_url.blank?
129+
130+
url = URI.parse(picture_url)
131+
host_regex = /^(\w+\.)?#{ENV.fetch('PICTURE_HOST', 'puzzle.ch')}$/
132+
url.host.match? host_regex
133+
rescue URI::InvalidURIError
134+
false
135+
end
136+
137+
def validate_url
138+
return if url_valid? picture_url
139+
140+
errors.add(:picture_url, :invalid_url)
141+
end
127142
end

app/views/people/_form.html.haml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
= form_with model: @person do |form|
22
%div.d-flex.flex-xl-row.flex-column
33
%div.col-xl-3.col-12{"data-controller"=>"image-upload"}
4-
- picture_src = @person.picture_url || @person.picture + Time.now.to_f
4+
- picture_src = @person.picture_url || @person.picture
55
%img.rounded-circle#avatar{src: picture_src, width: '141', height: '141'}
66
%span.fw-normal
77
= t "people.profile.image_url"
88
= form.text_field :picture_url, {class: "mw-100 form-control ", "data-action" => "image-upload#changeImage", id: "avatar-url"}
9-
oder
109
%label.btn.btn-link.p-0{for: "avatar-uploader"}
1110
= t "people.profile.upload_image"
1211
%div.visually-hidden= form.file_field :picture, { accept: "image/*", "data-action" => "image-upload#changeImage", id: "avatar-uploader" }

app/views/people/_profile.html.haml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
%turbo-frame{id: "#{dom_id @person}"}
66
%div.d-flex.flex-xl-row.flex-column
77
%div.col-xl-3.col-12
8-
- picture_src = @person.picture_url || @person.picture + Time.now.to_f
8+
- picture_src = @person.picture_url || @person.picture
99
%img.rounded-circle{src: picture_src, width: '141', height: '141'}
1010
%div.mt-3
1111
= edit_action_link

config/locales/de-CH.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ de-CH:
8080
one: Funktion
8181
other: Funktionä
8282
picture: Biud
83+
picture_url: Biudadresse
8384
projects:
8485
one: Projekt
8586
other: Projektä
@@ -222,6 +223,7 @@ de-CH:
222223
chart_data_empty: Wähl e Abteilig, e Skill und es Jahr us, um d date ds zeige.
223224
chart_results_empty: Es si keni Snapshots gfunde worde, wo de gwählte Filter entspreche.
224225
invalid_date_range: muess vorem Änddatum si.
226+
invalid_url: muess e validi URL si
225227
max_size_10MB: darf nid grösser aus 10MB si.
226228
max_size_error: darf nid grösser aus 10MB si.
227229
profile-not-found: Profiu isch nid gfungä wordä.
@@ -337,15 +339,15 @@ de-CH:
337339
export_form:
338340
anonymised_cv: Anonymisierter CV
339341
competences_skills: Chärnkompetenzä - Skills
340-
location: 'Niderlassig (für Footer):'
341-
skills_by_level: Skills nach Level
342-
trainee: Trainee
343342
customer_code: Chundächürzu
344-
department_code: Abteiligschürzu
345-
project_code: Projektchürzu
346343
customer_code_placeholder: Ds Chundächürzu wird i dr Chopfzielä azeigt
344+
department_code: Abteiligschürzu
347345
department_code_placeholder: Ds Abteiligschürzu wird i dr Chopfzielä azeigt
346+
location: 'Niderlassig (für Footer):'
347+
project_code: Projektchürzu
348348
project_code_placeholder: Ds Projektchürzu wird i dr Chopfzielä azeigt
349+
skills_by_level: Skills nach Level
350+
trainee: Trainee
349351
form:
350352
ptime_data: Diä Datä si usem Puzzle Time, drum chasch du diä nid veränderä.
351353
global:
@@ -370,8 +372,9 @@ de-CH:
370372
add_language: Sprache hinzuäfüegä
371373
change_image: Biud änderä
372374
core_competences: Chärnkompetenzä
375+
image_url: Biudadrässä igä
373376
personals: Personaliä
374-
upload_image: Biud hochladä
377+
upload_image: oder es Biud hochladä
375378
projects:
376379
link:
377380
add: Neues Projekt

config/locales/de.yml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ de:
8080
one: Funktion
8181
other: Funktionen
8282
picture: Bild
83+
picture_url: Bildadresse
8384
projects:
8485
one: Projekt
8586
other: Projekte
@@ -207,6 +208,7 @@ de:
207208
chart_data_empty: Wähle eine Abteilung, einen Skill und ein Jahr aus, um Daten anzuzeigen.
208209
chart_results_empty: Es wurden keine Snapshots gefunden, die den gewählten Filtern entsprechen.
209210
invalid_date_range: muss vor dem Enddatum sein.
211+
invalid_url: muss eine valide URL sein
210212
max_size_10MB: darf nicht grösser als 10MB sein.
211213
max_size_error: darf nicht grösser als 10MB sein.
212214
profile-not-found: Profil konnte nicht gefunden werden.
@@ -320,15 +322,15 @@ de:
320322
export_form:
321323
anonymised_cv: Anonymisierter CV
322324
competences_skills: Kernkompetenzen - Skills
323-
location: 'Niederlassung (für Footer):'
324-
skills_by_level: Skills nach Level
325-
trainee: Trainee
326325
customer_code: Kundenkürzel
327-
department_code: Bereichskürzel
328-
project_code: Projektkürzel
329326
customer_code_placeholder: Das Kundenkürzel wird in der Kopfzeile angezeigt
327+
department_code: Bereichskürzel
330328
department_code_placeholder: Das Bereichskürzel wird in der Kopfzeile angezeigt
329+
location: 'Niederlassung (für Footer):'
330+
project_code: Projektkürzel
331331
project_code_placeholder: Das Projektkürzel wird in der Kopfzeile angezeigt
332+
skills_by_level: Skills nach Level
333+
trainee: Trainee
332334
form:
333335
ptime_data: Diese Daten stammen aus dem Puzzle Time, daher kannst du diese nicht bearbeiten.
334336
global:
@@ -352,10 +354,10 @@ de:
352354
add_function: Funktion hinzufügen
353355
add_language: Sprache hinzufügen
354356
change_image: Bild ändern
355-
image_url: Bildadresse eingeben
356357
core_competences: Kernkompetenzen
358+
image_url: Bildadresse eingeben
357359
personals: Personalien
358-
upload_image: Bild hochladen
360+
upload_image: oder ein Bild hochladen
359361
projects:
360362
link:
361363
add: Neues Projekt

config/locales/en.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ en:
8080
one: Function
8181
other: Functions
8282
picture: Image
83+
picture_url: Image URL
8384
projects:
8485
one: Project
8586
other: Projects
@@ -203,6 +204,7 @@ en:
203204
chart_data_empty: Select a department, skill and a year to display data.
204205
chart_results_empty: No snapshots matching the selected filters were found.
205206
invalid_date_range: must be before the end date.
207+
invalid_url: must be a valid URL
206208
max_size_10MB: must not be larger than 10MB.
207209
max_size_error: must not be larger than 10MB.
208210
profile-not-found: Profile could not be found.
@@ -316,15 +318,15 @@ en:
316318
export_form:
317319
anonymised_cv: Anonymized CV
318320
competences_skills: Core competencies - Skills
319-
location: 'Branch office (for footer):'
320-
skills_by_level: Skills by level
321-
trainee: Trainee
322321
customer_code: Client code
323-
department_code: Department code
324-
project_code: Project code
325322
customer_code_placeholder: The customer code is displayed in the header
323+
department_code: Department code
326324
department_code_placeholder: The department code is displayed in the header
325+
location: 'Branch office (for footer):'
326+
project_code: Project code
327327
project_code_placeholder: The project code is displayed in the header
328+
skills_by_level: Skills by level
329+
trainee: Trainee
328330
form:
329331
ptime_data: This data comes from Puzzle Time, therefore you cannot edit it.
330332
global:
@@ -349,8 +351,9 @@ en:
349351
add_language: Add language
350352
change_image: Change picture
351353
core_competences: Core competencies
354+
image_url: Enter image URL
352355
personals: Personal details
353-
upload_image: Upload image
356+
upload_image: or Upload an image
354357
projects:
355358
link:
356359
add: New project

config/locales/fr.yml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ fr:
8080
one: Fonction
8181
other: Fonctions
8282
picture: Image
83+
picture_url: URL de l’image
8384
projects:
8485
one: Projet
8586
other: Projets
@@ -203,6 +204,7 @@ fr:
203204
chart_data_empty: Sélectionnez un département, une compétence et une année pour afficher les données.
204205
chart_results_empty: Aucun instantané correspondant aux filtres sélectionnés n'a été trouvé.
205206
invalid_date_range: doit être antérieure à la date de fin.
207+
invalid_url: doit être une URL valide
206208
max_size_10MB: ne doit pas dépasser 10 Mo.
207209
max_size_error: ne doit pas dépasser 10 Mo.
208210
profile-not-found: Le profil n'a pas été trouvé.
@@ -316,15 +318,15 @@ fr:
316318
export_form:
317319
anonymised_cv: CV anonyme
318320
competences_skills: Compétences clés - Skills
319-
location: 'Établissement (pour le pied de page) :'
320-
skills_by_level: Compétences par niveau
321-
trainee: Stagiaire
322321
customer_code: Abréviation du client
322+
customer_code_placeholder: le code client s'affiche dans l'en-tête
323323
department_code: Abréviation du département
324+
department_code_placeholder: le code département s'affiche dans l'en-tête
325+
location: 'Établissement (pour le pied de page) :'
324326
project_code: Abréviation du projet
325-
customer_code_placeholder : le code client s'affiche dans l'en-tête
326-
department_code_placeholder : le code département s'affiche dans l'en-tête
327-
project_code_placeholder : le code projet s'affiche dans l'en-tête
327+
project_code_placeholder: le code projet s'affiche dans l'en-tête
328+
skills_by_level: Compétences par niveau
329+
trainee: Stagiaire
328330
form:
329331
ptime_data: Ces données proviennent de Puzzle Time, vous ne pouvez donc pas les modifier.
330332
global:
@@ -349,8 +351,9 @@ fr:
349351
add_language: Ajouter une langue
350352
change_image: Modifier l'image
351353
core_competences: Compétences clés
354+
image_url: saisir l’URL de l’image
352355
personals: Données personnelles
353-
upload_image: Télécharger une image
356+
upload_image: ou télécharger une image
354357
projects:
355358
link:
356359
add: Nouveau projet

config/locales/it.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ it:
8080
one: Funzione
8181
other: Funzioni
8282
picture: Immagine
83+
picture_url: URL dell'immagine
8384
projects:
8485
one: Progetto
8586
other: Progetti
@@ -203,6 +204,7 @@ it:
203204
chart_data_empty: Selezionare un unità organizzativa, una competenza e un anno per visualizzare i dati.
204205
chart_results_empty: Non sono state trovate istantanee corrispondenti ai filtri selezionati.
205206
invalid_date_range: deve essere precedente alla data di scadenza.
207+
invalid_url: deve essere un URL valido
206208
max_size_10MB: non deve essere più grande di 10 MB.
207209
max_size_error: non deve essere più grande di 10 MB.
208210
profile-not-found: Il profilo non è stato trovato.
@@ -316,15 +318,15 @@ it:
316318
export_form:
317319
anonymised_cv: CV anonimo
318320
competences_skills: Competenze di base - Capacità
319-
location: 'Sede secondaria (per il piè di pagina):'
320-
skills_by_level: Competenze per livello
321-
trainee: Apprendista
322321
customer_code: Abbreviazione cliente
323-
department_code: Abbreviazione reparto
324-
project_code: Abbreviazione progetto
325322
customer_code_placeholder: il codice cliente viene visualizzato nell'intestazione
323+
department_code: Abbreviazione reparto
326324
department_code_placeholder: il codice reparto viene visualizzato nell'intestazione
325+
location: 'Sede secondaria (per il piè di pagina):'
326+
project_code: Abbreviazione progetto
327327
project_code_placeholder: il codice progetto viene visualizzato nell'intestazione
328+
skills_by_level: Competenze per livello
329+
trainee: Apprendista
328330
form:
329331
ptime_data: Questi dati provengono da Puzzle Time, pertanto non è possibile modificarli.
330332
global:
@@ -349,8 +351,9 @@ it:
349351
add_language: Aggiungi lingua
350352
change_image: Cambia immagine
351353
core_competences: Competenze di base
354+
image_url: Inserisci l’URL dell’immagine
352355
personals: Dati personali
353-
upload_image: Carica immagine
356+
upload_image: oppure carica un'immagine
354357
projects:
355358
link:
356359
add: Nuovo progetto

config/locales/ja.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ ja:
8080
one: 職務
8181
other: 職務
8282
picture: 写真
83+
picture_url: 画像のURL
8384
projects:
8485
one: プロジェクト
8586
other: プロジェクト
@@ -203,6 +204,7 @@ ja:
203204
chart_data_empty: データを表示するには、部署、スキル、年を選択してください
204205
chart_results_empty: 選択したフィルターに一致するスナップショットは見つかりませんでした。
205206
invalid_date_range: 終了日より前の日付でなければなりません。
207+
invalid_url: 有効なURLである必要があります
206208
max_size_10MB: 10MBを超えてはいけません。
207209
max_size_error: 10MBを超えてはいけません。
208210
profile-not-found: プロフィールが見つかりませんでした。
@@ -316,15 +318,15 @@ ja:
316318
export_form:
317319
anonymised_cv: 匿名化された履歴書
318320
competences_skills: コアコンピタンス - スキル
319-
location: 支店(フッター用):
320-
skills_by_level: レベル別スキル
321-
trainee: 研修生
322321
customer_code: クライアント略称
323-
department_code: 部門略称
324-
project_code: プロジェクト略称
325322
customer_code_placeholder: 顧客コードはヘッダーに表示されます
323+
department_code: 部門略称
326324
department_code_placeholder: 部門コードはヘッダーに表示されます
325+
location: 支店(フッター用):
326+
project_code: プロジェクト略称
327327
project_code_placeholder: プロジェクトコードはヘッダーに表示されます
328+
skills_by_level: レベル別スキル
329+
trainee: 研修生
328330
form:
329331
ptime_data: このデータはPuzzle Timeのものです。そのため、編集できません。
330332
global:
@@ -349,8 +351,9 @@ ja:
349351
add_language: 言語を追加
350352
change_image: 画像を変更
351353
core_competences: コアコンピテンシー
354+
image_url: 画像のURLを入力
352355
personals: 個人情報
353-
upload_image: 画像をアップロード
356+
upload_image: または画像をアップロード
354357
projects:
355358
link:
356359
add: 新しいプロジェクト

spec/features/people_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def common_languages_translated
6262

6363
def fill_out_person_form
6464
page.attach_file("avatar-uploader", Rails.root + 'app/assets/images/anonymous_profile_picture.png')
65+
fill_in 'avatar-url', with: 'https://www.puzzle.ch/app/uploads/2024/04/graphic-hero.svg'
6566
fill_in 'person_name', with: 'Hansjakobli'
6667
fill_in 'person_email', with: 'hanswurst@somemail.com'
6768
fill_in 'person_title', with: 'Wurstexperte'
@@ -97,6 +98,7 @@ def assert_form_persisted(old_number_of_roles)
9798

9899
person = Person.find_by(name: 'Hansjakobli')
99100
expect(person.picture.identifier).to eql('anonymous_profile_picture.png')
101+
expect(person.picture_url).to eql('https://www.puzzle.ch/app/uploads/2024/04/graphic-hero.svg')
100102
expect(person.email).to eql('hanswurst@somemail.com')
101103
expect(person.title).to eql('Wurstexperte')
102104
expect(person.person_roles.count).to eql(old_number_of_roles + 1)

0 commit comments

Comments
 (0)