diff --git a/demo/demo.sql b/demo/demo.sql index 2cc51bf..008aba6 100644 --- a/demo/demo.sql +++ b/demo/demo.sql @@ -595,4 +595,56 @@ values (72, 77, 'en', 'Legend') , (76, 103, 'es', 'Leyenda') ; +alter table surroundings_highlight alter column surroundings_highlight_id restart with 112; + +select add_surroundings_highlight(52, 62, 'El Pont del Llierca', '
Pont d’estil romànic i bany natural a 400 m del càmping.
'); +select add_surroundings_highlight(52, 63, 'Alta Garrotxa', 'Excursions pels voltants que no us podeu perdre:
Zona d’escalada de Sadernes a 5 km del càmping
Escalada esportiva.
Descens de barrancs.
'); +select add_surroundings_highlight(52, 65, 'Besalú', 'Vila comtal medieval a 15 minuts
'); +select add_surroundings_highlight(52, 65, 'Parc natural de la zona volcànica de la Garrotxa', 'El millor exponent de paisatge volcànic de la península a només 20 minuts.
'); +select add_surroundings_highlight(52, 66, 'Les millors platges a només una hora', ''); +select add_surroundings_highlight(52, 67, 'Empordà', 'Esplèndida comarca entre el Pirineu i el Mediterrani. Figueres i el Museu Dalí a només 30 minuts.
visitfigueres.cat
salvador-dali.org
Una experiència inoblidable, la Ruta del vi DO Empordà.
Autor de la foto: Rafael Lopez-Monné
'); +select add_surroundings_highlight(52, 69, 'Pirineus', 'Pirineu de Girona
Cims de quasi 3.000 metres, valls i paratges màgics com la Vall de Núria.
'); +select add_surroundings_highlight(52, 70, 'Girona', 'Val la pena visitar Girona: us recomanem visitar el Call Jueu, les Rambles, la catedral i els jardins que l’envolten…
'); +select add_surroundings_highlight(52, 71, 'Barcelona', 'Barcelona és més que botigues o el Barça… Descobreix els seus barris i les seves «joies» i respira el seu ambient.
'); + +select order_surroundings_highlights('{112,113,114,115,116,117,118,119,120,121,122}'); + +select translate_surroundings_highlight(112, 'en', 'Bridge of Llierca', 'Romanesque style bridge and natural bath at only 400 m from the camp site.
'); +select translate_surroundings_highlight(113, 'en', 'Alta Garrotxa', 'Walks in the neighbourhood that nobody should miss:
The Sadernes climbing area only 5 km from the camp site
Sport climbing.
Canyoning.
'); +select translate_surroundings_highlight(115, 'en', 'Besalú', 'County medieval village only 15 minutes distance
'); +select translate_surroundings_highlight(116, 'en', 'La Garrotxa volcanic zone natural park', 'The best exponent of volcanic scenery in the Iberian Peninsula at 20 minutes.
'); +select translate_surroundings_highlight(117, 'en', 'The best beaches at only one hour', ''); +select translate_surroundings_highlight(118, 'en', 'Empordà', 'Splendid region between the Pyrenees and the Mediterranean sea. Figueres and the Dalí Museum at only 30 minutes.
visitfigueres.cat
salvador-dali.org
An unforgetable experience, the DO Empordà wine rute.
Photo author: Rafael Lopez-Monné
'); +select translate_surroundings_highlight(120, 'en', 'Pyrenees', 'The Girona Pyrenees
With mountains of up to 3.000 meters, valleys and magic places as the Núria Valley.
'); +select translate_surroundings_highlight(121, 'en', 'Girona', 'Girona is worthwhile: we recommend to visit the Jewis Call, the Rambles, the cathedral and the gardens nearby…
'); +select translate_surroundings_highlight(122, 'en', 'Barcelona', 'Barcelona is more than shops or Barça… Discover the quarters, their “jewels” and breathe the ambiance.
'); + +select translate_surroundings_highlight(112, 'es', 'El Puente del Llierca', 'Puente de estilo románico y baño natural a 400 m del camping.
'); +select translate_surroundings_highlight(113, 'es', 'Alta Garrotxa', 'Excursiones por los alrededores que no os podéis perder:
Zona de escalada de Sadernes a 5 km del camping Escalada deportiva Descenso de barrancos.
'); +select translate_surroundings_highlight(115, 'es', 'Besalú', 'Villa condal medieval a 15 minutos.
'); +select translate_surroundings_highlight(116, 'es', 'Parque Natural de la Zona Volcánica de la Garrotxa', 'El mejor exponente de paisaje volcánico de la península a sólo 20 minutos.
'); +select translate_surroundings_highlight(117, 'es', 'Las mejores playas a sólo una hora', ''); +select translate_surroundings_highlight(118, 'es', 'Empordà', 'Espléndida comarca entre los Pirineos y el Mediterráneo. Figueres y el Museo Dalí a sólo 30 minutos.
visitfigueres.cat
salvador-dali.org
Una experiéncia inolvidable, la Ruta del vino DO Empordà.
Autor de la foto: Rafael Lopez-Monné
'); +select translate_surroundings_highlight(120, 'es', 'Pirineos', 'Pirineos de Girona
Cimas de casi 3.000 metros, valles y parajes mágicos como el Valle de Núria.
'); +select translate_surroundings_highlight(121, 'es', 'Girona', 'Girona vale una visita: os recomendamos visitar el Call Judío, las Ramblas, la catedral y los jardines que la rodean…
'); +select translate_surroundings_highlight(122, 'es', 'Barcelona', 'Barcelona es más que tiendas o el Barça… Descubre sus barrios y sus «joyas» y respira su ambiente.
'); + +select translate_surroundings_highlight(112, 'fr', 'Le Pont de Llierca', 'Pont de style romain et bain naturel à 400 m du camping.
'); +select translate_surroundings_highlight(113, 'fr', 'Haute Garrotxa', 'Randonnées incontournables:
Zone d’escalade de Sadernes a 5 km du camping.
Escalade sportive.
Canyoning.
'); +select translate_surroundings_highlight(115, 'fr', 'Besalú', 'Village médiévale à 15 minutes.
'); +select translate_surroundings_highlight(116, 'fr', 'Parc naturel de la zone volcanique de la Garrotxa', 'Un magnifique paysage volcanique à seulement 20 minutes.
'); +select translate_surroundings_highlight(117, 'fr', 'Les plus belles plages à moins d’une heure', ''); +select translate_surroundings_highlight(118, 'fr', 'Empordà', 'Magnifique région entre Pyrénées et Méditerranée.
Figueres et le musée Dalí a seulement 30 minutes.
visitfigueres.cat
salvador-dali.org
Une expérience inoubliable, la route des Vin DO Empordà
Auteur de la photo: Rafael Lopez-Monné
'); +select translate_surroundings_highlight(120, 'fr', 'Pyrénées', 'Pyrénées de Gérone.
Sommet de prêt de 3.000 mètres, vallées et lieux magiques comme la Vall de Núria.
'); +select translate_surroundings_highlight(121, 'fr', 'Gérone', 'Visite incontournable, principalement: le quartier juifs, les Rambles, la cathédrale et les jardins qui l’entourent … Sans oublier ses nombreuses boutiques !
'); +select translate_surroundings_highlight(122, 'fr', 'Barcelone', 'Barcelone c’est plus que des boutiques et le Barça … Découvrez la richesse de ces quartiers: Gràcia, Barceloneta, …
'); + commit; diff --git a/deploy/add_surroundings_highlight.sql b/deploy/add_surroundings_highlight.sql new file mode 100644 index 0000000..d50e729 --- /dev/null +++ b/deploy/add_surroundings_highlight.sql @@ -0,0 +1,23 @@ +-- Deploy camper:add_surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight + +begin; + +set search_path to camper, public; + +create or replace function add_surroundings_highlight(company integer, media_id integer, name text, description text) returns integer as +$$ + insert into surroundings_highlight (company_id, media_id, name, description) + values (company, media_id, name, xmlparse(content description)) + returning surroundings_highlight_id + ; +$$ + language sql +; + +revoke execute on function add_surroundings_highlight(integer, integer, text, text) from public; +grant execute on function add_surroundings_highlight(integer, integer, text, text) to admin; + +commit; diff --git a/deploy/edit_surroundings_highlight.sql b/deploy/edit_surroundings_highlight.sql new file mode 100644 index 0000000..bdee7f8 --- /dev/null +++ b/deploy/edit_surroundings_highlight.sql @@ -0,0 +1,25 @@ +-- Deploy camper:edit_surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight + +begin; + +set search_path to camper, public; + +create or replace function edit_surroundings_highlight(highlight_id integer, media_id integer, name text, description text) returns integer as +$$ + update surroundings_highlight + set media_id = coalesce(edit_surroundings_highlight.media_id, surroundings_highlight.media_id) + , name = edit_surroundings_highlight.name + , description = xmlparse(content edit_surroundings_highlight.description) + where surroundings_highlight_id = highlight_id + returning surroundings_highlight_id; +$$ + language sql +; + +revoke execute on function edit_surroundings_highlight(integer, integer, text, text) from public; +grant execute on function edit_surroundings_highlight(integer, integer, text, text) to admin; + +commit; diff --git a/deploy/order_surroundings_highlights.sql b/deploy/order_surroundings_highlights.sql new file mode 100644 index 0000000..08b6243 --- /dev/null +++ b/deploy/order_surroundings_highlights.sql @@ -0,0 +1,24 @@ +-- Deploy camper:order_surroundings_highlights to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight + +begin; + +set search_path to camper, public; + +create or replace function order_surroundings_highlights(positions integer[]) returns void as +$$ + update surroundings_highlight + set position = cast(temp.position as integer) + from unnest(positions) with ordinality as temp(surroundings_highlight_id, position) + where surroundings_highlight.surroundings_highlight_id = temp.surroundings_highlight_id + ; +$$ + language sql +; + +revoke execute on function order_surroundings_highlights(integer[]) from public; +grant execute on function order_surroundings_highlights(integer[]) to admin; + +commit; diff --git a/deploy/remove_surroundings_highlight.sql b/deploy/remove_surroundings_highlight.sql new file mode 100644 index 0000000..5ac863b --- /dev/null +++ b/deploy/remove_surroundings_highlight.sql @@ -0,0 +1,22 @@ +-- Deploy camper:remove_surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight +-- requires: surroundings_highlight_i18n + +begin; + +set search_path to camper, public; + +create or replace function remove_surroundings_highlight(highlight_id integer) returns void as +$$ + delete from surroundings_highlight_i18n where surroundings_highlight_id = highlight_id; + delete from surroundings_highlight where surroundings_highlight_id = highlight_id; +$$ + language sql +; + +revoke execute on function remove_surroundings_highlight(integer) from public; +grant execute on function remove_surroundings_highlight(integer) to admin; + +commit; diff --git a/deploy/surroundings_highlight.sql b/deploy/surroundings_highlight.sql new file mode 100644 index 0000000..05eea3b --- /dev/null +++ b/deploy/surroundings_highlight.sql @@ -0,0 +1,58 @@ +-- Deploy camper:surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: company +-- requires: media +-- requires: user_profile + +begin; + +set search_path to camper, public; + +create table surroundings_highlight ( + surroundings_highlight_id integer generated by default as identity primary key, + company_id integer not null references company, + media_id integer not null references media, + name text not null constraint name_not_empty check(length(trim(name)) > 0), + description xml not null, + position integer not null default 2147483647 +); + +grant select on table surroundings_highlight to guest; +grant select on table surroundings_highlight to employee; +grant select, insert, update, delete on table surroundings_highlight to admin; + + +alter table surroundings_highlight enable row level security; + +create policy guest_ok +on surroundings_highlight +for select +using (true) +; + +create policy insert_to_company +on surroundings_highlight +for insert +with check ( + company_id in (select company_id from user_profile) +) +; + +create policy update_company +on surroundings_highlight +for update +using ( + company_id in (select company_id from user_profile) +) +; + +create policy delete_from_company +on surroundings_highlight +for delete +using ( + company_id in (select company_id from user_profile) +) +; + +commit; diff --git a/deploy/surroundings_highlight_i18n.sql b/deploy/surroundings_highlight_i18n.sql new file mode 100644 index 0000000..1802fa4 --- /dev/null +++ b/deploy/surroundings_highlight_i18n.sql @@ -0,0 +1,23 @@ +-- Deploy camper:surroundings_highlight_i18n to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight +-- requires: language + +begin; + +set search_path to camper, public; + +create table surroundings_highlight_i18n ( + surroundings_highlight_id integer not null references surroundings_highlight, + lang_tag text not null references language, + name text not null, + description xml not null, + primary key (surroundings_highlight_id, lang_tag) +); + +grant select on table surroundings_highlight_i18n to guest; +grant select on table surroundings_highlight_i18n to employee; +grant select, insert, update, delete on table surroundings_highlight_i18n to admin; + +commit; diff --git a/deploy/translate_surroundings_highlight.sql b/deploy/translate_surroundings_highlight.sql new file mode 100644 index 0000000..0ef3b6f --- /dev/null +++ b/deploy/translate_surroundings_highlight.sql @@ -0,0 +1,25 @@ +-- Deploy camper:translate_surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight_i18n + +begin; + +set search_path to camper, public; + +create or replace function translate_surroundings_highlight(highlight_id integer, lang_tag text, name text, description text) returns void as +$$ + insert into surroundings_highlight_i18n (surroundings_highlight_id, lang_tag, name, description) + values (highlight_id, lang_tag, name, xmlparse(content coalesce(description, ''))) + on conflict (surroundings_highlight_id, lang_tag) do update + set name = excluded.name + , description = excluded.description + ; +$$ + language sql +; + +revoke execute on function translate_surroundings_highlight(integer, text, text, text) from public; +grant execute on function translate_surroundings_highlight(integer, text, text, text) to admin; + +commit; diff --git a/pkg/app/admin.go b/pkg/app/admin.go index 7ddf4f6..8846a9b 100644 --- a/pkg/app/admin.go +++ b/pkg/app/admin.go @@ -20,32 +20,35 @@ import ( "dev.tandem.ws/tandem/camper/pkg/media" "dev.tandem.ws/tandem/camper/pkg/season" "dev.tandem.ws/tandem/camper/pkg/services" + "dev.tandem.ws/tandem/camper/pkg/surroundings" "dev.tandem.ws/tandem/camper/pkg/template" ) type adminHandler struct { - campsite *campsite.AdminHandler - company *company.AdminHandler - home *home.AdminHandler - legal *legal.AdminHandler - location *location.AdminHandler - media *media.AdminHandler - payment *booking.AdminHandler - season *season.AdminHandler - services *services.AdminHandler + campsite *campsite.AdminHandler + company *company.AdminHandler + home *home.AdminHandler + legal *legal.AdminHandler + location *location.AdminHandler + media *media.AdminHandler + payment *booking.AdminHandler + season *season.AdminHandler + services *services.AdminHandler + surroundings *surroundings.AdminHandler } func newAdminHandler(mediaDir string) *adminHandler { return &adminHandler{ - campsite: campsite.NewAdminHandler(), - company: company.NewAdminHandler(), - home: home.NewAdminHandler(), - legal: legal.NewAdminHandler(), - location: location.NewAdminHandler(), - media: media.NewAdminHandler(mediaDir), - payment: booking.NewAdminHandler(), - season: season.NewAdminHandler(), - services: services.NewAdminHandler(), + campsite: campsite.NewAdminHandler(), + company: company.NewAdminHandler(), + home: home.NewAdminHandler(), + legal: legal.NewAdminHandler(), + location: location.NewAdminHandler(), + media: media.NewAdminHandler(mediaDir), + payment: booking.NewAdminHandler(), + season: season.NewAdminHandler(), + services: services.NewAdminHandler(), + surroundings: surroundings.NewAdminHandler(), } } @@ -83,6 +86,8 @@ func (h *adminHandler) Handle(user *auth.User, company *auth.Company, conn *data h.season.Handler(user, company, conn).ServeHTTP(w, r) case "services": h.services.Handler(user, company, conn).ServeHTTP(w, r) + case "surroundings": + h.surroundings.Handler(user, company, conn).ServeHTTP(w, r) case "": switch r.Method { case http.MethodGet: diff --git a/pkg/app/public.go b/pkg/app/public.go index 5b10661..b7c2c0b 100644 --- a/pkg/app/public.go +++ b/pkg/app/public.go @@ -6,7 +6,6 @@ package app import ( - "dev.tandem.ws/tandem/camper/pkg/legal" "net/http" "dev.tandem.ws/tandem/camper/pkg/auth" @@ -15,28 +14,32 @@ import ( "dev.tandem.ws/tandem/camper/pkg/database" "dev.tandem.ws/tandem/camper/pkg/home" httplib "dev.tandem.ws/tandem/camper/pkg/http" + "dev.tandem.ws/tandem/camper/pkg/legal" "dev.tandem.ws/tandem/camper/pkg/location" "dev.tandem.ws/tandem/camper/pkg/services" + "dev.tandem.ws/tandem/camper/pkg/surroundings" "dev.tandem.ws/tandem/camper/pkg/template" ) type publicHandler struct { - home *home.PublicHandler - booking *booking.PublicHandler - campsite *campsite.PublicHandler - legal *legal.PublicHandler - location *location.PublicHandler - services *services.PublicHandler + home *home.PublicHandler + booking *booking.PublicHandler + campsite *campsite.PublicHandler + legal *legal.PublicHandler + location *location.PublicHandler + services *services.PublicHandler + surroundings *surroundings.PublicHandler } func newPublicHandler() *publicHandler { return &publicHandler{ - home: home.NewPublicHandler(), - booking: booking.NewPublicHandler(), - campsite: campsite.NewPublicHandler(), - legal: legal.NewPublicHandler(), - location: location.NewPublicHandler(), - services: services.NewPublicHandler(), + home: home.NewPublicHandler(), + booking: booking.NewPublicHandler(), + campsite: campsite.NewPublicHandler(), + legal: legal.NewPublicHandler(), + location: location.NewPublicHandler(), + services: services.NewPublicHandler(), + surroundings: surroundings.NewPublicHandler(), } } @@ -60,27 +63,7 @@ func (h *publicHandler) Handler(user *auth.User, company *auth.Company, conn *da case "services": h.services.Handler(user, company, conn).ServeHTTP(w, r) case "surroundings": - surroundingsHandler(user, company, conn).ServeHTTP(w, r) - default: - http.NotFound(w, r) - } - }) -} - -func surroundingsHandler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var head string - head, r.URL.Path = httplib.ShiftPath(r.URL.Path) - switch head { - case "": - switch r.Method { - case http.MethodGet: - page := template.NewPublicPage() - page.Setup(r, user, company, conn) - template.MustRenderPublic(w, r, user, company, "surroundings.gohtml", page) - default: - httplib.MethodNotAllowed(w, r, http.MethodGet) - } + h.surroundings.Handler(user, company, conn).ServeHTTP(w, r) default: http.NotFound(w, r) } diff --git a/pkg/database/funcs.go b/pkg/database/funcs.go index 3616342..2f68f2f 100644 --- a/pkg/database/funcs.go +++ b/pkg/database/funcs.go @@ -150,3 +150,27 @@ func (c *Conn) OrderServices(ctx context.Context, ids []int) error { _, err := c.Exec(ctx, "select order_services($1)", ids) return err } + +func (tx *Tx) AddSurroundingsHighlight(ctx context.Context, companyID int, mediaID int, name string, description string) (int, error) { + return tx.GetInt(ctx, "select add_surroundings_highlight($1, $2, $3, $4)", companyID, mediaID, name, description) +} + +func (tx *Tx) EditSurroundingsHighlight(ctx context.Context, id int, mediaID int, name string, description string) error { + _, err := tx.Exec(ctx, "select edit_surroundings_highlight($1, $2, $3, $4)", id, mediaID, name, description) + return err +} + +func (tx *Tx) TranslateSurroundingsHighlight(ctx context.Context, id int, langTag language.Tag, name string, description string) error { + _, err := tx.Exec(ctx, "select translate_surroundings_highlight($1, $2, $3, $4)", id, langTag, name, description) + return err +} + +func (c *Conn) OrderSurroundingsHighlights(ctx context.Context, ids []int) error { + _, err := c.Exec(ctx, "select order_surroundings_highlights($1)", ids) + return err +} + +func (c *Conn) RemoveSurroundingsHighlight(ctx context.Context, id int) error { + _, err := c.Exec(ctx, "select remove_surroundings_highlight($1)", id) + return err +} diff --git a/pkg/surroundings/admin.go b/pkg/surroundings/admin.go new file mode 100644 index 0000000..14349c5 --- /dev/null +++ b/pkg/surroundings/admin.go @@ -0,0 +1,327 @@ +/* + * SPDX-FileCopyrightText: 2023 jordi fita masWhat
') $$, + 'Should be able to add a surroundings highlight to the first company' +); + +select lives_ok( + $$ select add_surroundings_highlight(2, 4, 'Highlight B', '') $$, + 'Should be able to add a surroundings highlight to the second company' +); + +select bag_eq( + $$ select company_id, media_id, name, description::text from surroundings_highlight $$, + $$ values (1, 3, 'Highlight A', 'What
') + , (2, 4, 'Highlight B', '') + $$, + 'Should have added all two surroundings highlight' +); + + +select * +from finish(); + +rollback; diff --git a/test/edit_surroundings_highlight.sql b/test/edit_surroundings_highlight.sql new file mode 100644 index 0000000..e9d7292 --- /dev/null +++ b/test/edit_surroundings_highlight.sql @@ -0,0 +1,74 @@ +-- Test edit_surroundings_highlight +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(12); + +set search_path to camper, public; + +select has_function('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text']); +select function_lang_is('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'sql'); +select function_returns('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'integer'); +select isnt_definer('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text']); +select volatility_is('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'edit_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'edit_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'edit_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'edit_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate surroundings_highlight cascade; +truncate media cascade; +truncate media_content cascade; +truncate company cascade; +reset client_min_messages; + + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (3, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) + , (4, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};')) +; + +insert into surroundings_highlight (surroundings_highlight_id, company_id, media_id, name, description) +values (8, 1, 2, 'Highlight A', 'Beautiful
') + , (4, 8, 'Barcelona', 'Shit
') +; + +prepare surroundings_highlight_data as +select company_id, name +from surroundings_highlight +order by company_id, name; + +set role guest; +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (4, 'Barcelona') + $$, + 'Everyone should be able to list all surroundings highlights across all companies' +); +reset role; + +select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2'); + +select lives_ok( + $$ insert into surroundings_highlight(company_id, media_id, name, description) values (2, 6, 'Another highlight', '') $$, + 'Admin from company 2 should be able to insert a new surroundings highlights to that company.' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (2, 'Another highlight') + , (4, 'Barcelona') + $$, + 'The new row should have been added' +); + +select lives_ok( + $$ update surroundings_highlight set name = 'Another' where company_id = 2 and name = 'Another highlight' $$, + 'Admin from company 2 should be able to update surroundings highlights of that company.' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (2, 'Another') + , (4, 'Barcelona') + $$, + 'The row should have been updated.' +); + +select lives_ok( + $$ delete from surroundings_highlight where company_id = 2 and name = 'Another' $$, + 'Admin from company 2 should be able to delete surroundings highlights from that company.' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (4, 'Barcelona') + $$, + 'The row should have been deleted.' +); + +select throws_ok( + $$ insert into surroundings_highlight (company_id, media_id, name, description) values (4, 8, 'Another highlight', '') $$, + '42501', 'new row violates row-level security policy for table "surroundings_highlight"', + 'Admin from company 2 should NOT be able to insert new surroundings highlights to company 4.' +); + +select lives_ok( + $$ update surroundings_highlight set name = 'Nope' where company_id = 4 $$, + 'Admin from company 2 should not be able to update new surroundings highlights of company 4, but no error if company_id is not changed.' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (4, 'Barcelona') + $$, + 'No row should have been changed.' +); + +select throws_ok( + $$ update surroundings_highlight set company_id = 4 where company_id = 2 $$, + '42501', 'new row violates row-level security policy for table "surroundings_highlight"', + 'Admin from company 2 should NOT be able to move surroundings highlights to company 4' +); + +select lives_ok( + $$ delete from surroundings_highlight where company_id = 4 $$, + 'Admin from company 2 should NOT be able to delete surroundings highlights from company 4, but not error is thrown' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (4, 'Barcelona') + $$, + 'No row should have been changed' +); + +select throws_ok( + $$ insert into surroundings_highlight (company_id, media_id, name, description) values (2, 6, ' ', '') $$, + '23514', 'new row for relation "surroundings_highlight" violates check constraint "name_not_empty"', + 'Should not be able to insert surroundings highlights with a blank name.' +); + + +reset role; + + +select * +from finish(); + +rollback; + diff --git a/test/surroundings_highlight_i18n.sql b/test/surroundings_highlight_i18n.sql new file mode 100644 index 0000000..2d2f318 --- /dev/null +++ b/test/surroundings_highlight_i18n.sql @@ -0,0 +1,49 @@ +-- Test surroundings_highlight_i18n +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(27); + +set search_path to camper, public; + +select has_table('surroundings_highlight_i18n'); +select has_pk('surroundings_highlight_i18n'); +select col_is_pk('surroundings_highlight_i18n', array['surroundings_highlight_id', 'lang_tag']); +select table_privs_are('surroundings_highlight_i18n', 'guest', array['SELECT']); +select table_privs_are('surroundings_highlight_i18n', 'employee', array['SELECT']); +select table_privs_are('surroundings_highlight_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('surroundings_highlight_i18n', 'authenticator', array[]::text[]); + +select has_column('surroundings_highlight_i18n', 'surroundings_highlight_id'); +select col_is_fk('surroundings_highlight_i18n', 'surroundings_highlight_id'); +select fk_ok('surroundings_highlight_i18n', 'surroundings_highlight_id', 'surroundings_highlight', 'surroundings_highlight_id'); +select col_type_is('surroundings_highlight_i18n', 'surroundings_highlight_id', 'integer'); +select col_not_null('surroundings_highlight_i18n', 'surroundings_highlight_id'); +select col_hasnt_default('surroundings_highlight_i18n', 'surroundings_highlight_id'); + +select has_column('surroundings_highlight_i18n', 'lang_tag'); +select col_is_fk('surroundings_highlight_i18n', 'lang_tag'); +select fk_ok('surroundings_highlight_i18n', 'lang_tag', 'language', 'lang_tag'); +select col_type_is('surroundings_highlight_i18n', 'lang_tag', 'text'); +select col_not_null('surroundings_highlight_i18n', 'lang_tag'); +select col_hasnt_default('surroundings_highlight_i18n', 'lang_tag'); + +select has_column('surroundings_highlight_i18n', 'name'); +select col_type_is('surroundings_highlight_i18n', 'name', 'text'); +select col_not_null('surroundings_highlight_i18n', 'name'); +select col_hasnt_default('surroundings_highlight_i18n', 'name'); + +select has_column('surroundings_highlight_i18n', 'description'); +select col_type_is('surroundings_highlight_i18n', 'description', 'xml'); +select col_not_null('surroundings_highlight_i18n', 'description'); +select col_hasnt_default('surroundings_highlight_i18n', 'description'); + + +select * +from finish(); + +rollback; + diff --git a/test/translate_surroundings_highlight.sql b/test/translate_surroundings_highlight.sql new file mode 100644 index 0000000..a3f80b7 --- /dev/null +++ b/test/translate_surroundings_highlight.sql @@ -0,0 +1,83 @@ +-- Test translate_surroundings_highlight +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(13); + +set search_path to camper, public; + +select has_function('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text']); +select function_lang_is('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'sql'); +select function_returns('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'void'); +select isnt_definer('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text']); +select volatility_is('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate surroundings_highlight cascade; +truncate media cascade; +truncate media_content cascade; +truncate company cascade; +reset client_min_messages; + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (3, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) + , (4, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};')) +; + +insert into surroundings_highlight (surroundings_highlight_id, company_id, media_id, name, description) +values (8, 1, 2, 'Highlight A', '{{( gettext "No highlights added yet." )}}
+ {{- end }} +{{- end }} diff --git a/web/templates/public/surroundings.gohtml b/web/templates/public/surroundings.gohtml index 3d432fe..7f1acef 100644 --- a/web/templates/public/surroundings.gohtml +++ b/web/templates/public/surroundings.gohtml @@ -7,47 +7,44 @@ {{- end }} {{ define "content" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/surroundings.surroundingsPage*/ -}}{{( gettext "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…." )}}
-{{( gettext "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking….")}}
-{{( gettext "You will also find museums in Olot, Figures, Girona.")}}
-{{( gettext "As well as music festivals, dance, theater…." )}}
-