Merge branch 'fix-csp' into 'main'

Add sha-256 hash for toggling dark theme code and remove inlined phoenix digest

Closes #993

See merge request framasoft/mobilizon!1313
This commit is contained in:
Thomas Citharel 2022-11-02 11:10:48 +00:00
commit 48da35ee41
8 changed files with 81 additions and 134 deletions

View file

@ -205,31 +205,34 @@ export const LOGGED_USER_DRAFTS = gql`
loggedUser {
id
drafts(page: $page, limit: $limit) {
id
uuid
title
draft
picture {
total
elements {
id
url
alt
}
beginsOn
status
visibility
attributedTo {
...ActorFragment
}
organizerActor {
...ActorFragment
}
participantStats {
going
notApproved
}
options {
maximumAttendeeCapacity
remainingAttendeeCapacity
uuid
title
draft
picture {
id
url
alt
}
beginsOn
status
visibility
attributedTo {
...ActorFragment
}
organizerActor {
...ActorFragment
}
participantStats {
going
notApproved
}
options {
maximumAttendeeCapacity
remainingAttendeeCapacity
}
}
}
}

View file

@ -54,7 +54,7 @@ export interface IUser extends ICurrentUser {
disabled: boolean;
participations: Paginate<IParticipant>;
mediaSize: number;
drafts: IEvent[];
drafts: Paginate<IEvent>;
settings: IUserSettings;
activitySettings: IActivitySetting[];
followedGroupEvents: Paginate<IFollowedGroupEvent>;

View file

@ -19,9 +19,9 @@
>
</div>
<!-- <o-loading v-model:active="$apollo.loading"></o-loading> -->
<div class="wrapper flex flex-wrap gap-4 items-start">
<div class="flex flex-wrap gap-4 items-start">
<div
class="event-filter rounded p-3 flex-auto md:flex-none bg-zinc-300 dark:bg-zinc-700"
class="rounded p-3 flex-auto md:flex-none bg-zinc-300 dark:bg-zinc-700"
>
<o-field>
<o-switch v-model="showUpcoming">{{
@ -73,15 +73,31 @@
/>
</o-field>
</div>
<div class="my-events flex-1">
<div class="flex-1 min-w-[300px]">
<section
class="py-4"
v-if="showUpcoming && showDrafts && drafts.length > 0"
class="py-4 first:pt-0"
v-if="showUpcoming && showDrafts && drafts && drafts.total > 0"
>
<multi-event-minimalist-card :events="drafts" :showOrganizer="true" />
<h2 class="text-2xl mb-2">{{ t("Drafts") }}</h2>
<multi-event-minimalist-card
:events="drafts.elements"
:showOrganizer="true"
/>
<o-pagination
class="mt-4"
v-show="drafts.total > LOGGED_USER_DRAFTS_LIMIT"
:total="drafts.total"
v-model:current="draftsPage"
:per-page="LOGGED_USER_DRAFTS_LIMIT"
:aria-next-label="t('Next page')"
:aria-previous-label="t('Previous page')"
:aria-page-label="t('Page')"
:aria-current-label="t('Current page')"
>
</o-pagination>
</section>
<section
class="py-4"
class="py-4 first:pt-0"
v-if="
showUpcoming && monthlyFutureEvents && monthlyFutureEvents.size > 0
"
@ -92,7 +108,7 @@
v-for="month of monthlyFutureEvents"
:key="month[0]"
>
<span class="upcoming-month">{{ month[0] }}</span>
<h2 class="text-2xl">{{ month[0] }}</h2>
<div v-for="element in month[1]" :key="element.id">
<event-participation-card
v-if="'role' in element"
@ -131,7 +147,7 @@
v-if="
showUpcoming &&
monthlyFutureEvents &&
monthlyFutureEvents.length === 0 &&
monthlyFutureEvents.size === 0 &&
true // !$apollo.loading
"
>
@ -209,10 +225,15 @@ import {
import { useQuery } from "@vue/apollo-composable";
import { computed, inject, ref, defineAsyncComponent } from "vue";
import { IUser } from "@/types/current-user.model";
import { booleanTransformer, useRouteQuery } from "vue-use-route-query";
import {
booleanTransformer,
integerTransformer,
useRouteQuery,
} from "vue-use-route-query";
import { Locale } from "date-fns";
import { useI18n } from "vue-i18n";
import { useRestrictions } from "@/composition/apollo/config";
import { useHead } from "@vueuse/head";
const EventParticipationCard = defineAsyncComponent(
() => import("@/components/Event/EventParticipationCard.vue")
@ -253,8 +274,6 @@ const dateFilter = useRouteQuery("dateFilter", new Date(), {
const hasMoreFutureParticipations = ref(true);
const hasMorePastParticipations = ref(true);
// config: CONFIG
const {
result: loggedUserUpcomingEventsResult,
fetchMore: fetchMoreUpcomingEvents,
@ -277,10 +296,17 @@ const groupEvents = computed(
.elements ?? []
);
const LOGGED_USER_DRAFTS_LIMIT = 10;
const draftsPage = useRouteQuery("draftsPage", 1, integerTransformer);
const { result: draftsResult } = useQuery<{
loggedUser: Pick<IUser, "drafts">;
}>(LOGGED_USER_DRAFTS, () => ({ page: 1, limit: 10 }));
const drafts = computed(() => draftsResult.value?.loggedUser.drafts ?? []);
}>(
LOGGED_USER_DRAFTS,
() => ({ page: draftsPage.value, limit: LOGGED_USER_DRAFTS_LIMIT }),
() => ({ fetchPolicy: "cache-and-network" })
);
const drafts = computed(() => draftsResult.value?.loggedUser.drafts);
const { result: participationsResult, fetchMore: fetchMoreParticipations } =
useQuery<{
@ -294,12 +320,6 @@ const pastParticipations = computed(
}
);
// metaInfo() {
// return {
// title: this.t("My events") as string,
// };
// },
const monthlyEvents = (
elements: Eventable[],
revertSort = false
@ -413,86 +433,8 @@ const dateFnsLocale = inject<Locale>("dateFnsLocale");
const firstDayOfWeek = computed((): number => {
return dateFnsLocale?.options?.weekStartsOn ?? 0;
});
useHead({
title: computed(() => t("My events")),
});
</script>
<style lang="scss" scoped>
.participation {
margin: 1rem auto;
}
section {
.upcoming-month,
.past-month {
text-transform: capitalize;
display: inline-block;
position: relative;
font-size: 1.3rem;
&::after {
position: absolute;
left: 0;
right: 0;
top: 100%;
content: "";
width: calc(100% + 30px);
height: 3px;
max-width: 150px;
}
}
}
.not-found {
margin-top: 2rem;
.img-container {
background-image: url("/img/pics/event_creation-480w.webp");
@media (min-resolution: 2dppx) {
& {
background-image: url("/img/pics/event_creation-1024w.webp");
}
}
max-width: 450px;
height: 300px;
box-shadow: 0 0 8px 8px white inset;
@media (prefers-color-scheme: dark) {
box-shadow: 0 0 8px 8px #374151 inset;
}
background-size: cover;
border-radius: 10px;
margin: auto auto 1rem;
}
}
.wrapper {
// display: grid;
// grid-template-areas: "filter" "events";
// align-items: start;
// // @include desktop {
// gap: 2rem;
// grid-template-columns: 1fr 3fr;
// grid-template-areas: "filter events";
// // }
.event-filter {
grid-area: filter;
// @include desktop {
// padding: 2rem 1.25rem;
// :deep(.field.is-grouped) {
// display: block;
// }
// }
:deep(.field > .field) {
margin: 0 auto 1.25rem !important;
}
.date-filter :deep(.field-body) {
display: block;
}
}
.my-events {
grid-area: events;
}
}
</style>

View file

@ -96,7 +96,9 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
resolve(&User.user_memberships/3)
end
field(:drafts, list_of(:event), description: "The list of draft events this user has created") do
field(:drafts, :paginated_event_list,
description: "The list of draft events this user has created"
) do
arg(:page, :integer,
default_value: 1,
description: "The page in the paginated drafts events list"

View file

@ -465,13 +465,13 @@ defmodule Mobilizon.Events do
|> Page.build_page(page, limit)
end
@spec list_drafts_for_user(integer, integer | nil, integer | nil) :: [Event.t()]
@spec list_drafts_for_user(integer, integer | nil, integer | nil) :: Page.t(Event.t())
def list_drafts_for_user(user_id, page \\ nil, limit \\ nil) do
Event
|> user_events_query(user_id)
|> filter_draft(true)
|> Page.paginate(page, limit)
|> Repo.all()
|> order_by(desc: :updated_at)
|> Page.build_page(page, limit)
end
@spec is_user_moderator_for_event?(integer | String.t(), integer | String.t()) :: boolean

View file

@ -85,7 +85,8 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
else
[
@script_src,
"'sha256-4RS22DYeB7U14dra4KcQYxmwt5HkOInieXK1NUMBmQI=' "
"'sha256-4RS22DYeB7U14dra4KcQYxmwt5HkOInieXK1NUMBmQI=' ",
"'sha256-zJdRXhLWm9NGI6BFr+sNmHBBrjAdJdFr7MpUq0EwK58=' "
]
end

View file

@ -20,7 +20,6 @@
<link rel="preload" href="/img/shape-3.svg" as="image" />
<% end %>
<%= tags(assigns) || assigns.tags %>
<%= Vite.inlined_phx_manifest() %>
<%= Vite.vite_client() %>
<%= Vite.vite_snippet("src/main.ts") %>
</head>

View file

@ -73,7 +73,7 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlugTest do
[csp] = Conn.get_resp_header(conn, "content-security-policy")
assert csp =~
~r/script-src 'self' 'unsafe-eval' 'sha256-[\w+\/=]*' example.com matomo.example.com ;/
~r/script-src 'self' 'unsafe-eval' 'sha256-[\w+\/=]*' 'sha256-[\w+\/=]*' example.com matomo.example.com ;/
end
end