From d50cf2da8682f98a27ab43c4d5b2609099b3a73c Mon Sep 17 00:00:00 2001 From: video-prize-ranch Date: Thu, 4 Aug 2022 19:41:55 -0400 Subject: [PATCH] Add support for .env configuration and privacy page (closes #44) --- .env.example | 35 +++++++++++ .gitignore | 1 + Dockerfile | 4 +- README.md | 35 ++++++++--- go.mod | 1 + go.sum | 2 + main.go | 8 +++ pages/privacy.go | 19 ++++++ static/css/privacy.css | 58 ++++++++++++++++++ utils/config.go | 21 +++++-- views/privacy.hbs | 135 +++++++++++++++++++++++++++++++++++++++++ 11 files changed, 306 insertions(+), 13 deletions(-) create mode 100644 .env.example create mode 100644 pages/privacy.go create mode 100644 static/css/privacy.css create mode 100644 views/privacy.hbs diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6b60415 --- /dev/null +++ b/.env.example @@ -0,0 +1,35 @@ +ADDRESS=0.0.0.0 +PORT=3000 +FIBER_PREFORK=false +IMGUR_CLIENT_ID=546c25a59c58ad7 + +# Instance privacy +# For more information, see https://codeberg.org/librarian/librarian/wiki/Instance-privacy +# Required to be on the instance list. + +# Link to a privacy policy (optional) +PRIVACY_POLICY= +# Explain how this data is used/why it is collected (optional) +PRIVACY_MESSAGE= +# Country where instance is located. Leave blank if running on Tor without clearnet. +PRIVACY_COUNTRY= +# Hosting provider or ISP name. Leave blank if running on Tor without clearnet. +PRIVACY_PROVIDER= +# Set to true if you use Cloudflare (using Cloudflare only as DNS (gray cloud icon), set to false) +PRIVACY_CLOUDFLARE=false + +# These settings are for NGINX without data collection disabled. +# Instructions for other reverse proxies and to disable data collection: +# https://codeberg.org/librarian/librarian/wiki/Instance-privacy + +# Set to true if no data is collected. (overrides all other options) +PRIVACY_NOT_COLLECTED=false +# IP address +PRIVACY_IP=true +# Request URL +PRIVACY_URL=true +# Device Type (User agent) +PRIVACY_DEVICE=true +# If the data collection is only collected when there is an error and only stored for +# a short amount of time while diagnosing an issue. +PRIVACY_DIAGNOSTICS=false diff --git a/.gitignore b/.gitignore index de4d1f0..d14eab8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ dist node_modules +.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index e7db2f7..1e1a9a8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,11 +3,11 @@ FROM --platform=$BUILDPLATFORM golang:alpine AS build ARG TARGETARCH WORKDIR /src -RUN apk --no-cache add ca-certificates +RUN apk --no-cache add ca-certificates git COPY . . RUN go mod download -RUN GOOS=linux GOARCH=$TARGETARCH CGO_ENABLED=0 go build +RUN GOOS=linux GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags "-X codeberg.org/video-prize-ranch/rimgo/pages.VersionInfo=$(date '+%Y-%m-%d')-$(git rev-list --abbrev-commit -1 HEAD)" FROM scratch as bin diff --git a/README.md b/README.md index 01c6d43..3efc013 100644 --- a/README.md +++ b/README.md @@ -111,18 +111,39 @@ You can now run rimgo. ./rimgo ``` +To include version information use: +``` +go build -ldflags "-X codeberg.org/librarian/librarian/pages.VersionInfo=$(date '+%Y-%m-%d')-$(git rev-list --abbrev-commit -1 HEAD)" +``` + +(optional) You can use a .env file to set environment variables for configuration. +``` +cp .env.example .env +nvim .env +``` + ## Configuration -rimgo can be configured using environment variables. +rimgo can be configured using environment variables. The path to the .env file can be changed the -c flag. ### Environment variables -| Name | Default | -|-----------------|-----------------| -| PORT | 3000 | -| ADDRESS | 0.0.0.0 | -| IMGUR_CLIENT_ID | 546c25a59c58ad7 | -| FORCE_WEBP | 0 | +| Name | Default | +|-----------------------|-----------------| +| PORT | 3000 | +| ADDRESS | 0.0.0.0 | +| IMGUR_CLIENT_ID | 546c25a59c58ad7 | +| FORCE_WEBP | 0 | +| PRIVACY_POLICY | | +| PRIVACY_MESSAGE | | +| PRIVACY_COUNTRY | | +| PRIVACY_PROVIDER | | +| PRIVACY_CLOUDFLARE | | +| PRIVACY_NOT_COLLECTED | | +| PRIVACY_IP | | +| PRIVACY_URL | | +| PRIVACY_DEVICE | | +| PRIVACY_DIAGNOSTICS | | ## Contributing diff --git a/go.mod b/go.mod index 65a5038..e70be3d 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/dustin/go-humanize v1.0.0 github.com/gofiber/fiber/v2 v2.32.0 github.com/gofiber/template v1.6.27 + github.com/joho/godotenv v1.4.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/tidwall/gjson v1.14.1 ) diff --git a/go.sum b/go.sum index 073c345..1a1eeb8 100644 --- a/go.sum +++ b/go.sum @@ -241,6 +241,8 @@ github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= diff --git a/main.go b/main.go index 2ab358c..9f902f3 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "flag" "fmt" "net/http" @@ -12,9 +13,15 @@ import ( "github.com/gofiber/fiber/v2/middleware/filesystem" "github.com/gofiber/fiber/v2/middleware/recover" "github.com/gofiber/template/handlebars" + "github.com/joho/godotenv" ) func main() { + envPath := flag.String("c", ".env", "Path to env file") + err := godotenv.Load(*envPath) + if err != nil { + fmt.Println(err) + } utils.LoadConfig() engine := handlebars.NewFileSystem(http.FS(views.GetFiles()), ".hbs") @@ -51,6 +58,7 @@ func main() { }) app.Get("/", pages.HandleFrontpage) + app.Get("/privacy", pages.HandlePrivacy) app.Get("/:postID.gifv", pages.HandleGifv) app.Get("/:baseName.:extension", pages.HandleMedia) app.Get("/:postID", pages.HandlePost) diff --git a/pages/privacy.go b/pages/privacy.go new file mode 100644 index 0000000..d0bc026 --- /dev/null +++ b/pages/privacy.go @@ -0,0 +1,19 @@ +package pages + +import ( + "github.com/gofiber/fiber/v2" + + "codeberg.org/video-prize-ranch/rimgo/utils" +) + +var VersionInfo string + +func HandlePrivacy(c *fiber.Ctx) error { + utils.SetHeaders(c) + c.Set("X-Frame-Options", "DENY") + + return c.Render("privacy", fiber.Map{ + "config": utils.Config, + "version": VersionInfo, + }) +} diff --git a/static/css/privacy.css b/static/css/privacy.css new file mode 100644 index 0000000..45c60a5 --- /dev/null +++ b/static/css/privacy.css @@ -0,0 +1,58 @@ +main { + margin: 0 24vw +} + +p { + margin: 1em 0 +} + +ul { + list-style: outside none none; + padding: 0; + margin: 0.25em; + text-align: left; +} + +.largeIcon { + font-size: 36px; + color: #2b95f2; +} + +.badgeWrapper { + margin: 0 10vw +} + +.badge { + background-color: #3b3b3b; + border-radius: 8px; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.25em; + padding: 1em; + text-align: center; +} + +.badge h3, +.badge p, +.largeIcon { + margin: 0; +} + +.privacyDetails summary { + cursor: pointer; + user-select: none; + color: #2b95f2; + font-weight: 700; +} + +.addInfo { + margin-top: 1em; +} + +@media only screen and (max-width: 812px) { + .badgeWrapper, + main { + margin: 0 + } +} \ No newline at end of file diff --git a/utils/config.go b/utils/config.go index 45599a7..e2d7d59 100644 --- a/utils/config.go +++ b/utils/config.go @@ -35,9 +35,22 @@ func LoadConfig() { } Config = map[string]interface{}{ - "port": port, - "addr": addr, - "imgurId": imgurId, + "port": port, + "addr": addr, + "imgurId": imgurId, "fiberPrefork": fiberPrefork, + "privacy": map[string]interface{}{ + "set": os.Getenv("PRIVACY_NOT_COLLECTED") != "", + "policy": os.Getenv("PRIVACY_POLICY"), + "message": os.Getenv("PRIVACY_MESSAGE"), + "country": os.Getenv("PRIVACY_COUNTRY"), + "provider": os.Getenv("PRIVACY_PROVIDER"), + "cloudflare": os.Getenv("PRIVACY_CLOUDFLARE") == "true", + "not_collected": os.Getenv("PRIVACY_NOT_COLLECTED") == "true", + "ip": os.Getenv("PRIVACY_IP") == "true", + "url": os.Getenv("PRIVACY_URL") == "true", + "device": os.Getenv("PRIVACY_DEVICE") == "true", + "diagnostics": os.Getenv("PRIVACY_DIAGNOSTICS") == "true", + }, } -} \ No newline at end of file +} diff --git a/views/privacy.hbs b/views/privacy.hbs new file mode 100644 index 0000000..3538ea0 --- /dev/null +++ b/views/privacy.hbs @@ -0,0 +1,135 @@ + + + + + {{> 'partials/head' }} + + + + Instance privacy - rimgo + + + + {{> 'partials/header' }} + +
+

Instance Privacy

+ {{#if config.privacy.policy}} +

The instance operator has indicated their instance's privacy practices below. For more information, see the + instance operator's privacy policy.

+ {{else}} +

The instance operator has indicated their instance's privacy practices below.

+ {{/if}} + + {{#if config.privacy.message}} +

{{{config.privacy.message}}}

+ {{/if}} + + {{#if config.privacy.not_collected}} +
+
+ + check_circle + +

Data Not Collected

+

The instance operator does not collect any data from this instance.

+
+
+ {{/if}} + + {{#unless config.privacy.set}} +
+
+ + report_problem + +

No Details Provided

+

The operator of this instance will be required to provide privacy details to be added to the instance list. +

+
+
+ {{else}} + {{#unless config.privacy.not_collected}} +
+
+ + error_outline + +

Data Collected

+

The following data may be collected:

+
    + {{#if config.privacy.ip}} +
  • + password + Internet address (IP Address) +
  • + {{/if}} + {{#if config.privacy.url}} +
  • + link + Page viewed (Request URL) +
  • + {{/if}} + {{#if config.privacy.device}} +
  • + phonelink + Device Type (User agent) +
  • + {{/if}} + {{#if config.privacy.diagnostics}} +
  • + settings + Diagnostics +
  • + {{/if}} +
+
+
+ {{/unless}} + {{/unless}} + +
+ What's this? +

+ Instance privacy aims to bring transparency to the data collected by frontends and encourage privacy friendly practices. There is often no privacy policy and users are forced to trust that the instance operator is not collecting data. However, there is a possibility that the instance operator can put false information so we encourage looking at other factors when selecting an instance. +

+
    +
  • + password + Internet address (IP Address) - This is an address that is given to your computer or internet connection. + This can be used to find your city or region and internet provider but can change depending on your connection. +
  • +
  • + link + Page viewed (Request URL) - This is what page you are viewing. Searches are kept private. +
  • +
  • + phonelink + Device Type (User agent) - This is what browser, device, and operating system you are using. + Advanced users can change this with an extension or browser setting. +
  • +
  • + settings + Diagnostics - When this data is only collected when there is an error or only a short amount of time while + diagnosing an issue. +
  • +
+
+ +

Additional information

+ +
+ + {{> 'partials/footer' }} + + + \ No newline at end of file