AI security fixes

This commit is contained in:
2026-04-08 21:23:12 +02:00
parent 2beb7aa75a
commit 149a488795
9 changed files with 279 additions and 17 deletions

3
.gitignore vendored
View File

@@ -4,3 +4,6 @@
/.idea
/._bootstrapTemplates
/env
.env
/blechreiz/static_collection
/blechreiz/media/user_images

View File

@@ -0,0 +1,7 @@
import os
def google_maps(request):
return {
"GOOGLE_MAPS_API_KEY": os.environ.get("GOOGLE_MAPS_API_KEY", ""),
}

View File

@@ -6,6 +6,13 @@ from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
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.
@@ -32,7 +39,7 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
EMAIL_HOST = "smtp.blechreiz.com"
EMAIL_HOST_USER = "m02b721a"
EMAIL_HOST_PASSWORD = "9Hp4WG5bZ2WVPX5z"
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD", "")
EMAIL_USE_TLS = False
@@ -83,7 +90,7 @@ STATICFILES_FINDERS = [
]
# 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 = [
"django.middleware.security.SecurityMiddleware",
@@ -119,7 +126,6 @@ TEMPLATES = [
"django.template.context_processors.media",
"django.template.context_processors.static",
"sekizai.context_processors.sekizai",
"blechreiz.context_processors.google_maps",
],
},
},
@@ -165,18 +171,12 @@ GCAL_COUPLING = {
"eventPrefix": "Blechreiz: ",
"developerKey": "blechreiz-homepage",
"clientId": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com",
"client_secret": "y4t9XBrJdCODPTO5UvtONWWn",
"client_secret": os.environ.get("GCAL_CLIENT_SECRET", ""),
"credentials_file": PROJECT_PATH + "/calendarCredentials.dat",
"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_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"

View File

@@ -2,6 +2,7 @@ import datetime
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from django.core.exceptions import PermissionDenied
from django.forms import TextInput
from django.forms.models import ModelForm
from django.http import HttpResponse
@@ -114,6 +115,8 @@ def events_grid(request):
def deleteEvent(request, pk):
if not EventParticipation.isAdmin(request.user):
raise PermissionDenied
Event.objects.get(pk=pk).delete()
return redirect(events_grid)

View 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;
}

View 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');
});
});

View File

@@ -1,6 +1,5 @@
import os
from django.conf import settings
from django.forms import widgets
from django.utils.safestring import mark_safe
@@ -57,7 +56,7 @@ class LocationWidget(widgets.TextInput):
@property
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"
return widgets.Media(

View File

@@ -5,6 +5,7 @@ from django import forms
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.contrib.auth.views import PasswordChangeView
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse_lazy
@@ -76,6 +77,9 @@ def own_profile(request):
def user_edit(request, 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":
form = UserEditForm(request.POST, instance=musician)
if form.is_valid():
@@ -93,7 +97,20 @@ class MusicianUpdate(UpdateView):
model = Musician
template_name = "musicians/musician_edit.html"
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):
@@ -137,11 +154,11 @@ def login_view(request):
result["err"] = ""
if user is not None:
if user.is_active:
if not request.POST.get("remember", None):
# Expire in one year
if request.POST.get("remember", None):
# "Remember me" checked: keep session for one year
request.session.set_expiry(timedelta(weeks=52))
else:
# Expire on browser close
# No "remember me": expire on browser close
request.session.set_expiry(0)
login(request, user)

View File

@@ -1,3 +1,5 @@
import os
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
@@ -10,7 +12,9 @@ from eventplanner.snippets import (
@login_required
def home_view(request):
context = {}
context = {
"GOOGLE_MAPS_API_KEY": os.environ.get("GOOGLE_MAPS_API_KEY", ""),
}
# Event participation for slider text
if EventParticipation.isMember(request.user):