diff --git a/README.md b/README.md
index 39f9b6b..992365d 100644
--- a/README.md
+++ b/README.md
@@ -68,13 +68,6 @@ Create `.env` file in the root directory or pass as environment variables.
| MAIL_SERVER | " |
| MAIL_USERNAME | " |
-### Login with Google via OAuth
-
-| Variable | Function |
-| --- | --- |
-| GOOGLE_OAUTH_CLIENT_ID | Client Id |
-| GOOGLE_OAUTH_CLIENT_SECRET | Secret |
-
### Resolve addresses with Google Maps
| Variable | Function |
diff --git a/project/__init__.py b/project/__init__.py
index a84680b..9b22a5f 100644
--- a/project/__init__.py
+++ b/project/__init__.py
@@ -23,10 +23,6 @@ app.config["SECURITY_RECOVERABLE"] = True
app.config["SECURITY_CHANGEABLE"] = True
app.config["SECURITY_EMAIL_SENDER"] = os.getenv("MAIL_DEFAULT_SENDER")
app.config["LANGUAGES"] = ["en", "de"]
-app.config["GOOGLE_OAUTH_CLIENT_ID"] = os.getenv("GOOGLE_OAUTH_CLIENT_ID")
-app.config["GOOGLE_OAUTH_CLIENT_SECRET"] = os.getenv("GOOGLE_OAUTH_CLIENT_SECRET")
-app.config["OAUTHLIB_INSECURE_TRANSPORT"] = True
-app.config["OAUTHLIB_RELAX_TOKEN_SCOPE"] = True
# Generate a nice key using secrets.token_urlsafe()
app.config["SECRET_KEY"] = os.environ.get(
@@ -86,14 +82,10 @@ app.json_encoder = DateTimeEncoder
# Setup Flask-Security
from project.models import User, Role
+from project.forms.security import ExtendedRegisterForm
user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role)
-security = Security(app, user_datastore)
-
-# OAuth
-from project.oauth import blueprint
-
-app.register_blueprint(blueprint, url_prefix="/login")
+security = Security(app, user_datastore, register_form=ExtendedRegisterForm)
from project import i10n
from project import jinja_filters
diff --git a/project/forms/common.py b/project/forms/common.py
index 5ad8265..b833814 100644
--- a/project/forms/common.py
+++ b/project/forms/common.py
@@ -1,8 +1,10 @@
+from flask import url_for
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import StringField, BooleanField, HiddenField
from wtforms.validators import Optional
+from markupsafe import Markup
import re
import base64
@@ -62,6 +64,24 @@ class Base64ImageForm(BaseImageForm):
obj.encoding_format = None
+def get_accept_tos_markup():
+ tos_open = '' % url_for("tos")
+ tos_close = ""
+
+ privacy_open = '' % url_for("privacy")
+ privacy_close = ""
+
+ return Markup(
+ lazy_gettext(
+ "I read and accept %(tos_open)sTerms of Service%(tos_close)s and %(privacy_open)sPrivacy%(privacy_close)s.",
+ tos_open=tos_open,
+ tos_close=tos_close,
+ privacy_open=privacy_open,
+ privacy_close=privacy_close,
+ )
+ )
+
+
event_rating_choices = [
(0, lazy_gettext("0 (Little relevant)")),
(10, "1"),
diff --git a/project/forms/event_suggestion.py b/project/forms/event_suggestion.py
index 9185ac0..7001e63 100644
--- a/project/forms/event_suggestion.py
+++ b/project/forms/event_suggestion.py
@@ -14,7 +14,7 @@ from project.models import (
EventRejectionReason,
Image,
)
-from project.forms.common import Base64ImageForm
+from project.forms.common import Base64ImageForm, get_accept_tos_markup
from project.forms.widgets import CustomDateTimeField, TagSelectField
@@ -88,15 +88,14 @@ class CreateEventSuggestionForm(FlaskForm):
"We recommend uploading a photo for the event. It looks a lot more, but of course it works without it."
),
)
- accept_tos = BooleanField(
- lazy_gettext(
- "I confirm that I have clarified all information (text, images, etc.) that I upload into the system with regard to their rights of use and declare that they may be passed on."
- ),
- validators=[DataRequired()],
- )
+ accept_tos = BooleanField(validators=[DataRequired()])
submit = SubmitField(lazy_gettext("Create event suggestion"))
+ def __init__(self, **kwargs):
+ super(CreateEventSuggestionForm, self).__init__(**kwargs)
+ self._fields["accept_tos"].label.text = get_accept_tos_markup()
+
def populate_obj(self, obj):
for name, field in self._fields.items():
if name == "photo" and not obj.photo:
diff --git a/project/forms/security.py b/project/forms/security.py
new file mode 100644
index 0000000..62ad06e
--- /dev/null
+++ b/project/forms/security.py
@@ -0,0 +1,12 @@
+from flask_security.forms import RegisterForm
+from wtforms import BooleanField
+from wtforms.validators import DataRequired
+from project.forms.common import get_accept_tos_markup
+
+
+class ExtendedRegisterForm(RegisterForm):
+ accept_tos = BooleanField(validators=[DataRequired()])
+
+ def __init__(self, *args, **kwargs):
+ super(ExtendedRegisterForm, self).__init__(*args, **kwargs)
+ self._fields["accept_tos"].label.text = get_accept_tos_markup()
diff --git a/project/oauth.py b/project/oauth.py
deleted file mode 100644
index e12fc59..0000000
--- a/project/oauth.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from flask import flash
-from flask_security import current_user, login_user
-from flask_dance.contrib.google import make_google_blueprint
-from flask_dance.consumer import oauth_authorized, oauth_error
-from flask_dance.consumer.storage.sqla import SQLAlchemyStorage
-from project.models import OAuth
-from project import db, user_datastore
-from flask_babelex import gettext
-
-blueprint = make_google_blueprint(
- scope=["profile", "email"],
- storage=SQLAlchemyStorage(OAuth, db.session, user=current_user),
-)
-
-
-# create/login local user on successful OAuth login
-@oauth_authorized.connect_via(blueprint)
-def google_logged_in(blueprint, token): # pragma: no cover
- if not token:
- flash("Failed to log in.", category="error")
- return False
-
- resp = blueprint.session.get("/oauth2/v1/userinfo")
- if not resp.ok:
- msg = "Failed to fetch user info."
- flash(msg, category="error")
- return False
-
- info = resp.json()
- user_id = info["id"]
-
- # Find this OAuth token in the database, or create it
- oauth = OAuth.query.filter_by(
- provider=blueprint.name, provider_user_id=user_id
- ).first()
- if oauth is None:
- oauth = OAuth(provider=blueprint.name, provider_user_id=user_id, token=token)
-
- if oauth.user:
- login_user(oauth.user, authn_via=["google"])
- user_datastore.commit()
- flash(gettext("Successfully signed in."), "success")
-
- else:
- # Create a new local user account for this user
- user = user_datastore.create_user(email=info["email"])
- # Associate the new local user account with the OAuth token
- oauth.user = user
- # Save and commit our database models
- db.session.add_all([user, oauth])
- db.session.commit()
- # Log in the new local user account
- login_user(user, authn_via=["google"])
- user_datastore.commit()
- flash(gettext("Successfully signed in."), "success")
-
- # Disable Flask-Dance's default behavior for saving the OAuth token
- return False
-
-
-# notify on OAuth provider error
-@oauth_error.connect_via(blueprint)
-def google_error(blueprint, message, response): # pragma: no cover
- msg = "OAuth error from {name}! message={message} response={response}".format(
- name=blueprint.name, message=message, response=response
- )
- flash(msg, category="error")
diff --git a/project/templates/_macros.html b/project/templates/_macros.html
index 59c82be..4dfe7f7 100644
--- a/project/templates/_macros.html
+++ b/project/templates/_macros.html
@@ -438,10 +438,6 @@
{% endmacro %}
-{% macro render_google_sign_in_button() %}
- {{ _('Sign in with Google') }}
-{% endmacro %}
-
{% macro render_google_place_autocomplete_header(location_only = False) %}