Skip to content
This repository has been archived by the owner on Nov 21, 2024. It is now read-only.

Commit

Permalink
Merge branch 'master' into fix-415-eventsignup-email
Browse files Browse the repository at this point in the history
  • Loading branch information
temparus authored Dec 17, 2023
2 parents 326c645 + ece574e commit 3b45865
Show file tree
Hide file tree
Showing 44 changed files with 1,141 additions and 244 deletions.
17 changes: 16 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
interval: "monthly"
groups:
all:
patterns:
- "*"
- package-ecosystem: "docker"
directory: "/"
schedule:
Expand All @@ -13,3 +17,14 @@ updates:
directory: "/"
schedule:
interval: "weekly"
groups:
eve:
patterns:
- "eve"
- "flask"
- "pymongo"
test:
patterns:
- "pytest*"
- "tox"
- "flake8"
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- 27017:27017

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
Expand Down Expand Up @@ -61,28 +61,28 @@ jobs:
IMAGE_NAME: amiveth/amivapi

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
# Login against a Docker registry except on PR
- name: Log into Docker Hub registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_NAME }}
tags: type=raw,value=latest
# Build and push Docker image with Buildx (don't push on PR)
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
pull: true
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ Now it's time to configure AMIV API. Create a file `config.py`


```python
import logging

# Root password, *definitely* change this!
ROOT_PASSWORD = 'root'

Expand All @@ -96,6 +98,8 @@ MONGO_DBNAME = 'amivapi'
MONGO_USERNAME = 'amivapi'
MONGO_PASSWORD = 'amivapi'

LOG_LEVEL = logging.INFO

# Sentry error logging
# SENTRY_DSN = "https://<key>@sentry.io/<project>"
# SENTRY_ENVIRONMENT = 'production'
Expand Down
34 changes: 17 additions & 17 deletions amivapi/auth/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""Sessions endpoint."""

import datetime
import re

from amivapi import ldap
from amivapi.auth import AmivTokenAuth
Expand All @@ -17,13 +18,7 @@
from flask import abort
from flask import current_app as app
from ldap3.core.exceptions import LDAPException


# Change when we drop python3.5 support
try:
from secrets import token_urlsafe
except ImportError:
from amivapi.utils import token_urlsafe
from secrets import token_urlsafe


class SessionAuth(AmivTokenAuth):
Expand Down Expand Up @@ -173,28 +168,33 @@ def process_login(items):
items (list): List of items as passed by EVE to post hooks.
"""
for item in items:
username = item['username']
username = ldap_username = item['username']
password = item['password']

# If the username matches an ethz email address, we just take the part
# before the @ as the username for the authentication against LDAP.
if re.match(r"^[^@]+@([^@]+[.]{1}){0,1}ethz.ch$", username):
ldap_username = username.split('@', 2)[0]

# LDAP
if (app.config.get('ldap_connector') and
ldap.authenticate_user(username, password)):
ldap.authenticate_user(ldap_username, password)):
# Success, sync user and get token
try:
user = ldap.sync_one(username)
user = ldap.sync_one(ldap_username)
app.logger.info(
"User '%s' was authenticated with LDAP" % username)
"User '%s' was authenticated with LDAP" % ldap_username)
except LDAPException:
# Sync failed! Try to find user in db.
user = _find_user(username)
user = _find_user(ldap_username)
if user:
app.logger.error(
f"User '{username}' authenticated with LDAP and found "
"in db, but LDAP sync failed.")
f"User '{ldap_username}' authenticated with LDAP and "
"found in db, but LDAP sync failed.")
else:
status = (f"Login failed: user '{username}' authenticated "
"with LDAP but not found in db, and LDAP sync "
"failed.")
status = (f"Login failed: user '{ldap_username}' "
"authenticated with LDAP but not found in db, "
"and LDAP sync failed.")
app.logger.error(status)
abort(401, description=debug_error_message(status))

Expand Down
33 changes: 19 additions & 14 deletions amivapi/blacklist/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from flask import current_app

from amivapi.utils import mail
from amivapi.utils import mail_from_template
from datetime import datetime

from amivapi.cron import schedulable, schedule_task
Expand Down Expand Up @@ -38,9 +38,12 @@ def send_removed_mail(item):

email, name = _get_email_and_name(_item)
fields = {'reason': _item['reason'], 'name': name}
mail(email, 'Your blacklist entry has been removed!',
current_app.config['BLACKLIST_REMOVED'].format(**fields),
current_app.config['BLACKLIST_REPLY_TO'])
mail_from_template(
to=email,
subject='Your blacklist entry has been removed!',
template_name='blacklist_removed',
template_args=fields,
reply_to=current_app.config['BLACKLIST_REPLY_TO'])


def notify_new_blacklist(items):
Expand All @@ -55,14 +58,13 @@ def notify_new_blacklist(items):

if item['price']:
fields['price'] = item['price']/100 # convert Rappen to CHF
template = current_app.config['BLACKLIST_ADDED_EMAIL_W_PRICE']
else:
template = current_app.config['BLACKLIST_ADDED_EMAIL_WO_PRICE']

mail(email,
'You have been blacklisted!',
template.format(**fields),
current_app.config['BLACKLIST_REPLY_TO'])
mail_from_template(
to=email,
subject='You have been blacklisted!',
template_name='blacklist_added',
template_args=fields,
reply_to=current_app.config['BLACKLIST_REPLY_TO'])

# If the end time is already known, schedule removal mail
if item['end_time'] and item['end_time'] > datetime.utcnow():
Expand Down Expand Up @@ -91,6 +93,9 @@ def notify_delete_blacklist(item):
email, name = _get_email_and_name(item)
fields = {'reason': item['reason'], 'name': name}

mail(email, 'Your blacklist entry has been removed!',
current_app.config['BLACKLIST_REMOVED'].format(**fields),
current_app.config['BLACKLIST_REPLY_TO'])
mail_from_template(
to=email,
subject='Your blacklist entry has been removed!',
template_name='blacklist_removed',
template_args=fields,
reply_to=current_app.config['BLACKLIST_REPLY_TO'])
2 changes: 2 additions & 0 deletions amivapi/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from os import getcwd, getenv
from os.path import abspath
import logging

from eve import Eve
from flask import Config
Expand Down Expand Up @@ -88,6 +89,7 @@ def create_app(config_file=None, **kwargs):
app = Eve("amivapi", # Flask needs this name to find the static folder
settings=config,
validator=ValidatorAMIV)
app.logger.setLevel(app.config.get('LOG_LEVEL') or logging.INFO)
app.logger.info(config_status)

# Set up error logging with sentry
Expand Down
4 changes: 4 additions & 0 deletions amivapi/events/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
)
from amivapi.events.queue import (
add_accepted_before_insert,
notify_users_after_update,
update_waiting_list_after_delete,
update_waiting_list_after_insert,
)
Expand Down Expand Up @@ -72,4 +73,7 @@ def init_app(app):
app.on_deleted_item_eventsignups += notify_signup_deleted
app.on_deleted_item_eventsignups += update_waiting_list_after_delete

# Notify users on manual updates
app.on_updated_eventsignups += notify_users_after_update

app.register_blueprint(email_blueprint)
4 changes: 2 additions & 2 deletions amivapi/events/authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ def has_item_write_permission(self, user_id, item):

# Remove tzinfo to compare to utcnow (API only accepts UTC anyways)
time_register_start = event['time_register_start'].replace(tzinfo=None)
time_register_end = event['time_register_end'].replace(tzinfo=None)
time_deregister_end = event['time_deregister_end'].replace(tzinfo=None)

# Only the user itself can modify the item (not moderators), and only
# within the signup window

return (user_id == str(event['moderator']) or
(('user' in item) and
(user_id == str(get_id(item['user']))) and
(time_register_start <= dt.utcnow() <= time_register_end)))
(time_register_start <= dt.utcnow() <= time_deregister_end)))

def has_resource_write_permission(self, user_id):
"""Anyone can sign up. Further requirements are enforced with validators
Expand Down
Loading

0 comments on commit 3b45865

Please sign in to comment.