diff --git a/package-lock.json b/package-lock.json index 1d5569525..607a6d4f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2799,10 +2799,24 @@ "url-regex": "~4.1.1" }, "dependencies": { + "ip-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", + "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=" + }, "normalize-url": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.2.0.tgz", "integrity": "sha512-WvF3Myk0NhXkG8S9bygFM4IC1KOvnVJGq0QoGeoqOYOBeinBZp5ybW3QuYbTc89lkWBMM9ZBO4QGRoc0353kKA==" + }, + "url-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-4.1.1.tgz", + "integrity": "sha512-ViSDgDPNKkrQHI81GLCjdDN+Rsk3tAW/uLXlBOJxtcHzWZjta58Z0APXhfXzS89YszsheMnEvXeDXsWUB53wwA==", + "requires": { + "ip-regex": "^1.0.1", + "tlds": "^1.187.0" + } } } }, @@ -18026,9 +18040,10 @@ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" }, "ip-regex": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", - "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.1.0.tgz", + "integrity": "sha512-pKnZpbgCTfH/1NLIlOduP/V+WRXzC2MOz3Qo8xmxk8C5GudJLgK5QyLVXOSWy3ParAH7Eemurl3xjv/WXYFvMA==", + "dev": true }, "ipaddr.js": { "version": "1.6.0", @@ -33949,12 +33964,13 @@ } }, "url-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-4.1.1.tgz", - "integrity": "sha512-ViSDgDPNKkrQHI81GLCjdDN+Rsk3tAW/uLXlBOJxtcHzWZjta58Z0APXhfXzS89YszsheMnEvXeDXsWUB53wwA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-5.0.0.tgz", + "integrity": "sha512-O08GjTiAFNsSlrUWfqF1jH0H1W3m35ZyadHrGv5krdnmPPoxP27oDTqux/579PtaroiSGm5yma6KT1mHFH6Y/g==", + "dev": true, "requires": { - "ip-regex": "^1.0.1", - "tlds": "^1.187.0" + "ip-regex": "^4.1.0", + "tlds": "^1.203.0" } }, "use": { diff --git a/package.json b/package.json index c9a6a8165..fc025d1e9 100644 --- a/package.json +++ b/package.json @@ -344,6 +344,7 @@ "typeface-source-sans-pro": "^0.0.54", "typescript": "3.3.4000", "typescript-snapshots-plugin": "^1.6.0", + "url-regex": "^5.0.0", "wait-for-expect": "^1.1.1", "webpack": "^4.30.0", "webpack-assets-manifest": "^3.1.1", diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfig.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfig.tsx index 2b07daf7f..01d870f66 100644 --- a/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfig.tsx @@ -8,6 +8,7 @@ import { parseStringList, ValidationMessage, } from "coral-framework/lib/form"; +import { validateStrictURLList } from "coral-framework/lib/validation"; import { FormField, HorizontalGutter, @@ -32,18 +33,21 @@ const PermittedDomainsConfig: FunctionComponent = ({ disabled }) => ( } > - Domains where your Coral instance is allowed to be embedded. Typical - use is localhost, staging.yourdomain.com, yourdomain.com, etc. + The domains you would like to permit for Coral, e.g. your local, + staging and production environments including the scheme (ex. + http://localhost:3000, https://staging.domain.com, + https://domain.com). {({ input, meta }) => ( <> diff --git a/src/core/client/admin/test/configure/__snapshots__/advanced.spec.tsx.snap b/src/core/client/admin/test/configure/__snapshots__/advanced.spec.tsx.snap index 5e3ac9bea..163dba561 100644 --- a/src/core/client/admin/test/configure/__snapshots__/advanced.spec.tsx.snap +++ b/src/core/client/admin/test/configure/__snapshots__/advanced.spec.tsx.snap @@ -299,9 +299,9 @@ each of your site’s stories.

- Domains where your Coral instance is allowed to be embedded. -Typical use is localhost, staging.yourdomain.com, -yourdomain.com, etc. + Domains where your Coral instance is allowed to be embedded +including the scheme (ex. http://localhost:3000, https://staging.domain.com, +https://domain.com).

diff --git a/src/core/client/admin/test/configure/advanced.spec.tsx b/src/core/client/admin/test/configure/advanced.spec.tsx index 00285ec04..b4d7386b1 100644 --- a/src/core/client/admin/test/configure/advanced.spec.tsx +++ b/src/core/client/admin/test/configure/advanced.spec.tsx @@ -216,8 +216,8 @@ it("change permitted domains to include more domains", async () => { Mutation: { updateSettings: ({ variables }) => { expectAndFail(variables.settings.allowedDomains).toEqual([ - "localhost:8080", - "localhost:3000", + "http://localhost:8080", + "http://localhost:3000", ]); return { settings: pureMerge(settings, variables.settings), @@ -238,7 +238,9 @@ it("change permitted domains to include more domains", async () => { ); // Let's change the permitted domains. - permittedDomainsField.props.onChange("localhost:8080, localhost:3000"); + permittedDomainsField.props.onChange( + "http://localhost:8080, http://localhost:3000" + ); // Send form within(configureContainer) diff --git a/src/core/client/admin/test/fixtures.ts b/src/core/client/admin/test/fixtures.ts index 042bf9518..378a5f224 100644 --- a/src/core/client/admin/test/fixtures.ts +++ b/src/core/client/admin/test/fixtures.ts @@ -50,7 +50,7 @@ export const settings = createFixture({ enabled: true, }, customCSSURL: "", - allowedDomains: ["localhost:8080"], + allowedDomains: ["http://localhost:8080"], editCommentWindowLength: 30000, communityGuidelines: { enabled: false, diff --git a/src/core/client/framework/lib/validation.spec.tsx b/src/core/client/framework/lib/validation.spec.tsx index e7f59800e..dc561b339 100644 --- a/src/core/client/framework/lib/validation.spec.tsx +++ b/src/core/client/framework/lib/validation.spec.tsx @@ -1,4 +1,4 @@ -import { createValidator } from "./validation"; +import { createValidator, validateStrictURLList } from "./validation"; describe("createValidator", () => { it("should report error when condition is unmet", () => { @@ -10,3 +10,25 @@ describe("createValidator", () => { expect(truthy(true, {})).toBe(undefined); }); }); + +describe("validateStrictURLList", () => { + it("should reject a URL without a scheme", () => { + expect(validateStrictURLList(["localhost"], {})).toBeDefined(); + }); + + it("should reject multiple URLs without a scheme", () => { + expect( + validateStrictURLList(["http://localhost", "localhost"], {}) + ).toBeDefined(); + }); + + it("should allow a URL with a scheme", () => { + expect(validateStrictURLList(["http://localhost"], {})).toBeUndefined(); + }); + + it("should allow multiple URLs with a scheme", () => { + expect( + validateStrictURLList(["http://localhost", "https://localhost"], {}) + ).toBeUndefined(); + }); +}); diff --git a/src/core/client/framework/lib/validation.tsx b/src/core/client/framework/lib/validation.tsx index 744d69c77..0f5d49fe9 100644 --- a/src/core/client/framework/lib/validation.tsx +++ b/src/core/client/framework/lib/validation.tsx @@ -58,7 +58,8 @@ export function composeValidators( * required is a Validator that checks that the value is truthy. */ export const required = createValidator( - v => v !== "" && v !== null && v !== undefined, + v => + Array.isArray(v) ? v.length > 0 : v !== "" && v !== null && v !== undefined, VALIDATION_REQUIRED() ); @@ -217,6 +218,28 @@ export const validatePercentage = (min: number, max: number) => NOT_A_WHOLE_NUMBER_BETWEEN(min * 100, max * 100) ); +export const validateStrictURLList = createValidator(v => { + if (!Array.isArray(v)) { + return false; + } + + for (const url of v) { + if (typeof url !== "string") { + return false; + } + + if (!URL_REGEX.test(url)) { + return false; + } + + if (!url.startsWith("http")) { + return false; + } + } + + return true; +}, INVALID_URL()); + /** * Condition represents a given check that can be performed for the purpose of * filtering a validation operation. diff --git a/src/core/client/install/App/steps/PermittedDomainsStep.tsx b/src/core/client/install/App/steps/PermittedDomainsStep.tsx index 743746c95..d98699b8b 100644 --- a/src/core/client/install/App/steps/PermittedDomainsStep.tsx +++ b/src/core/client/install/App/steps/PermittedDomainsStep.tsx @@ -5,9 +5,12 @@ import { Field, Form } from "react-final-form"; import { colorFromMeta, + formatStringList, OnSubmit, + parseStringList, ValidationMessage, } from "coral-framework/lib/form"; +import { validateStrictURLList } from "coral-framework/lib/validation"; import { Button, CallOut, @@ -23,7 +26,7 @@ import { import BackButton from "./BackButton"; interface FormProps { - allowedDomains: string; + allowedDomains: string[]; } interface Props { @@ -34,9 +37,8 @@ interface Props { } class PermittedDomainsStep extends Component { - private onSubmit: OnSubmit = async (input, form) => { + private onSubmit: OnSubmit = async ({ allowedDomains }, form) => { try { - const allowedDomains = input.allowedDomains.split(","); await this.props.onInstall({ allowedDomains }); return this.props.onGoToNextStep(); } catch (error) { @@ -48,7 +50,7 @@ class PermittedDomainsStep extends Component {
{({ handleSubmit, submitting, submitError }) => ( @@ -59,11 +61,12 @@ class PermittedDomainsStep extends Component { Permitted Domains - + Enter the domains you would like to permit for Coral, e.g. - your local, staging and production environments (ex. - localhost:3000, staging.domain.com, domain.com). + your local, staging and production environments including the + scheme (ex. http://localhost:3000, https://staging.domain.com, + https://domain.com). @@ -73,7 +76,12 @@ class PermittedDomainsStep extends Component { )} - + {({ input, meta }) => ( diff --git a/src/core/common/helpers/validate.ts b/src/core/common/helpers/validate.ts index cde19e11c..42829adfb 100644 --- a/src/core/common/helpers/validate.ts +++ b/src/core/common/helpers/validate.ts @@ -1,3 +1,5 @@ +import url from "url-regex"; + export const USERNAME_REGEX = new RegExp(/^[a-zA-Z0-9_.]+$/); export const USERNAME_MAX_LENGTH = 30; export const USERNAME_MIN_LENGTH = 3; @@ -6,9 +8,7 @@ export const PASSWORD_MIN_LENGTH = 8; export const EMAIL_REGEX = new RegExp(/^\S+@\S+.\S+$/); -export const URL_REGEX = new RegExp( - /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ -); +export const URL_REGEX = url({ exact: true, strict: true }); /** * ADDITIONAL_DETAILS_MAX_LENGTH defines the maximum length for the diff --git a/src/core/server/app/handlers/api/install.ts b/src/core/server/app/handlers/api/install.ts index 59e331f46..053f82252 100644 --- a/src/core/server/app/handlers/api/install.ts +++ b/src/core/server/app/handlers/api/install.ts @@ -35,7 +35,7 @@ const TenantInstallBodySchema = Joi.object().keys({ allowedDomains: Joi.array().items( Joi.string() .trim() - .uri() + .uri({ scheme: ["http", "https"] }) ), locale: Joi.string() .default(null) diff --git a/src/core/server/app/middleware/csp/tenant.spec.ts b/src/core/server/app/middleware/csp/tenant.spec.ts index 4b4c0cc0c..2c73a7edf 100644 --- a/src/core/server/app/middleware/csp/tenant.spec.ts +++ b/src/core/server/app/middleware/csp/tenant.spec.ts @@ -60,45 +60,3 @@ it("allows from the domain when it does provide a match and there are multiple t "allow-from https://news.coralproject.net" ); }); - -it("it prefixes domains of the tenant when generating the frame option", () => { - const tenant = { - allowedDomains: ["coralproject.net", "news.coralproject.net"], - }; - const req = { - headers: {}, - query: { parentUrl: "http://news.coralproject.net/a/page" }, - } as Request; - - expect(generateFrameOptions(req, tenant)).toEqual( - "allow-from http://news.coralproject.net" - ); -}); - -it("it prefixes domains of the tenant when generating the frame option", () => { - const tenant = { - allowedDomains: ["coralproject.net", "news.coralproject.net"], - }; - const req = { - headers: {}, - query: { parentUrl: "https://news.coralproject.net/a/page" }, - } as Request; - - expect(generateFrameOptions(req, tenant)).toEqual( - "allow-from https://news.coralproject.net" - ); -}); - -it("it prefixes domains of the tenant when generating the frame option and denies based on it", () => { - const tenant = { - allowedDomains: ["coralproject.net", "news.coralproject.net"], - }; - const req = { - headers: {}, - query: { parentUrl: "http://news.coralproject.net/a/page" }, - } as Request; - - expect(generateFrameOptions(req, tenant)).toEqual( - "allow-from http://news.coralproject.net" - ); -}); diff --git a/src/core/server/app/middleware/csp/tenant.ts b/src/core/server/app/middleware/csp/tenant.ts index 8373efe9a..42f1ecced 100644 --- a/src/core/server/app/middleware/csp/tenant.ts +++ b/src/core/server/app/middleware/csp/tenant.ts @@ -1,11 +1,5 @@ import builder from "content-security-policy-builder"; -import { - doesRequireSchemePrefixing, - extractParentsURL, - getOrigin, - isURLSecure, - prefixSchemeIfRequired, -} from "coral-server/app/url"; +import { extractParentsURL, getOrigin } from "coral-server/app/url"; import { Tenant } from "coral-server/models/tenant"; import { isURLPermitted } from "coral-server/services/tenant/url"; import { Request, RequestHandler } from "coral-server/types/express"; @@ -23,7 +17,7 @@ export const cspTenantMiddleware: RequestHandler = (req, res, next) => { res.setHeader( "Content-Security-Policy", - generateContentSecurityPolicy(req, tenant) + generateContentSecurityPolicy(tenant) ); // Add some fallbacks for IE. @@ -33,10 +27,7 @@ export const cspTenantMiddleware: RequestHandler = (req, res, next) => { next(); }; -function generateContentSecurityPolicy( - req: Request, - tenant: Pick -) { +function generateContentSecurityPolicy(tenant: Pick) { const directives: Record = {}; // Only the domains that are allowed by the tenant may embed Coral. @@ -58,12 +49,8 @@ export function generateFrameOptions( return "deny"; } - // If there is only one domain on the tenant, and we don't require - // prefixing, then return it! - if ( - tenant.allowedDomains.length === 1 && - !doesRequireSchemePrefixing(tenant.allowedDomains[0]) - ) { + // If there is only one domain on the tenant then return it! + if (tenant.allowedDomains.length === 1) { return `allow-from ${getOrigin(tenant.allowedDomains[0])}`; } @@ -78,23 +65,6 @@ export function generateFrameOptions( return "deny"; } - // Grab the status if the parent url is secure. - const parentSecure = isURLSecure(parentsOrigin); - if (parentSecure === null) { - return "deny"; - } - - // If there is only one domain on the tenant, and we require prefixing, then - // return it with prefixing! - if ( - tenant.allowedDomains.length === 1 && - !doesRequireSchemePrefixing(tenant.allowedDomains[0]) - ) { - return `allow-from ${getOrigin( - prefixSchemeIfRequired(parentSecure, tenant.allowedDomains[0]) - )}`; - } - // Determine if this origin is allowed. if (!isURLPermitted(tenant, parentsURL)) { return "deny"; @@ -105,7 +75,7 @@ export function generateFrameOptions( // We need to find the domain that is asking so we can respond with the right // result, sort of like CORS! const allowFrom = tenant.allowedDomains - .map(domain => getOrigin(prefixSchemeIfRequired(parentSecure, domain))) + .map(domain => getOrigin(domain)) .find(origin => origin === parentsOrigin); if (!allowFrom) { return "deny"; diff --git a/src/locales/da/admin.ftl b/src/locales/da/admin.ftl index b85636a3e..8c3ef157d 100644 --- a/src/locales/da/admin.ftl +++ b/src/locales/da/admin.ftl @@ -87,9 +87,9 @@ configure-permissionField-dontAllow = Ikke tilladt ### General configure-general-guidelines-title = Oversigt over fællesskabsretningslinjer configure-general-guidelines-explanation = - Skriv en oversigt over dine fællesskabsretningslinjer, - der vises øverst i hver side af kommentarstrømmen. - Dit resume kan formateres ved hjælp af Markdown Syntax. + Skriv en oversigt over dine fællesskabsretningslinjer, + der vises øverst i hver side af kommentarstrømmen. + Dit resume kan formateres ved hjælp af Markdown Syntax. Mere information om hvordan du bruger Markdown kan findes her. configure-general-guidelines-showCommunityGuidelines = Vis oversigt over fællesskabsretningslinjer @@ -97,9 +97,9 @@ configure-general-guidelines-showCommunityGuidelines = Vis oversigt over fælles ### Sitewide Commenting configure-general-sitewideCommenting-title = Kommentar på webstedet configure-general-sitewideCommenting-explanation = - Åbn eller luk kommentarstrømme for nye kommentarer overalt. - Når nye kommentarer deaktiveres overalt, kan nye kommentarer - ikke indsendes, men eksisterende kommentarer kan fortsætte + Åbn eller luk kommentarstrømme for nye kommentarer overalt. + Når nye kommentarer deaktiveres overalt, kan nye kommentarer + ikke indsendes, men eksisterende kommentarer kan fortsætte med at modtage reaktioner, rapporteres og deles. configure-general-sitewideCommenting-enableNewCommentsSitewide = Aktivér nye kommentarer overalt @@ -132,8 +132,8 @@ configure-general-commentLength-validateLongerThanMin = #### Comment Editing configure-general-commentEditing-title = Kommentarredigering configure-general-commentEditing-explanation = - Sæt en grænse for, hvor længe kommentatorer skal redigere deres - kommentarer på siden. Redigerede kommentarer markeres som (Redigeret) + Sæt en grænse for, hvor længe kommentatorer skal redigere deres + kommentarer på siden. Redigerede kommentarer markeres som (Redigeret) i kommentarstrømmen og moderationspanelet. configure-general-commentEditing-commentEditTimeFrame = Kommentar Rediger tidsramme configure-general-commentEditing-seconds = Sekunder @@ -148,8 +148,8 @@ configure-organization-nameExplanation = Dit organisationsnavn vises på e-mails sendt af { -product-name } til dit community og organisationsmedlemmer. configure-organization-email = Organisations-e-mail configure-organization-emailExplanation = - Denne e-mail-adresse bruges som i e-mails og på tværs af platformen, - hvor medlemmer af samfundet kan komme i kontakt med organisationen, + Denne e-mail-adresse bruges som i e-mails og på tværs af platformen, + hvor medlemmer af samfundet kan komme i kontakt med organisationen, hvis de har spørgsmål om status for deres konti eller moderationsspørgsmål. ### Email @@ -183,19 +183,19 @@ configure-auth-targetFilterCommentStream = Kommentarer configure-auth-redirectURI = Omdiriger URI configure-auth-registration = Registrering configure-auth-registrationDescription = - Lad brugere, der ikke har tilmeldt sig tidligere med denne + Lad brugere, der ikke har tilmeldt sig tidligere med denne godkendelsesintegration, registrere sig for en ny konto. configure-auth-registrationCheckBox = Tillad registrering configure-auth-pleaseEnableAuthForAdmin = Aktivér mindst én godkendelsesintegration til Administration af { -product-name } configure-auth-confirmNoAuthForCommentStream = - Der er ikke aktiveret nogen godkendelsesintegration for kommentarstrømmen. + Der er ikke aktiveret nogen godkendelsesintegration for kommentarstrømmen. Vil du virkelig fortsætte? configure-auth-facebook-loginWith = Log ind med Facebook configure-auth-facebook-toEnableIntegration = - For at aktivere integrationen med Facebook-godkendelse skal - du oprette og konfigurere en webapplikation. + For at aktivere integrationen med Facebook-godkendelse skal + du oprette og konfigurere en webapplikation. For mere information besøg: . configure-auth-facebook-useLoginOn = Brug Facebook til at logge på @@ -225,9 +225,9 @@ configure-auth-oidc-providerNameDescription = Udbyderen af OpenID Connect-integrationen. Dette bruges, når udbyderens navn skal vises, f.eks. “Log ind med <Facebook>”. configure-auth-oidc-issuer = Udsteder configure-auth-oidc-issuerDescription = - Når du har indtastet dine udstederoplysninger, + Når du har indtastet dine udstederoplysninger, skal du klikke på knappen Opdag for at få { -product-name } - til at udfylde de resterende felter. Du kan også + til at udfylde de resterende felter. Du kan også indtaste oplysningerne manuelt. configure-auth-oidc-authorizationURL = Autoriserings-URL configure-auth-oidc-tokenURL = Token URL @@ -238,7 +238,7 @@ configure-auth-oidc-useLoginOn = Brug Open ID Connect til at logge på #### Pre-Moderation configure-moderation-preModeration-title = Pre-moderation configure-moderation-preModeration-explanation = - Når pre-moderation er aktiveret, offentliggøres kommentarer ikke, + Når pre-moderation er aktiveret, offentliggøres kommentarer ikke, medmindre de er godkendt af en moderator. configure-moderation-preModeration-moderation = Formoderer alle kommentarer overalt @@ -249,18 +249,18 @@ configure-moderation-apiKey = API-nøgle configure-moderation-akismet-title = Akismet-spamdetekteringsfilter configure-moderation-akismet-explanation = - Indsendte kommentarer videresendes til Akismet API til spamdetektion. + Indsendte kommentarer videresendes til Akismet API til spamdetektion. Hvis en kommentar er bestemt til at være spam, vil den bede brugeren og indikere, at kommentaren kan betragtes som spam. Hvis brugeren fortsætter efter dette punkt med den stadig spam-lignende kommentar, - markeres kommentaren som indeholdende spam, offentliggøres ikke og - placeres i den ventende kø til gennemgang af en moderator. - Hvis godkendt af en moderator, vil kommentaren blive offentliggjort. + markeres kommentaren som indeholdende spam, offentliggøres ikke og + placeres i den ventende kø til gennemgang af en moderator. + Hvis godkendt af en moderator, vil kommentaren blive offentliggjort. #### Akismet configure-moderation-akismet-filter = Spamdetekteringsfilter configure-moderation-akismet-accountNote = - Bemærk: Du skal tilføje dit / de aktive domæner + Bemærk: Du skal tilføje dit / de aktive domæner på din Akismet-konto: https://akismet.com/account/ configure-moderation-akismet-siteURL = Hjemmeside URL @@ -282,7 +282,7 @@ configure-moderation-perspective-toxicityThresholdDescription = ifølge Perspective API. Som standard er tærsklen indstillet til { $default }. configure-moderation-perspective-toxicityModel = Toksicitetsmodel cofigure-moderation-perspective-toxicityModelDescription = - Vælg din perspektivmodel. Standard er { $default }. + Vælg din perspektivmodel. Standard er { $default }. Du kan finde ud af mere om modelvalg her. configure-moderation-perspective-allowStoreCommentData = Tillad Google at gemme kommissionsdata configure-moderation-perspective-allowStoreCommentDataDescription = @@ -317,8 +317,6 @@ configure-advanced-customCSS-explanation = URL til et CSS-stilark, der tilsidesætter standardindlejring af streams. Kan være intern eller ekstern. configure-advanced-permittedDomains = Tilladte domæner -configure-advanced-permittedDomains-explanation = - Domæner, hvor din forekomst af Coral må integreres. Typisk brug er localhost, staging.yourdomain.com, yourdomain.com osv. configure-advanced-liveUpdates = Kommentar Stream Live-opdateringer configure-advanced-liveUpdates-explanation = Når det er aktiveret, vil der blive realtid indlæst og opdateret af kommentarer, når nye kommentarer og svar offentliggøres. @@ -588,8 +586,8 @@ community-suspendModal-cancel = Afbestille community-suspendModal-suspendUser = Suspender bruger community-suspendModal-emailTemplate = Hej { $username }, - - I henhold til { $organizationName }'s community-retningslinjer er din konto midlertidigt suspenderet. Under suspensionen vil du ikke være i stand til at kommentere, markere eller samarbejde med andre kommentatorer. Genindgå samtalen om { framework-timeago-time } + + I henhold til { $organizationName }'s community-retningslinjer er din konto midlertidigt suspenderet. Under suspensionen vil du ikke være i stand til at kommentere, markere eller samarbejde med andre kommentatorer. Genindgå samtalen om { framework-timeago-time } community-suspendModal-customize = Tilpas suspension af e-mail-meddelelse diff --git a/src/locales/en-US/admin.ftl b/src/locales/en-US/admin.ftl index 30d5bb31b..fa98428b9 100644 --- a/src/locales/en-US/admin.ftl +++ b/src/locales/en-US/admin.ftl @@ -340,10 +340,10 @@ configure-advanced-customCSS-explanation = URL of a CSS stylesheet that will override default Embed Stream styles. Can be internal or external. configure-advanced-permittedDomains = Permitted Domains -configure-advanced-permittedDomains-explanation = - Domains where your { -product-name } instance is allowed to be embedded. - Typical use is localhost, staging.yourdomain.com, - yourdomain.com, etc. +configure-advanced-permittedDomains-description = + Domains where your { -product-name } instance is allowed to be embedded + including the scheme (ex. http://localhost:3000, https://staging.domain.com, + https://domain.com). configure-advanced-liveUpdates = Comment Stream Live Updates configure-advanced-liveUpdates-explanation = @@ -723,7 +723,7 @@ invite-tokenNotFound = The specified link is invalid, check to see if it was copied correctly. userDetails-banned-on = Banned on { $timestamp } -userDetails-banned-by = by { $username } +userDetails-banned-by = by { $username } userDetails-suspended-by = Suspended by { $username } userDetails-suspension-start = Start: { $timestamp } -userDetails-suspension-end = End: { $timestamp } \ No newline at end of file +userDetails-suspension-end = End: { $timestamp } diff --git a/src/locales/en-US/install.ftl b/src/locales/en-US/install.ftl index 6e23b391c..d5de3ebb6 100644 --- a/src/locales/en-US/install.ftl +++ b/src/locales/en-US/install.ftl @@ -41,7 +41,11 @@ install-createYourAccount-confirmPasswordTextField = install-permittedDomains-stepTitle = Add Permitted Domains install-permittedDomains-title = Permitted Domains -install-permittedDomains-description = Enter the domains you would like to permit for { -product-name }, e.g. your local, staging and production environments (ex. localhost:3000, staging.domain.com, domain.com). +install-permittedDomains-description-with-scheme = + Enter the domains you would like to permit for { -product-name }, e.g. + your local, staging and production environments including the + scheme (ex. http://localhost:3000, https://staging.domain.com, + https://domain.com). install-permittedDomains-permittedDomains = Permitted Domains install-permittedDomains-permittedDomainsTextField = .placeholder = Domains diff --git a/src/locales/es/admin.ftl b/src/locales/es/admin.ftl index f24a2637b..50a701574 100644 --- a/src/locales/es/admin.ftl +++ b/src/locales/es/admin.ftl @@ -49,7 +49,7 @@ restricted-contactAdmin = Si cree que esto es un error, comuníquese con su admi login-signInTo = Registrarse en login-signIn-enterAccountDetailsBelow = Ingrese los detalles de su cuenta a continuación -login-emailAddressLabel = Correo electrónico +login-emailAddressLabel = Correo electrónico login-emailAddressTextField = .placeholder = Correo electrónico @@ -318,10 +318,6 @@ configure-advanced-customCSS-explanation = URL of a CSS stylesheet that will override default Embed Stream styles. Can be internal or external. configure-advanced-permittedDomains = Permitted Domains -configure-advanced-permittedDomains-explanation = - Domains where your { -product-name } instance is allowed to be embedded. - Typical use is localhost, staging.yourdomain.com, - yourdomain.com, etc. configure-advanced-liveUpdates = Comment Stream Live Updates configure-advanced-liveUpdates-explanation = diff --git a/src/locales/es/install.ftl b/src/locales/es/install.ftl index c61bc3c5b..6d421f8aa 100644 --- a/src/locales/es/install.ftl +++ b/src/locales/es/install.ftl @@ -41,7 +41,6 @@ install-createYourAccount-confirmPasswordTextField = install-permittedDomains-stepTitle = Agregar dominios permitidos install-permittedDomains-title = Dominios permitidos -install-permittedDomains-description = Ingrese los dominios que desea permitir para {- nombre-producto}, p. sus entornos locales, de preparación y producción (por ejemplo, localhost: 3000, staging.domain.com, domain.com). install-permittedDomains-permittedDomains = Dominios permitidos install-permittedDomains-permittedDomainsTextField = .placeholder = Dominios diff --git a/src/locales/pt-BR/admin.ftl b/src/locales/pt-BR/admin.ftl index 87ae754e3..360f5a297 100644 --- a/src/locales/pt-BR/admin.ftl +++ b/src/locales/pt-BR/admin.ftl @@ -218,7 +218,7 @@ configure-auth-oidc-useLoginOn = Usar login com OpenID Connect ligado #### Pre-Moderation configure-moderation-preModeration-title = Pre-moderation configure-moderation-preModeration-explanation = - Quando a pré-moderação está ativada, os comentários não serão publicados, a menos que sejam + Quando a pré-moderação está ativada, os comentários não serão publicados, a menos que sejam aprovados por um moderador. configure-moderation-preModeration-moderation = Pré-moderar todos os comentários em todo o site @@ -298,10 +298,6 @@ configure-advanced-customCSS-explanation = URL de uma folha de estilo CSS que substituirá o estilo padrão dos fluxos de comentário das páginas. Pode ser interno ou externo. configure-advanced-permittedDomains = Domínios Permitidos -configure-advanced-permittedDomains-explanation = - Domínios nos quais sua instância Coral pode ser incorporada. -  O uso típico é localhost, staging.yourdomain.com, -  yourdomain.com, etc. configure-advanced-liveUpdates = Atualizações ao vivo do Stream de comentários configure-advanced-liveUpdates-explanation = @@ -514,15 +510,15 @@ community-invite-role-staff = ou mudar qualquer configuração { -product-name }. community-invite-role-moderator = Função Moderador: Recebe um crachá “Staff”, e - seus comentários são aprovados automaticamente. Tem privilégios - totais de moderação (aprovar, rejeitar e destacar comentários). + seus comentários são aprovados automaticamente. Tem privilégios + totais de moderação (aprovar, rejeitar e destacar comentários). Pode configurar artigos individuais, mas não possui privilégios de configuração do site. community-invite-role-admin = Função Admin: Recebe um crachá “Staff”, e - seus comentários são aprovados automaticamente. Tem privilégios - totais de moderação (aprovar, rejeitar e destacar comentários). - Pode configurar artigos individuais e tem privilégios de + seus comentários são aprovados automaticamente. Tem privilégios + totais de moderação (aprovar, rejeitar e destacar comentários). + Pode configurar artigos individuais e tem privilégios de configuração do site. community-invite-invitationsSent = Seus convites foram enviados! community-invite-close = Fechar diff --git a/src/locales/pt-BR/install.ftl b/src/locales/pt-BR/install.ftl index 3f722787e..e31525121 100644 --- a/src/locales/pt-BR/install.ftl +++ b/src/locales/pt-BR/install.ftl @@ -41,7 +41,6 @@ install-createYourAccount-confirmPasswordTextField = install-permittedDomains-stepTitle = Adicionar domínios permitidos install-permittedDomains-title = Domínios Permitidos -install-permittedDomains-description = Insira os domínios que você gostaria de permitir para Coral, por exemplo seus ambientes locais, de preparação e produção (ex. localhost: 3000, staging.domain.com, domain.com). install-permittedDomains-permittedDomains = Domínios Permitidos install-permittedDomains-permittedDomainsTextField = .placeholder = Domínios