Compare commits

..

19 commits

Author SHA1 Message Date
PCoder
50e47d5961 Changes to get the server up and running 2023-07-31 08:30:24 +00:00
PCoder
61d41a2879 Add docker-compose.yml 2023-07-31 05:11:05 +00:00
PCoder
2679c2ddd5 Add missing importlib_metadata dependency 2023-05-30 03:57:13 +00:00
PCoder
c52dff2c10 Rename celery.py to pr_celery => causing conflict in names 2023-05-30 03:56:46 +00:00
PCoder
10c3c2381c Update Dockerfile 2023-05-30 03:55:09 +00:00
PCoder
934c1f98de Updates : stalled with celery
alpine:~/dynamicweb# docker run -ti dynamicweb:latest
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7f9ede435cb0>
Traceback (most recent call last):
  File "/venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 116, in inner_run
    autoreload.raise_last_exception()
  File "/venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 251, in raise_last_exception
    six.reraise(*_exception)
  File "/venv/lib/python3.7/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/__init__.py", line 27, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/venv/lib/python3.7/site-packages/django/apps/registry.py", line 108, in populate
    app_config.import_models()
  File "/venv/lib/python3.7/site-packages/django/apps/config.py", line 202, in import_models
    self.models_module = import_module(models_module_name)
  File "/usr/local/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/app/opennebula_api/models.py", line 11, in <module>
    from utils.tasks import save_ssh_key, save_ssh_key_error_handler
  File "/app/utils/tasks.py", line 5, in <module>
    from celery.result import AsyncResult
  File "/venv/lib/python3.7/site-packages/celery/result.py", line 14, in <module>
    from . import current_app, states
ImportError: cannot import name 'current_app' from 'celery' (/venv/lib/python3.7/site-packages/celery/__init__.py)
2023-05-29 11:53:55 +00:00
PCoder
56cae7b8ab Update more dependencies; fails at no module django_celery_results 2023-05-27 08:43:22 +00:00
PCoder
e1764736fc Update django to fix the error SyntaxError: Generator expression must be parenthesized
alpine:~/dynamicweb# docker run -ti dynamicweb:latest
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7fdc22767710>
Traceback (most recent call last):
  File "/venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 227, in wrapper
    fn(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 117, in inner_run
    autoreload.raise_last_exception()
  File "/venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 250, in raise_last_exception
    six.reraise(*_exception)
  File "/venv/lib/python3.7/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 227, in wrapper
    fn(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/__init__.py", line 27, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/venv/lib/python3.7/site-packages/django/apps/registry.py", line 85, in populate
    app_config = AppConfig.create(entry)
  File "/venv/lib/python3.7/site-packages/django/apps/config.py", line 94, in create
    module = import_module(entry)
  File "/usr/local/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/venv/lib/python3.7/site-packages/django/contrib/admin/__init__.py", line 4, in <module>
    from django.contrib.admin.filters import (
  File "/venv/lib/python3.7/site-packages/django/contrib/admin/filters.py", line 10, in <module>
    from django.contrib.admin.options import IncorrectLookupParameters
  File "/venv/lib/python3.7/site-packages/django/contrib/admin/options.py", line 12, in <module>
    from django.contrib.admin import helpers, widgets
  File "/venv/lib/python3.7/site-packages/django/contrib/admin/widgets.py", line 151
    '%s=%s' % (k, v) for k, v in params.items(),
    ^
SyntaxError: Generator expression must be parenthesized
2023-05-27 07:03:23 +00:00
PCoder
fc6c4c2241 Comment out celery for the moment 2023-05-27 07:02:19 +00:00
PCoder
21816e4884 Prepare a venv 2023-05-27 07:01:39 +00:00
PCoder
cfffc67f55 Update django-cms, django-filer, django-formtools, django-treebeard, djangocms-admin-style, celery, kombu, amqp, vine to suitable versions 2023-05-24 01:44:38 +00:00
PCoder
792868dd64 Remove aldryn dependencies
We don't seem to be using it
2023-05-24 01:43:03 +00:00
PCoder
fbeb18070b Try with python 3.7 because Django 1.11 is supported by it 2023-05-24 01:42:14 +00:00
PCoder
449b78c3eb Remove django-celery-results and update amqp to >=5.0.9
New error:
Traceback (most recent call last):
  File "/app/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 302, in execute
    settings.INSTALLED_APPS
  File "/usr/local/lib/python3.10/site-packages/django/conf/__init__.py", line 55, in __getattr__
    self._setup(name)
  File "/usr/local/lib/python3.10/site-packages/django/conf/__init__.py", line 43, in _setup
    self._wrapped = Settings(settings_module)
  File "/usr/local/lib/python3.10/site-packages/django/conf/__init__.py", line 99, in __init__
    mod = importlib.import_module(self.SETTINGS_MODULE)
  File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 992, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/app/dynamicweb/__init__.py", line 3, in <module>
    from .celery import app as celery_app
  File "/app/dynamicweb/celery.py", line 7, in <module>
    app = Celery('dynamicweb')
  File "/usr/local/lib/python3.10/site-packages/celery/app/base.py", line 291, in __init__
    self._fixups = [symbol_by_name(fixup)(self) for fixup in self.fixups]
  File "/usr/local/lib/python3.10/site-packages/celery/app/base.py", line 291, in <listcomp>
    self._fixups = [symbol_by_name(fixup)(self) for fixup in self.fixups]
  File "/usr/local/lib/python3.10/site-packages/celery/fixups/django.py", line 44, in fixup
    _verify_django_version(django)
  File "/usr/local/lib/python3.10/site-packages/celery/fixups/django.py", line 32, in _verify_django_version
    raise ImproperlyConfigured('Celery 5.x requires Django 1.11 or later.')
celery.exceptions.ImproperlyConfigured: Celery 5.x requires Django 1.11 or later.
2023-05-23 17:40:12 +00:00
Nico Schottelius
23cd61ad54 requirements: upgrade celery (5.2.7) and friends
Failing with:

The conflict is caused by:
    The user requested Django==1.9.4
    aldryn-boilerplates 0.7.4 depends on Django<1.9.999 and >=1.5
    aldryn-categories 1.0.3 depends on django<1.10 and >=1.6
    aldryn-newsblog 1.2.1 depends on Django<1.10 and >=1.6
    aldryn-people 1.2.0 depends on Django<1.10 and >=1.6
    aldryn-reversion 1.0.8 depends on Django<1.10 and >=1.6
    aldryn-search 0.2.11 depends on Django>=1.4
    cmsplugin-filer 1.0.1 depends on Django>=1.5
    django-appdata 0.1.5 depends on Django>=1.4.10
    django-classy-tags 0.7.2 depends on Django>1.3
    django-cms 3.2.5 depends on Django<1.10 and >=1.6.9
    django-debug-toolbar 1.4 depends on Django>=1.7
    django-filer 1.2.0 depends on Django<1.9.999 and >=1.5
    django-formtools 1.0 depends on Django>=1.7
    django-guardian 1.4.4 depends on Django>=1.7
    django-haystack 2.4.1 depends on Django
    django-model-utils 2.5 depends on Django>=1.4.2
    django-mptt 0.8.4 depends on Django>=1.8
    django-reversion 1.10.2 depends on django>=1.8
    django-standard-form 1.1.1 depends on Django>=1.3
    django-stored-messages 1.4.0 depends on Django>=1.8
    django-taggit-templatetags 0.2.5 depends on django>=1.1
    django-treebeard 4.0.1 depends on Django>=1.7
    djangocms-picture 1.0.0 depends on django>=1.6
    easy-thumbnails 2.3 depends on django>=1.4.2
    model-mommy 1.2.6 depends on Django
    django-celery-results 2.5.1 depends on Django>=3.2.18
2023-05-23 19:20:44 +02:00
Nico Schottelius
d60032c59a requirements: update some packages to newer versions
Fixing a lot of pip install issues
2023-05-23 19:05:57 +02:00
Nico Schottelius
179a2e6349 [gitignore] ignore venv/ 2023-05-23 19:05:15 +02:00
PCoder
8ba6ecadf2 Library updates -- still fails on installing pillow 2023-05-23 08:10:26 +00:00
PCoder
b173d7d8a2 Fix requirements 2023-05-19 13:42:32 +00:00
33 changed files with 262 additions and 1075 deletions

View file

@ -1,2 +1 @@
.git
.env

4
.gitignore vendored
View file

@ -15,6 +15,7 @@ media/
!media/keep
/CACHE/
/static/
/venv/
\#*#
.\#*
@ -44,6 +45,3 @@ secret-key
!.gitkeep
*.orig
.vscode/settings.json
2024-*
2025-*
2023-*

View file

@ -1,32 +1,44 @@
# FROM python:3.10.0-alpine3.15
FROM python:3.5-alpine3.12
FROM python:3.7-alpine3.15
WORKDIR /usr/src/app
WORKDIR /app
COPY . /app/
RUN apk add --update --no-cache \
git \
build-base \
openldap-dev \
python3-dev \
postgresql-dev \
jpeg-dev \
libpq-dev \
libjpeg \
libmemcached-dev \
libxml2-dev \
libxslt-dev \
libmemcached-dev \
zlib \
jpeg-dev \
zlib-dev \
&& rm -rf /var/cache/apk/*
## For alpine 3.15 replace postgresql-dev with libpq-dev
# FIX https://github.com/python-ldap/python-ldap/issues/432
RUN echo 'INPUT ( libldap.so )' > /usr/lib/libldap_r.so
COPY requirements.txt ./
#RUN LIBRARY_PATH=/lib:/usr/lib /bin/sh -c "pip install --no-cache-dir -r requirements.txt"
# Pillow seems to need LIBRARY_PATH set as follows: (see: https://github.com/python-pillow/Pillow/issues/1763#issuecomment-222383534)
RUN LIBRARY_PATH=/lib:/usr/lib /bin/sh -c "pip install --no-cache-dir -r requirements.txt"
# Create a virtual environment
RUN python3 -m venv /venv
COPY ./ .
COPY entrypoint.sh /
ENV PATH="/venv/bin:$PATH"
RUN pip install --no-cache-dir --upgrade pip
#RUN CFLAGS="-Wno-cpp -Wno-unused-function -Wno-unused-variable -Wno-missing-noreturn -I/usr/include/libxml2" pip install lxml
RUN pip install --no-cache-dir -r requirements.txt
# Copy entrypoint.sh script and grant execute permissions
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# Run migrations and start the server
ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT ["/entrypoint.sh" ]

View file

@ -31,10 +31,9 @@ class ContactView(FormView):
return context
def form_valid(self, form):
print("alplora contactusform")
#form.save()
#form.send_email(email_to='info@alplora.ch')
#messages.add_message(self.request, messages.SUCCESS, self.success_message)
form.save()
form.send_email(email_to='info@alplora.ch')
messages.add_message(self.request, messages.SUCCESS, self.success_message)
return render(self.request, 'alplora/contact_success.html', {})

View file

@ -1,23 +0,0 @@
#!/bin/sh
if [ $# -lt 1 ]; then
echo "$0 imageversion [push]"
echo "Version could be: $(git describe --always)"
echo "If push is specified, also push to our harbor"
exit 1
fi
tagprefix=harbor.k8s.ungleich.ch/ungleich-public/dynamicweb
version=$1; shift
tag=${tagprefix}:${version}
set -ex
docker build -t "${tag}" .
push=$1; shift
if [ "$push" ]; then
docker push "${tag}"
fi

View file

@ -1,9 +1,8 @@
from django.core.management.base import BaseCommand
from opennebula_api.models import OpenNebulaManager
from datacenterlight.models import VMTemplate
from datacenterlight.cms_models import DCLCalculatorPluginModel
from membership.models import CustomUser
from utils.tasks import send_plain_email_task
from django.conf import settings
from time import sleep
import datetime
@ -22,7 +21,6 @@ class Command(BaseCommand):
def handle(self, *args, **options):
result_dict = {}
error_dict = {}
user_email = options['user_email'] if 'user_email' in options else ""
if user_email:
@ -33,12 +31,8 @@ class Command(BaseCommand):
PROJECT_PATH = os.path.abspath(os.path.dirname(__name__))
if not os.path.exists("%s/outputs" % PROJECT_PATH):
os.mkdir("%s/outputs" % PROJECT_PATH)
public_templates_plugin = DCLCalculatorPluginModel.objects.filter(cmsplugin_ptr_id=23356).first()
ipv6_templates_plugin = DCLCalculatorPluginModel.objects.filter(cmsplugin_ptr_id=21943).first()
templates = public_templates_plugin.vm_templates_to_show + ipv6_templates_plugin.vm_templates_to_show
vm_templates = VMTemplate.objects.filter(opennebula_vm_template_id__in=templates)
for vm_template in vm_templates:
vm_name = 'test-%s-%s' % (vm_template.vm_type, vm_template.name)
for vm_template in VMTemplate.objects.all():
vm_name = 'test-%s' % vm_template.name
vm_id = manager.create_vm(
template_id=vm_template.opennebula_vm_template_id,
specs=specs,
@ -58,7 +52,6 @@ class Command(BaseCommand):
%s %s''' % (vm_name,
vm_template.opennebula_vm_template_id,
vm_template.vm_type)
error_dict[vm_name] = result_dict[vm_name]
self.stdout.write(self.style.ERROR(result_dict[vm_name]))
sleep(1)
date_str = datetime.datetime.strftime(
@ -69,12 +62,4 @@ class Command(BaseCommand):
'w',
encoding='utf-8') as f:
f.write(json.dumps(result_dict))
if error_dict:
email_data = {
'subject': 'Check VM Templates ERROR',
'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
'to': [settings.ADMIN_EMAIL],
'body': json.dumps(error_dict),
}
send_plain_email_task.delay(email_data)
self.stdout.write(self.style.SUCCESS("Done"))

View file

@ -1,54 +0,0 @@
from django.core.management.base import BaseCommand
from datacenterlight.tasks import handle_metadata_and_emails
from datacenterlight.models import StripePlan
from opennebula_api.models import OpenNebulaManager
from membership.models import CustomUser
from hosting.models import GenericProduct
import logging
import json
import sys
import stripe
logger = logging.getLogger(__name__)
class Command(BaseCommand):
help = '''Stripe plans created before version 3.4 saved the plan name like generic-{subscription_id}-amount. This
command aims at replacing this with the actual product name
'''
def handle(self, *args, **options):
cnt = 0
self.stdout.write(
self.style.SUCCESS(
'In Fix generic stripe plan product names'
)
)
plans_to_change = StripePlan.objects.filter(stripe_plan_id__startswith='generic')
for plan in plans_to_change:
response = input("Press 'y' to continue: ")
# Check if the user entered 'y'
if response.lower() == 'y':
plan_name = plan.stripe_plan_id
first_index_hyphen = plan_name.index("-") + 1
product_id = plan_name[
first_index_hyphen:(plan_name[first_index_hyphen:].index("-")) + first_index_hyphen]
gp = GenericProduct.objects.get(id=product_id)
if gp:
cnt += 1
# update stripe
sp = stripe.Plan.retrieve(plan_name)
pr = stripe.Product.retrieve(sp.product)
pr.name = gp.product_name
pr.save()
# update local
spl = StripePlan.objects.get(stripe_plan_id=plan_name)
spl.stripe_plan_name = gp.product_name
spl.save()
print("%s. %s => %s" % (cnt, plan_name, gp.product_name))
else:
print("Invalid input. Please try again.")
sys.exit()
print("Done")

View file

@ -9,7 +9,7 @@ from django.core.urlresolvers import reverse
from django.utils import translation
from django.utils.translation import ugettext_lazy as _
from dynamicweb.celery import app
from dynamicweb.pr_celery import app
from hosting.models import HostingOrder
from membership.models import CustomUser
from opennebula_api.models import OpenNebulaManager

View file

@ -73,7 +73,6 @@ def get_line_item_from_hosting_order_charge(hosting_order_id):
:return:
"""
try:
print("Hositng order id = %s" % hosting_order_id)
hosting_order = HostingOrder.objects.get(id = hosting_order_id)
if hosting_order.stripe_charge_id:
return mark_safe("""
@ -145,7 +144,7 @@ def get_line_item_from_stripe_invoice(invoice):
""".format(
vm_id=vm_id if vm_id > 0 else "",
ip_addresses=mark_safe(get_ip_addresses(vm_id)) if vm_id > 0 else
mark_safe(get_product_name(plan_name)) if plan_name.startswith("generic-") else plan_name,
mark_safe(get_product_name(plan_name)),
period=mark_safe("%s &mdash; %s" % (
datetime.datetime.fromtimestamp(start_date).strftime('%Y-%m-%d'),
datetime.datetime.fromtimestamp(end_date).strftime('%Y-%m-%d'))),
@ -161,7 +160,8 @@ def get_product_name(plan_name):
product_name = ""
if plan_name and plan_name.startswith("generic-"):
first_index_hyphen = plan_name.index("-") + 1
product_id = plan_name[first_index_hyphen:(plan_name[first_index_hyphen:].index("-")) + first_index_hyphen]
product_id = plan_name[first_index_hyphen:
(plan_name[first_index_hyphen:].index("-")) + first_index_hyphen]
try:
product = GenericProduct.objects.get(id=product_id)
product_name = product.product_name

View file

@ -42,8 +42,6 @@ from .utils import (
get_cms_integration, create_vm, clear_all_session_vars, validate_vat_number
)
from datacenterlight.templatetags.custom_tags import get_product_name
logger = logging.getLogger(__name__)
@ -65,23 +63,23 @@ class ContactUsView(FormView):
)
def form_valid(self, form):
#form.save()
#from_emails = {
# 'glasfaser': 'glasfaser@ungleich.ch'
#}
#from_page = self.request.POST.get('from_page')
#email_data = {
# 'subject': "{dcl_text} Message from {sender}".format(
# dcl_text=settings.DCL_TEXT,
# sender=form.cleaned_data.get('email')
# ),
# 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
# 'to': [from_emails.get(from_page, 'support@ungleich.ch')],
# 'body': "\n".join(
# ["%s=%s" % (k, v) for (k, v) in form.cleaned_data.items()]),
# 'reply_to': [form.cleaned_data.get('email')],
#}
#send_plain_email_task.delay(email_data)
form.save()
from_emails = {
'glasfaser': 'glasfaser@ungleich.ch'
}
from_page = self.request.POST.get('from_page')
email_data = {
'subject': "{dcl_text} Message from {sender}".format(
dcl_text=settings.DCL_TEXT,
sender=form.cleaned_data.get('email')
),
'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
'to': [from_emails.get(from_page, 'support@ungleich.ch')],
'body': "\n".join(
["%s=%s" % (k, v) for (k, v) in form.cleaned_data.items()]),
'reply_to': [form.cleaned_data.get('email')],
}
send_plain_email_task.delay(email_data)
if self.request.is_ajax():
return self.render_to_response(
self.get_context_data(success=True, contact_form=form))
@ -201,8 +199,6 @@ class IndexView(CreateView):
ssd_size=storage,
pricing_name=vm_pricing_name
)
if request.user.id == 51:
print("User is test")
specs = {
'cpu': cores,
'memory': memory,
@ -590,9 +586,6 @@ class OrderConfirmationView(DetailView, FormView):
context = {}
# this is amount to be charge/subscribed before VAT and discount
# and expressed in chf. To convert to cents, multiply by 100
print("******************************")
print("User = {}, ID = {}".format(request.user, request.user.id))
print("******************************")
amount_to_charge = 0
vm_specs = None
if (('specs' not in request.session or 'user' not in request.session)
@ -618,7 +611,7 @@ class OrderConfirmationView(DetailView, FormView):
# TODO check when we go through this case (to me, it seems useless)
card_id = self.request.session.get('card_id')
logger.debug("NO id_payment_method, using card: %s" % card_id)
card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
card_detail = UserCardDetail.objects.get(id=card_id)
context['cc_last4'] = card_detail.last4
context['cc_brand'] = card_detail.brand
context['cc_exp_year'] = card_detail.exp_year
@ -652,8 +645,6 @@ class OrderConfirmationView(DetailView, FormView):
pricing_name=vm_specs['pricing_name'],
vat_rate=user_country_vat_rate * 100
)
if request.user.id == 51:
print("User is test")
vm_specs["price"] = price
vm_specs["price_after_discount"] = price - discount["amount"]
amount_to_charge = price
@ -859,7 +850,7 @@ class OrderConfirmationView(DetailView, FormView):
return show_error(msg, self.request)
elif 'card_id' in request.session:
card_id = request.session.get('card_id')
user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
user_card_detail = UserCardDetail.objects.get(id=card_id)
card_details_dict = {
'last4': user_card_detail.last4,
'brand': user_card_detail.brand,
@ -909,21 +900,15 @@ class OrderConfirmationView(DetailView, FormView):
2
)
)
stripe_plan_id = "generic-{0}-{1:.2f}".format(
plan_name = "generic-{0}-{1:.2f}".format(
request.session['generic_payment_details']['product_id'],
amount_to_be_charged
)
try:
product = GenericProduct.objects.get(id=request.session['generic_payment_details']['product_id'])
plan_name = product.product_name
except Exception as ex:
logger.debug("Errori {}" % str(ex))
plan_name = get_product_name(stripe_plan_id)
stripe_plan_id = plan_name
recurring_interval = request.session['generic_payment_details']['recurring_interval']
if recurring_interval == "year":
stripe_plan_id = "{}-yearly".format(stripe_plan_id)
plan_name = "{} (yearly)".format(plan_name)
logger.debug("Plan name = {}, Stripe Plan id = {}".format(plan_name, stripe_plan_id))
plan_name = "{}-yearly".format(plan_name)
stripe_plan_id = plan_name
else:
template = request.session.get('template')
specs = request.session.get('specs')
@ -1016,8 +1001,6 @@ class OrderConfirmationView(DetailView, FormView):
# due to some reason. So, we would want to dissociate this card
# here.
# ...
logger.debug("In 1 ***")
logger.debug("stripe_subscription_obj == %s" % stripe_subscription_obj)
msg = subscription_result.get('error')
return show_error(msg, self.request)
elif stripe_subscription_obj.status == 'incomplete':
@ -1211,10 +1194,9 @@ def get_or_create_custom_user(request, stripe_api_cus_id):
def set_user_card(card_id, stripe_api_cus_id, custom_user,
card_details_response):
logger.debug(":: set_user_card")
if card_id:
logger.debug("card_id %s was in request" % card_id)
user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
user_card_detail = UserCardDetail.objects.get(id=card_id)
card_details_dict = {
'last4': user_card_detail.last4,
'brand': user_card_detail.brand,
@ -1226,24 +1208,21 @@ def set_user_card(card_id, stripe_api_cus_id, custom_user,
stripe_source_id=user_card_detail.card_id
)
else:
logger.debug(" card_id was NOT in request, using "
logger.debug("card_id was NOT in request, using "
"card_details_response")
ucd = UserCardDetail.get_or_create_user_card_detail(
stripe_customer=custom_user.stripecustomer,
card_details=card_details_response
)
logger.debug(" ucd = %s" % ucd)
UserCardDetail.save_default_card_local(
custom_user.stripecustomer.stripe_id,
ucd.card_id
)
logger.debug(" after save_default_card_local")
card_details_dict = {
'last4': ucd.last4,
'brand': ucd.brand,
'card_id': ucd.card_id
}
logger.debug("card_detail_dict = %s" % card_details_dict)
return card_details_dict
@ -1437,30 +1416,6 @@ def do_provisioning(request, stripe_api_cus_id, card_details_response,
"""
logger.debug("do_provisioning")
try:
params = {
'request': request,
'stripe_api_cus_id': stripe_api_cus_id,
'card_details_response': card_details_response,
'stripe_subscription_obj': stripe_subscription_obj,
'stripe_onetime_charge': stripe_onetime_charge,
'gp_details': gp_details,
'specs': specs,
'vm_template_id': vm_template_id,
'template': template,
'billing_address_data': billing_address_data,
'real_request': real_request
}
print("Input Parameters:")
for key, value in params.items():
try:
print("{}: {}".format(key, value))
except Exception as e:
print("{}: [Error printing value: {}]".format(key, str(e)))
except Exception as e:
print("Error printing parameters: {}".format(str(e)))
user = request.get('user', None)
# Create user if the user is not logged in and if he is not already
@ -1472,7 +1427,6 @@ def do_provisioning(request, stripe_api_cus_id, card_details_response,
card_details_dict = set_user_card(card_id, stripe_api_cus_id, custom_user,
card_details_response)
logger.debug("after set_user_card %s" % card_details_dict)
# Save billing address
billing_address_data.update({
@ -1495,7 +1449,6 @@ def do_provisioning(request, stripe_api_cus_id, card_details_response,
vat_number=billing_address_data['vat_number']
)
billing_address.save()
logger.debug("billing_address saved")
order = HostingOrder.create(
price=request['generic_payment_details']['amount'],
@ -1503,7 +1456,6 @@ def do_provisioning(request, stripe_api_cus_id, card_details_response,
billing_address=billing_address,
vm_pricing=VMPricing.get_default_pricing()
)
logger.debug("hosting order created")
# Create a Hosting Bill
HostingBill.create(customer=stripe_cus,
@ -1560,9 +1512,7 @@ def do_provisioning(request, stripe_api_cus_id, card_details_response,
["%s=%s" % (k, v) for (k, v) in context.items()]),
'reply_to': [context['email']],
}
logger.debug("Sending email")
send_plain_email_task.delay(email_data)
logger.debug("After Sending email")
recurring_text = _(" This is a monthly recurring plan.")
if gp_details['recurring_interval'] == "year":
recurring_text = _(" This is an yearly recurring plan.")
@ -1586,7 +1536,6 @@ def do_provisioning(request, stripe_api_cus_id, card_details_response,
),
'reply_to': ['info@ungleich.ch'],
}
logger.debug("Before Sending customer email")
send_plain_email_task.delay(email_data)
redirect_url = reverse('datacenterlight:index')
logger.debug("Sent user/admin emails")
@ -1630,7 +1579,7 @@ def do_provisioning(request, stripe_api_cus_id, card_details_response,
def get_error_response_dict(msg, request):
logger.debug("Init get_error_response_dict {}".format(msg))
logger.error(msg)
response = {
'status': False,
'redirect': "{url}#{section}".format(

View file

@ -835,10 +835,9 @@ class ContactView(FormView):
success_message = _('Message Successfully Sent')
def form_valid(self, form):
print("digital glarus contactusform")
#form.save()
#form.send_email()
#messages.add_message(self.request, messages.SUCCESS, self.success_message)
form.save()
form.send_email()
messages.add_message(self.request, messages.SUCCESS, self.success_message)
return super(ContactView, self).form_valid(form)

42
docker-compose.yml Normal file
View file

@ -0,0 +1,42 @@
version: '3'
services:
# Django app service
web:
build:
context: .
dockerfile: Dockerfile
container_name: dynamicweb
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
depends_on:
- db
# PostgreSQL database service
db:
image: postgres:13
container_name: my_postgres_db
environment:
POSTGRES_USER: your_postgres_username
POSTGRES_PASSWORD: your_postgres_password
POSTGRES_DB: your_database_name
volumes:
- postgres_data:/var/lib/postgresql/data
# Nginx service
nginx:
image: nginx:latest
container_name: my_nginx_server
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
ports:
- "80:80"
depends_on:
- web
volumes:
postgres_data:

View file

@ -1,5 +1,5 @@
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ['celery_app']
#from .celery import app as celery_app
#
#__all__ = ['celery_app']

View file

@ -56,9 +56,6 @@ dotenv.load_dotenv("{0}/.env".format(PROJECT_DIR))
from multisite import SiteID
RECAPTCHA_PUBLIC_KEY = env('RECAPTCHA_PUBLIC_KEY')
RECAPTCHA_PRIVATE_KEY = env('RECAPTCHA_PRIVATE_KEY')
UNGLEICH_BLOG_SITE_ID = int_env("UNGLEICH_BLOG_SITE_ID")
SITE_ID = SiteID(default=(UNGLEICH_BLOG_SITE_ID if
UNGLEICH_BLOG_SITE_ID > 0 else 1))
@ -116,7 +113,7 @@ INSTALLED_APPS = (
'aldryn_common',
'aldryn_newsblog',
'aldryn_people',
'aldryn_reversion',
#'aldryn_reversion',
'aldryn_translation_tools',
'treebeard', # utilities for implementing a tree
'sekizai', # for javascript and css management
@ -128,7 +125,6 @@ INSTALLED_APPS = (
'djangocms_file',
'djangocms_picture',
'djangocms_video',
'django_recaptcha',
# 'djangocms_flash',
# 'djangocms_googlemap',
# 'djangocms_inherit',
@ -160,7 +156,7 @@ INSTALLED_APPS = (
'webhook',
)
MIDDLEWARE_CLASSES = (
MIDDLEWARE = (
'django.contrib.sessions.middleware.SessionMiddleware',
'utils.middleware.MultipleProxyMiddleware',
'django.middleware.common.CommonMiddleware',
@ -243,8 +239,12 @@ CMS_TEMPLATES = (
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'app',
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'your_database_name',
'USER': 'your_postgres_username',
'PASSWORD': 'your_postgres_password',
'HOST': 'db',
'PORT': '5432'
}
}
@ -777,9 +777,3 @@ if DEBUG:
from .local import * # flake8: noqa
else:
from .prod import * # flake8: noqa
# Try to load dynamic configuration, if it exists
try:
from .dynamic import * # flake8: noqa
except ImportError:
pass

View file

@ -15,7 +15,7 @@ CACHES = {
}
}
MIDDLEWARE_CLASSES += ("debug_toolbar.middleware.DebugToolbarMiddleware",)
MIDDLEWARE += ("debug_toolbar.middleware.DebugToolbarMiddleware",)
INSTALLED_APPS += (
'django_extensions',

26
entrypoint.sh Executable file → Normal file
View file

@ -1,19 +1,15 @@
#!/bin/sh
set -uex
# Wait for the database to be available
while ! nc -z db 5432; do
sleep 0.1
done
cd /usr/src/app/
cat > dynamicweb/settings/dynamic.py <<EOF
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': '${POSTGRES_DB}',
'USER': '${POSTGRES_USER}',
'PASSWORD': '${POSTGRES_PASSWORD}',
'HOST': '${POSTGRES_HOST}',
'PORT': '5432',
}
}
EOF
# Apply database migrations
python manage.py migrate
exec "$@"
# Collect static files
python manage.py collectstatic --no-input
# Start the server
python manage.py runserver 0.0.0.0:8000

View file

@ -1,144 +0,0 @@
from django.core.management.base import BaseCommand
import datetime
import csv
import logging
import stripe
from hosting.models import VATRates
from utils.hosting_utils import get_vat_rate_for_country
from django.conf import settings
from membership.models import CustomUser, StripeCustomer
stripe.api_key = settings.STRIPE_API_PRIVATE_KEY
logger = logging.getLogger(__name__)
class Command(BaseCommand):
help = '''CH vat rate changes on 2024-01-01 from 7.7% to 8.1%. This commands makes the necessary changes'''
def handle(self, *args, **options):
MAKE_MODIFS=False
try:
country_to_change = 'CH'
currency_to_change = 'CHF'
new_rate = 0.081
user_country_vat_rate = get_vat_rate_for_country(country_to_change)
logger.debug("Existing VATRate for %s %s " % (country_to_change, user_country_vat_rate))
vat_rate = VATRates.objects.get(
territory_codes=country_to_change, start_date__isnull=False, stop_date=None
)
logger.debug("VAT rate for %s is %s" % (country_to_change, vat_rate.rate))
logger.debug("vat_rate object = %s" % vat_rate)
logger.debug("Create end date for the VATRate %s" % vat_rate.id)
# if MAKE_MODIFS:
# vat_rate.stop_date = datetime.date(2023, 12, 31)
# vat_rate.save()
# print("Creating a new VATRate for CH")
# obj, created = VATRates.objects.get_or_create(
# start_date=datetime.date(2024, 1, 1),
# stop_date=None,
# territory_codes=country_to_change,
# currency_code=currency_to_change,
# rate=new_rate,
# rate_type="standard",
# description="Switzerland standard VAT (added manually on %s)" % datetime.datetime.now()
# )
# if created:
# logger.debug("Created new VAT Rate for %s with the new rate %s" % (country_to_change, new_rate))
# logger.debug(obj)
# else:
# logger.debug("VAT Rate for %s already exists with the rate %s" % (country_to_change, new_rate))
#
logger.debug("Getting all subscriptions of %s that need a VAT Rate change")
subscriptions = stripe.Subscription.list(limit=100) # Increase the limit to 100 per page (maximum)
ch_subs = []
while subscriptions:
for subscription in subscriptions:
if len(subscription.default_tax_rates) > 0 and subscription.default_tax_rates[0].jurisdiction and subscription.default_tax_rates[0].jurisdiction.lower() == 'ch':
ch_subs.append(subscription)
elif len(subscription.default_tax_rates) > 0:
print("subscription %s belongs to %s" % (subscription.id, subscription.default_tax_rates[0].jurisdiction))
else:
print("subscription %s does not have a tax rate" % subscription.id)
if subscriptions.has_more:
print("FETCHING MORE")
subscriptions = stripe.Subscription.list(limit=100, starting_after=subscriptions.data[-1])
else:
break
logger.debug("There are %s ch subscription that need VAT rate update" % len(ch_subs))
# CSV column headers
csv_headers = [
"customer_name",
"customer_email",
"stripe_customer_id",
"subscription_id",
"subscription_name",
"amount",
"vat_rate"
]
# CSV file name
csv_filename = "ch_subscriptions_change_2024.csv"
# Write subscription data to CSV file
with open(csv_filename, mode='w', newline='') as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=csv_headers)
writer.writeheader()
for subscription in ch_subs:
subscription_id = subscription["id"]
stripe_customer_id = subscription.get("customer", "")
vat_rate = subscription.get("tax_percent", "")
c_user = CustomUser.objects.get(
id=StripeCustomer.objects.filter(stripe_id=stripe_customer_id)[0].user.id)
if c_user:
customer_name = c_user.name.encode('utf-8')
customer_email = c_user.email
items = subscription.get("items", {}).get("data", [])
for item in items:
subscription_name = item.get("plan", {}).get("id", "")
amount = item.get("plan", {}).get("amount", "")
# Convert amount to a proper format (e.g., cents to dollars)
amount_in_chf = amount / 100 # Adjust this conversion as needed
# Writing to CSV
writer.writerow({
"customer_name": customer_name,
"customer_email": customer_email,
"stripe_customer_id": stripe_customer_id,
"subscription_id": subscription_id,
"subscription_name": subscription_name,
"amount": amount_in_chf,
"vat_rate": vat_rate # Fill in VAT rate if available
})
else:
print("No customuser for %s %s" % (stripe_customer_id, subscription_id))
if MAKE_MODIFS:
print("Making modifications now")
tax_rate_obj = stripe.TaxRate.create(
display_name="VAT",
description="VAT for %s" % country_to_change,
jurisdiction=country_to_change,
percentage=new_rate,
inclusive=False,
)
stripe_tax_rate = StripeTaxRate.objects.create(
display_name=tax_rate_obj.display_name,
description=tax_rate_obj.description,
jurisdiction=tax_rate_obj.jurisdiction,
percentage=tax_rate_obj.percentage,
inclusive=False,
tax_rate_id=tax_rate_obj.id
)
for ch_sub in ch_subs:
ch_sub.default_tax_rates = [stripe_tax_rate.tax_rate_id]
ch_sub.save()
logger.debug("Default tax rate updated for %s" % ch_sub.id)
else:
print("Not making any modifications because MAKE_MODIFS=False")
except Exception as e:
print(" *** Error occurred. Details {}".format(str(e)))

View file

@ -1,143 +0,0 @@
from django.core.management.base import BaseCommand
import datetime
import csv
import logging
import stripe
from hosting.models import VATRates, StripeTaxRate
from utils.hosting_utils import get_vat_rate_for_country
from django.conf import settings
from membership.models import CustomUser, StripeCustomer
stripe.api_key = settings.STRIPE_API_PRIVATE_KEY
logger = logging.getLogger(__name__)
class Command(BaseCommand):
help = '''FI vat rate changes on 2024-09-01 from 24% to 25.5%. This commands makes the necessary changes'''
def handle(self, *args, **options):
MAKE_MODIFS=False
try:
country_to_change = 'FI'
currency_to_change = 'EUR'
new_rate = 25.5
user_country_vat_rate = get_vat_rate_for_country(country_to_change)
logger.debug("Existing VATRate for %s %s " % (country_to_change, user_country_vat_rate))
vat_rate = VATRates.objects.get(
territory_codes=country_to_change, start_date__isnull=False, stop_date=None
)
logger.debug("VAT rate for %s is %s" % (country_to_change, vat_rate.rate))
logger.debug("vat_rate object = %s" % vat_rate)
logger.debug("Create end date for the VATRate %s" % vat_rate.id)
#if MAKE_MODIFS:
# vat_rate.stop_date = datetime.date(2024, 8, 31)
# vat_rate.save()
# print("Creating a new VATRate for FI")
# obj, created = VATRates.objects.get_or_create(
# start_date=datetime.date(2024, 9, 1),
# stop_date=None,
# territory_codes=country_to_change,
# currency_code=currency_to_change,
# rate=new_rate * 0.01,
# rate_type="standard",
# description="FINLAND standard VAT (added manually on %s)" % datetime.datetime.now()
# )
# if created:
# logger.debug("Created new VAT Rate for %s with the new rate %s" % (country_to_change, new_rate))
# logger.debug(obj)
# else:
# logger.debug("VAT Rate for %s already exists with the rate %s" % (country_to_change, new_rate))
logger.debug("Getting all subscriptions of %s that need a VAT Rate change")
subscriptions = stripe.Subscription.list(limit=100) # Increase the limit to 100 per page (maximum)
fi_subs = []
while subscriptions:
for subscription in subscriptions:
if len(subscription.default_tax_rates) > 0 and subscription.default_tax_rates[0].jurisdiction and subscription.default_tax_rates[0].jurisdiction.lower() == 'fi':
fi_subs.append(subscription)
elif len(subscription.default_tax_rates) > 0:
print("subscription %s belongs to %s" % (subscription.id, subscription.default_tax_rates[0].jurisdiction))
else:
print("subscription %s does not have a tax rate" % subscription.id)
if subscriptions.has_more:
print("FETCHING MORE")
subscriptions = stripe.Subscription.list(limit=100, starting_after=subscriptions.data[-1])
else:
break
logger.debug("There are %s FI subscription that need VAT rate update" % len(fi_subs))
# CSV column headers
csv_headers = [
"customer_name",
"customer_email",
"stripe_customer_id",
"subscription_id",
"subscription_name",
"amount",
"vat_rate"
]
# CSV file name
csv_filename = "fi_subscriptions_change_2024.csv"
# Write subscription data to CSV file
with open(csv_filename, mode='w', newline='') as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=csv_headers)
writer.writeheader()
for subscription in fi_subs:
subscription_id = subscription["id"]
stripe_customer_id = subscription.get("customer", "")
vat_rate = subscription.get("tax_percent", "")
c_user = CustomUser.objects.get(
id=StripeCustomer.objects.filter(stripe_id=stripe_customer_id)[0].user.id)
if c_user:
customer_name = c_user.name.encode('utf-8')
customer_email = c_user.email
items = subscription.get("items", {}).get("data", [])
for item in items:
subscription_name = item.get("plan", {}).get("id", "")
amount = item.get("plan", {}).get("amount", "")
# Convert amount to a proper format (e.g., cents to dollars)
amount_in_chf = amount / 100 # Adjust this conversion as needed
# Writing to CSV
writer.writerow({
"customer_name": customer_name,
"customer_email": customer_email,
"stripe_customer_id": stripe_customer_id,
"subscription_id": subscription_id,
"subscription_name": subscription_name,
"amount": amount_in_chf,
"vat_rate": vat_rate # Fill in VAT rate if available
})
else:
print("No customuser for %s %s" % (stripe_customer_id, subscription_id))
if MAKE_MODIFS:
print("Making modifications now")
tax_rate_obj = stripe.TaxRate.create(
display_name="VAT",
description="VAT for %s" % country_to_change,
jurisdiction=country_to_change,
percentage=new_rate,
inclusive=False,
)
stripe_tax_rate = StripeTaxRate.objects.create(
display_name=tax_rate_obj.display_name,
description=tax_rate_obj.description,
jurisdiction=tax_rate_obj.jurisdiction,
percentage=tax_rate_obj.percentage,
inclusive=False,
tax_rate_id=tax_rate_obj.id
)
for fi_sub in fi_subs:
fi_sub.default_tax_rates = [stripe_tax_rate.tax_rate_id]
fi_sub.save()
logger.debug("Default tax rate updated for %s" % fi_sub.id)
else:
print("Not making any modifications because MAKE_MODIFS=False")
except Exception as e:
print(" *** Error occurred. Details {}".format(str(e)))

View file

@ -1,25 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2023-07-27 08:12
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hosting', '0065_auto_20201231_1041'),
]
operations = [
migrations.AlterField(
model_name='genericproduct',
name='product_price',
field=models.DecimalField(decimal_places=2, max_digits=10),
),
migrations.AlterField(
model_name='genericproduct',
name='product_vat',
field=models.DecimalField(decimal_places=4, default=0, max_digits=10),
),
]

View file

@ -1,10 +1,7 @@
from django.contrib import messages
from django.shortcuts import redirect
from django.conf import settings
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from opennebula_api.exceptions import TemplateNotFoundError
from opennebula_api.serializers import VirtualMachineTemplateSerializer
from opennebula_api.models import OpenNebulaManager
@ -17,15 +14,7 @@ class ProcessVMSelectionMixin(object):
template_id = int(request.POST.get('vm_template_id'))
configuration_id = int(request.POST.get('configuration'))
try:
template = OpenNebulaManager().get_template(template_id)
except TemplateNotFoundError:
messages.error(
request,
_('The selected configuration is no longer available. '
'Please choose another one.')
)
return redirect(reverse('hosting:index'))
template = OpenNebulaManager().get_template(template_id)
data = VirtualMachineTemplateSerializer(template).data
configuration = HostingPlan.objects.get(id=configuration_id)

View file

@ -75,8 +75,8 @@ class GenericProduct(AssignPermissionsMixin, models.Model):
)
product_description = models.CharField(max_length=500, default="")
created_at = models.DateTimeField(auto_now_add=True)
product_price = models.DecimalField(max_digits=10, decimal_places=2)
product_vat = models.DecimalField(max_digits=10, decimal_places=4, default=0)
product_price = models.DecimalField(max_digits=6, decimal_places=2)
product_vat = models.DecimalField(max_digits=6, decimal_places=4, default=0)
product_is_subscription = models.BooleanField(default=True)
product_subscription_interval = models.CharField(
max_length=10, default="month",
@ -699,116 +699,15 @@ class UserCardDetail(AssignPermissionsMixin, models.Model):
@staticmethod
def save_default_card_local(stripe_api_cus_id, card_id):
print("save_default_card_local {}, {}".format(stripe_api_cus_id, card_id))
stripe_cust = StripeCustomer.objects.get(stripe_id=stripe_api_cus_id)
print(" stripe_cust={}".format(stripe_cust))
user_card_detail = UserCardDetail.get_ucd_from_stripe_cust_n_card_id(
stripe_cust, card_id
user_card_detail = UserCardDetail.objects.get(
stripe_customer=stripe_cust, card_id=card_id
)
print(" user_card_detail={}".format(user_card_detail.__dict__))
for card in stripe_cust.usercarddetail_set.all():
card.preferred = False
card.save()
user_card_detail.preferred = True
user_card_detail.save()
print(" save_default_card_local DONE")
@staticmethod
def get_ucd_from_card_id(card_id):
try:
user_card_details = UserCardDetail.objects.filter(
card_id=card_id
).order_by('-id')
if user_card_details.count() > 1:
# Log a warning about the duplicate entries
logger.warning(
"Multiple UserCardDetail objects found for card_id={}. "
"Found {} objects. Using the latest one.".format(
card_id, user_card_details.count()
)
)
# Use the first object found
user_card_detail = user_card_details.first()
elif user_card_details.count() == 1:
# Exactly one object found, proceed as intended
user_card_detail = user_card_details.first()
else:
# No object found for the given customer and card_id.
# Depending on expected behavior, you might want to raise an error or handle this case.
# If the original get() call happened here, it would raise DoesNotExist.
logger.error(
"No UserCardDetail found for card_id={}.".format(card_id)
)
raise UserCardDetail.DoesNotExist("No UserCardDetail found for card {}".format(card_id))
if user_card_details.count() > 1:
# Log a warning about the duplicate entries
logger.warning(
"Multiple UserCardDetail objects found for card_id={}. "
"Found {} objects. Using the first one.".format(
card_id, user_card_details.count()
)
)
# Use the first object found
user_card_detail = user_card_details.first()
elif user_card_details.count() == 1:
# Exactly one object found, proceed as intended
user_card_detail = user_card_details.first()
else:
# No object found for the given customer and card_id.
# Depending on expected behavior, you might want to raise an error or handle this case.
# If the original get() call happened here, it would raise DoesNotExist.
logger.error(
"No UserCardDetail found for card_id={}.".format(card_id)
)
raise UserCardDetail.DoesNotExist("No UserCardDetail found for card {}".format(card_id))
except Exception as e:
# Catch other potential exceptions during the filter/get process if necessary
logger.error("An unexpected error occurred while fetching UserCardDetail: {}".format(e))
raise
return user_card_detail
@staticmethod
def get_ucd_from_stripe_cust_n_card_id(stripe_cust, card_id):
try:
user_card_details = UserCardDetail.objects.filter(
stripe_customer=stripe_cust, card_id=card_id
).order_by('-id')
if user_card_details.count() > 1:
# Log a warning about the duplicate entries
logger.warning(
"Multiple UserCardDetail objects found for stripe_customer_id={} and card_id={}. "
"Found {} objects. Using the first one.".format(
stripe_cust.id, card_id, user_card_details.count()
)
)
# Use the first object found
user_card_detail = user_card_details.first()
elif user_card_details.count() == 1:
# Exactly one object found, proceed as intended
user_card_detail = user_card_details.first()
else:
# No object found for the given customer and card_id.
# Depending on expected behavior, you might want to raise an error or handle this case.
# If the original get() call happened here, it would raise DoesNotExist.
logger.error(
"No UserCardDetail found for stripe_customer_id={} and card_id={}.".format(
stripe_cust.id, card_id
)
)
raise UserCardDetail.DoesNotExist(
"No UserCardDetail found for customer {}, card {}".format(
stripe_cust.id, card_id
)
)
except Exception as e:
# Catch other potential exceptions during the filter/get process if necessary
logger.error("An unexpected error occurred while fetching UserCardDetail: {}".format(e))
raise
return user_card_detail
@staticmethod
def get_user_card_details(stripe_customer, card_details):

View file

@ -46,7 +46,7 @@
<div class="vm-vmid">
<div class="vm-item-subtitle">{% trans "Current Pricing" %}</div>
<div class="vm-item-lg">{{order.price|floatformat:2|intcomma}} CHF/{% if order.generic_product %}{% trans order.generic_product.product_subscription_interval %}{% else %}{% trans "Month" %}{% endif %}</div>
{% if inv_url %}<a class="btn btn-vm-invoice" href="{{inv_url}}" target="_blank">{% trans "See Invoice" %}</a>{%else%}{% trans "No invoice as of now" %}{% endif %}
<a class="btn btn-vm-invoice" href="{{inv_url}}" target="_blank">{% trans "See Invoice" %}</a>
</div>
</div>
<div class="vm-detail-item">

View file

@ -554,23 +554,14 @@ class SettingsView(LoginRequiredMixin, FormView):
Check if the user already saved contact details. If so, then show
the form populated with those details, to let user change them.
"""
username = self.request.GET.get('username')
if self.request.user.is_admin and username:
user = CustomUser.objects.get(username=username)
else:
user = self.request.user
return form_class(
instance=user.billing_addresses.first(),
instance=self.request.user.billing_addresses.first(),
**self.get_form_kwargs())
def get_context_data(self, **kwargs):
context = super(SettingsView, self).get_context_data(**kwargs)
# Get user
username = self.request.GET.get('username')
if self.request.user.is_admin and username:
user = CustomUser.objects.get(username=username)
else:
user = self.request.user
user = self.request.user
stripe_customer = None
if hasattr(user, 'stripecustomer'):
stripe_customer = user.stripecustomer
@ -810,7 +801,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
card_id = form.cleaned_data.get('card')
customer = owner.stripecustomer
try:
user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
user_card_detail = UserCardDetail.objects.get(id=card_id)
if not request.user.has_perm(
'view_usercarddetail', user_card_detail
):
@ -1014,7 +1005,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
context['cc_exp_month'] = card_details_response['exp_month']
else:
card_id = self.request.session.get('card_id')
card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
card_detail = UserCardDetail.objects.get(id=card_id)
context['cc_last4'] = card_detail.last4
context['cc_brand'] = card_detail.brand
context['cc_exp_year'] = card_detail.exp_year
@ -1128,7 +1119,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
return JsonResponse(response)
else:
card_id = request.session.get('card_id')
user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
user_card_detail = UserCardDetail.objects.get(id=card_id)
card_details_dict = {
'last4': user_card_detail.last4,
'brand': user_card_detail.brand,
@ -1339,7 +1330,7 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
).order_by('-created_at')
stripe_chgs = []
for ho in hosting_orders:
stripe_chgs.append({ho: stripe.Charge.retrieve(ho.stripe_charge_id)})
stripe_chgs.append({ho.id: stripe.Charge.retrieve(ho.stripe_charge_id)})
paginator_charges = Paginator(stripe_chgs, 10)
try:
@ -1544,12 +1535,7 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
ordering = '-id'
def get_queryset(self):
username = self.request.GET.get('username')
if self.request.user.is_admin and username:
user = CustomUser.objects.get(username=username)
else:
user = self.request.user
owner = user
owner = self.request.user
manager = OpenNebulaManager(email=owner.username,
password=owner.password)
try:
@ -1557,11 +1543,6 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
serializer = VirtualMachineSerializer(queryset, many=True)
return serializer.data
except ConnectionRefusedError:
logger.exception(
"Could not load VMs of user %s (%s) from OpenNebula" % (
owner.username, owner.email
)
)
messages.error(self.request,
'We could not load your VMs due to a backend connection \
error. Please try again in a few minutes'
@ -1713,11 +1694,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
login_url = reverse_lazy('hosting:login')
def get_object(self):
username = self.request.GET.get('username')
if self.request.user.is_admin and username:
owner = CustomUser.objects.get(username=username)
else:
owner = self.request.user
owner = self.request.user
vm = None
manager = OpenNebulaManager(
email=owner.username,
@ -1773,10 +1750,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
subscription=hosting_order.subscription_id,
count=1
)
if stripe_obj.data:
inv_url = stripe_obj.data[0].hosted_invoice_url
else:
inv_url = ''
inv_url = stripe_obj.data[0].hosted_invoice_url
elif hosting_order.stripe_charge_id:
stripe_obj = stripe.Charge.retrieve(
hosting_order.stripe_charge_id

View file

@ -8,13 +8,3 @@ class UserExistsError(Exception):
class UserCredentialError(Exception):
pass
class TemplateNotFoundError(Exception):
"""Raised when an OpenNebula VM template id does not exist (any more)."""
def __init__(self, template_id):
super(TemplateNotFoundError, self).__init__(
"OpenNebula template %s does not exist" % template_id
)
self.template_id = template_id

View file

@ -9,10 +9,7 @@ from oca.pool import WrongNameError, WrongIdError
from hosting.models import HostingOrder
from utils.models import CustomUser
from utils.tasks import save_ssh_key, save_ssh_key_error_handler
from .exceptions import (
KeyExistsError, UserExistsError, UserCredentialError,
TemplateNotFoundError
)
from .exceptions import KeyExistsError, UserExistsError, UserCredentialError
logger = logging.getLogger(__name__)
@ -428,60 +425,16 @@ class OpenNebulaManager():
except:
return []
@staticmethod
def resolve_template_id(template_id):
"""
Map a (possibly retired) template id to its replacement, as
configured in settings.UPDATED_TEMPLATES_DICT. Ids without a
mapping are returned unchanged.
"""
template_id = int(template_id)
return settings.UPDATED_TEMPLATES_DICT.get(template_id, template_id)
def get_template_names(self):
"""
Return a dict {template_id: template_name} of every template
visible to oneadmin, in a single RPC call.
:raises ConnectionRefusedError: if OpenNebula is unreachable
"""
try:
template_pool = self._get_template_pool()
return dict(
(template.id, template.name) for template in template_pool
)
except ConnectionRefusedError:
raise
except Exception:
# Any other failure (socket timeout, XML-RPC fault, ...) is a
# backend problem as far as the callers are concerned
logger.exception("Could not fetch the OpenNebula template pool")
raise ConnectionRefusedError
def get_template(self, template_id):
"""
Return the oca template object for the given id.
:raises TemplateNotFoundError: if the template (after applying
settings.UPDATED_TEMPLATES_DICT) does not exist in OpenNebula
:raises ConnectionRefusedError: if OpenNebula is unreachable or
fails in any other way
"""
template_id = self.resolve_template_id(template_id)
template_id = int(template_id)
try:
template_pool = self._get_template_pool()
if template_id in settings.UPDATED_TEMPLATES_DICT.keys():
template_id = settings.UPDATED_TEMPLATES_DICT[template_id]
return template_pool.get_by_id(template_id)
except WrongIdError:
logger.error(
"OpenNebula template %s does not exist" % template_id
)
raise TemplateNotFoundError(template_id)
except ConnectionRefusedError:
raise
except Exception:
logger.exception(
"Could not fetch OpenNebula template %s" % template_id
)
except Exception as ex:
logger.debug("Template Id we are looking for : %s" % template_id)
logger.error(str(ex))
raise ConnectionRefusedError
def create_template(self, name, cores, memory, disk_size, core_price,

View file

@ -1,44 +1,12 @@
import ipaddress
import logging
from builtins import hasattr
from rest_framework import serializers
from oca import OpenNebulaException
from .exceptions import TemplateNotFoundError
from .models import OpenNebulaManager
logger = logging.getLogger(__name__)
TEMPLATE_NAME_PREFIXES = ('public-', 'ipv6only-')
def strip_template_prefix(name):
"""
Remove the DCL naming prefix ('public-', 'ipv6only-') from a template
or VM name. str.lstrip() must not be used here: it strips a character
set, so 'public-ubuntu'.lstrip('public-') gives 'ntu'.
"""
for prefix in TEMPLATE_NAME_PREFIXES:
if name.startswith(prefix):
return name[len(prefix):]
return name
def template_name_from_vm_name(vm_name, vm_id):
"""
VMs created by dynamicweb are named '<template name>-<vm id>' (see
OpenNebulaManager.create_vm), so the template name can be recovered
from the VM name when the template itself has been deleted. VMs that
were created or renamed outside dynamicweb do not follow that pattern
and are returned unchanged.
"""
suffix = '-%s' % vm_id
if vm_name.endswith(suffix):
return vm_name[:-len(suffix)]
return vm_name
class VirtualMachineTemplateSerializer(serializers.Serializer):
"""Serializer to map the virtual machine template instance into JSON format."""
@ -68,7 +36,10 @@ class VirtualMachineTemplateSerializer(serializers.Serializer):
return int(obj.template.memory) / 1024
def get_name(self, obj):
return strip_template_prefix(obj.name)
if obj.name.startswith('public-'):
return obj.name.lstrip('public-')
else:
return obj.name
class VirtualMachineSerializer(serializers.Serializer):
@ -162,45 +133,13 @@ class VirtualMachineSerializer(serializers.Serializer):
price += int(disk.size) / 1024 * 0.6
return price
def _template_name(self, template_id):
"""
Resolve a template id to its name using one template pool fetch per
serializer instance. With many=True the child serializer is shared
across all VMs, so a whole VM list costs a single RPC call instead
of one OpenNebulaManager (and template pool fetch) per VM.
:raises TemplateNotFoundError: if the template no longer exists
:raises ConnectionRefusedError: if OpenNebula is unreachable
"""
if not hasattr(self, '_template_names'):
self._template_names = OpenNebulaManager().get_template_names()
template_id = OpenNebulaManager.resolve_template_id(template_id)
if template_id not in self._template_names:
raise TemplateNotFoundError(template_id)
return self._template_names[template_id]
def get_configuration(self, obj):
"""
The name of the template the VM was created from, without the DCL
prefix. A VM whose template has since been deleted from OpenNebula
must not break serialization of the whole VM list, so fall back to
the template name embedded in the VM name.
"""
template_id = obj.template.template_id
try:
name = self._template_name(template_id)
except TemplateNotFoundError as err:
logger.warning(
"VM %s: %s, falling back to VM name" % (obj.id, err)
)
name = template_name_from_vm_name(obj.name, obj.id)
except ConnectionRefusedError:
logger.error(
"VM %s: could not fetch template pool, falling back to "
"VM name" % obj.id
)
name = template_name_from_vm_name(obj.name, obj.id)
return strip_template_prefix(name)
template = OpenNebulaManager().get_template(template_id)
if template.name.startswith('public-'):
return template.name.lstrip('public-')
else:
return template.name
def get_ipv4(self, obj):
"""
@ -229,7 +168,10 @@ class VirtualMachineSerializer(serializers.Serializer):
return '-'
def get_name(self, obj):
return strip_template_prefix(obj.name)
if obj.name.startswith('public-'):
return obj.name.lstrip('public-')
else:
return obj.name
class VMTemplateSerializer(serializers.Serializer):

View file

@ -2,18 +2,11 @@ import random
import string
from django.conf import settings
from django.test import TestCase, override_settings
from django.test import TestCase
from unittest import skipIf
from unittest.mock import MagicMock, patch
from oca.pool import WrongIdError
from .exceptions import TemplateNotFoundError
from .models import OpenNebulaManager
from .serializers import (
VirtualMachineSerializer, strip_template_prefix,
template_name_from_vm_name
)
from .serializers import VirtualMachineSerializer
from utils.models import CustomUser
@ -156,124 +149,3 @@ class VirtualMachineSerializerTestCase(TestCase):
serialized.data.get('name'), vm.name.lstrip('public-')
)
break
class TemplateNameHelpersTestCase(TestCase):
def test_strip_template_prefix(self):
self.assertEqual(strip_template_prefix('public-Ubuntu 20.10'),
'Ubuntu 20.10')
self.assertEqual(strip_template_prefix('ipv6only-Alpine 3.21'),
'Alpine 3.21')
self.assertEqual(strip_template_prefix('Devuan Beowulf'),
'Devuan Beowulf')
def test_strip_template_prefix_is_not_lstrip(self):
# str.lstrip('public-') strips a character set and would give 'ntu'
self.assertEqual(strip_template_prefix('public-ubuntu'), 'ubuntu')
def test_template_name_from_vm_name(self):
self.assertEqual(
template_name_from_vm_name('public-Ubuntu 20.10-26623', 26623),
'public-Ubuntu 20.10'
)
def test_template_name_from_vm_name_keeps_custom_names(self):
# VMs created or renamed outside dynamicweb
self.assertEqual(template_name_from_vm_name('gitea', 27001), 'gitea')
self.assertEqual(
template_name_from_vm_name('ipv6only-Alpine 3.15-27397-Jonas',
27397),
'ipv6only-Alpine 3.15-27397-Jonas'
)
def _fake_vm(vm_id, name, template_id):
vm = MagicMock()
vm.id = vm_id
vm.name = name
vm.template.template_id = template_id
return vm
class VirtualMachineSerializerMissingTemplateTestCase(TestCase):
"""
A VM whose OpenNebula template has been deleted must not break the
serialization of the whole VM list (the symptom was the generic
"backend connection error" banner on /hosting/my-virtual-machines).
"""
def _configuration(self, vms, template_names):
serializer = VirtualMachineSerializer(vms, many=True)
with patch.object(OpenNebulaManager, '__init__', return_value=None), \
patch.object(OpenNebulaManager, 'get_template_names',
return_value=template_names) as get_names:
configurations = [
serializer.child.get_configuration(vm) for vm in vms
]
return configurations, get_names
@override_settings(UPDATED_TEMPLATES_DICT={})
def test_missing_template_falls_back_to_vm_name(self):
vms = [
_fake_vm(28344, 'public-Alpine 3.21-28344', 310),
_fake_vm(26623, 'public-Ubuntu 20.10-26623', 164),
]
configurations, _ = self._configuration(
vms, {310: 'public-Alpine 3.21'}
)
self.assertEqual(configurations, ['Alpine 3.21', 'Ubuntu 20.10'])
@override_settings(UPDATED_TEMPLATES_DICT={164: 192})
def test_updated_templates_mapping_is_applied(self):
vms = [_fake_vm(26623, 'public-Ubuntu 20.10-26623', 164)]
configurations, _ = self._configuration(
vms, {192: 'public-Ubuntu 20.10 (new)'}
)
self.assertEqual(configurations, ['Ubuntu 20.10 (new)'])
@override_settings(UPDATED_TEMPLATES_DICT={})
def test_template_pool_is_fetched_once_per_list(self):
vms = [
_fake_vm(1, 'public-Alpine 3.21-1', 310),
_fake_vm(2, 'public-Alpine 3.21-2', 310),
_fake_vm(3, 'public-Ubuntu 20.10-3', 164),
]
_, get_names = self._configuration(vms, {310: 'public-Alpine 3.21'})
self.assertEqual(get_names.call_count, 1)
@override_settings(UPDATED_TEMPLATES_DICT={})
def test_unreachable_template_pool_falls_back_to_vm_name(self):
vms = [_fake_vm(26623, 'public-Ubuntu 20.10-26623', 164)]
serializer = VirtualMachineSerializer(vms, many=True)
with patch.object(OpenNebulaManager, '__init__', return_value=None), \
patch.object(OpenNebulaManager, 'get_template_names',
side_effect=ConnectionRefusedError):
configuration = serializer.child.get_configuration(vms[0])
self.assertEqual(configuration, 'Ubuntu 20.10')
class OpenNebulaManagerGetTemplateTestCase(TestCase):
@override_settings(UPDATED_TEMPLATES_DICT={164: 192})
def test_resolve_template_id(self):
self.assertEqual(OpenNebulaManager.resolve_template_id(164), 192)
self.assertEqual(OpenNebulaManager.resolve_template_id('164'), 192)
self.assertEqual(OpenNebulaManager.resolve_template_id(310), 310)
@override_settings(UPDATED_TEMPLATES_DICT={})
def test_missing_template_raises_template_not_found(self):
pool = MagicMock()
pool.get_by_id.side_effect = WrongIdError
with patch.object(OpenNebulaManager, '__init__', return_value=None), \
patch.object(OpenNebulaManager, '_get_template_pool',
return_value=pool):
with self.assertRaises(TemplateNotFoundError) as ctx:
OpenNebulaManager().get_template(164)
self.assertEqual(ctx.exception.template_id, 164)
@override_settings(UPDATED_TEMPLATES_DICT={})
def test_unreachable_pool_still_raises_connection_error(self):
with patch.object(OpenNebulaManager, '__init__', return_value=None), \
patch.object(OpenNebulaManager, '_get_template_pool',
side_effect=ConnectionRefusedError):
with self.assertRaises(ConnectionRefusedError):
OpenNebulaManager().get_template(164)

View file

@ -1,56 +1,57 @@
setuptools<58.0.0
Babel==2.3.4
Django==1.9.4
Django==1.11.18
Django-Select2==4.3.2
Pillow==3.2.0
Pillow==9.5.0
URLObject==2.4.0
Unidecode==0.04.19
Unidecode==1.0.23
YURL==0.13
aldryn-apphooks-config==0.2.7
aldryn-boilerplates==0.7.4
aldryn-categories==1.0.3
aldryn-common==1.0.1
aldryn-newsblog==1.2.1
aldryn-people==1.2.0
aldryn-reversion==1.0.8
#aldryn-apphooks-config==0.2.7
#aldryn-boilerplates==0.7.4
aldryn-categories==1.2.0
aldryn-common==1.0.5
aldryn-newsblog==2.2.1
aldryn-people==2.2.0
#aldryn-reversion==1.0.8
aldryn-search==0.2.11
aldryn-translation-tools==0.2.1
aldryn-translation-tools==0.3.0
backport-collections==0.1
cmsplugin-filer==1.0.1
#cmsplugin-filer==1.1.3
django-appconf==1.0.2
django-appdata==0.1.5
django-appdata==0.2.1
django-bootstrap3==7.0.1
django-classy-tags==0.7.2
django-cms==3.2.5
django-cms==3.6.0
django-compressor==2.0
django-debug-toolbar==1.4
python-dotenv==0.10.3
django-extensions==1.6.7
django-filer==1.2.0
django-filer==1.5.0
django-filter==0.13.0
django-formtools==1.0
django-formtools==2.1
django-guardian==1.4.4
django-haystack==2.4.1
django-meta==1.2
django-meta-mixin==0.3.0
django-model-utils==2.5
django-mptt==0.8.4
django-parler==1.6.3
django-mptt==0.11
django-parler==1.9.2
django-phonenumber-field==1.1.0
django-polymorphic==0.9.2
django-polymorphic==2.0.2
django-reversion==1.10.2
django-sekizai==0.9.0
django-sortedm2m==1.2.2
django-sortedm2m==3.1.1
django-spurl==0.6.4
django-standard-form==1.1.1
django-stored-messages==1.4.0
django-taggit==0.18.3
django-taggit==0.23.0
django-taggit-autosuggest==0.2.8
django-taggit-templatetags==0.2.5
django-templatetag-sugar==1.0
django-treebeard==4.0.1
djangocms-admin-style==1.1.1
django-treebeard==4.3
djangocms-admin-style>=1.2
djangocms-apphook-setup==0.1.2
djangocms-blog==0.9.0
djangocms-blog==0.8.13
djangocms-file==1.0
djangocms-flash==0.3.0
djangocms-googlemap==0.4.0
@ -59,26 +60,25 @@ djangocms-link==1.7.2
djangocms-page-meta==0.5.11
djangocms-picture==1.0.0
djangocms-teaser==0.2.0
djangocms-text-ckeditor==2.9.3
djangocms-text-ckeditor==3.7.0
djangocms-video==1.0.0
easy-thumbnails==2.3
html5lib==0.9999999
easy-thumbnails==2.4.1
html5lib==0.999999999
ldap3==2.6.1
lxml==3.6.0
lxml
model-mommy==1.2.6
phonenumbers==7.4.0
phonenumberslite==7.4.0
psycopg2==2.7.3.2
pycryptodome==3.6.6
pylibmc==1.5.1
phonenumbers==8.13.11
psycopg2==2.8.4
pycryptodome==3.8.0
pylibmc==1.6.3
python-dateutil==2.5.3
python-slugify==1.2.0
pytz==2016.4
python-slugify==1.2.6
pytz>=2023.3
rcssmin==1.0.6
requests==2.10.0
requests>=2.20
rjsmin==1.0.12
six==1.10.0
sqlparse==0.1.19
sqlparse==0.4.4
stripe==2.41.0
wheel==0.29.0
django-admin-honeypot==1.0.0
@ -87,16 +87,17 @@ git+https://github.com/ungleich/python-oca.git#egg=oca
djangorestframework==3.6.3
flake8==3.3.0
python-memcached==1.58
celery==4.0.2
celery==4.4.7
redis==2.10.5
django-celery-results==1.0.1
kombu==4.1.0
django-celery-results==1.0.2
kombu>=4.6.10
mccabe==0.6.1
pycodestyle==2.3.1
pyflakes==1.5.0
billiard==3.5.0.3
amqp==2.2.1
vine==1.1.4
billiard==3.6.4.0
amqp>=2.6.0
vine==1.3.0
cdist==5.0.1
git+https://github.com/ungleich/djangocms-multisite.git#egg=djangocms_multisite
pyotp
importlib_metadata<5

View file

@ -25,10 +25,9 @@ class ContactView(FormView):
success_message = _('Message Successfully Sent')
def form_valid(self, form):
print("ungleich_page contactusform")
#form.save()
#form.send_email()
#messages.add_message(self.request, messages.SUCCESS, self.success_message)
form.save()
form.send_email()
messages.add_message(self.request, messages.SUCCESS, self.success_message)
return super(ContactView, self).form_valid(form)
def get_context_data(self, **kwargs):

View file

@ -1,8 +1,7 @@
from django.utils.translation import ugettext as _
from django.db import models
# Old: http://xml.coverpages.org/country3166.html
# 2023-12-29: Updated list of countries from https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
# http://xml.coverpages.org/country3166.html
COUNTRIES = (
('AD', _('Andorra')),
('AE', _('United Arab Emirates')),
@ -11,6 +10,7 @@ COUNTRIES = (
('AI', _('Anguilla')),
('AL', _('Albania')),
('AM', _('Armenia')),
('AN', _('Netherlands Antilles')),
('AO', _('Angola')),
('AQ', _('Antarctica')),
('AR', _('Argentina')),
@ -18,7 +18,6 @@ COUNTRIES = (
('AT', _('Austria')),
('AU', _('Australia')),
('AW', _('Aruba')),
('AX', _('Aland Islands')),
('AZ', _('Azerbaijan')),
('BA', _('Bosnia and Herzegovina')),
('BB', _('Barbados')),
@ -29,13 +28,11 @@ COUNTRIES = (
('BH', _('Bahrain')),
('BI', _('Burundi')),
('BJ', _('Benin')),
('BL', _('St. Barts')),
('BM', _('Bermuda')),
('BN', _('Brunei')),
('BN', _('Brunei Darussalam')),
('BO', _('Bolivia')),
('BQ', _('Caribbean Netherlands')),
('BR', _('Brazil')),
('BS', _('Bahamas')),
('BS', _('Bahama')),
('BT', _('Bhutan')),
('BV', _('Bouvet Island')),
('BW', _('Botswana')),
@ -43,12 +40,11 @@ COUNTRIES = (
('BZ', _('Belize')),
('CA', _('Canada')),
('CC', _('Cocos (Keeling) Islands')),
('CD', _('Congo - Kinshasa')),
('CF', _('Central African Republic')),
('CG', _('Congo - Brazzaville')),
('CG', _('Congo')),
('CH', _('Switzerland')),
('CI', _('Ivory Coast')),
('CK', _('Cook Islands')),
('CK', _('Cook Iislands')),
('CL', _('Chile')),
('CM', _('Cameroon')),
('CN', _('China')),
@ -56,10 +52,9 @@ COUNTRIES = (
('CR', _('Costa Rica')),
('CU', _('Cuba')),
('CV', _('Cape Verde')),
('CW', _('Curacao')),
('CX', _('Christmas Island')),
('CY', _('Cyprus')),
('CZ', _('Czechia')),
('CZ', _('Czech Republic')),
('DE', _('Germany')),
('DJ', _('Djibouti')),
('DK', _('Denmark')),
@ -75,16 +70,16 @@ COUNTRIES = (
('ET', _('Ethiopia')),
('FI', _('Finland')),
('FJ', _('Fiji')),
('FK', _('Falkland Islands')),
('FK', _('Falkland Islands (Malvinas)')),
('FM', _('Micronesia')),
('FO', _('Faroe Islands')),
('FR', _('France')),
('FX', _('France, Metropolitan')),
('GA', _('Gabon')),
('GB', _('United Kingdom')),
('GB', _('United Kingdom (Great Britain)')),
('GD', _('Grenada')),
('GE', _('Georgia')),
('GF', _('French Guiana')),
('GG', _('Guernsey')),
('GH', _('Ghana')),
('GI', _('Gibraltar')),
('GL', _('Greenland')),
@ -98,7 +93,7 @@ COUNTRIES = (
('GU', _('Guam')),
('GW', _('Guinea-Bissau')),
('GY', _('Guyana')),
('HK', _('Hong Kong SAR China')),
('HK', _('Hong Kong')),
('HM', _('Heard & McDonald Islands')),
('HN', _('Honduras')),
('HR', _('Croatia')),
@ -107,14 +102,12 @@ COUNTRIES = (
('ID', _('Indonesia')),
('IE', _('Ireland')),
('IL', _('Israel')),
('IM', _('Isle of Man')),
('IN', _('India')),
('IO', _('British Indian Ocean Territory')),
('IQ', _('Iraq')),
('IR', _('Iran')),
('IR', _('Islamic Republic of Iran')),
('IS', _('Iceland')),
('IT', _('Italy')),
('JE', _('Jersey')),
('JM', _('Jamaica')),
('JO', _('Jordan')),
('JP', _('Japan')),
@ -124,14 +117,14 @@ COUNTRIES = (
('KI', _('Kiribati')),
('KM', _('Comoros')),
('KN', _('St. Kitts and Nevis')),
('KP', _('North Korea')),
('KR', _('South Korea')),
('KP', _('Korea, Democratic People\'s Republic of')),
('KR', _('Korea, Republic of')),
('KW', _('Kuwait')),
('KY', _('Cayman Islands')),
('KZ', _('Kazakhstan')),
('LA', _('Laos')),
('LA', _('Lao People\'s Democratic Republic')),
('LB', _('Lebanon')),
('LC', _('St. Lucia')),
('LC', _('Saint Lucia')),
('LI', _('Liechtenstein')),
('LK', _('Sri Lanka')),
('LR', _('Liberia')),
@ -139,23 +132,20 @@ COUNTRIES = (
('LT', _('Lithuania')),
('LU', _('Luxembourg')),
('LV', _('Latvia')),
('LY', _('Libya')),
('LY', _('Libyan Arab Jamahiriya')),
('MA', _('Morocco')),
('MC', _('Monaco')),
('MD', _('Moldova')),
('ME', _('Montenegro')),
('MF', _('St. Martin')),
('MD', _('Moldova, Republic of')),
('MG', _('Madagascar')),
('MH', _('Marshall Islands')),
('MK', _('North Macedonia')),
('ML', _('Mali')),
('MM', _('Myanmar (Burma)')),
('MN', _('Mongolia')),
('MO', _('Macao SAR China')),
('MM', _('Myanmar')),
('MO', _('Macau')),
('MP', _('Northern Mariana Islands')),
('MQ', _('Martinique')),
('MR', _('Mauritania')),
('MS', _('Montserrat')),
('MS', _('Monserrat')),
('MT', _('Malta')),
('MU', _('Mauritius')),
('MV', _('Maldives')),
@ -184,17 +174,15 @@ COUNTRIES = (
('PK', _('Pakistan')),
('PL', _('Poland')),
('PM', _('St. Pierre & Miquelon')),
('PN', _('Pitcairn Islands')),
('PN', _('Pitcairn')),
('PR', _('Puerto Rico')),
('PS', _('Palestinian Territories')),
('PT', _('Portugal')),
('PW', _('Palau')),
('PY', _('Paraguay')),
('QA', _('Qatar')),
('RE', _('Reunion')),
('RO', _('Romania')),
('RS', _('Serbia')),
('RU', _('Russia')),
('RU', _('Russian Federation')),
('RW', _('Rwanda')),
('SA', _('Saudi Arabia')),
('SB', _('Solomon Islands')),
@ -204,19 +192,17 @@ COUNTRIES = (
('SG', _('Singapore')),
('SH', _('St. Helena')),
('SI', _('Slovenia')),
('SJ', _('Svalbard and Jan Mayen')),
('SJ', _('Svalbard & Jan Mayen Islands')),
('SK', _('Slovakia')),
('SL', _('Sierra Leone')),
('SM', _('San Marino')),
('SN', _('Senegal')),
('SO', _('Somalia')),
('SR', _('Suriname')),
('SS', _('South Sudan')),
('ST', _('Sao Tome & Principe')),
('SV', _('El Salvador')),
('SX', _('Sint Maarten')),
('SY', _('Syria')),
('SZ', _('Eswatini')),
('SY', _('Syrian Arab Republic')),
('SZ', _('Swaziland')),
('TC', _('Turks & Caicos Islands')),
('TD', _('Chad')),
('TF', _('French Southern Territories')),
@ -224,34 +210,36 @@ COUNTRIES = (
('TH', _('Thailand')),
('TJ', _('Tajikistan')),
('TK', _('Tokelau')),
('TL', _('Timor-Leste')),
('TM', _('Turkmenistan')),
('TN', _('Tunisia')),
('TO', _('Tonga')),
('TP', _('East Timor')),
('TR', _('Turkey')),
('TT', _('Trinidad & Tobago')),
('TV', _('Tuvalu')),
('TW', _('Taiwan')),
('TZ', _('Tanzania')),
('TW', _('Taiwan, Province of China')),
('TZ', _('Tanzania, United Republic of')),
('UA', _('Ukraine')),
('UG', _('Uganda')),
('UM', _('U.S. Outlying Islands')),
('US', _('United States')),
('UM', _('United States Minor Outlying Islands')),
('US', _('United States of America')),
('UY', _('Uruguay')),
('UZ', _('Uzbekistan')),
('VA', _('Vatican City')),
('VC', _('St. Vincent & Grenadines')),
('VA', _('Vatican City State (Holy See)')),
('VC', _('St. Vincent & the Grenadines')),
('VE', _('Venezuela')),
('VG', _('British Virgin Islands')),
('VI', _('U.S. Virgin Islands')),
('VN', _('Vietnam')),
('VI', _('United States Virgin Islands')),
('VN', _('Viet Nam')),
('VU', _('Vanuatu')),
('WF', _('Wallis & Futuna')),
('WF', _('Wallis & Futuna Islands')),
('WS', _('Samoa')),
('YE', _('Yemen')),
('YT', _('Mayotte')),
('YU', _('Yugoslavia')),
('ZA', _('South Africa')),
('ZM', _('Zambia')),
('ZR', _('Zaire')),
('ZW', _('Zimbabwe')),
)

View file

@ -4,8 +4,6 @@ from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from django_recaptcha.fields import ReCaptchaField
from membership.models import CustomUser
from .models import ContactMessage, BillingAddress, UserBillingAddress
@ -190,7 +188,6 @@ class UserBillingAddressForm(forms.ModelForm):
class ContactUsForm(forms.ModelForm):
error_css_class = 'autofocus'
captcha = ReCaptchaField()
class Meta:
model = ContactMessage
@ -209,12 +206,11 @@ class ContactUsForm(forms.ModelForm):
}
def send_email(self, email_to='info@digitalglarus.ch'):
pass
#text_content = render_to_string(
# 'emails/contact.txt', {'data': self.cleaned_data})
#html_content = render_to_string(
# 'emails/contact.html', {'data': self.cleaned_data})
#email = EmailMultiAlternatives('Subject', text_content)
#email.attach_alternative(html_content, "text/html")
#email.to = [email_to]
#email.send()
text_content = render_to_string(
'emails/contact.txt', {'data': self.cleaned_data})
html_content = render_to_string(
'emails/contact.html', {'data': self.cleaned_data})
email = EmailMultiAlternatives('Subject', text_content)
email.attach_alternative(html_content, "text/html")
email.to = [email_to]
email.send()

View file

@ -8,7 +8,7 @@ from celery.utils.log import get_task_logger
from django.conf import settings
from django.core.mail import EmailMessage
from dynamicweb.celery import app
from dynamicweb.pr_celery import app
logger = get_task_logger(__name__)