Skip to content
Snippets Groups Projects
Commit 79919c90 authored by Luca's avatar Luca
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
Pipeline #138330 failed
Showing
with 621 additions and 0 deletions
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
.ropeproject/
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
# Django stuff:
*.log
data/
# Sphinx documentation
docs/_build/
# PyBuilder
target/
#Ipython Notebook
.ipynb_checkpoints
---
stages:
- linting
# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
cache:
paths:
- .cache
docformatter:
stage: linting
image: python:3
before_script:
- pip3 install -U pip docformatter
script:
- docformatter --check -r .
black:
stage: linting
image: python:3
before_script:
- pip3 install -U pip black
script:
- black --check .
isort:
stage: linting
image: python:3
before_script:
- pip3 install -U pip isort
script:
- isort -c .
flake8:
stage: linting
image: python:3
before_script:
- pip3 install -U pip flake8
script:
- flake8 .
#!/bin/sh
REPO_DIR=$(git rev-parse --show-toplevel)
GIT_DIR=$REPO_DIR/.git
VENV_ACTIVATE=$VIRTUAL_ENV/bin/activate
if [[ ! -f $VENV_ACTIVATE ]]
then
echo "Could not find your virtual environment"
fi
echo "#!/bin/sh" >> $GIT_DIR/hooks/pre-commit
echo "set -e" >> $GIT_DIR/hooks/pre-commit
echo "source $VENV_ACTIVATE" >> $GIT_DIR/hooks/pre-commit
echo "docformatter --check -r ." >> $GIT_DIR/hooks/pre-commit
echo "black --check ." >> $GIT_DIR/hooks/pre-commit
echo "isort -c ." >> $GIT_DIR/hooks/pre-commit
echo "flake8 ." >> $GIT_DIR/hooks/pre-commit
chmod +x $GIT_DIR/hooks/pre-commit
LICENSE 0 → 100644
MIT License
Copyright (c) 2023 Fachschaft Informatik TU Dortmund
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
recursive-include pretix_keycloak_create_user/static *
recursive-include pretix_keycloak_create_user/templates *
recursive-include pretix_keycloak_create_user/locale *
include LICENSE
exclude .gitlab-ci.yml
Makefile 0 → 100644
all: localecompile
LNGS:=`find pretix_keycloak_create_user/locale/ -mindepth 1 -maxdepth 1 -type d -printf "-l %f "`
localecompile:
django-admin compilemessages
localegen:
django-admin makemessages --keep-pot -i build -i dist -i "*egg*" $(LNGS)
.PHONY: all localecompile localegen
# Keycloak user creator
This is a plugin for [pretix](https://github.com/pretix/pretix).
Let users create an keycloak acccount
## Installation
Activate the virtual environment for your Pretix installation and run
pip install pretix-keycloak-create-user
## Configuration
Each event can enable this plugin in Settings > Plugins > Features.
Once the plugin is enabled you can configure it in Settings > Keycloak user creator.
## Development setup
1. Make sure that you have a working [pretix development
setup](https://docs.pretix.eu/en/latest/development/setup.html).
2. Clone this repository.
3. Activate the virtual environment you use for pretix development.
4. Execute `python setup.py develop` within this directory to register
this application with pretix's plugin registry.
5. Execute `make` within this directory to compile translations.
6. Restart your local pretix server. You can now use the plugin from
this repository for your events by enabling it in the 'plugins' tab
in the settings.
This plugin has CI set up to enforce a few code style rules. To check
locally, you need these packages installed:
pip install flake8 isort black docformatter
To check your plugin for rule violations, run:
docformatter --check -r .
black --check .
isort -c .
flake8 .
You can auto-fix some of these issues by running:
docformatter -r .
isort .
black .
To automatically check for these issues before you commit, you can run
`.install-hooks`.
## License
Copyright 2023 Fachschaft Informatik TU Dortmund
Released under the terms of the MIT License
from django.utils.translation import gettext_lazy
try:
from pretix.base.plugins import PluginConfig
except ImportError:
raise RuntimeError("Please use pretix 2.7 or above to run this plugin!")
__version__ = "1.5.0"
class PluginApp(PluginConfig):
name = "pretix_keycloak_create_user"
verbose_name = "Keycloak user creator"
class PretixPluginMeta:
name = gettext_lazy("Keycloak user creator")
author = "Fachschaft Informatik TU Dortmund"
description = gettext_lazy(
"Create users from pretix participants in a Keycloak realm."
)
visible = True
version = __version__
category = "FEATURE"
compatibility = "pretix>=2.7.0"
def ready(self):
from . import signals # NOQA
default_app_config = "pretix_keycloak_create_user.PluginApp"
from django.forms import (
CharField,
CheckboxSelectMultiple,
MultipleChoiceField,
)
from django.utils.translation import ugettext_lazy as _
from i18nfield.forms import I18nFormField, I18nTextInput
from pretix.base.forms import SettingsForm
class KeycloakCreatorForm(SettingsForm):
keycloak_create_user_items = MultipleChoiceField(
widget=CheckboxSelectMultiple(attrs={"class": "scrolling-multiple-choice"}),
label=_("Ask Username for"),
required=True,
choices=[],
help_text=_("These products will ask for a username."),
)
keycloak_create_user_authorization_token = CharField(
label=_("Access token"),
strip=True,
help_text=_(
"Access token for the keycloak server. "
),
)
keycloak_create_user_realm_url = CharField(
label=_("Keycloak realm url"),
strip=True,
help_text=_("The url to keycloak including realm."),
)
keycloak_create_user_hint = I18nFormField(
widget=I18nTextInput,
label=_("Username field help text"),
required=True,
help_text=_(
"Explains what to enter"
),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["keycloak_create_user_items"].choices = [
(i.pk, i.name) for i in self.obj.items.all()
]
import json
from django import forms
from django.dispatch import receiver
from django.urls import resolve, reverse
from django.utils.translation import gettext_noop, ugettext_lazy as _
from i18nfield.strings import LazyI18nString
from pretix.base.settings import settings_hierarkey
from pretix.base.signals import (
order_modified,
order_placed,
)
from pretix.base.templatetags.rich_text import rich_text_snippet
from pretix.control.signals import nav_event_settings
from pretix.presale.signals import question_form_fields
from .tasks import keycloak_create_user
settings_hierarkey.add_default("keycloak_create_user_items", [], list)
settings_hierarkey.add_default("keycloak_create_user_authorization_token", "", str)
settings_hierarkey.add_default("keycloak_create_user_realm_url", "", str)
settings_hierarkey.add_default(
"keycloak_create_user_hint",
LazyI18nString.from_gettext(
gettext_noop("Your keycloak user will be created.")
),
LazyI18nString,
)
settings_hierarkey.add_default(
"keycloak_create_user_reason",
"",
LazyI18nString,
)
@receiver(question_form_fields, dispatch_uid="keycloak_create_user_questions")
def add_keycloak_username_question(sender, position, **kwargs):
if str(position.item.pk) not in sender.settings.get("keycloak_create_user_items"):
return {}
if (
not sender.settings.keycloak_create_user_authorization_token
and not sender.settings.keycloak_create_user_realm_url
):
return {}
return {
"keycloak_create_user_keycloak_username": forms.RegexField(
label=_("Username"),
required=False,
regex="[a-z0-9._=/-]+",
strip=True,
error_messages={
"invalid": _("Enter a valid username")
},
help_text=rich_text_snippet(sender.settings.keycloak_create_user_hint),
)
}
@receiver(order_placed, dispatch_uid="keycloak_create_user_order_placed")
@receiver(order_modified, dispatch_uid="keycloak_create_user_order_modified")
def keycloak_create_user_create_async(sender, order, **kwargs):
if (
not sender.settings.keycloak_create_user_authorization_token
and not sender.settings.keycloak_create_user_realm_url
):
return
for order_position in order.positions.all():
if str(order_position.item.pk) not in sender.settings.get(
"keycloak_create_user_items"
):
continue
if not order_position.meta_info_data.get("question_form_data", {}).get(
"keycloak_create_user_keycloak_username"
):
continue
keycloak_create_user.apply_async(
args=(
sender.pk,
order.pk,
order_position.pk
)
)
@receiver(nav_event_settings, dispatch_uid="keycloak_create_user_keycloak_username_nav_settings")
def navbar_settings(sender, request=None, **kwargs):
url = resolve(request.path_info)
return [
{
"label": _("Create User"),
"url": reverse(
"plugins:pretix_keycloak_create_user:settings",
kwargs={
"event": request.event.slug,
"organizer": request.organizer.slug,
},
),
"active": url.namespace == "plugins:pretix_keycloak_create_user"
and url.url_name == "settings",
}
]
import logging
import requests
from celery.exceptions import MaxRetriesExceededError
from pretix.base.models import Order, OrderPosition
from pretix.base.services.tasks import ProfiledEventTask
from pretix.celery_app import app
logger = logging.getLogger(__name__)
@app.task(
base=ProfiledEventTask,
bind=True,
max_retries=10,
retry_backoff=True,
retry_backoff_max=3600,
)
def keycloak_create_user(
self,
event: int,
order: int,
order_position: int
):
order_position = OrderPosition.objects.get(pk=order_position)
username = order_position.meta_info_data.get("question_form_data", {}).get(
"keycloak_create_user_keycloak_username"
)
if not username:
return
order = Order.objects.get(pk=order)
server = event.settings.keycloak_create_user_realm_url
token = event.settings.keycloak_create_user_authorization_token
payload = {"rep": {"username": username, "email": order_position.order.email}}
try:
r = requests.post(
"{}/users".format(
server
),
headers={
"Authorization": "Bearer {}".format(token),
},
json=payload,
)
r.raise_for_status()
except (requests.ConnectionError, requests.HTTPError) as e:
if r.status_code in (400, 403):
order.log_action(
"pretix_keycloak_create_user.error",
data={
"error": "HTTP Code {} ({})".format(
r.status_code, r.json()["error"]
),
},
)
else:
try:
if r.status_code == 429:
backoff = r.json()["retry_after_ms"] / 1000
self.retry(countdown=backoff)
else:
self.retry()
except MaxRetriesExceededError:
order.log_action(
"pretix_keycloak_create_user.error",
data={
"error": "HTTP Code {}".format(r.status_code),
},
)
raise e
else:
order.log_action(
"pretix_keycloak_create_user.created_user",
data={"username": username},
)
{% extends "pretixcontrol/event/settings_base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block title %} {% trans "Keycloak create user settings" %} {% endblock %}
{% block inside %}
<h1>{% trans "Keycloak create user" %}</h1>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<fieldset>
<legend>{% trans "Keycloak create user settings" %}</legend>
{% bootstrap_form form layout="horizontal" %}
</fieldset>
<div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>
</div>
</form>
{% endblock %}
from django.conf.urls import url
from .views import KeycloakCreatorView
urlpatterns = [
url(
r"^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/keycloak_create_user/$",
KeycloakCreatorView.as_view(),
name="settings",
)
]
from django.urls import reverse
from pretix.base.models import Event
from pretix.control.views.event import EventSettingsFormView, EventSettingsViewMixin
from .forms import KeycloakCreatorForm
class KeycloakCreatorView(EventSettingsViewMixin, EventSettingsFormView):
model = Event
permission = "can_change_settings"
form_class = KeycloakCreatorForm
template_name = "pretix_keycloak_create_user/settings.html"
def get_success_url(self, **kwargs):
return reverse(
"plugins:pretix_keycloak_create_user:settings",
kwargs={
"organizer": self.request.event.organizer.slug,
"event": self.request.event.slug,
},
)
[flake8]
ignore = N802,W503,E402
max-line-length = 160
exclude = migrations,.ropeproject,static,_static,build
[isort]
combine_as_imports = true
default_section = THIRDPARTY
include_trailing_comma = true
known_third_party = pretix
known_standard_library = typing
multi_line_output = 3
skip = setup.py
use_parentheses = True
force_grid_wrap = 0
line_length = 88
known_first_party = pretix_keycloak_create_user
[tool:pytest]
DJANGO_SETTINGS_MODULE = pretix.testutils.settings
[coverage:run]
source = pretix_keycloak_create_user
omit = */migrations/*,*/urls.py,*/tests/*
[coverage:report]
exclude_lines =
pragma: no cover
def __str__
der __repr__
if settings.DEBUG
NOQA
NotImplementedError
[check-manifest]
ignore =
.update-locales.sh
.install-hooks.sh
Makefile
manage.py
tests/*
setup.py 0 → 100644
import os
from distutils.command.build import build
from django.core import management
from setuptools import find_packages, setup
from pretix_keycloak_create_user import __version__
try:
with open(
os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8"
) as f:
long_description = f.read()
except Exception:
long_description = ""
class CustomBuild(build):
def run(self):
management.call_command("compilemessages", verbosity=1)
build.run(self)
cmdclass = {"build": CustomBuild}
setup(
name="pretix-keycloak-create-user",
version=__version__,
description="Invite Pretix participants to a Keycloak realm.",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://gitlab.fachschaften.org/tudo-fsinfo/admin/pretix-keycloak-create-user",
project_urls={
"Changelog": "https://gitlab.fachschaften.org/tudo-fsinfo/admin/pretix-keycloak-create-user/-/blob/main/CHANGELOG.md",
"Tracker": "https://gitlab.fachschaften.org/tudo-fsinfo/admin/pretix-keycloak-create-user/-/issues",
"Pretix Marketplace": "https://marketplace.pretix.eu/products/pretix-keycloak-create-user/",
},
author="Fachschaft Informatik TU Dortmund",
author_email="root@oh14.de",
license="MIT",
classifiers=[
"Development Status :: 5 - Production/Stable",
"Framework :: Django",
"License :: OSI Approved :: MIT License",
"Topic :: Communications :: Chat",
],
install_requires=["requests"],
packages=find_packages(exclude=["tests", "tests.*"]),
include_package_data=True,
cmdclass=cmdclass,
entry_points="""
[pretix.plugin]
pretix_keycloak_create_user=pretix_keycloak_create_user:PretixPluginMeta
""",
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment