Merge branch 'xss-fixes' into 'main'

Security and docker fixes

See merge request framasoft/mobilizon!1500
This commit is contained in:
Thomas Citharel
2023-12-07 11:14:36 +00:00
89 changed files with 1755 additions and 897 deletions

View File

@@ -347,7 +347,7 @@ const asyncData = async (query: string): Promise<void> => {
const result =
(await searchAddressLoad(undefined, queryVars)) ||
(await searchAddressRefetch(queryVars))?.data
(await searchAddressRefetch(queryVars))?.data;
if (!result) {
isFetching.value = false;

View File

@@ -40,7 +40,7 @@
<div
class="mb-2 line-clamp-3"
dir="auto"
v-html="saneSummary"
v-html="group.summary"
v-if="showSummary"
/>
<div>
@@ -91,7 +91,6 @@ import { addressFullName } from "@/types/address.model";
import { useI18n } from "vue-i18n";
import AccountGroup from "vue-material-design-icons/AccountGroup.vue";
import Account from "vue-material-design-icons/Account.vue";
import { htmlToText } from "@/utils/html";
import { computed } from "vue";
import LinkOrRouterLink from "../core/LinkOrRouterLink.vue";
@@ -108,8 +107,6 @@ const props = withDefaults(
const { t } = useI18n({ useScope: "global" });
const saneSummary = computed(() => htmlToText(props.group.summary ?? ""));
const isInternal = computed(() => {
return props.isRemoteGroup && props.isLoggedIn === false;
});

View File

@@ -60,9 +60,9 @@
</div>
</div>
<div
class="mt-3 prose dark:prose-invert lg:prose-xl line-clamp-2"
class="mt-3 prose dark:prose-invert lg:prose-xl prose-p:m-0 line-clamp-2"
v-if="member.parent.summary"
v-html="htmlToText(member.parent.summary)"
v-html="member.parent.summary"
/>
</div>
<div>
@@ -95,7 +95,6 @@ import DotsHorizontal from "vue-material-design-icons/DotsHorizontal.vue";
import AccountGroup from "vue-material-design-icons/AccountGroup.vue";
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
import Tag from "@/components/TagElement.vue";
import { htmlToText } from "@/utils/html";
import { useI18n } from "vue-i18n";
defineProps<{

View File

@@ -63,7 +63,9 @@
{{ t("Reported by an unknown actor") }}
</span>
</div>
<div class="" v-if="report.content" v-html="report.content" />
<div class="line-clamp-1" v-if="report.content">
{{ report.content }}
</div>
</div>
</div>
</template>

View File

@@ -1,4 +1,3 @@
import nl2br from "@/filters/utils";
import {
formatDateString,
formatTimeString,
@@ -11,6 +10,5 @@ export default {
vue.filter("formatDateString", formatDateString);
vue.filter("formatTimeString", formatTimeString);
vue.filter("formatDateTimeString", formatDateTimeString);
vue.filter("nl2br", nl2br);
},
};

View File

@@ -1,9 +0,0 @@
/**
* New Line to <br>
*
* @param {string} str Input text
* @return {string} Filtered text
*/
export default function nl2br(str: string): string {
return `${str}`.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1<br>");
}

View File

@@ -4,7 +4,7 @@ import { i18n } from "@/utils/i18n";
const t = i18n.global.t;
export enum ConversationRouteName {
CONVERSATION_LIST = "DISCUSSION_LIST",
CONVERSATION_LIST = "CONVERSATION_LIST",
CONVERSATION = "CONVERSATION",
}

View File

@@ -1,16 +1,3 @@
export function nl2br(text: string): string {
return text.replace(/(?:\r\n|\r|\n)/g, "<br>");
}
export function htmlToText(html: string) {
const template = document.createElement("template");
const trimmedHTML = html.trim();
template.innerHTML = trimmedHTML;
const text = template.content.textContent;
template.remove();
return text;
}
export const getValueFromMeta = (name: string): string | null => {
const element = document.querySelector(`meta[name="${name}"]`);
if (element && element.getAttribute("content")) {

View File

@@ -613,8 +613,8 @@ const organizerDomain = computed((): string | undefined => {
});
const nonPassedRelatedEvents = computed((): IEvent[] | undefined => {
let relatedEvents = event.value?.relatedEvents;
const relatedEvents = event.value?.relatedEvents;
return relatedEvents?.filter((relatedEvent: IEvent) => {
const endsOn = relatedEvent.endsOn
? new Date(relatedEvent.endsOn)

View File

@@ -189,16 +189,15 @@
<p v-else>
{{ props.row.metadata.message }}
</p>
<button
type="button"
class="button is-text"
<o-button
variant="primary"
v-if="props.row.metadata.message.length > MESSAGE_ELLIPSIS_LENGTH"
@click.stop="toggleQueueDetails(props.row)"
>
{{
openDetailedRows[props.row.id] ? t("View less") : t("View more")
}}
</button>
</o-button>
</div>
<p v-else class="has-text-grey-dark">
{{ t("No message") }}
@@ -212,7 +211,9 @@
</span>
</o-table-column>
<template #detail="props">
<article v-html="nl2br(props.row.metadata.message)" />
<p>
{{ props.row.metadata.message }}
</p>
</template>
<template #empty>
<EmptyContent icon="account-circle" :inline="true">
@@ -265,7 +266,6 @@ import {
UPDATE_PARTICIPANT,
} from "@/graphql/event";
import { usernameWithDomain } from "@/types/actor";
import { nl2br } from "@/utils/html";
import { asyncForEach } from "@/utils/asyncForEach";
import RouteName from "@/router/name";
import { useCurrentActorClient } from "@/composition/apollo/actor";

View File

@@ -261,7 +261,7 @@ const copyURL = async (): Promise<void> => {
onGroupResult(async ({ data }) => {
if (!data) return;
editableGroup.value = data.group;
editableGroup.value = { ...data.group };
try {
avatarFile.value = await buildFileFromIMedia(editableGroup.value?.avatar);
bannerFile.value = await buildFileFromIMedia(editableGroup.value?.banner);

View File

@@ -216,11 +216,9 @@
</div>
<p v-else>{{ t("Unknown actor") }}</p>
</div>
<div
class="prose dark:prose-invert"
v-if="report.content"
v-html="nl2br(report.content)"
/>
<div class="prose dark:prose-invert" v-if="report.content">
{{ report.content }}
</div>
<p v-else>{{ t("No comment") }}</p>
</div>
</section>
@@ -407,7 +405,6 @@ import {
} from "@/types/actor";
import { DELETE_EVENT } from "@/graphql/event";
import uniq from "lodash/uniq";
import { nl2br } from "@/utils/html";
import { DELETE_COMMENT } from "@/graphql/comment";
import { IComment } from "@/types/comment.model";
import { ActorType, AntiSpamFeedback, ReportStatusEnum } from "@/types/enums";