From 62247b983bd47a514861bc35f3ee3b0ff44cf83c Mon Sep 17 00:00:00 2001 From: Laura Witulski Morales Date: Mon, 15 Sep 2025 16:12:11 +0200 Subject: [PATCH 1/2] fix: disable creation of mock user on staging --- .env.example | 3 ++- .github/workflows/reusable-build-job.yml | 1 + .github/workflows/reusable-deploy-job.yml | 1 + packages/backend/src/resolvers/auth.resolver.ts | 8 +++++--- packages/frontend/webpack.config.js | 5 ++++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 15aaf242..f3b97c5d 100644 --- a/.env.example +++ b/.env.example @@ -26,10 +26,11 @@ ALEXA_AMAZON_CLIENT_SECRET = secret LARA_SECRET = secret STAGE = dev +NODE_ENV = development FRONTEND_CERTIFICATE_ARN = arn:aws:acm:eu-west-1:123456789012:certificate/12345678-1234-1234-1234-123456789012 BACKEND_CERTIFICATE_ARN = arn:aws:acm:eu-west-1:123456789012:certificate/12345678-1234-1234-1234-123456789012 HOSTED_ZONE_ID = Z0000000000000 FRONTEND_URL_WITHOUT_HTTPS = localhost:8080 -BACKEND_URL_WITHOUT_HTTPS = localhost:3000/dev \ No newline at end of file +BACKEND_URL_WITHOUT_HTTPS = localhost:3000/dev diff --git a/.github/workflows/reusable-build-job.yml b/.github/workflows/reusable-build-job.yml index dda20d76..6aa67139 100644 --- a/.github/workflows/reusable-build-job.yml +++ b/.github/workflows/reusable-build-job.yml @@ -22,6 +22,7 @@ jobs: name: build-job environment: ${{ inputs.environmentName }} env: + NODE_ENV: ${{ inputs.environmentName }} DEBUG: ${{ inputs.debug }} MODE: ${{ inputs.mode }} AUTH_HEADER: ${{ secrets.AUTH_HEADER }} diff --git a/.github/workflows/reusable-deploy-job.yml b/.github/workflows/reusable-deploy-job.yml index cdaac0b8..c8240c84 100644 --- a/.github/workflows/reusable-deploy-job.yml +++ b/.github/workflows/reusable-deploy-job.yml @@ -25,6 +25,7 @@ jobs: id-token: write contents: read env: + NODE_ENV: ${{ inputs.target }} ALEXA_SKILL_STAGE: ${{ inputs.alexaSkillStage }} DEBUG: ${{ inputs.debug }} ALEXA_AMAZON_CLIENT_ID: ${{ secrets.ALEXA_AMAZON_CLIENT_ID }} diff --git a/packages/backend/src/resolvers/auth.resolver.ts b/packages/backend/src/resolvers/auth.resolver.ts index fbed3428..bb1af8ef 100644 --- a/packages/backend/src/resolvers/auth.resolver.ts +++ b/packages/backend/src/resolvers/auth.resolver.ts @@ -6,7 +6,7 @@ import { GqlResolvers } from '@lara/api' import { t } from '../i18n' import { isDebug } from '../permissions' -import { saveUser, userByEmail, userById } from '../repositories/user.repo' +import { userById, userByEmail, saveUser } from '../repositories/user.repo' import { createOAuthData } from '../services/oauth.service' import { generateTrainee } from '../services/trainee.service' @@ -24,6 +24,8 @@ const createMockUser = async (email: string) => { return saveUser(userModel) } +const isDevEnv = (): boolean => process.env.NODE_ENV === 'development' + export const authResolver: GqlResolvers = { Mutation: { login: async (_parent, { email }) => { @@ -34,12 +36,12 @@ export const authResolver: GqlResolvers = { let user = await userByEmail(email) // creates mock user on dev stages - if (!user && isDebug()) { + if (!user && isDevEnv()) { user = await createMockUser(email) } if (!user) { - return + throw new GraphQLError('USER_NOT_REGISTERED') } return createOAuthData(user) diff --git a/packages/frontend/webpack.config.js b/packages/frontend/webpack.config.js index b0c4eda8..49b28eeb 100644 --- a/packages/frontend/webpack.config.js +++ b/packages/frontend/webpack.config.js @@ -7,6 +7,7 @@ const path = require('path') const dotenv = require('dotenv') const { + NODE_ENV, MICROSOFT_CLIENT_ID, MICROSOFT_TENANT_ID, DEBUG, @@ -21,7 +22,7 @@ const { const DEFAULT_ENVIRONMENT = 'development' const DEFAULT_MODE = 'development' -/** @returns {{mode: string, authHeader: string, supportMail: string, debug: boolean, microsoftClientID: string, frontendUrl: string, name: (*|string), microsoftTenantID: string, backendUrl: string}}} */ +/** @returns {{mode: string, authHeader: string, supportMail: string, debug: boolean, microsoftClientID: string, frontendUrl: string, name: (*|string), microsoftTenantID: string, backendUrl: string, nodeEnv: string}}} */ const getEnvironmentConfig = () => { const name = ENVIRONMENT_NAME ?? DEFAULT_ENVIRONMENT @@ -34,6 +35,7 @@ const getEnvironmentConfig = () => { console.log(`Using environment variables from ${envVarsPath}`) return { name, + nodeEnv: parsed.NODE_ENV ?? DEFAULT_ENVIRONMENT, mode: parsed.MODE, microsoftClientID: parsed.MICROSOFT_CLIENT_ID, microsoftTenantID: parsed.MICROSOFT_TENANT_ID, @@ -55,6 +57,7 @@ const getEnvironmentConfig = () => { console.log(`Using injected environment variables from process.env`) return { name, + nodeEnv: NODE_ENV ?? DEFAULT_ENVIRONMENT, mode: MODE ?? '', microsoftClientID: MICROSOFT_CLIENT_ID ?? '', microsoftTenantID: MICROSOFT_TENANT_ID ?? '', From e925c29a61ae31f063291ebcef2e0ff9f3f93de9 Mon Sep 17 00:00:00 2001 From: alexander-schefe Date: Tue, 16 Sep 2025 11:02:40 +0200 Subject: [PATCH 2/2] feat: show user not registered error on failed login attempt --- .../frontend/src/components/ms-sign-in-button.tsx | 11 ++++++++++- packages/frontend/src/locales/de.ts | 7 +++++++ packages/frontend/src/locales/en.ts | 6 ++++++ packages/frontend/src/locales/translation.ts | 6 ++++++ .../frontend/src/templates/secondary-template.tsx | 12 ++++++++---- 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/components/ms-sign-in-button.tsx b/packages/frontend/src/components/ms-sign-in-button.tsx index 2784e8f6..97580461 100644 --- a/packages/frontend/src/components/ms-sign-in-button.tsx +++ b/packages/frontend/src/components/ms-sign-in-button.tsx @@ -7,6 +7,8 @@ import { useLoginPageLoginMutation } from '../graphql' import { useIsAuthenticated } from '@azure/msal-react' import { EventMessage, EventType, PopupEvent } from '@azure/msal-browser' import { useNavigate } from 'react-router' +import { useToastContext } from '../hooks/use-toast-context' +import strings from '../locales/localization' export interface ButtonProps extends ButtonHTMLAttributes { fullsize?: boolean @@ -18,6 +20,7 @@ export const SignInButton: React.FunctionComponent = () => { const [mutate] = useLoginPageLoginMutation() const isAuthenticated = useIsAuthenticated() const navigate = useNavigate() + const { addToast } = useToastContext() const [popupWindow, setPopupWindow] = useState(null) @@ -52,7 +55,13 @@ export const SignInButton: React.FunctionComponent = () => { login(data.login) }) .catch((err) => { - console.log(err) + console.error(err) + addToast({ + icon: 'Error', + title: strings.login.userNotRegisteredError.title, + text: strings.login.userNotRegisteredError.description, + type: 'error', + }) }) } } catch (error) { diff --git a/packages/frontend/src/locales/de.ts b/packages/frontend/src/locales/de.ts index 382085bc..a02d3c3f 100644 --- a/packages/frontend/src/locales/de.ts +++ b/packages/frontend/src/locales/de.ts @@ -24,6 +24,13 @@ const germanTranslation: Translation = { back: 'zurück', on: 'an', off: 'aus', + login: { + userNotRegisteredError: { + title: 'Fehler bei der Anmeldung', + description: + 'Leider sind Sie noch nicht registriert. Bitte wenden Sie sich an den Administrator oder Ihren Ausbilder.', + }, + }, modal: { defaultClose: 'Schließen', }, diff --git a/packages/frontend/src/locales/en.ts b/packages/frontend/src/locales/en.ts index c55cb0cb..84b07d03 100644 --- a/packages/frontend/src/locales/en.ts +++ b/packages/frontend/src/locales/en.ts @@ -24,6 +24,12 @@ const englishTranslation: Translation = { back: 'back', on: 'on', off: 'off', + login: { + userNotRegisteredError: { + title: 'Login failed', + description: 'Unfortunately, you are not yet registered. Please contact the administrator or your trainer.', + }, + }, modal: { defaultClose: 'Close', }, diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index d818f265..989520d0 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -22,6 +22,12 @@ export default interface Translation { back: string on: string off: string + login: { + userNotRegisteredError: { + title: string + description: string + } + } modal: { defaultClose: string } diff --git a/packages/frontend/src/templates/secondary-template.tsx b/packages/frontend/src/templates/secondary-template.tsx index a0ab8355..58456f77 100644 --- a/packages/frontend/src/templates/secondary-template.tsx +++ b/packages/frontend/src/templates/secondary-template.tsx @@ -1,16 +1,20 @@ import React, { ReactNode } from 'react' import { Paragraph, StyledSecondaryTemplateWrapper } from '@lara/components' +import { Toasts } from '../components/toasts' interface SecondaryTemplateProps { children: ReactNode } const SecondaryTemplate: React.FunctionComponent = ({ children }) => ( - - {children} - Lara {TAG || `pre-release @ ${REVISION.substring(0, 7)}`} - +
+ + + {children} + Lara {TAG || `pre-release @ ${REVISION.substring(0, 7)}`} + +
) export default SecondaryTemplate