AI security fixes
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,3 +4,6 @@
|
|||||||
/.idea
|
/.idea
|
||||||
/._bootstrapTemplates
|
/._bootstrapTemplates
|
||||||
/env
|
/env
|
||||||
|
.env
|
||||||
|
/blechreiz/static_collection
|
||||||
|
/blechreiz/media/user_images
|
||||||
7
blechreiz/context_processors.py
Normal file
7
blechreiz/context_processors.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def google_maps(request):
|
||||||
|
return {
|
||||||
|
"GOOGLE_MAPS_API_KEY": os.environ.get("GOOGLE_MAPS_API_KEY", ""),
|
||||||
|
}
|
||||||
@@ -6,6 +6,13 @@ from pathlib import Path
|
|||||||
BASE_DIR = Path(__file__).resolve().parent
|
BASE_DIR = Path(__file__).resolve().parent
|
||||||
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
|
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
# Load environment variables from .env file if python-dotenv is installed
|
||||||
|
try:
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv(os.path.join(PROJECT_PATH, ".env"))
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Django settings for blechreiz project.
|
# Django settings for blechreiz project.
|
||||||
|
|
||||||
@@ -32,7 +39,7 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|||||||
|
|
||||||
EMAIL_HOST = "smtp.blechreiz.com"
|
EMAIL_HOST = "smtp.blechreiz.com"
|
||||||
EMAIL_HOST_USER = "m02b721a"
|
EMAIL_HOST_USER = "m02b721a"
|
||||||
EMAIL_HOST_PASSWORD = "9Hp4WG5bZ2WVPX5z"
|
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD", "")
|
||||||
EMAIL_USE_TLS = False
|
EMAIL_USE_TLS = False
|
||||||
|
|
||||||
|
|
||||||
@@ -83,7 +90,7 @@ STATICFILES_FINDERS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Make this unique, and don't share it with anybody.
|
# Make this unique, and don't share it with anybody.
|
||||||
SECRET_KEY = "x$8&9s6t%eeg=wyhar87934wh_s$dbpm(73g4ho&n)9_wogj6p"
|
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
"django.middleware.security.SecurityMiddleware",
|
"django.middleware.security.SecurityMiddleware",
|
||||||
@@ -119,7 +126,6 @@ TEMPLATES = [
|
|||||||
"django.template.context_processors.media",
|
"django.template.context_processors.media",
|
||||||
"django.template.context_processors.static",
|
"django.template.context_processors.static",
|
||||||
"sekizai.context_processors.sekizai",
|
"sekizai.context_processors.sekizai",
|
||||||
"blechreiz.context_processors.google_maps",
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -165,18 +171,12 @@ GCAL_COUPLING = {
|
|||||||
"eventPrefix": "Blechreiz: ",
|
"eventPrefix": "Blechreiz: ",
|
||||||
"developerKey": "blechreiz-homepage",
|
"developerKey": "blechreiz-homepage",
|
||||||
"clientId": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com",
|
"clientId": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com",
|
||||||
"client_secret": "y4t9XBrJdCODPTO5UvtONWWn",
|
"client_secret": os.environ.get("GCAL_CLIENT_SECRET", ""),
|
||||||
"credentials_file": PROJECT_PATH + "/calendarCredentials.dat",
|
"credentials_file": PROJECT_PATH + "/calendarCredentials.dat",
|
||||||
"push_url": "https://blechreiz.bauer.technology/eventplanner_gcal/gcalApiCallback",
|
"push_url": "https://blechreiz.bauer.technology/eventplanner_gcal/gcalApiCallback",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Google Maps API Key
|
|
||||||
# Get your API key from https://console.cloud.google.com/apis/credentials
|
|
||||||
# Enable the Maps JavaScript API and Geocoding API
|
|
||||||
GOOGLE_MAPS_API_KEY = "AIzaSyCf9Lm5ckjmVd08scTOd7fB1dC_UCoumKg"
|
|
||||||
|
|
||||||
|
|
||||||
# Crispy Forms configuration
|
# Crispy Forms configuration
|
||||||
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
|
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
|
||||||
CRISPY_TEMPLATE_PACK = "bootstrap5"
|
CRISPY_TEMPLATE_PACK = "bootstrap5"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import datetime
|
|||||||
|
|
||||||
from crispy_forms.helper import FormHelper
|
from crispy_forms.helper import FormHelper
|
||||||
from crispy_forms.layout import Submit
|
from crispy_forms.layout import Submit
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.forms import TextInput
|
from django.forms import TextInput
|
||||||
from django.forms.models import ModelForm
|
from django.forms.models import ModelForm
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
@@ -114,6 +115,8 @@ def events_grid(request):
|
|||||||
|
|
||||||
|
|
||||||
def deleteEvent(request, pk):
|
def deleteEvent(request, pk):
|
||||||
|
if not EventParticipation.isAdmin(request.user):
|
||||||
|
raise PermissionDenied
|
||||||
Event.objects.get(pk=pk).delete()
|
Event.objects.get(pk=pk).delete()
|
||||||
return redirect(events_grid)
|
return redirect(events_grid)
|
||||||
|
|
||||||
|
|||||||
39
location_field/static/location_field/form.css
Normal file
39
location_field/static/location_field/form.css
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
/* Hide map dialog initially - jQuery UI dialog will show it */
|
||||||
|
.map_dialog {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.locationwidget
|
||||||
|
{
|
||||||
|
cursor: pointer !important;
|
||||||
|
background-color: rgb(255, 255, 255) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map_dialog .form-horizontal
|
||||||
|
{
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map_dialog input
|
||||||
|
{
|
||||||
|
width: 390px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.map_dialog input.displayed_location_input
|
||||||
|
{
|
||||||
|
width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map_dialog .map_canvas img
|
||||||
|
{
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map_dialog label
|
||||||
|
{
|
||||||
|
margin-bottom: 0px;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
190
location_field/static/location_field/form.js
Normal file
190
location_field/static/location_field/form.js
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
($ || django.jQuery)(function($){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// map: the div that is made to the map
|
||||||
|
// coordinate_field: input element where position & zoom is stored ( and read to init the map )
|
||||||
|
function MapObject( mapDiv, coordinate_field, init_position, init_zoom )
|
||||||
|
{
|
||||||
|
// Default Argument for init_position
|
||||||
|
init_position = typeof init_position !== 'undefined' ? init_position : new google.maps.LatLng( 49.340174,10.890595 );
|
||||||
|
init_zoom = typeof init_zoom !== 'undefined' ? init_zoom : 16;
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Members --------------------------------------
|
||||||
|
|
||||||
|
this.map = new google.maps.Map( mapDiv, {
|
||||||
|
mapTypeId: google.maps.MapTypeId.HYBRID,
|
||||||
|
zoomControl: true,
|
||||||
|
streetViewControl: false,
|
||||||
|
zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL }
|
||||||
|
} );
|
||||||
|
|
||||||
|
this.geocoder = new google.maps.Geocoder();
|
||||||
|
this.geocoder.region = "de";
|
||||||
|
this.geocoder.location = init_position;
|
||||||
|
|
||||||
|
this.marker = new google.maps.Marker({
|
||||||
|
map: this.map,
|
||||||
|
position: init_position,
|
||||||
|
draggable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Methods --------------------------------------
|
||||||
|
|
||||||
|
this.placeMarkerUsingAddressString = function ( addressStr )
|
||||||
|
{
|
||||||
|
var theObject = this;
|
||||||
|
this.geocode( addressStr , function(l) {
|
||||||
|
theObject.placeMarker( l );
|
||||||
|
theObject.saveToInputField();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.placeMarker = function( location )
|
||||||
|
{
|
||||||
|
this.marker.setPosition( location );
|
||||||
|
this.map.setCenter( location );
|
||||||
|
this.map.panTo( location );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.geocode = function(address, cb)
|
||||||
|
{
|
||||||
|
var result;
|
||||||
|
if (this.geocoder) {
|
||||||
|
this.geocoder.geocode({"address": address}, function(results, status) {
|
||||||
|
if (status == google.maps.GeocoderStatus.OK) {
|
||||||
|
cb(results[0].geometry.location);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.geocode_reverse = function( cb)
|
||||||
|
{
|
||||||
|
if (this.geocoder) {
|
||||||
|
this.geocoder.geocode({"latLng": this.marker.getPosition() }, function(results, status) {
|
||||||
|
if (status == google.maps.GeocoderStatus.OK) {
|
||||||
|
cb( results );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveToInputField = function()
|
||||||
|
{
|
||||||
|
var p = this.marker.getPosition();
|
||||||
|
coordinate_field.value = p.lat().toFixed(6) + "," + p.lng().toFixed(6) + "," + this.map.getZoom() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadFromInputField = function()
|
||||||
|
{
|
||||||
|
if ( coordinate_field.value ) // Already values in the coordinate field
|
||||||
|
{
|
||||||
|
var l = coordinate_field.value.split(/,/);
|
||||||
|
if (l.length > 1)
|
||||||
|
{
|
||||||
|
this.placeMarker( new google.maps.LatLng(l[0], l[1]) );
|
||||||
|
this.map.setZoom( parseInt( l[2] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.placeMarker( init_position );
|
||||||
|
this.map.setZoom( 16 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Constructor -------------------------------------
|
||||||
|
|
||||||
|
this.init = function()
|
||||||
|
{
|
||||||
|
var theObject = this;
|
||||||
|
// Event handling
|
||||||
|
google.maps.event.addListener( this.marker, 'dragend', function(mouseEvent) {
|
||||||
|
theObject.saveToInputField();
|
||||||
|
});
|
||||||
|
|
||||||
|
google.maps.event.addListener( this.map, 'click', function(mouseEvent){
|
||||||
|
theObject.placeMarker( mouseEvent.latLng );
|
||||||
|
theObject.saveToInputField();
|
||||||
|
});
|
||||||
|
|
||||||
|
google.maps.event.addListener( this.map, 'zoom_changed', function(mouseEvent){
|
||||||
|
theObject.saveToInputField();
|
||||||
|
});
|
||||||
|
|
||||||
|
theObject.loadFromInputField();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(".map_dialog").dialog( {
|
||||||
|
modal: true,
|
||||||
|
width: 650,
|
||||||
|
height: 730,
|
||||||
|
resizeable: false,
|
||||||
|
autoOpen: false
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
$('input[data-location-widget]').click( function() {
|
||||||
|
|
||||||
|
var formCoordField = $(this);
|
||||||
|
var $basedField = $( formCoordField.attr('data-based-field') );
|
||||||
|
var $dialogElement = $( formCoordField.attr('data-dialog-id') );
|
||||||
|
|
||||||
|
var $dialogCoordField = $dialogElement.find(".coordinate_input");
|
||||||
|
var $dialogLocationField = $dialogElement.find(".displayed_location_input");
|
||||||
|
$dialogLocationField.val( $basedField.val() );
|
||||||
|
$dialogCoordField.val( formCoordField.val() );
|
||||||
|
|
||||||
|
// Init Map if not yet initialized:
|
||||||
|
var map;
|
||||||
|
if ( ! $dialogElement[0].map )
|
||||||
|
{
|
||||||
|
map = $( formCoordField.attr('data-map') )[0];
|
||||||
|
var zoom = parseInt( formCoordField.attr('data-zoom') );
|
||||||
|
|
||||||
|
// Add Buttons
|
||||||
|
$dialogElement.dialog( "option", "buttons", {
|
||||||
|
Abbrechen: function() {
|
||||||
|
$( this ).dialog( "close" );
|
||||||
|
},
|
||||||
|
Ok: function() {
|
||||||
|
$(formCoordField).val( $dialogCoordField.val() );
|
||||||
|
$basedField.val( $dialogLocationField.val() );
|
||||||
|
$( this ).dialog( "close" );
|
||||||
|
} }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Init Map
|
||||||
|
$dialogElement[0].map = new MapObject( map, $dialogCoordField[0] );
|
||||||
|
}
|
||||||
|
$dialogElement[0].map.placeMarkerUsingAddressString( $dialogLocationField.val() );
|
||||||
|
|
||||||
|
$dialogLocationField.on("keypress", function(e) {
|
||||||
|
if ( e.keyCode == 13 ) { // enter
|
||||||
|
$dialogElement[0].map.placeMarkerUsingAddressString( $dialogLocationField.val() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$dialogElement.find(".coord_to_display_button").click( function() {
|
||||||
|
$dialogElement[0].map.geocode_reverse( function(result) {
|
||||||
|
$dialogLocationField.val( result[0].formatted_address );
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$dialogElement.dialog('open');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ class LocationWidget(widgets.TextInput):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def media(self):
|
def media(self):
|
||||||
api_key = getattr(settings, "GOOGLE_MAPS_API_KEY", "")
|
api_key = os.environ.get("GOOGLE_MAPS_API_KEY", "")
|
||||||
maps_url = f"https://maps.googleapis.com/maps/api/js?key={api_key}&language=de"
|
maps_url = f"https://maps.googleapis.com/maps/api/js?key={api_key}&language=de"
|
||||||
|
|
||||||
return widgets.Media(
|
return widgets.Media(
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from django import forms
|
|||||||
from django.contrib.auth import authenticate, login, logout
|
from django.contrib.auth import authenticate, login, logout
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.auth.views import PasswordChangeView
|
from django.contrib.auth.views import PasswordChangeView
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.http import HttpResponse, HttpResponseRedirect
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
@@ -76,6 +77,9 @@ def own_profile(request):
|
|||||||
def user_edit(request, username):
|
def user_edit(request, username):
|
||||||
musician = get_object_or_404(Musician, user__username=username)
|
musician = get_object_or_404(Musician, user__username=username)
|
||||||
|
|
||||||
|
if request.user != musician.user and not request.user.is_staff:
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = UserEditForm(request.POST, instance=musician)
|
form = UserEditForm(request.POST, instance=musician)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
@@ -93,7 +97,20 @@ class MusicianUpdate(UpdateView):
|
|||||||
model = Musician
|
model = Musician
|
||||||
template_name = "musicians/musician_edit.html"
|
template_name = "musicians/musician_edit.html"
|
||||||
success_url = "/books/"
|
success_url = "/books/"
|
||||||
fields = "__all__"
|
fields = [
|
||||||
|
"image",
|
||||||
|
"small_image",
|
||||||
|
"instrument",
|
||||||
|
"birthday",
|
||||||
|
"street",
|
||||||
|
"city",
|
||||||
|
"zip_code",
|
||||||
|
"phone_home",
|
||||||
|
"phone_mobile",
|
||||||
|
"phone_work",
|
||||||
|
"position",
|
||||||
|
"public_description",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def addressbook(request):
|
def addressbook(request):
|
||||||
@@ -137,11 +154,11 @@ def login_view(request):
|
|||||||
result["err"] = ""
|
result["err"] = ""
|
||||||
if user is not None:
|
if user is not None:
|
||||||
if user.is_active:
|
if user.is_active:
|
||||||
if not request.POST.get("remember", None):
|
if request.POST.get("remember", None):
|
||||||
# Expire in one year
|
# "Remember me" checked: keep session for one year
|
||||||
request.session.set_expiry(timedelta(weeks=52))
|
request.session.set_expiry(timedelta(weeks=52))
|
||||||
else:
|
else:
|
||||||
# Expire on browser close
|
# No "remember me": expire on browser close
|
||||||
request.session.set_expiry(0)
|
request.session.set_expiry(0)
|
||||||
|
|
||||||
login(request, user)
|
login(request, user)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
@@ -10,7 +12,9 @@ from eventplanner.snippets import (
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def home_view(request):
|
def home_view(request):
|
||||||
context = {}
|
context = {
|
||||||
|
"GOOGLE_MAPS_API_KEY": os.environ.get("GOOGLE_MAPS_API_KEY", ""),
|
||||||
|
}
|
||||||
|
|
||||||
# Event participation for slider text
|
# Event participation for slider text
|
||||||
if EventParticipation.isMember(request.user):
|
if EventParticipation.isMember(request.user):
|
||||||
|
|||||||
Reference in New Issue
Block a user