From bb24ed3ecf3e8265b29101ece9a3ba6395d7561a Mon Sep 17 00:00:00 2001 From: winkidney Date: Wed, 4 Dec 2019 22:48:23 +0800 Subject: [PATCH] Feature: Add pin-creation from remote-url + Add CSRF protection for every request --- pinry-spa/public/index.html | 1 + pinry-spa/src/components/PHeader.vue | 37 ++---- pinry-spa/src/components/api.js | 12 ++ pinry-spa/src/components/modals.js | 45 +++++++ .../src/components/pin_create/FileUpload.vue | 63 ++++++++++ .../components/pin_create/PinCreateModal.vue | 114 ++++++++++++++++++ pinry-spa/src/views/PinCreate.vue | 17 +++ pinry/middleware.py | 11 ++ pinry/settings/base.py | 3 + 9 files changed, 279 insertions(+), 24 deletions(-) create mode 100644 pinry-spa/src/components/modals.js create mode 100644 pinry-spa/src/components/pin_create/FileUpload.vue create mode 100644 pinry-spa/src/components/pin_create/PinCreateModal.vue create mode 100644 pinry-spa/src/views/PinCreate.vue create mode 100644 pinry/middleware.py diff --git a/pinry-spa/public/index.html b/pinry-spa/public/index.html index d5c8029..1fe5067 100644 --- a/pinry-spa/public/index.html +++ b/pinry-spa/public/index.html @@ -13,5 +13,6 @@
+ diff --git a/pinry-spa/src/components/PHeader.vue b/pinry-spa/src/components/PHeader.vue index 960e34f..8c67223 100644 --- a/pinry-spa/src/components/PHeader.vue +++ b/pinry-spa/src/components/PHeader.vue @@ -27,16 +27,15 @@ Create
import api from './api'; -import LoginForm from './LoginForm.vue'; -import SignUpForm from './SignUpForm.vue'; +import modals from './modals'; export default { name: 'p-header', @@ -128,6 +126,8 @@ export default { onSignUpSucceed() { this.initializeUser(true); }, + onPinCreated() { + }, logOut() { api.User.logOut().then( () => { @@ -136,24 +136,13 @@ export default { ); }, logIn() { - this.$buefy.modal.open({ - parent: this, - component: LoginForm, - hasModalCard: true, - events: { - 'login.succeed': this.onLoginSucceed, - }, - }); + modals.openLogin(this, this.onLoginSucceed); + }, + createPin() { + modals.openPinCreate(this, this.onPinCreated); }, signUp() { - this.$buefy.modal.open({ - parent: this, - component: SignUpForm, - hasModalCard: true, - events: { - 'signup.succeed': this.onSignUpSucceed, - }, - }); + modals.openSignUp(this, this.onSignUpSucceed); }, initializeUser(force = false) { const self = this; diff --git a/pinry-spa/src/components/api.js b/pinry-spa/src/components/api.js index 31c44fd..e26170b 100644 --- a/pinry-spa/src/components/api.js +++ b/pinry-spa/src/components/api.js @@ -3,6 +3,17 @@ import storage from './utils/storage'; const API_PREFIX = '/api/v2/'; +const Pin = { + createFromURL(jsonData) { + const url = `${API_PREFIX}pins/`; + return axios.post( + url, + jsonData, + ); + }, +}; + + function fetchPins(offset, tagFilter, userFilter) { const url = `${API_PREFIX}pins/`; const queryArgs = { @@ -160,6 +171,7 @@ const User = { }; export default { + Pin, fetchPin, fetchPins, fetchPinsForBoard, diff --git a/pinry-spa/src/components/modals.js b/pinry-spa/src/components/modals.js new file mode 100644 index 0000000..bd9dc62 --- /dev/null +++ b/pinry-spa/src/components/modals.js @@ -0,0 +1,45 @@ +import PinCreateModal from './pin_create/PinCreateModal.vue'; +import LoginForm from './LoginForm.vue'; +import SignUpForm from './SignUpForm.vue'; + + +function openPinCreate(vm, onCreate) { + vm.$buefy.modal.open( + { + parent: vm, + component: PinCreateModal, + hasModalCard: true, + events: { + 'create.succeed': onCreate, + }, + }, + ); +} + +function openLogin(vm, onSucceed) { + vm.$buefy.modal.open({ + parent: vm, + component: LoginForm, + hasModalCard: true, + events: { + 'login.succeed': onSucceed, + }, + }); +} + +function openSignUp(vm, onSignUpSucceed) { + vm.$buefy.modal.open({ + parent: vm, + component: SignUpForm, + hasModalCard: true, + events: { + 'signup.succeed': onSignUpSucceed, + }, + }); +} + +export default { + openPinCreate, + openLogin, + openSignUp, +}; diff --git a/pinry-spa/src/components/pin_create/FileUpload.vue b/pinry-spa/src/components/pin_create/FileUpload.vue new file mode 100644 index 0000000..284deba --- /dev/null +++ b/pinry-spa/src/components/pin_create/FileUpload.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/pinry-spa/src/components/pin_create/PinCreateModal.vue b/pinry-spa/src/components/pin_create/PinCreateModal.vue new file mode 100644 index 0000000..b48deff --- /dev/null +++ b/pinry-spa/src/components/pin_create/PinCreateModal.vue @@ -0,0 +1,114 @@ + + + diff --git a/pinry-spa/src/views/PinCreate.vue b/pinry-spa/src/views/PinCreate.vue new file mode 100644 index 0000000..aec66ed --- /dev/null +++ b/pinry-spa/src/views/PinCreate.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/pinry/middleware.py b/pinry/middleware.py new file mode 100644 index 0000000..d3471ef --- /dev/null +++ b/pinry/middleware.py @@ -0,0 +1,11 @@ +from django.middleware.csrf import get_token + + +class ForceCSRFCookieMiddleware: + def process_request(self, request): + if "CSRF_TOKEN" not in request.META: + get_token(request) + else: + if request.method != "GET": + get_token(request) + return diff --git a/pinry/settings/base.py b/pinry/settings/base.py index 0b89271..b1560ca 100644 --- a/pinry/settings/base.py +++ b/pinry/settings/base.py @@ -26,12 +26,15 @@ INSTALLED_APPS = [ ROOT_URLCONF = 'pinry.urls' MIDDLEWARE_CLASSES = [ + + 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'pinry.middleware.ForceCSRFCookieMiddleware', 'users.middleware.Public', ]