fix(terms): Display template notice, support custom terms loading
Closes #1523
This commit is contained in:
@@ -23,3 +23,7 @@ test
|
||||
views/index.html
|
||||
|
||||
data/*
|
||||
|
||||
terms/*
|
||||
!terms/_template
|
||||
!terms/cloud
|
||||
|
||||
@@ -138,3 +138,7 @@ views/index.html
|
||||
|
||||
data/*
|
||||
!data/.gitkeep
|
||||
|
||||
terms/*
|
||||
!terms/_template
|
||||
!terms/cloud
|
||||
|
||||
@@ -57,6 +57,12 @@
|
||||
* format: uri
|
||||
* description: URL to the customer management panel (conditionally added for admins if configured)
|
||||
* example: https://panel.example.com
|
||||
* termsLanguages:
|
||||
* type: array
|
||||
* description: List of available language codes for terms localization
|
||||
* items:
|
||||
* type: string
|
||||
* example: [de-DE, en-US]
|
||||
* version:
|
||||
* type: string
|
||||
* description: Current version of the PLANKA application
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
* description: Language code for terms localization
|
||||
* schema:
|
||||
* type: string
|
||||
* enum: [de-DE, en-US]
|
||||
* example: en-US
|
||||
* responses:
|
||||
* 200:
|
||||
@@ -41,7 +40,6 @@
|
||||
* properties:
|
||||
* language:
|
||||
* type: string
|
||||
* enum: [de-DE, en-US]
|
||||
* description: Language code used
|
||||
* example: en-US
|
||||
* content:
|
||||
@@ -65,7 +63,6 @@ module.exports = {
|
||||
inputs: {
|
||||
language: {
|
||||
type: 'string',
|
||||
isIn: User.LANGUAGES,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ module.exports = {
|
||||
fn(inputs) {
|
||||
const data = {
|
||||
oidc: inputs.oidc,
|
||||
termsLanguages: sails.hooks.terms.getLanguages(),
|
||||
version: sails.config.custom.version,
|
||||
};
|
||||
|
||||
|
||||
@@ -12,25 +12,35 @@
|
||||
*/
|
||||
|
||||
const fsPromises = require('fs').promises;
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const LANGUAGES = ['de-DE', 'en-US'];
|
||||
const DEFAULT_LANGUAGE = 'en-US';
|
||||
|
||||
const getContent = (language = DEFAULT_LANGUAGE) =>
|
||||
fsPromises.readFile(
|
||||
`${sails.config.appPath}/terms/${sails.config.custom.termsType}/${language}.md`,
|
||||
'utf8',
|
||||
);
|
||||
const PATH = path.join(sails.config.appPath, 'terms');
|
||||
const TEMPLATE_TYPE = '_template';
|
||||
|
||||
const hashContent = (content) => crypto.createHash('sha256').update(content).digest('hex');
|
||||
|
||||
module.exports = function defineTermsHook(sails) {
|
||||
let type;
|
||||
let languages;
|
||||
let defaultLanguage;
|
||||
let signature;
|
||||
|
||||
return {
|
||||
LANGUAGES,
|
||||
const getLanguages = async () => {
|
||||
const entries = await fsPromises.readdir(path.join(PATH, type), {
|
||||
withFileTypes: true,
|
||||
});
|
||||
|
||||
return entries
|
||||
.filter((entry) => entry.isFile() && path.extname(entry.name) === '.md')
|
||||
.map((entry) => path.basename(entry.name, '.md'))
|
||||
.sort();
|
||||
};
|
||||
|
||||
const getContent = (language) =>
|
||||
fsPromises.readFile(path.join(PATH, type, `${language}.md`), 'utf8');
|
||||
|
||||
return {
|
||||
/**
|
||||
* Runs when this Sails app loads/lifts.
|
||||
*/
|
||||
@@ -38,13 +48,32 @@ module.exports = function defineTermsHook(sails) {
|
||||
async initialize() {
|
||||
sails.log.info('Initializing custom hook (`terms`)');
|
||||
|
||||
const content = await getContent();
|
||||
type = sails.config.custom.termsType;
|
||||
|
||||
try {
|
||||
languages = await getLanguages();
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
if (!languages || languages.length === 0) {
|
||||
sails.log.warn('Custom terms not found, falling back to template');
|
||||
|
||||
type = TEMPLATE_TYPE;
|
||||
languages = await getLanguages();
|
||||
}
|
||||
|
||||
defaultLanguage = languages.includes(sails.config.i18n.defaultLocale)
|
||||
? sails.config.i18n.defaultLocale
|
||||
: languages[0];
|
||||
|
||||
const content = await getContent(defaultLanguage);
|
||||
signature = hashContent(content);
|
||||
},
|
||||
|
||||
async getPayload(language = DEFAULT_LANGUAGE) {
|
||||
if (!LANGUAGES.includes(language)) {
|
||||
language = DEFAULT_LANGUAGE; // eslint-disable-line no-param-reassign
|
||||
async getPayload(language) {
|
||||
if (!language || !languages.includes(language)) {
|
||||
language = defaultLanguage; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
const content = await getContent(language);
|
||||
@@ -56,6 +85,10 @@ module.exports = function defineTermsHook(sails) {
|
||||
};
|
||||
},
|
||||
|
||||
getLanguages() {
|
||||
return languages;
|
||||
},
|
||||
|
||||
isSignatureValid(value) {
|
||||
return value === signature;
|
||||
},
|
||||
|
||||
@@ -113,7 +113,7 @@ module.exports.custom = {
|
||||
/* Internal */
|
||||
|
||||
internalAccessToken: process.env.INTERNAL_ACCESS_TOKEN,
|
||||
termsType: process.env.TERMS_TYPE || 'self-hosted',
|
||||
termsType: process.env.TERMS_TYPE || 'custom',
|
||||
customerPanelUrl: process.env.CUSTOMER_PANEL_URL,
|
||||
demoMode: process.env.DEMO_MODE === 'true',
|
||||
};
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
# ⚠️ DIES IST NUR EINE BEISPIEL-VORLAGE
|
||||
|
||||
Wenn Sie Administrator dieser Instanz sind, können Sie diese Bedingungen an Ihre eigenen Bedürfnisse und rechtlichen Anforderungen anpassen.
|
||||
|
||||
Eine Anleitung zum Anpassen dieser Vorlage finden Sie in diesem [Guide](https://docs.planka.cloud/docs/configuration/customizing-end-user-terms/).
|
||||
|
||||
---
|
||||
|
||||
# Nutzungsbedingungen für Endbenutzer – On-Premise-Version
|
||||
|
||||
**Stand: 11. Februar 2026 – v1.0**
|
||||
@@ -76,6 +84,7 @@ Der Anbieter kann diese Nutzungsbedingungen mit Wirkung für die Zukunft ändern
|
||||
|
||||
*PLANKA Software GmbH · Lindauer Str. 4 · 87439 Kempten · Deutschland*
|
||||
|
||||
[confirmations]::
|
||||
---
|
||||
|
||||
✔️ **Ich habe diese Nutzungsbedingungen gelesen und akzeptiere sie**
|
||||
@@ -1,3 +1,11 @@
|
||||
# ⚠️ THIS IS ONLY A TEMPLATE
|
||||
|
||||
If you are the admin of this instance, you can customize these Terms to suit your own needs and legal requirements.
|
||||
|
||||
For guidance on updating this template, see this [guide](https://docs.planka.cloud/docs/configuration/customizing-end-user-terms/).
|
||||
|
||||
---
|
||||
|
||||
# End User Terms of Service – On-Premise Version
|
||||
|
||||
**Effective: February 11, 2026 – v1.0**
|
||||
@@ -76,6 +84,7 @@ The Provider may amend these End User Terms of Service with effect for the futur
|
||||
|
||||
*PLANKA Software GmbH · Lindauer Str. 4 · 87439 Kempten · Germany*
|
||||
|
||||
[confirmations]::
|
||||
---
|
||||
|
||||
✔️ **I have read and accept these End User Terms of Service**
|
||||
@@ -124,6 +124,7 @@ Die vollständige Datenschutzerklärung mit allen Details zu Sub-Auftragsverarbe
|
||||
|
||||
*PLANKA Software GmbH · Lindauer Str. 4 · 87439 Kempten · Deutschland*
|
||||
|
||||
[confirmations]::
|
||||
---
|
||||
|
||||
✔️ **Ich habe die Nutzungsbedingungen (Teil I) gelesen und akzeptiere sie**
|
||||
|
||||
@@ -124,6 +124,7 @@ The full Privacy Policy with complete details on sub-processors, technical measu
|
||||
|
||||
*PLANKA Software GmbH · Lindauer Str. 4 · 87439 Kempten · Germany*
|
||||
|
||||
[confirmations]::
|
||||
---
|
||||
|
||||
✔️ **I have read and accept the Terms of Service (Part I)**
|
||||
|
||||
Reference in New Issue
Block a user