diff --git a/Pipfile b/Pipfile index a5ac7cf..5006b17 100644 --- a/Pipfile +++ b/Pipfile @@ -19,9 +19,9 @@ hashids = "==1.2.0" psycopg2 = "==2.7.4" redis = "==2.10.5" requests = "==2.1.0" +SQLAlchemy = "==1.0.13" stripe = "==1.55.0" structlog = "==16.1.0" -SQLAlchemy = "==1.0.13" Flask = "==1" Flask-CDN = "==1.5.3" Flask-Cors = "==3.0.2" diff --git a/formspree/forms/api.py b/formspree/forms/api.py index 3ff8249..f5784e2 100644 --- a/formspree/forms/api.py +++ b/formspree/forms/api.py @@ -14,7 +14,7 @@ from .models import Form, Submission @login_required def list(): # grab all the forms this user controls - if current_user.upgraded: + if current_user.has_feature('dashboard'): forms = current_user.forms.order_by(Form.id.desc()).all() else: forms = [] @@ -22,8 +22,8 @@ def list(): return jsonify({ 'ok': True, 'user': { - 'upgraded': current_user.upgraded, - 'email': current_user.email + 'features': {f: True for f in current_user.features}, + 'email': current_user.email }, 'forms': [f.serialize() for f in forms] }) @@ -37,8 +37,8 @@ def create(): if referrer != service: return jsonerror(400, {'error': 'Improper request.'}) - if not current_user.upgraded: - g.log.info('Failed to create form from dashboard. User is not upgraded.') + if not current_user.has_feature('dashboard'): + g.log.info('Failed to create form from dashboard. Forbidden.') return jsonerror(402, {'error': "Please upgrade your account."}) email = request.get_json().get('email') @@ -97,7 +97,7 @@ def create(): @login_required def get(hashid): - if not current_user.upgraded: + if not current_user.has_feature('dashboard'): return jsonerror(402, {'error': "Please upgrade your account."}) form = Form.get_with_hashid(hashid) diff --git a/formspree/forms/models.py b/formspree/forms/models.py index ed5d9a5..40641dd 100644 --- a/formspree/forms/models.py +++ b/formspree/forms/models.py @@ -6,6 +6,8 @@ import datetime from flask import url_for, render_template, render_template_string, g from sqlalchemy.sql import table from sqlalchemy.sql.expression import delete +from sqlalchemy.dialects.postgresql import JSON +from sqlalchemy.ext.mutable import MutableDict from sqlalchemy import func from werkzeug.datastructures import ImmutableMultiDict, \ ImmutableOrderedMultiDict @@ -14,6 +16,7 @@ from formspree import settings from formspree.stuff import DB, redis_store, TEMPLATES from formspree.utils import send_email, unix_time_for_12_months_from_now, \ next_url, IS_VALID_EMAIL, request_wants_json +from formspree.users.models import Plan from .helpers import HASH, HASHIDS_CODEC, REDIS_COUNTER_KEY, \ http_form_to_dict, referrer_to_path, \ store_first_submission, fetch_first_submission, \ @@ -103,10 +106,9 @@ class Form(DB.Model): .filter(Form.id == self.id) return by_email.union(by_creation) - @property - def upgraded(self): - upgraded_controllers = [i for i in self.controllers if i.upgraded] - return len(upgraded_controllers) > 0 + def has_feature(self, feature): + c = [user for user in self.controllers if user.has_feature(feature)] + return len(c) > 0 @classmethod def get_with_hashid(cls, hashid): @@ -207,8 +209,8 @@ class Form(DB.Model): # increment the forms counter self.counter = Form.counter + 1 - # if submission storage is disabled and form is upgraded, don't store submission - if self.disable_storage and self.upgraded: + # if submission storage is disabled, don't store submission + if self.disable_storage and self.has_feature('dashboard'): pass else: DB.session.add(self) @@ -239,17 +241,18 @@ class Form(DB.Model): # url to request_unconfirm_form page unconfirm = url_for('request_unconfirm_form', form_id=self.id, _external=True) - # check if the forms are over the counter and the user is not upgraded + # check if the forms are over the counter and the user has unlimited submissions overlimit = False monthly_counter = self.get_monthly_counter() monthly_limit = settings.MONTHLY_SUBMISSIONS_LIMIT \ if self.id > settings.FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE \ else settings.GRANDFATHER_MONTHLY_LIMIT - if monthly_counter > monthly_limit and not self.upgraded: + if monthly_counter > monthly_limit and not self.has_feature('unlimited'): overlimit = True - if monthly_counter == int(monthly_limit * 0.9) and not self.upgraded: + if monthly_counter == int(monthly_limit * 0.9) and \ + not self.has_feature('unlimited'): # send email notification send_email( to=self.email, @@ -295,8 +298,8 @@ class Form(DB.Model): else: return {'code': Form.STATUS_OVERLIMIT} - # if emails are disabled and form is upgraded, don't send email notification - if self.disable_email and self.upgraded: + # if emails are disabled, don't send email notification + if self.disable_email and self.has_feature('dashboard'): return {'code': Form.STATUS_NO_EMAIL, 'next': next} else: result = send_email( @@ -483,15 +486,12 @@ class Form(DB.Model): return True -from sqlalchemy.dialects.postgresql import JSON -from sqlalchemy.ext.mutable import MutableDict - class Submission(DB.Model): __tablename__ = 'submissions' id = DB.Column(DB.Integer, primary_key=True) submitted_at = DB.Column(DB.DateTime) - form_id = DB.Column(DB.Integer, DB.ForeignKey('forms.id')) + form_id = DB.Column(DB.Integer, DB.ForeignKey('forms.id'), nullable=False) data = DB.Column(MutableDict.as_mutable(JSON)) def __init__(self, form_id): diff --git a/formspree/forms/views.py b/formspree/forms/views.py index 8fcca47..f8893b7 100644 --- a/formspree/forms/views.py +++ b/formspree/forms/views.py @@ -195,8 +195,8 @@ def send(email_or_string): captcha_verified or settings.TESTING) - # if form is upgraded check if captcha is disabled - if form.upgraded: + # check if captcha is disabled + if form.has_feature('dashboard'): needs_captcha = needs_captcha and not form.captcha_disabled if needs_captcha: @@ -492,7 +492,7 @@ def serve_dashboard(hashid=None, s=None): @login_required def export_submissions(hashid, format=None): - if not current_user.upgraded: + if not current_user.has_feature('dashboard'): return jsonerror(402, {'error': "Please upgrade your account."}) form = Form.get_with_hashid(hashid) diff --git a/formspree/js/forms/CreateForm.js b/formspree/js/forms/CreateForm.js index ae0d047..f3771eb 100644 --- a/formspree/js/forms/CreateForm.js +++ b/formspree/js/forms/CreateForm.js @@ -36,7 +36,7 @@ module.exports = class CreateForm extends React.Component { } render() { - if (!this.props.user.upgraded) { + if (!this.props.user.features.dashboard) { return (
diff --git a/formspree/js/forms/FormList.js b/formspree/js/forms/FormList.js index 5fa5644..d5fc41a 100644 --- a/formspree/js/forms/FormList.js +++ b/formspree/js/forms/FormList.js @@ -109,7 +109,7 @@ module.exports = class FormList extends React.Component { {this.state.enabled_forms.length === 0 && this.state.disabled_forms.length === 0 && - this.state.user.upgraded ? ( + this.state.user.features.dashboard ? (
You don't have any forms associated with this account, maybe you should verify your email. diff --git a/formspree/templates/layouts/base.html b/formspree/templates/layouts/base.html index 3bfc0a2..94a7f14 100644 --- a/formspree/templates/layouts/base.html +++ b/formspree/templates/layouts/base.html @@ -64,7 +64,7 @@