Get user from database based on cookie and serve login if not logged in
To get the user from the database i have to set the cookie first, that
was already done in database.MustAcquire, but i thought they were too
far apart, even thought they are so related. So, the cookie, and thus
the role, is set when getting the user, that is actually the first thing
to do once the connection is acquired. However, that way the database
package has no knowledge of cookies, and the code that sets the cookie
and retrieves the user are next to each other.
I applied the same logic to the changes of locale.Match: it has not
business knowing that the accept language string comes from a request;
it only needs the actual string. Also, the TODO comment about getting
the user’s locale made no sense, now, because app already knows that
locale, so there is no need to pass the user to the locale package.
Getting the locale is done after retrieving the user from the database,
for the same reason the connection is Acquired as far up as possible:
almost every request will need this value, together with the user and
the database connection.
I am a bit affraid that i will end up with functions that always expect
these three values. Maybe i can put the locale inside user, as it is
the user’s locale, after all, no matter if it came from the database or
the user agent, but connection and user must be separate, i think.
We’ll see.
2023-07-25 23:50:39 +00:00
|
|
|
|
<!--
|
|
|
|
|
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
-->
|
|
|
|
|
{{ define "title" -}}
|
Split templates and handlers into admin and public
I need to check that the user is an employee (or admin) in
administration handlers, but i do not want to do it for each handler,
because i am bound to forget it. Thus, i added the /admin sub-path for
these resources.
The public-facing web is the rest of the resources outside /admin, but
for now there is only home, to test whether it works as expected or not.
The public-facing web can not relay on the user’s language settings, as
the guest user has no way to set that. I would be happy to just use the
Accept-Language header for that, but apparently Google does not use that
header[0], and they give four alternatives: a country-specific domain,
a subdomain with a generic top-level domain (gTLD), subdirectories with
a gTLD, or URL parameters (e.g., site.com?loc=de).
Of the four, Google does not recommend URL parameters, and the customer
is already using subdirectories with the current site, therefor that’s
what i have chosen.
Google also tells me that it is a very good idea to have links between
localized version of the same resources, either with <link> elements,
Link HTTP response headers, or a sitemap file[1]; they are all
equivalent in the eyes of Google.
I have choosen the Link response headers way, because for that i can
simply “augment” ResponseHeader to automatically add these headers when
the response status is 2xx, otherwise i would need to pass down the
original URL path until it reaches the template.
Even though Camper is supposed to be a “generic”, multi-company
application, i think i will stick to the easiest route and write the
templates for just the “first” customer.
[0]: https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites
[1]: https://developers.google.com/search/docs/specialty/international/localized-versions
2023-08-05 01:42:37 +00:00
|
|
|
|
{{( pgettext "Home" "title" )}}
|
Get user from database based on cookie and serve login if not logged in
To get the user from the database i have to set the cookie first, that
was already done in database.MustAcquire, but i thought they were too
far apart, even thought they are so related. So, the cookie, and thus
the role, is set when getting the user, that is actually the first thing
to do once the connection is acquired. However, that way the database
package has no knowledge of cookies, and the code that sets the cookie
and retrieves the user are next to each other.
I applied the same logic to the changes of locale.Match: it has not
business knowing that the accept language string comes from a request;
it only needs the actual string. Also, the TODO comment about getting
the user’s locale made no sense, now, because app already knows that
locale, so there is no need to pass the user to the locale package.
Getting the locale is done after retrieving the user from the database,
for the same reason the connection is Acquired as far up as possible:
almost every request will need this value, together with the user and
the database connection.
I am a bit affraid that i will end up with functions that always expect
these three values. Maybe i can put the locale inside user, as it is
the user’s locale, after all, no matter if it came from the database or
the user agent, but connection and user must be separate, i think.
We’ll see.
2023-07-25 23:50:39 +00:00
|
|
|
|
{{- end }}
|
|
|
|
|
|
2023-09-05 02:40:48 +00:00
|
|
|
|
{{ define "head" -}}
|
|
|
|
|
<link rel="stylesheet" media="screen" href="/static/slick@1.8.1.css">
|
|
|
|
|
{{- end }}
|
|
|
|
|
|
Get user from database based on cookie and serve login if not logged in
To get the user from the database i have to set the cookie first, that
was already done in database.MustAcquire, but i thought they were too
far apart, even thought they are so related. So, the cookie, and thus
the role, is set when getting the user, that is actually the first thing
to do once the connection is acquired. However, that way the database
package has no knowledge of cookies, and the code that sets the cookie
and retrieves the user are next to each other.
I applied the same logic to the changes of locale.Match: it has not
business knowing that the accept language string comes from a request;
it only needs the actual string. Also, the TODO comment about getting
the user’s locale made no sense, now, because app already knows that
locale, so there is no need to pass the user to the locale package.
Getting the locale is done after retrieving the user from the database,
for the same reason the connection is Acquired as far up as possible:
almost every request will need this value, together with the user and
the database connection.
I am a bit affraid that i will end up with functions that always expect
these three values. Maybe i can put the locale inside user, as it is
the user’s locale, after all, no matter if it came from the database or
the user agent, but connection and user must be separate, i think.
We’ll see.
2023-07-25 23:50:39 +00:00
|
|
|
|
{{ define "content" -}}
|
Add cover media to campsite types
This is the image that is shown at the home page, and maybe other pages
in the future. We can not use a static file because this image can be
changed by the customer, not us; just like name and description.
I decided to keep the actual media content in the database, but to copy
this file out to the file system the first time it is accessed. This is
because we are going to replicate the database to a public instance that
must show exactly the same image, but the customer will update the image
from the private instance, behind a firewall. We could also synchronize
the folder where they upload the images, the same way we will replicate,
but i thought that i would make the whole thing a little more brittle:
this way if it can replicate the update of the media, it is impossible
to not have its contents; dumping it to a file is to improve subsequent
requests to the same media.
I use the hex representation of the media’s hash as the URL to the
resource, because PostgreSQL’s base64 is not URL save (i.e., it uses
RFC2045’s charset that includes the forward slash[0]), and i did not
feel necessary write a new function just to slightly reduce the URLs’
length.
Before checking if the file exists, i make sure that the given hash is
an hex string, like i do for UUID, otherwise any other check is going
to fail for sure. I moved out hex.Valid function from UUID to check for
valid hex values, but the actual hash check is inside app/media because
i doubt it will be used outside that module.
[0]: https://datatracker.ietf.org/doc/html/rfc2045#section-6.8
2023-09-10 01:04:18 +00:00
|
|
|
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/app.homePage*/ -}}
|
2023-09-05 02:40:48 +00:00
|
|
|
|
<section class="nature">
|
|
|
|
|
<div style="--background-image:url('/static/images/todd-trapani-5LHzBpiTuzQ-unsplash.jpg')">
|
|
|
|
|
<h2>{{ (gettext "The pleasure of camping in the middle of nature…")}}</h2>
|
|
|
|
|
<a href="/{{ currentLocale }}/reservation">{{( pgettext "Booking" "link" )}} <span>→</span></a>
|
|
|
|
|
</div>
|
Add cover media to campsite types
This is the image that is shown at the home page, and maybe other pages
in the future. We can not use a static file because this image can be
changed by the customer, not us; just like name and description.
I decided to keep the actual media content in the database, but to copy
this file out to the file system the first time it is accessed. This is
because we are going to replicate the database to a public instance that
must show exactly the same image, but the customer will update the image
from the private instance, behind a firewall. We could also synchronize
the folder where they upload the images, the same way we will replicate,
but i thought that i would make the whole thing a little more brittle:
this way if it can replicate the update of the media, it is impossible
to not have its contents; dumping it to a file is to improve subsequent
requests to the same media.
I use the hex representation of the media’s hash as the URL to the
resource, because PostgreSQL’s base64 is not URL save (i.e., it uses
RFC2045’s charset that includes the forward slash[0]), and i did not
feel necessary write a new function just to slightly reduce the URLs’
length.
Before checking if the file exists, i make sure that the given hash is
an hex string, like i do for UUID, otherwise any other check is going
to fail for sure. I moved out hex.Valid function from UUID to check for
valid hex values, but the actual hash check is inside app/media because
i doubt it will be used outside that module.
[0]: https://datatracker.ietf.org/doc/html/rfc2045#section-6.8
2023-09-10 01:04:18 +00:00
|
|
|
|
{{ with .CampsiteTypes -}}
|
2023-09-05 02:40:48 +00:00
|
|
|
|
<div>
|
|
|
|
|
{{ range . -}}
|
Add cover media to campsite types
This is the image that is shown at the home page, and maybe other pages
in the future. We can not use a static file because this image can be
changed by the customer, not us; just like name and description.
I decided to keep the actual media content in the database, but to copy
this file out to the file system the first time it is accessed. This is
because we are going to replicate the database to a public instance that
must show exactly the same image, but the customer will update the image
from the private instance, behind a firewall. We could also synchronize
the folder where they upload the images, the same way we will replicate,
but i thought that i would make the whole thing a little more brittle:
this way if it can replicate the update of the media, it is impossible
to not have its contents; dumping it to a file is to improve subsequent
requests to the same media.
I use the hex representation of the media’s hash as the URL to the
resource, because PostgreSQL’s base64 is not URL save (i.e., it uses
RFC2045’s charset that includes the forward slash[0]), and i did not
feel necessary write a new function just to slightly reduce the URLs’
length.
Before checking if the file exists, i make sure that the given hash is
an hex string, like i do for UUID, otherwise any other check is going
to fail for sure. I moved out hex.Valid function from UUID to check for
valid hex values, but the actual hash check is inside app/media because
i doubt it will be used outside that module.
[0]: https://datatracker.ietf.org/doc/html/rfc2045#section-6.8
2023-09-10 01:04:18 +00:00
|
|
|
|
<section style="--background-image:url('{{ .Media }}')">
|
2023-09-05 02:40:48 +00:00
|
|
|
|
<h3><a href="{{ .HRef }}"><span>{{ .Label }}</span></a></h3>
|
|
|
|
|
</section>
|
|
|
|
|
{{- end }}
|
|
|
|
|
</div>
|
|
|
|
|
{{- end }}
|
|
|
|
|
</section>
|
|
|
|
|
<section class="services">
|
|
|
|
|
<h2><a href="/{{ currentLocale }}/services">{{( gettext "Our services")}} <span>→</span></a></h2>
|
|
|
|
|
</section>
|
|
|
|
|
<section class="environment">
|
|
|
|
|
<h2 class="sr-only">{{ (gettext "Environment")}}</h2>
|
|
|
|
|
<div>
|
|
|
|
|
<div class="spiel">
|
|
|
|
|
<p>Situats a l’<strong>Alta Garrotxa</strong>, entre els <strong>Pirineus</strong> i la <strong>Costa
|
|
|
|
|
Brava</strong>.</p>
|
|
|
|
|
<p>A prop teniu els <strong>gorgs de Sadernes</strong>, <strong>volcans</strong>, <strong>La Fageda d’en
|
|
|
|
|
Jordà</strong>, el call jueu de <strong>Besalú</strong>, la cinglera basàltica de <strong>Castellfollit
|
|
|
|
|
de la Roca</strong>… molt per veure i molt per fer.</p>
|
|
|
|
|
<p>A menys d’una hora de <strong>Girona</strong>, a una de <strong>La Bisbal d’Empordà</strong> i a dues
|
|
|
|
|
de
|
|
|
|
|
<strong>Barcelona</strong>.</p>
|
|
|
|
|
<p><a href="/{{currentLocale}}/environment/">Descobreix l’entorn <span>→</span></a></p>
|
|
|
|
|
</div>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/Volca_de_Santa_Margarida.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/Gorga_fosca_Sadernes.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/castellfolit_de_la_roca.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/besalu.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/santa_pau.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/banyoles.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/girn-a.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/costa_brava.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
<figure>
|
|
|
|
|
<img src="/static/images/barcelona-1.jpg" alt=""/>
|
|
|
|
|
<figcaption>{{( gettext "Legend" )}}</figcaption>
|
|
|
|
|
</figure>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
<p class="enjoy">{{( gettext "Come and enjoy!")}}</p>
|
|
|
|
|
|
|
|
|
|
<script src="/static/jquery@3.7.1.min.js"></script>
|
|
|
|
|
<script src="/static/slick@1.8.1.min.js"></script>
|
|
|
|
|
<script>
|
|
|
|
|
jQuery(function () {
|
|
|
|
|
jQuery('.environment > div').slick({
|
|
|
|
|
slidesToShow: 2,
|
|
|
|
|
slidesToScroll: 1,
|
|
|
|
|
infinite: false,
|
|
|
|
|
arrows: true,
|
|
|
|
|
prevArrow: '<button type="button" class="slick-prev">←</button>',
|
|
|
|
|
nextArrow: '<button type="button" class="slick-next">→</button>',
|
|
|
|
|
responsive: [
|
|
|
|
|
{
|
|
|
|
|
breakpoint: 768,
|
|
|
|
|
settings: {
|
|
|
|
|
slidesToShow: 1,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
</script>
|
Get user from database based on cookie and serve login if not logged in
To get the user from the database i have to set the cookie first, that
was already done in database.MustAcquire, but i thought they were too
far apart, even thought they are so related. So, the cookie, and thus
the role, is set when getting the user, that is actually the first thing
to do once the connection is acquired. However, that way the database
package has no knowledge of cookies, and the code that sets the cookie
and retrieves the user are next to each other.
I applied the same logic to the changes of locale.Match: it has not
business knowing that the accept language string comes from a request;
it only needs the actual string. Also, the TODO comment about getting
the user’s locale made no sense, now, because app already knows that
locale, so there is no need to pass the user to the locale package.
Getting the locale is done after retrieving the user from the database,
for the same reason the connection is Acquired as far up as possible:
almost every request will need this value, together with the user and
the database connection.
I am a bit affraid that i will end up with functions that always expect
these three values. Maybe i can put the locale inside user, as it is
the user’s locale, after all, no matter if it came from the database or
the user agent, but connection and user must be separate, i think.
We’ll see.
2023-07-25 23:50:39 +00:00
|
|
|
|
{{- end }}
|