Merged in feature/VBV-370-dev-live-loginpage (pull request #114)
Feature/VBV-370 Separate local and SSO login page * Implement local and SSO login pages * Add translations * Fix typechecks * Fix env detection Approved-by: Christian Cueni
This commit is contained in:
parent
ded684ecc2
commit
1a0a431768
|
|
@ -1,5 +1,9 @@
|
||||||
{
|
{
|
||||||
|
"Benutzername": "Benutzername",
|
||||||
|
"Klicke auf den Button, um dich über SSO anzumelden oder zu registrieren.": "Klicke auf den Button, um dich über SSO anzumelden oder zu registrieren.",
|
||||||
"Nächste Termine": "Nächste Termine",
|
"Nächste Termine": "Nächste Termine",
|
||||||
|
"Passwort": "Passwort",
|
||||||
|
"SSO Login/Registration": "SSO Login/Registration",
|
||||||
"Zur Zeit sind keine Termine vorhanden": "Zur Zeit sind keine Termine vorhanden",
|
"Zur Zeit sind keine Termine vorhanden": "Zur Zeit sind keine Termine vorhanden",
|
||||||
"assignment": {
|
"assignment": {
|
||||||
"acceptConditionsDisclaimer": "Bedingungen akzeptieren und Ergebnisse abgeben",
|
"acceptConditionsDisclaimer": "Bedingungen akzeptieren und Ergebnisse abgeben",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
{
|
{
|
||||||
|
"Benutzername": "Nom d'utilisateur",
|
||||||
|
"Klicke auf den Button, um dich über SSO anzumelden oder zu registrieren.": "Clique sur le bouton pour te connecter ou t'inscrire via SSO.",
|
||||||
|
"Nächste Termine": "Prochains rendez-vous",
|
||||||
|
"Passwort": "Mot de passe",
|
||||||
|
"SSO Login/Registration": "Connexion/enregistrement SSO",
|
||||||
|
"Zur Zeit sind keine Termine vorhanden": "Il n'y a pas de rendez-vous pour le moment",
|
||||||
"circlePage": {
|
"circlePage": {
|
||||||
"circleContentBoxTitle": "C'est ce que tu apprends dans ce Cercle.",
|
"circleContentBoxTitle": "C'est ce que tu apprends dans ce Cercle.",
|
||||||
"contactExpertButton": "Contacter l'expert",
|
"contactExpertButton": "Contacter l'expert",
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useUserStore } from "@/stores/user";
|
import { useUserStore } from "@/stores/user";
|
||||||
|
import type { LoginMethod } from "@/types";
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
import { reactive } from "vue";
|
import { reactive } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
loginMethod: LoginMethod;
|
||||||
|
}>();
|
||||||
|
|
||||||
log.debug("LoginView.vue created");
|
log.debug("LoginView.vue created");
|
||||||
log.debug(route.query);
|
log.debug(route.query);
|
||||||
|
|
||||||
|
|
@ -23,6 +28,7 @@ const userStore = useUserStore();
|
||||||
<h1 class="mb-8">Login</h1>
|
<h1 class="mb-8">Login</h1>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
|
v-if="loginMethod === 'local'"
|
||||||
class="bg-white p-4 lg:p-8"
|
class="bg-white p-4 lg:p-8"
|
||||||
@submit.prevent="
|
@submit.prevent="
|
||||||
userStore.handleLogin(
|
userStore.handleLogin(
|
||||||
|
|
@ -33,22 +39,24 @@ const userStore = useUserStore();
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label class="mb-1 block" for="email">Username</label>
|
<label class="mb-1 block" for="email">{{ $t("Benutzername") }}</label>
|
||||||
<input
|
<input
|
||||||
id="username"
|
id="username"
|
||||||
v-model="state.username"
|
v-model="state.username"
|
||||||
type="text"
|
type="text"
|
||||||
name="username"
|
name="username"
|
||||||
|
autocomplete="username"
|
||||||
class="mt-1 block w-96 max-w-full border px-3 py-2"
|
class="mt-1 block w-96 max-w-full border px-3 py-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label class="mb-1 block" for="password">Password</label>
|
<label class="mb-1 block" for="password">{{ $t("Passwort") }}</label>
|
||||||
<input
|
<input
|
||||||
id="password"
|
id="password"
|
||||||
v-model="state.password"
|
v-model="state.password"
|
||||||
type="password"
|
type="password"
|
||||||
name="password"
|
name="password"
|
||||||
|
autocomplete="current-password"
|
||||||
class="mt-1 block w-96 max-w-full border px-3 py-2"
|
class="mt-1 block w-96 max-w-full border px-3 py-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -62,9 +70,21 @@ const userStore = useUserStore();
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<p class="pt-8">
|
|
||||||
<a :href="`/sso/login/?lang=${userStore.language}`">Login mit SSO</a>
|
<div v-if="loginMethod === 'sso'" class="bg-white p-4 lg:p-8">
|
||||||
</p>
|
<p>
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
"Klicke auf den Button, um dich über SSO anzumelden oder zu registrieren."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<p class="btn-primary mt-8">
|
||||||
|
<a :href="`/sso/login/?lang=${userStore.language}`">
|
||||||
|
{{ $t("SSO Login/Registration") }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ export const updateLoggedIn: NavigationGuard = async () => {
|
||||||
export const redirectToLoginIfRequired: NavigationGuard = (to) => {
|
export const redirectToLoginIfRequired: NavigationGuard = (to) => {
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
if (loginRequired(to) && !userStore.loggedIn) {
|
if (loginRequired(to) && !userStore.loggedIn) {
|
||||||
return `/login?next=${to.fullPath}`;
|
const sentryEnv = import.meta.env.VITE_SENTRY_ENV;
|
||||||
|
const ssoLogin = sentryEnv === "production" || sentryEnv === "staging";
|
||||||
|
return ssoLogin ? `/login?next=${to.fullPath}` : `/login-local?next=${to.fullPath}`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,16 @@ const router = createRouter({
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: "/login",
|
||||||
component: LoginPage,
|
component: LoginPage,
|
||||||
|
props: { loginMethod: "sso" },
|
||||||
|
meta: {
|
||||||
|
// no login required -> so `public === true`
|
||||||
|
public: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/login-local",
|
||||||
|
component: LoginPage,
|
||||||
|
props: { loginMethod: "local" },
|
||||||
meta: {
|
meta: {
|
||||||
// no login required -> so `public === true`
|
// no login required -> so `public === true`
|
||||||
public: true,
|
public: true,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import type { Circle } from "@/services/circle";
|
import type { Circle } from "@/services/circle";
|
||||||
import type { Component } from "vue";
|
import type { Component } from "vue";
|
||||||
|
|
||||||
|
export type LoginMethod = "local" | "sso";
|
||||||
|
|
||||||
export type CourseCompletionStatus = "unknown" | "fail" | "success";
|
export type CourseCompletionStatus = "unknown" | "fail" | "success";
|
||||||
|
|
||||||
export interface BaseCourseWagtailPage {
|
export interface BaseCourseWagtailPage {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue