added CORS middleware
This commit is contained in:
parent
9a62b6e4e7
commit
a341fd8ebe
@ -7,7 +7,7 @@ from .models import (Comment, CookLog, Food, Ingredient, InviteLink, Keyword,
|
|||||||
RecipeBook, RecipeBookEntry, RecipeImport, ShareLink,
|
RecipeBook, RecipeBookEntry, RecipeImport, ShareLink,
|
||||||
ShoppingList, ShoppingListEntry, ShoppingListRecipe,
|
ShoppingList, ShoppingListEntry, ShoppingListRecipe,
|
||||||
Space, Step, Storage, Sync, SyncLog, Unit, UserPreference,
|
Space, Step, Storage, Sync, SyncLog, Unit, UserPreference,
|
||||||
ViewLog, Supermarket, SupermarketCategory, SupermarketCategoryRelation,
|
ViewLog, Supermarket, SupermarketCategory, SupermarketCategoryRelation,
|
||||||
ImportLog, TelegramBot, BookmarkletImport)
|
ImportLog, TelegramBot, BookmarkletImport)
|
||||||
|
|
||||||
|
|
||||||
@ -229,6 +229,7 @@ class BookmarkletImportAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
admin.site.register(BookmarkletImport, BookmarkletImportAdmin)
|
admin.site.register(BookmarkletImport, BookmarkletImportAdmin)
|
||||||
|
|
||||||
|
|
||||||
class TelegramBotAdmin(admin.ModelAdmin):
|
class TelegramBotAdmin(admin.ModelAdmin):
|
||||||
list_display = ('id', 'name', 'created_by',)
|
list_display = ('id', 'name', 'created_by',)
|
||||||
|
|
||||||
|
@ -476,7 +476,7 @@ class BookmarkletImportSerializer(serializers.ModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = BookmarkletImport
|
model = BookmarkletImport
|
||||||
fields = ('id', 'url', 'html', 'created_by', 'created_at')
|
fields = ('id', 'url', 'html', 'created_by', 'created_at')
|
||||||
read_only_fields = ('created_by',)
|
read_only_fields = ('created_by', 'space')
|
||||||
|
|
||||||
# Export/Import Serializers
|
# Export/Import Serializers
|
||||||
|
|
||||||
|
@ -18,28 +18,30 @@
|
|||||||
}
|
}
|
||||||
function initBookmarklet() {
|
function initBookmarklet() {
|
||||||
(window.bookmarkletTandoor = function() {
|
(window.bookmarkletTandoor = function() {
|
||||||
var recipe = document.documentElement.innerHTML
|
let recipe = document.documentElement.innerHTML
|
||||||
var form = document.createElement("form");
|
let windowName = "ImportRecipe"
|
||||||
var windowName = "ImportRecipe"
|
let url = localStorage.getItem('importURL')
|
||||||
form.setAttribute("method", "post");
|
let redirect = localStorage.getItem('redirectURL')
|
||||||
form.setAttribute("action", localStorage.getItem('importURL'));
|
let token = localStorage.getItem('token')
|
||||||
form.setAttribute("target",'importRecipe');
|
let params = { 'html' : recipe,'url': window.location.href};
|
||||||
var params = { 'recipe' : recipe,'url': window.location};
|
console.log(window.location.href)
|
||||||
|
|
||||||
for (var i in params) {
|
const xhr = new XMLHttpRequest();
|
||||||
if (params.hasOwnProperty(i)) {
|
xhr.open('POST', url, true);
|
||||||
var input = document.createElement('input');
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
input.type = 'hidden';
|
xhr.setRequestHeader('Authorization', 'Token ' + token);
|
||||||
input.name = i;
|
|
||||||
input.value = params[i];
|
// listen for `onload` event
|
||||||
form.appendChild(input);
|
xhr.onload = () => {
|
||||||
|
// process response
|
||||||
|
if (xhr.readyState == 4 && xhr.status == 201) {
|
||||||
|
// parse JSON data
|
||||||
|
console.log(JSON.parse(xhr.response));
|
||||||
|
} else {
|
||||||
|
console.error('Error!');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
document.body.appendChild(form);
|
xhr.send(JSON.stringify(params));
|
||||||
window.open('', windowName);
|
|
||||||
form.target = windowName;
|
|
||||||
form.submit();
|
|
||||||
document.body.removeChild(form);
|
|
||||||
}
|
}
|
||||||
)();
|
)();
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<h2> {% trans 'Import' %}</h2>
|
<h2> {% trans 'Import' %}</h2>
|
||||||
<a class="btn btn-outline-info btn-sm"
|
<a class="btn btn-outline-info btn-sm"
|
||||||
style="height:50%"
|
style="height:50%"
|
||||||
href="{% bookmarklet request.get_host request.is_secure %}"
|
href="{% bookmarklet request %}"
|
||||||
title="{% trans 'Drag me to your bookmarks to import recipes from anywhere' %}">
|
title="{% trans 'Drag me to your bookmarks to import recipes from anywhere' %}">
|
||||||
<img src="{% static 'assets/favicon-16x16.png' %}">{% trans 'Bookmark Me!' %} </a>
|
<img src="{% static 'assets/favicon-16x16.png' %}">{% trans 'Bookmark Me!' %} </a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,6 +10,7 @@ from django.db.models import Avg
|
|||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
from django.urls import NoReverseMatch, reverse
|
from django.urls import NoReverseMatch, reverse
|
||||||
from recipes import settings
|
from recipes import settings
|
||||||
|
from rest_framework.authtoken.models import Token
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
@ -111,20 +112,26 @@ def is_debug():
|
|||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def bookmarklet(host, secure):
|
def bookmarklet(request):
|
||||||
if secure:
|
if request.is_secure():
|
||||||
prefix = "https://"
|
prefix = "https://"
|
||||||
else:
|
else:
|
||||||
prefix = "http://"
|
prefix = "http://"
|
||||||
|
server = prefix + request.get_host()
|
||||||
|
# TODO is it safe to store the token in clear text in a bookmark?
|
||||||
|
if (api_token := Token.objects.filter(user=request.user).first()) is None:
|
||||||
|
api_token = Token.objects.create(user=request.user)
|
||||||
|
|
||||||
bookmark = "javascript: \
|
bookmark = "javascript: \
|
||||||
(function(){ \
|
(function(){ \
|
||||||
if(window.bookmarkletTandoor!==undefined){ \
|
if(window.bookmarkletTandoor!==undefined){ \
|
||||||
bookmarkletTandoor(); \
|
bookmarkletTandoor(); \
|
||||||
} else { \
|
} else { \
|
||||||
localStorage.setItem('importURL', '" + prefix + host + reverse('api_bookmarklet') + "'); \
|
localStorage.setItem('importURL', '" + server + reverse('api:bookmarkletimport-list') + "'); \
|
||||||
|
localStorage.setItem('redirectURL', '" + server + reverse('data_import_url') + "'); \
|
||||||
|
localStorage.setItem('token', '" + api_token.__str__() + "'); \
|
||||||
document.body.appendChild(document.createElement(\'script\')).src=\'" \
|
document.body.appendChild(document.createElement(\'script\')).src=\'" \
|
||||||
+ prefix + host + static('js/bookmarklet.js') + "? \
|
+ server + static('js/bookmarklet.js') + "? \
|
||||||
r=\'+Math.floor(Math.random()*999999999);}})();"
|
r=\'+Math.floor(Math.random()*999999999);}})();"
|
||||||
|
|
||||||
return re.sub(r"[\n\t]*", "", bookmark)
|
return re.sub(r"[\n\t\s]*", "", bookmark)
|
||||||
|
@ -51,8 +51,8 @@ from cookbook.serializer import (FoodSerializer, IngredientSerializer,
|
|||||||
StorageSerializer, SyncLogSerializer,
|
StorageSerializer, SyncLogSerializer,
|
||||||
SyncSerializer, UnitSerializer,
|
SyncSerializer, UnitSerializer,
|
||||||
UserNameSerializer, UserPreferenceSerializer,
|
UserNameSerializer, UserPreferenceSerializer,
|
||||||
ViewLogSerializer, CookLogSerializer,
|
ViewLogSerializer, CookLogSerializer,
|
||||||
RecipeBookEntrySerializer, RecipeOverviewSerializer,
|
RecipeBookEntrySerializer, RecipeOverviewSerializer,
|
||||||
SupermarketSerializer, ImportLogSerializer, BookmarkletImportSerializer)
|
SupermarketSerializer, ImportLogSerializer, BookmarkletImportSerializer)
|
||||||
from recipes.settings import DEMO
|
from recipes.settings import DEMO
|
||||||
from recipe_scrapers import scrape_me, WebsiteNotImplementedError, NoSchemaFoundInWildMode
|
from recipe_scrapers import scrape_me, WebsiteNotImplementedError, NoSchemaFoundInWildMode
|
||||||
|
@ -94,8 +94,8 @@ def batch_edit(request):
|
|||||||
'Batch edit done. %(count)d recipe was updated.',
|
'Batch edit done. %(count)d recipe was updated.',
|
||||||
'Batch edit done. %(count)d Recipes where updated.',
|
'Batch edit done. %(count)d Recipes where updated.',
|
||||||
count) % {
|
count) % {
|
||||||
'count': count,
|
'count': count,
|
||||||
}
|
}
|
||||||
messages.add_message(request, messages.SUCCESS, msg)
|
messages.add_message(request, messages.SUCCESS, msg)
|
||||||
|
|
||||||
return redirect('data_batch_edit')
|
return redirect('data_batch_edit')
|
||||||
|
@ -14,6 +14,7 @@ import os
|
|||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
from corsheaders.defaults import default_headers
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
@ -76,6 +77,7 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'django.contrib.postgres',
|
'django.contrib.postgres',
|
||||||
'django_tables2',
|
'django_tables2',
|
||||||
|
'corsheaders',
|
||||||
'django_filters',
|
'django_filters',
|
||||||
'crispy_forms',
|
'crispy_forms',
|
||||||
'emoji_picker',
|
'emoji_picker',
|
||||||
@ -97,6 +99,7 @@ SOCIALACCOUNT_PROVIDERS = ast.literal_eval(
|
|||||||
os.getenv('SOCIALACCOUNT_PROVIDERS') if os.getenv('SOCIALACCOUNT_PROVIDERS') else '{}')
|
os.getenv('SOCIALACCOUNT_PROVIDERS') if os.getenv('SOCIALACCOUNT_PROVIDERS') else '{}')
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
'corsheaders.middleware.CorsMiddleware',
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
@ -249,5 +252,17 @@ STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
|
|||||||
|
|
||||||
TEST_RUNNER = "cookbook.helper.CustomTestRunner.CustomTestRunner"
|
TEST_RUNNER = "cookbook.helper.CustomTestRunner.CustomTestRunner"
|
||||||
|
|
||||||
# future versions of django will make undeclared default django.db.models.BigAutoField which will force migrations on all models
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
# settings for cross site origin (CORS)
|
||||||
|
# all origins allowed to support bookmarklet
|
||||||
|
# all of this may or may not work with nginx or other web servers
|
||||||
|
# TODO make this user configureable - enable or disable bookmarklets
|
||||||
|
# TODO since token auth is enabled - this all should be https by default
|
||||||
|
CORS_ORIGIN_ALLOW_ALL = True
|
||||||
|
|
||||||
|
# django rest_framework requires authentication header
|
||||||
|
#CORS_ALLOW_HEADERS = list(default_headers) + ['authentication',]
|
||||||
|
|
||||||
|
# enable CORS only for bookmarklet api and only for posts, get and options
|
||||||
|
CORS_URLS_REGEX = r'^/api/bookmarklet-import.*$'
|
||||||
|
CORS_ALLOW_METHODS = ['GET', 'OPTIONS', 'POST']
|
||||||
|
@ -33,5 +33,6 @@ django-js-reverse==0.9.1
|
|||||||
django-allauth==0.44.0
|
django-allauth==0.44.0
|
||||||
recipe-scrapers==12.2.1
|
recipe-scrapers==12.2.1
|
||||||
django-scopes==1.2.0
|
django-scopes==1.2.0
|
||||||
pytest==6.2.3
|
pytest==6.2.2
|
||||||
pytest-django==4.2.0
|
pytest-django==4.1.0
|
||||||
|
django-cors-headers==3.7.0
|
||||||
|
Loading…
Reference in New Issue
Block a user