Skip to content
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: 0 additions & 2 deletions .github/workflows/uptime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ on:
push:
branches:
- master
schedule:
- cron: "*/15 * * * *"
workflow_dispatch:

permissions:
Expand Down
28 changes: 28 additions & 0 deletions Petabit.Tests/ApplicationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,34 @@ public async Task PrivacyPageLoadsGlobalReadableContentStyles()
Assert.Contains("body.dark-mode .table", styles);
}

[Theory]
[InlineData("en", "Cookie policy", "Manage analytics cookies")]
[InlineData("hr", "Politika kolačića", "Upravljaj analitičkim kolačićima")]
[InlineData("de", "Cookie-Richtlinie", "Analyse-Cookies verwalten")]
public async Task PrivacyCookieDetailsUseRequestedLanguage(string culture, string heading, string manageText)
{
using var request = new HttpRequestMessage(HttpMethod.Get, "/Home/Privacy");
request.Headers.AcceptLanguage.ParseAdd(culture);

var response = await _client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();

Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Contains($"<html lang=\"{culture}\">", body);
Assert.Contains(heading, body);
Assert.Contains(manageText, body);
}

[Fact]
public async Task BooksPageUsesRealPublisherLinks()
{
var body = await _client.GetStringAsync("/Home/Books");

Assert.DoesNotContain("example.com", body);
Assert.Contains("informit.com/store/clean-code", body);
Assert.Contains("store.pragprog.com/titles/tpp20", body);
}

[Fact]
public async Task ContentSecurityPolicyMatchesEveryInlineScriptNonce()
{
Expand Down
20 changes: 20 additions & 0 deletions Petabit/Resources/Views.Home.Privacy.de.resx
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,24 @@
<data name="YourRightsText" xml:space="preserve">
<value>Da wir keine personenbezogenen Daten sammeln, haben Sie keine Anfragen zum Zugriff, zur Berichtigung oder Löschung personenbezogener Daten. Wenn Sie Fragen zum Datenschutz haben, kontaktieren Sie uns bitte.</value>
</data>
<data name="CookiePolicy" xml:space="preserve"><value>Cookie-Richtlinie</value></data>
<data name="CookiePolicyIntro" xml:space="preserve"><value>Petabit verwendet nur notwendige funktionale Technologien und, mit Ihrer Einwilligung, Analyse-Cookies. Die Analyse ist für die Nutzung der Website nicht erforderlich.</value></data>
<data name="NecessaryTechnologies" xml:space="preserve"><value>Notwendige funktionale Technologien</value></data>
<data name="Name" xml:space="preserve"><value>Name</value></data>
<data name="Purpose" xml:space="preserve"><value>Zweck</value></data>
<data name="Duration" xml:space="preserve"><value>Dauer</value></data>
<data name="CulturePurpose" xml:space="preserve"><value>Speichert die ausgewählte Sprache der Website.</value></data>
<data name="OneYear" xml:space="preserve"><value>1 Jahr</value></data>
<data name="ConsentPurpose" xml:space="preserve"><value>Speichert die Entscheidung zu Analyse-Cookies lokal im Browser.</value></data>
<data name="ConsentDuration" xml:space="preserve"><value>Bis Sie Ihre Entscheidung ändern oder die Browserdaten löschen</value></data>
<data name="AnalyticsCookies" xml:space="preserve"><value>Analyse-Cookies – Google Analytics 4</value></data>
<data name="AnalyticsDescription" xml:space="preserve"><value>Google Analytics wird erst geladen, nachdem Sie Akzeptieren ausgewählt haben. Es erfasst zusammengefasste Daten wie Benutzer- und Sitzungszahlen, ungefähren Standort, Browser, Gerät und Zugriffsquelle. Wir verwenden es nicht, um Besucher direkt zu identifizieren.</value></data>
<data name="GaPurpose" xml:space="preserve"><value>Unterscheidet einzelne Benutzer.</value></data>
<data name="GaSessionPurpose" xml:space="preserve"><value>Speichert den Sitzungsstatus für Google Analytics 4.</value></data>
<data name="UpToTwoYears" xml:space="preserve"><value>Bis zu 2 Jahre</value></data>
<data name="GaMoreInfo" xml:space="preserve"><value>Mehr über GA4-Cookies:</value></data>
<data name="GaDocumentation" xml:space="preserve"><value>Google-Analytics-Dokumentation</value></data>
<data name="ConsentManagement" xml:space="preserve"><value>Einwilligung verwalten</value></data>
<data name="ConsentManagementText" xml:space="preserve"><value>Sie können Analyse-Cookies beim ersten Besuch akzeptieren oder ablehnen. Sie können Ihre Entscheidung jederzeit ändern.</value></data>
<data name="ManageConsent" xml:space="preserve"><value>Analyse-Cookies verwalten</value></data>
</root>
20 changes: 20 additions & 0 deletions Petabit/Resources/Views.Home.Privacy.en.resx
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,24 @@
<data name="YourRightsText" xml:space="preserve">
<value>Since we do not collect personal data, you have no requests for access, correction, or deletion of personal data. If you have privacy-related questions, feel free to contact us.</value>
</data>
<data name="CookiePolicy" xml:space="preserve"><value>Cookie policy</value></data>
<data name="CookiePolicyIntro" xml:space="preserve"><value>Petabit uses only necessary functional technologies and, with your consent, analytics cookies. Analytics is not required to use the site.</value></data>
<data name="NecessaryTechnologies" xml:space="preserve"><value>Necessary functional technologies</value></data>
<data name="Name" xml:space="preserve"><value>Name</value></data>
<data name="Purpose" xml:space="preserve"><value>Purpose</value></data>
<data name="Duration" xml:space="preserve"><value>Duration</value></data>
<data name="CulturePurpose" xml:space="preserve"><value>Remembers the selected site language.</value></data>
<data name="OneYear" xml:space="preserve"><value>1 year</value></data>
<data name="ConsentPurpose" xml:space="preserve"><value>Stores the analytics-cookie choice locally in the browser.</value></data>
<data name="ConsentDuration" xml:space="preserve"><value>Until you change your choice or clear browser data</value></data>
<data name="AnalyticsCookies" xml:space="preserve"><value>Analytics cookies – Google Analytics 4</value></data>
<data name="AnalyticsDescription" xml:space="preserve"><value>Google Analytics loads only after you select Accept. It collects aggregate data such as user and session counts, approximate location, browser, device, and traffic source. We do not use it to directly identify visitors.</value></data>
<data name="GaPurpose" xml:space="preserve"><value>Distinguishes unique users.</value></data>
<data name="GaSessionPurpose" xml:space="preserve"><value>Stores session state for Google Analytics 4.</value></data>
<data name="UpToTwoYears" xml:space="preserve"><value>Up to 2 years</value></data>
<data name="GaMoreInfo" xml:space="preserve"><value>More about GA4 cookies:</value></data>
<data name="GaDocumentation" xml:space="preserve"><value>Google Analytics documentation</value></data>
<data name="ConsentManagement" xml:space="preserve"><value>Consent management</value></data>
<data name="ConsentManagementText" xml:space="preserve"><value>You can accept or reject analytics cookies on your first visit. You can change your choice at any time.</value></data>
<data name="ManageConsent" xml:space="preserve"><value>Manage analytics cookies</value></data>
</root>
20 changes: 20 additions & 0 deletions Petabit/Resources/Views.Home.Privacy.hr.resx
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,24 @@
<data name="YourRightsText" xml:space="preserve">
<value>Budući da ne prikupljamo osobne podatke, nemate zahtjeve za pristup, ispravak ili brisanje osobnih podataka.</value>
</data>
<data name="CookiePolicy" xml:space="preserve"><value>Politika kolačića</value></data>
<data name="CookiePolicyIntro" xml:space="preserve"><value>Petabit koristi samo nužne funkcionalne tehnologije i, uz vašu privolu, analitičke kolačiće. Analitika nije potrebna za korištenje stranice.</value></data>
<data name="NecessaryTechnologies" xml:space="preserve"><value>Nužne funkcionalne tehnologije</value></data>
<data name="Name" xml:space="preserve"><value>Naziv</value></data>
<data name="Purpose" xml:space="preserve"><value>Svrha</value></data>
<data name="Duration" xml:space="preserve"><value>Trajanje</value></data>
<data name="CulturePurpose" xml:space="preserve"><value>Pamti odabrani jezik stranice.</value></data>
<data name="OneYear" xml:space="preserve"><value>1 godina</value></data>
<data name="ConsentPurpose" xml:space="preserve"><value>Lokalna pohrana odluke o analitičkim kolačićima u pregledniku.</value></data>
<data name="ConsentDuration" xml:space="preserve"><value>Dok ne promijenite odluku ili ne obrišete podatke preglednika</value></data>
<data name="AnalyticsCookies" xml:space="preserve"><value>Analitički kolačići – Google Analytics 4</value></data>
<data name="AnalyticsDescription" xml:space="preserve"><value>Google Analytics učitava se samo nakon odabira Prihvaćam. Prikuplja zbirne podatke kao što su broj korisnika i sesija, približna lokacija, preglednik, uređaj i izvor dolaska. Ne koristimo ga za izravno utvrđivanje identiteta posjetitelja.</value></data>
<data name="GaPurpose" xml:space="preserve"><value>Razlikuje jedinstvene korisnike.</value></data>
<data name="GaSessionPurpose" xml:space="preserve"><value>Čuva stanje sesije za Google Analytics 4.</value></data>
<data name="UpToTwoYears" xml:space="preserve"><value>Do 2 godine</value></data>
<data name="GaMoreInfo" xml:space="preserve"><value>Više o GA4 kolačićima:</value></data>
<data name="GaDocumentation" xml:space="preserve"><value>Google Analytics dokumentacija</value></data>
<data name="ConsentManagement" xml:space="preserve"><value>Upravljanje privolom</value></data>
<data name="ConsentManagementText" xml:space="preserve"><value>Analitičke kolačiće možete prihvatiti ili odbiti pri prvom posjetu. Svoju odluku možete promijeniti u bilo kojem trenutku.</value></data>
<data name="ManageConsent" xml:space="preserve"><value>Upravljaj analitičkim kolačićima</value></data>
</root>
4 changes: 2 additions & 2 deletions Petabit/Views/Home/Books.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
<h1>📚 @Localizer["LearnWithBooks"]</h1>
<ul class="list-group mt-3">
<li class="list-group-item">
<a href="https://example.com/clean-code" target="_blank" rel="noopener noreferrer">@Localizer["Clean Code – Robert C. Martin"]</a>
<a href="https://www.informit.com/store/clean-code-a-handbook-of-agile-software-craftsmanship-9780132350884" target="_blank" rel="noopener noreferrer">@Localizer["Clean Code – Robert C. Martin"]</a>
</li>
<li class="list-group-item">
<a href="https://example.com/pragmatic-programmer" target="_blank" rel="noopener noreferrer">@Localizer["The Pragmatic Programmer"]</a>
<a href="https://store.pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/" target="_blank" rel="noopener noreferrer">@Localizer["The Pragmatic Programmer"]</a>
</li>
<!-- More books to come -->
</ul>
Expand Down
30 changes: 15 additions & 15 deletions Petabit/Views/Home/Privacy.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,40 @@
<li>@Localizer["CookiesPoint2"]</li>
</ul>

<h2>Politika kolačića</h2>
<p>Petabit koristi samo nužne funkcionalne tehnologije i, uz vašu privolu, analitičke kolačiće. Analitika nije potrebna za korištenje stranice.</p>
<h2>@Localizer["CookiePolicy"]</h2>
<p>@Localizer["CookiePolicyIntro"]</p>

<h3>Nužne funkcionalne tehnologije</h3>
<h3>@Localizer["NecessaryTechnologies"]</h3>
<div class="table-responsive">
<table class="table">
<thead>
<tr><th>Naziv</th><th>Svrha</th><th>Trajanje</th></tr>
<tr><th>@Localizer["Name"]</th><th>@Localizer["Purpose"]</th><th>@Localizer["Duration"]</th></tr>
</thead>
<tbody>
<tr><td>.AspNetCore.Culture</td><td>Pamti odabrani jezik stranice.</td><td>1 godina</td></tr>
<tr><td>petabit-analytics-consent</td><td>Lokalna pohrana odluke o analitičkim kolačićima u pregledniku.</td><td>Dok ne promijenite odluku ili ne obrišete podatke preglednika</td></tr>
<tr><td>.AspNetCore.Culture</td><td>@Localizer["CulturePurpose"]</td><td>@Localizer["OneYear"]</td></tr>
<tr><td>petabit-analytics-consent</td><td>@Localizer["ConsentPurpose"]</td><td>@Localizer["ConsentDuration"]</td></tr>
</tbody>
</table>
</div>

<h3>Analitički kolačići – Google Analytics 4</h3>
<p>Google Analytics učitava se samo nakon odabira <strong>Prihvaćam</strong>. Prikuplja zbirne podatke kao što su broj korisnika i sesija, približna lokacija, preglednik, uređaj i izvor dolaska. Ne koristimo ga za izravno utvrđivanje identiteta posjetitelja.</p>
<h3>@Localizer["AnalyticsCookies"]</h3>
<p>@Localizer["AnalyticsDescription"]</p>
<div class="table-responsive">
<table class="table">
<thead>
<tr><th>Naziv</th><th>Svrha</th><th>Trajanje</th></tr>
<tr><th>@Localizer["Name"]</th><th>@Localizer["Purpose"]</th><th>@Localizer["Duration"]</th></tr>
</thead>
<tbody>
<tr><td>_ga</td><td>Razlikuje jedinstvene korisnike.</td><td>Do 2 godine</td></tr>
<tr><td>_ga_W5Z2EDHVY4</td><td>Čuva stanje sesije za Google Analytics 4.</td><td>Do 2 godine</td></tr>
<tr><td>_ga</td><td>@Localizer["GaPurpose"]</td><td>@Localizer["UpToTwoYears"]</td></tr>
<tr><td>_ga_W5Z2EDHVY4</td><td>@Localizer["GaSessionPurpose"]</td><td>@Localizer["UpToTwoYears"]</td></tr>
</tbody>
</table>
</div>
<p>Više o GA4 kolačićima: <a href="https://support.google.com/analytics/answer/11397207" target="_blank" rel="noopener noreferrer">Google Analytics dokumentacija</a>.</p>
<p>@Localizer["GaMoreInfo"] <a href="https://support.google.com/analytics/answer/11397207" target="_blank" rel="noopener noreferrer">@Localizer["GaDocumentation"]</a>.</p>

<h3>Upravljanje privolom</h3>
<p>Analitičke kolačiće možete prihvatiti ili odbiti pri prvom posjetu. Svoju odluku možete promijeniti u bilo kojem trenutku.</p>
<button id="manage-analytics-consent" type="button" class="btn btn-outline-primary">Upravljaj analitičkim kolačićima</button>
<h3>@Localizer["ConsentManagement"]</h3>
<p>@Localizer["ConsentManagementText"]</p>
<button id="manage-analytics-consent" type="button" class="btn btn-outline-primary">@Localizer["ManageConsent"]</button>

<h2>@Localizer["DataSecurity"]</h2>
<p>@Localizer["DataSecurityText"]</p>
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

[![CI](https://github.com/ChevCellios/Petabit/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/ChevCellios/Petabit/actions/workflows/ci.yml)
[![Security](https://github.com/ChevCellios/Petabit/actions/workflows/security.yml/badge.svg?branch=master)](https://github.com/ChevCellios/Petabit/actions/workflows/security.yml)
[![Production](https://github.com/ChevCellios/Petabit/actions/workflows/uptime.yml/badge.svg?branch=master)](https://github.com/ChevCellios/Petabit/actions/workflows/uptime.yml)
[![Production smoke test](https://github.com/ChevCellios/Petabit/actions/workflows/uptime.yml/badge.svg?branch=master)](https://github.com/ChevCellios/Petabit/actions/workflows/uptime.yml)
[![Station status freshness](https://github.com/ChevCellios/Petabit/actions/workflows/station-status-freshness.yml/badge.svg?branch=master)](https://github.com/ChevCellios/Petabit/actions/workflows/station-status-freshness.yml)
[![Monitored by Better Stack](https://img.shields.io/badge/uptime-Better%20Stack-5B45FF)](https://betterstack.com/uptime)
![.NET](https://img.shields.io/badge/.NET-10.0-blueviolet)
![Language](https://img.shields.io/badge/language-C%23-orange)
![Localization](https://img.shields.io/badge/i18n-HR%20%7C%20EN%20%7C%20DE-green)
Expand Down Expand Up @@ -64,7 +66,7 @@ Izvori podataka:
- timeout, retry i circuit breaker za vanjski ISS servis
- `/health/live` provjera procesa i `/health/ready` provjera dostupnosti ISS servisa
- post-deployment smoke test nakon svakog pusha u `master`
- uptime provjera produkcije svakih 15 minuta
- Better Stack provjera produkcijskih liveness, readiness i ISS API endpointova svake 3 minute
- tjedna provjera starosti kuriranih podataka o ISS posadi i letjelicama
- smoke test početne stranice, readiness endpointa i ISS trackera
- strukturirani JSON logovi u produkciji
Expand Down
Loading