From f464d9ba4b0ac61a637eb16a6a533700e73524da Mon Sep 17 00:00:00 2001 From: Tassilo Pitrasch <60175677+TassiloPitrasch@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:22:33 +0100 Subject: [PATCH] Added memcached support for the new TTL feature (#32) * Reworked the memcached-client to return a static TTL. Adapted the frontend to handle invalid TTLs and use the translation mechanism * Updated Docker deployment for memcached --- .../insecure-memcached/docker-compose.yml | 32 ++++++++++++------- pkg/server/memcached.go | 1 + website/public/locales/en.json | 5 ++- website/src/displaySecret/DisplaySecret.tsx | 5 +-- website/src/displaySecret/Secret.tsx | 25 ++++++++++++--- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/deploy/docker-compose/insecure-memcached/docker-compose.yml b/deploy/docker-compose/insecure-memcached/docker-compose.yml index 614cc6a47..e16bee51e 100644 --- a/deploy/docker-compose/insecure-memcached/docker-compose.yml +++ b/deploy/docker-compose/insecure-memcached/docker-compose.yml @@ -1,15 +1,25 @@ -version: "3.0" - services: - memcached: - image: memcached - restart: always - expose: - - "11211" - yopass: - image: jhaals/yopass + image: TassiloPitrasch/yopass:latest + container_name: yopass restart: always + networks: + - yopass_internal + - yopass_external ports: - - "127.0.0.1:80:80" - command: "--memcached=memcached:11211 --port 80" + - "80:80" + command: "--database=memcached --memcached=yopass_memcached:11211 --port 80" + + memcached: + image: memcached:latest + container_name: yopass_memcached + restart: always + networks: + - yopass_internal + +networks: + yopass_internal: + internal: true + yopass_external: + driver: bridge + internal: false diff --git a/pkg/server/memcached.go b/pkg/server/memcached.go index 496fa82a2..beefe16ab 100644 --- a/pkg/server/memcached.go +++ b/pkg/server/memcached.go @@ -20,6 +20,7 @@ type Memcached struct { // Get key in memcached func (m *Memcached) Get(key string) (yopass.Secret, error) { var s yopass.Secret + s.TTL = -1 r, err := m.Client.Get(key) if err != nil { diff --git a/website/public/locales/en.json b/website/public/locales/en.json index ddbf4431a..7be8c4c8a 100644 --- a/website/public/locales/en.json +++ b/website/public/locales/en.json @@ -46,7 +46,10 @@ "secret": { "titleFile": "File downloaded", "titleMessage": "Decrypted message", - "buttonCopy": "Copy" + "buttonCopy": "Copy", + "expiresOn": "This secret will expire on {{formattedExpiryDate}}. Be sure to copy/download it until then!", + "expireUnkown": "Could not parse the secret's remaining time-to-live. Be sure to copy/download the secret NOW!", + "oneTime": "This secret is one-time only. It's not stored anywhere anymore. Be sure to copy/download it NOW!" }, "delete": { "buttonDelete": "Delete", diff --git a/website/src/displaySecret/DisplaySecret.tsx b/website/src/displaySecret/DisplaySecret.tsx index 5b4fb5d88..ea52c201b 100644 --- a/website/src/displaySecret/DisplaySecret.tsx +++ b/website/src/displaySecret/DisplaySecret.tsx @@ -143,12 +143,9 @@ const DisplaySecret = () => { ); } if (value) { - var expiryDate = new Date(); - expiryDate.setMilliseconds(data.ttl / 1000000); - return ( <> - + {data.one_time ? null : } ); diff --git a/website/src/displaySecret/Secret.tsx b/website/src/displaySecret/Secret.tsx index 70fffe374..06fa3bf2a 100644 --- a/website/src/displaySecret/Secret.tsx +++ b/website/src/displaySecret/Secret.tsx @@ -111,27 +111,42 @@ const DownloadSecret = ({ const Secret = ({ secret, fileName, - expiryDate, + ttl, oneTime, }: { readonly secret: string; readonly fileName?: string; - readonly expiryDate: Date; + readonly ttl: number; readonly oneTime: boolean; }) => { + const { t } = useTranslation(); if (! oneTime) { const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; const DateTimeFormat = Intl.DateTimeFormat.supportedLocalesOf([i18n.language], {localeMatcher: "lookup"}) ? i18n.language : "en-US"; - var formattedDate = new Intl.DateTimeFormat(DateTimeFormat, { + var expiryDate = new Date(); + try { + + if (ttl < 0) { + throw RangeError; + } + else { + expiryDate.setMilliseconds(ttl / 1000000); + } + + var formattedExpiryDate = new Intl.DateTimeFormat(DateTimeFormat, { dateStyle: 'full', timeStyle: 'long', timeZone: timeZone, }).format(expiryDate); - var notice = "This secret will expire on " + formattedDate + ". Be sure to copy/download it until then!"; + var notice = t('secret.expiresOn', {formattedExpiryDate: formattedExpiryDate});; + } + catch(RangeError) { + var notice = t('secret.expireUnkown'); + } } else { - var notice = "This secret is one-time only. It's not stored anywhere anymore. Be sure to copy/download it NOW!"; + var notice = t('secret.oneTime'); } if (fileName) { return ;