Add loggedIn guard, add basic login component
This commit is contained in:
parent
fb225b926d
commit
062269f030
|
|
@ -11,6 +11,7 @@
|
|||
import SimpleLayout from '@/layouts/SimpleLayout';
|
||||
import BlankLayout from '@/layouts/BlankLayout';
|
||||
import FullScreenLayout from '@/layouts/FullScreenLayout';
|
||||
import PublicLayout from '@/layouts/PublicLayout';
|
||||
import Modal from '@/components/Modal';
|
||||
import MobileNavigation from '@/components/MobileNavigation';
|
||||
import NewContentBlockWizard from '@/components/content-block-form/NewContentBlockWizard';
|
||||
|
|
@ -36,6 +37,7 @@
|
|||
SimpleLayout,
|
||||
BlankLayout,
|
||||
FullScreenLayout,
|
||||
PublicLayout,
|
||||
Modal,
|
||||
MobileNavigation,
|
||||
NewContentBlockWizard,
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import {ApolloClient} from 'apollo-client/index'
|
|||
import {ApolloLink} from 'apollo-link'
|
||||
import fetch from 'unfetch'
|
||||
|
||||
export default function (uri) {
|
||||
const httpLink = new HttpLink({
|
||||
// uri: process.env.NODE_ENV !== 'production' ? 'http://localhost:8000/api/graphql/' : '/api/graphql/',
|
||||
uri: '/api/graphql/',
|
||||
uri,
|
||||
credentials: 'include',
|
||||
fetch: fetch,
|
||||
headers: {
|
||||
|
|
@ -66,9 +67,10 @@ cache.readQuery = (...args) => {
|
|||
};
|
||||
|
||||
// Create the apollo client
|
||||
export default new ApolloClient({
|
||||
return new ApolloClient({
|
||||
link: composedLink,
|
||||
// link: httpLink,
|
||||
cache: cache,
|
||||
connectToDevTools: true
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
mutation Login($input: LoginInput!) {
|
||||
login(input: $input) {
|
||||
success
|
||||
errors {
|
||||
field
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<div class="container skillbox">
|
||||
<logo></logo>
|
||||
<router-view class="skillbox__content"></router-view>
|
||||
<footer class="skillbox__footer">Footer</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Logo from '@/components/icons/Logo';
|
||||
|
||||
export default {
|
||||
components: {Logo},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
@import "@/styles/_default-layout.scss";
|
||||
|
||||
</style>
|
||||
|
|
@ -3,7 +3,7 @@ import Vue from 'vue'
|
|||
import axios from 'axios'
|
||||
import VueAxios from 'vue-axios'
|
||||
import VueVimeoPlayer from 'vue-vimeo-player'
|
||||
import apolloClient from './graphql/client'
|
||||
import apolloClientFactory from './graphql/client'
|
||||
import VueApollo from 'vue-apollo'
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
|
|
@ -63,8 +63,14 @@ if (process.env.GOOGLE_ANALYTICS_ID) {
|
|||
Vue.directive('click-outside', clickOutside);
|
||||
Vue.directive('auto-grow', autoGrow);
|
||||
|
||||
const publicApolloClient = apolloClientFactory('/api/graphql-public/');
|
||||
const privateApolloClient = apolloClientFactory('/api/graphql/');
|
||||
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: apolloClient
|
||||
clients: {
|
||||
publicClient: publicApolloClient
|
||||
},
|
||||
defaultClient: privateApolloClient
|
||||
});
|
||||
|
||||
Validator.extend('required', required);
|
||||
|
|
@ -98,6 +104,28 @@ Vue.use(VeeValidate, {
|
|||
|
||||
Vue.filter('date', dateFilter);
|
||||
|
||||
/* logged in guard */
|
||||
|
||||
const publicPages = ['login']
|
||||
|
||||
function getCookieValue(a) {
|
||||
var b = document.cookie.match('(^|[^;]+)\\s*' + a + '\\s*=\\s*([^;]+)');
|
||||
return b ? b.pop() : '';
|
||||
}
|
||||
|
||||
function redirectIfLoginRequird(nameOfPage) {
|
||||
return publicPages.indexOf(nameOfPage) === -1 && getCookieValue('loginStatus') !== 'True';
|
||||
}
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (redirectIfLoginRequird(to.name)) {
|
||||
next('/login');
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
// todo handle public pages for user
|
||||
});
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,158 @@
|
|||
<template>
|
||||
<div class="login">
|
||||
<h1 class="login__title">Login</h1>
|
||||
<form class="login__form login-form" novalidate @submit.prevent="validateBeforeSubmit">
|
||||
<div class="login-form__field sbform-input">
|
||||
<label for="email" class="sbform-input__label">E-Mail</label>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="text"
|
||||
v-model="email"
|
||||
v-validate="'required'"
|
||||
:class="{ 'sbform-input__input--error': errors.has('email') }"
|
||||
class="change-form__email skillbox-input sbform-input__input"
|
||||
autocomplete="off"
|
||||
data-cy="email"
|
||||
/>
|
||||
<small
|
||||
v-if="errors.has('email') && submitted"
|
||||
class="sbform-input__error"
|
||||
data-cy="email-local-errors"
|
||||
>{{ errors.first('email') }}</small>
|
||||
<small
|
||||
v-for="error in emailErrors"
|
||||
:key="error"
|
||||
class="sbform-input__error"
|
||||
data-cy="email-remote-errors"
|
||||
>{{ error }}</small>
|
||||
</div>
|
||||
<div class="change-form__field sbform-input">
|
||||
<label for="pw" class="sbform-input__label">Passwort</label>
|
||||
<input
|
||||
id="pw"
|
||||
name="password"
|
||||
type="password"
|
||||
v-model="password"
|
||||
v-validate="'required'"
|
||||
:class="{ 'sbform-input__input--error': errors.has('password') }"
|
||||
class="change-form__new skillbox-input sbform-input__input"
|
||||
autocomplete="off"
|
||||
data-cy="password"
|
||||
/>
|
||||
<small
|
||||
v-if="errors.has('password') && submitted"
|
||||
class="sbform-input__error"
|
||||
data-cy="password-local-errors"
|
||||
>{{ errors.first('password') }}</small>
|
||||
<small
|
||||
v-for="error in passwordErrors"
|
||||
:key="error"
|
||||
class="sbform-input__error"
|
||||
data-cy="password-remote-errors"
|
||||
>{{ error }}</small>
|
||||
</div>
|
||||
<div class="login-error">
|
||||
<small class="sbform-input__error" v-if="loginError">{{loginError}}</small>
|
||||
</div>
|
||||
<button class="button button--primary change-form__submit" data-cy="change-password-button">Anmelden</button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LOGIN_MUTATION from '@/graphql/gql/mutations/login.gql';
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
|
||||
methods: {
|
||||
validateBeforeSubmit() {
|
||||
this.$validator.validate().then(result => {
|
||||
this.submitted = true;
|
||||
let that = this;
|
||||
if (result) {
|
||||
this.$apollo.mutate({
|
||||
client: 'publicClient',
|
||||
mutation: LOGIN_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
usernameInput: this.email,
|
||||
passwordInput: this.password
|
||||
}
|
||||
},
|
||||
update(
|
||||
store,
|
||||
{
|
||||
data: {
|
||||
login: { success }
|
||||
}
|
||||
}
|
||||
) {
|
||||
try {
|
||||
console.log('success', success)
|
||||
if (success) {
|
||||
} else {
|
||||
that.loginError = 'Die E-Mail oder das Passwort ist falsch. Bitte versuchen Sie nochmals.';
|
||||
}
|
||||
} catch (e) {
|
||||
that.loginError = 'Es ist ein Fehler aufgetreten. Bitte versuchen Sie nochmals.';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
resetForm() {
|
||||
this.email = '';
|
||||
this.password = '';
|
||||
this.submitted = false;
|
||||
this.$validator.reset();
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
email: '',
|
||||
password: '',
|
||||
emailErrors: [],
|
||||
passwordErrors: [],
|
||||
loginError: ''
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_buttons.scss";
|
||||
.sbform-input {
|
||||
margin-bottom: 20px;
|
||||
font-family: $sans-serif-font-family;
|
||||
|
||||
&__label {
|
||||
margin-bottom: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&__input {
|
||||
width: 100%;
|
||||
|
||||
&--error {
|
||||
border-color: $color-error;
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
margin-top: 10px;
|
||||
color: $color-error;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&__hint {
|
||||
margin-top: $small-spacing;
|
||||
font-family: $sans-serif-font-family;
|
||||
color: $color-silver-dark;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -27,11 +27,23 @@ import newProject from '@/pages/newProject'
|
|||
import surveyPage from '@/pages/survey'
|
||||
import styleGuidePage from '@/pages/styleguide'
|
||||
import moduleRoom from '@/pages/moduleRoom'
|
||||
import login from '@/pages/login'
|
||||
|
||||
import store from '@/store/index';
|
||||
|
||||
const routes = [
|
||||
{path: '/', component: start, meta: {layout: 'blank'}},
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: start,
|
||||
meta: {layout: 'blank'}
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: login,
|
||||
meta: {layout: 'public'}
|
||||
},
|
||||
{
|
||||
path: '/module/:slug',
|
||||
component: moduleBase,
|
||||
|
|
@ -118,6 +130,7 @@ const router = new Router({
|
|||
return {x: 0, y: 0}
|
||||
}
|
||||
});
|
||||
|
||||
router.afterEach((to, from) => {
|
||||
store.dispatch('showMobileNavigation', false);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -75,3 +75,23 @@ class CommonRedirectMiddleware(MiddlewareMixin):
|
|||
# or dummy image: return 'http://via.placeholder.com/{}'.format(m.group('dimensions'))
|
||||
if '.png' in path or '.jpg' in path or '.svg' in path or 'not-found' in path:
|
||||
return 'https://picsum.photos/400/400'
|
||||
|
||||
|
||||
# https://stackoverflow.com/questions/4898408/how-to-set-a-login-cookie-in-django
|
||||
class UserLoggedInCookieMiddleWare(MiddlewareMixin):
|
||||
"""
|
||||
Middleware to set user cookie
|
||||
If user is authenticated and there is no cookie, set the cookie,
|
||||
If the user is not authenticated and the cookie remains, delete it
|
||||
"""
|
||||
|
||||
cookie_name = 'loginStatus'
|
||||
|
||||
def process_response(self, request, response):
|
||||
#if user and no cookie, set cookie
|
||||
if request.user.is_authenticated and not request.COOKIES.get(self.cookie_name):
|
||||
response.set_cookie(self.cookie_name, 'true')
|
||||
elif not request.user.is_authenticated and request.COOKIES.get(self.cookie_name):
|
||||
#else if if no user and cookie remove user cookie, logout
|
||||
response.delete_cookie(self.cookie_name)
|
||||
return response
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ MIDDLEWARE += [
|
|||
|
||||
'core.middleware.ThreadLocalMiddleware',
|
||||
'core.middleware.CommonRedirectMiddleware',
|
||||
'core.middleware.UserLoggedInCookieMiddleWare',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'core.urls'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import requests
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.views import PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, \
|
||||
PasswordResetCompleteView
|
||||
|
|
@ -16,7 +15,6 @@ class PrivateGraphQLView(LoginRequiredMixin, GraphQLView):
|
|||
pass
|
||||
|
||||
|
||||
@login_required
|
||||
@ensure_csrf_cookie
|
||||
def home(request):
|
||||
if settings.DEBUG:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ from django.contrib.auth.forms import PasswordResetForm
|
|||
from django.contrib.auth.views import PasswordResetView, PasswordResetConfirmView, INTERNAL_RESET_URL_TOKEN
|
||||
from graphene import relay
|
||||
|
||||
from core import settings
|
||||
from users.models import User
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue