From c169639530ddb2cc52572a2f930dfe21895f12d9 Mon Sep 17 00:00:00 2001 From: Ludvig Svedberg Date: Tue, 22 Aug 2023 14:41:19 +0200 Subject: [PATCH] :bug: Fix issues regarding nolla page scroll and hidden stab (#1228) * Make "#main-container" scroll on nolla pages * Only hide stab for non-admin users * Also allow anyone with nolla:see_stab access to see stab * Move scroll container to actual content * Fix how "Staben" is shown on frontend author signatures --- .../seeds/helpers/insertApiAccessPolicies.ts | 7 + .../services/core/src/datasources/Mandate.ts | 9 +- .../services/core/src/datasources/Position.ts | 4 +- backend/services/core/src/shared/database.ts | 25 +++- frontend/components/News/articleSet.tsx | 12 +- frontend/components/Nolla/Article.tsx | 14 +- frontend/components/Nolla/layout.tsx | 125 ++++++++++-------- frontend/functions/authorFunctions.ts | 4 + frontend/pages/members/[id]/index.tsx | 9 -- 9 files changed, 115 insertions(+), 94 deletions(-) diff --git a/backend/services/core/seeds/helpers/insertApiAccessPolicies.ts b/backend/services/core/seeds/helpers/insertApiAccessPolicies.ts index 2910fd872..9fb2cbb8e 100644 --- a/backend/services/core/seeds/helpers/insertApiAccessPolicies.ts +++ b/backend/services/core/seeds/helpers/insertApiAccessPolicies.ts @@ -87,5 +87,12 @@ export default async function insertApiAccessPolicies(knex: Knex) { { api_name: 'core:mail:alias:update', role: '*' }, { api_name: 'governing_document:read', role: '*' }, { api_name: 'governing_document:write', role: '_' }, + { api_name: 'nolla:news', role: 'dsek.infu.dwww' }, + { api_name: 'nolla:news', role: 'dsek.noll' }, + { api_name: 'nolla:events', role: 'dsek.noll' }, + { api_name: 'nolla:events', role: 'dsek.infu.dwww' }, + { api_name: 'nolla:admin', role: 'dsek.infu.dwww' }, + { api_name: 'nolla:admin', role: 'dsek.noll.stab' }, + { api_name: 'nolla:see_stab', role: 'dsek.noll.stab' }, ]); } diff --git a/backend/services/core/src/datasources/Mandate.ts b/backend/services/core/src/datasources/Mandate.ts index 95d1751be..0f388e0cb 100644 --- a/backend/services/core/src/datasources/Mandate.ts +++ b/backend/services/core/src/datasources/Mandate.ts @@ -22,7 +22,8 @@ export default class MandateAPI extends dbUtils.KnexDataSource { const res = (await this.knex('mandates').select('*').where({ id }))[0]; if (!res) { return undefined; } - if (await this.isStabHidden() && STAB_IDS.includes(res.position_id)) { + // Returns undefined for stab mandates during the nollning. + if (await this.isStabHiddenForUser(ctx, res.member_id) && STAB_IDS.includes(res.position_id)) { return undefined; } return convertMandate(res); @@ -65,7 +66,8 @@ export default class MandateAPI extends dbUtils.KnexDataSource { } } } - if (await this.isStabHidden()) { + // Removes all mandates that are stab mandates, during the nollning. + if (await this.isStabHiddenForUser(ctx)) { filtered = filtered.whereNotIn('position_id', STAB_IDS); // hide ALL stab mandates (even old ones) // Remove active stab members from the list, even their other/old mandates filtered = filtered @@ -109,7 +111,8 @@ export default class MandateAPI extends dbUtils.KnexDataSource { query = query.andWhereRaw('CURRENT_DATE BETWEEN start_date AND end_date'); } const res = await query; - if (await this.isStabHidden()) { + // Remove stab info + if (await this.isStabHiddenForUser(ctx, memberId)) { // if user has an active stab mandate, hide all other mandates if (res.some((m) => m.end_date > new Date() && STAB_IDS.includes(m.position_id))) { return []; diff --git a/backend/services/core/src/datasources/Position.ts b/backend/services/core/src/datasources/Position.ts index 26e98619a..12ae20a89 100644 --- a/backend/services/core/src/datasources/Position.ts +++ b/backend/services/core/src/datasources/Position.ts @@ -17,7 +17,7 @@ export default class PositionAPI extends dbUtils.KnexDataSource { return undefined; } - if (await this.isStabHidden() && STAB_IDS.includes(position.id)) { + if (await this.isStabHiddenForUser(ctx) && STAB_IDS.includes(position.id)) { return undefined; } if (!position.active) { @@ -62,7 +62,7 @@ export default class PositionAPI extends dbUtils.KnexDataSource { ...filter, }); } - if (await this.isStabHidden()) { + if (await this.isStabHiddenForUser(ctx)) { STAB_IDS.forEach((id) => { query = query.whereNot({ id }); }); diff --git a/backend/services/core/src/shared/database.ts b/backend/services/core/src/shared/database.ts index d4a57a916..73b136355 100644 --- a/backend/services/core/src/shared/database.ts +++ b/backend/services/core/src/shared/database.ts @@ -15,6 +15,8 @@ import { slugify } from './utils'; attachPaginate(); +const ONE_DAY_IN_SECONDS = 1000 * 60 * 60 * 24; + type Keycloak = { keycloak_id: string, member_id: UUID, @@ -242,6 +244,9 @@ export class KnexDataSource extends DataSource { // used to cache the stab hidden setting private stabHidden = false; + /** + * last time stab hidden setting was checked in milliseconds + */ private lastStabHiddenCheck = 0; private async checkStabHiddenSetting() { @@ -271,11 +276,29 @@ export class KnexDataSource extends DataSource { async isStabHidden() { // check max once per day if stab is hidden const now = Date.now(); - if (now - this.lastStabHiddenCheck > 1000 * 60 * 60 * 24) { + if (now - this.lastStabHiddenCheck > ONE_DAY_IN_SECONDS * 1000) { await this.checkStabHiddenSetting(); } return this.stabHidden; } + + /** + * Checks admin settings if stab is currently hidden. + * Admin users can see stab even if it is hidden. + * User's can always see themselves. + * @param ctx Context for logged in user + * @param memberId Relevant memberId of the member which might be hidden, if applicable + * @returns true if should be hidden + */ + async isStabHiddenForUser(ctx: UserContext, memberId?: string) { + if (!(await this.isStabHidden())) { + return false; + } + if (await this.hasAccess(['nolla:admin', 'nolla:see_stab', 'admin:settings:update', 'core:admin'], ctx, memberId)) { + return false; + } + return true; + } } export default knex(knexConfig); diff --git a/frontend/components/News/articleSet.tsx b/frontend/components/News/articleSet.tsx index ef669882b..521938e92 100644 --- a/frontend/components/News/articleSet.tsx +++ b/frontend/components/News/articleSet.tsx @@ -1,4 +1,3 @@ -import React, { useEffect, useState } from 'react'; import { useTranslation } from 'next-i18next'; import { useNewsPageQuery } from '../../generated/graphql'; import Article from './article'; @@ -34,14 +33,9 @@ export default function ArticleSet({ }, }); const { t } = useTranslation('news'); - const [articles, setArticles] = useState(data?.news?.articles); - useEffect(() => { - if (data?.news?.articles) { - setArticles(data.news.articles); - } - }, [data]); + const articles = data?.news?.articles; - if (!articles || loading) { + if (loading) { return ( <> @@ -54,7 +48,7 @@ export default function ArticleSet({ } if (error) return

{t('failedLoadingNews')}

; - + if (!articles) return null; return ( <> {articles.map((article) => diff --git a/frontend/components/Nolla/Article.tsx b/frontend/components/Nolla/Article.tsx index 9bd9e7c82..79d09f8ab 100644 --- a/frontend/components/Nolla/Article.tsx +++ b/frontend/components/Nolla/Article.tsx @@ -23,7 +23,6 @@ import selectTranslation from '~/functions/selectTranslation'; import { ArticleQuery, ArticleRequestStatus, - Author, } from '~/generated/graphql'; import { hasAccess, useApiAccess } from '~/providers/ApiAccessProvider'; import { useUser } from '~/providers/UserProvider'; @@ -35,17 +34,6 @@ type ArticleProps = { article: ArticleQuery['article']; }; -const getNollaNewsAuthor = (i18n: any, author: Partial) => { - if (author.__typename === 'Member') { - return getSignature(author); - } - if (author.position?.name === 'Stabsmedlem') { - return 'Staben'; - } - - return getSignature(author); -}; - export default function Article({ article }: ArticleProps) { const classes = articleStyles(); const { t, i18n } = useTranslation('common'); @@ -79,7 +67,7 @@ export default function Article({ article }: ArticleProps) { }} /> - {getNollaNewsAuthor(i18n, article.author)} + {getSignature(article.author)} {timeAgo(date)} diff --git a/frontend/components/Nolla/layout.tsx b/frontend/components/Nolla/layout.tsx index 38d92e32d..a38f42f8c 100644 --- a/frontend/components/Nolla/layout.tsx +++ b/frontend/components/Nolla/layout.tsx @@ -140,8 +140,6 @@ function NollaLayout({ return ( @@ -213,62 +212,74 @@ function NollaLayout({ {drawer} + - - {children} - + + {children} + - - - - - {translate('footer')} - + + + + + {translate('footer')} + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); } diff --git a/frontend/functions/authorFunctions.ts b/frontend/functions/authorFunctions.ts index f6ac3290c..708dc6e51 100644 --- a/frontend/functions/authorFunctions.ts +++ b/frontend/functions/authorFunctions.ts @@ -9,6 +9,10 @@ export const getSignature = (author: Partial): string => { return getFullName(author as Member); } const mandate = (author as Mandate); + if (mandate.position?.id?.startsWith('dsek.noll.stab')) { + return 'Staben'; + } + return `${getFullName(mandate.member)}, ${mandate.position.name}`; }; diff --git a/frontend/pages/members/[id]/index.tsx b/frontend/pages/members/[id]/index.tsx index 4f756238d..4164d1236 100644 --- a/frontend/pages/members/[id]/index.tsx +++ b/frontend/pages/members/[id]/index.tsx @@ -63,15 +63,6 @@ export default function MemberPage() { if (!member) { return <>{t('member:memberError')}; } - if ( - member.activeMandates.some( - (m) => m.position.id === 'dsek.noll.stab.mdlm', - ) - && member.id !== user?.id - && !hasAccess('nolla:admin') - ) { - return <>{t('member:memberError')}; - } return (