def send_user_signup_notification(user): """Send notification to admin about new signed up commercial user.""" pairs_list_to_string = lambda pairs_list: '\n'.join([ '%s: %s' % (pair[0], pair[1]) for pair in pairs_list ]) send_mail( subject="[MetaBrainz] New commercial user signed up", text=pairs_list_to_string([ ('Organization name', user.org_name), ('Description', user.org_desc), ('Contact name', user.contact_name), ('Contact email', user.contact_email), ('Website URL', user.website_url), ('Logo image URL', user.org_logo_url), ('API URL', user.api_url), ('Street', user.address_street), ('City', user.address_city), ('State', user.address_state), ('Postal code', user.address_postcode), ('Country', user.address_country), ('Tier', str(user.tier)), ('Payment method', user.payment_method), ('Amount pledged', '$%s' % str(user.amount_pledged)), ('Data usage description', user.data_usage_desc), ]), recipients=current_app.config['NOTIFICATION_RECIPIENTS'], )
def send_user_signup_notification(user): """Send notification to admin about new signed up commercial user.""" pairs_list_to_string = lambda pairs_list: '\n'.join( ['%s: %s' % (pair[0], pair[1]) for pair in pairs_list]) send_mail( subject="[MetaBrainz] New commercial user signed up", text=pairs_list_to_string([ ('Organization name', user.org_name), ('Description', user.org_desc), ('Contact name', user.contact_name), ('Contact email', user.contact_email), ('Website URL', user.website_url), ('Logo image URL', user.org_logo_url), ('API URL', user.api_url), ('Street', user.address_street), ('City', user.address_city), ('State', user.address_state), ('Postal code', user.address_postcode), ('Country', user.address_country), ('Tier', str(user.tier)), ('Amount pledged', '$%s' % str(user.amount_pledged)), ('Data usage description', user.data_usage_desc), ]), recipients=current_app.config['NOTIFICATION_RECIPIENTS'], )
def signup_noncommercial(): """Sign up endpoint for non-commercial users.""" mb_username = session.fetch_data(SESSION_KEY_MB_USERNAME) if not mb_username: session.persist_data(**{ SESSION_KEY_ACCOUNT_TYPE: ACCOUNT_TYPE_NONCOMMERCIAL, }) return redirect(url_for(".signup")) mb_email = session.fetch_data(SESSION_KEY_MB_EMAIL) form = NonCommercialSignUpForm(default_email=mb_email) if form.validate_on_submit(): new_user = User.add( is_commercial=False, musicbrainz_id=mb_username, contact_name=form.contact_name.data, contact_email=form.contact_email.data, data_usage_desc=form.usage_desc.data, ) login_user(new_user) flash.success("Thanks for signing up!") send_mail( subject="[MetaBrainz] Sign up confirmation", text='Dear %s,\n\nThank you for signing up!\n\nYou can now generate ' 'an access token for the MetaBrainz API on your profile page.' % new_user.contact_name, recipients=[new_user.contact_email], ) return redirect(url_for('.profile')) return render_template("users/signup-non-commercial.html", form=form)
def send_user_signup_notification(user): """Send notification to admin about new signed up commercial user.""" pairs_list_to_string = lambda pairs_list: "\n".join(["%s: %s" % (pair[0], pair[1]) for pair in pairs_list]) send_mail( subject="[MetaBrainz] New commercial user signed up", text=pairs_list_to_string( [ ("Organization name", user.org_name), ("Description", user.org_desc), ("Contact name", user.contact_name), ("Contact email", user.contact_email), ("Website URL", user.website_url), ("Logo image URL", user.org_logo_url), ("API URL", user.api_url), ("Street", user.address_street), ("City", user.address_city), ("State", user.address_state), ("Postal code", user.address_postcode), ("Country", user.address_country), ("Tier", str(user.tier)), ("Amount pledged", "$%s" % str(user.amount_pledged)), ("Data usage description", user.data_usage_desc), ] ), recipients=current_app.config["NOTIFICATION_RECIPIENTS"], )
def signup_noncommercial(): """Sign up endpoint for non-commercial users.""" mb_username = session.fetch_data(SESSION_KEY_MB_USERNAME) if not mb_username: session.persist_data(**{ SESSION_KEY_ACCOUNT_TYPE: ACCOUNT_TYPE_NONCOMMERCIAL, }) return redirect(url_for(".signup")) mb_email = session.fetch_data(SESSION_KEY_MB_EMAIL) form = NonCommercialSignUpForm(default_email=mb_email) if form.validate_on_submit(): # Checking if this user already exists new_user = User.get(musicbrainz_id=mb_username) if not new_user: new_user = User.add( is_commercial=False, musicbrainz_id=mb_username, contact_name=form.contact_name.data, contact_email=form.contact_email.data, data_usage_desc=form.usage_desc.data, ) login_user(new_user) flash.success("Thanks for signing up!") send_mail( subject="[MetaBrainz] Sign up confirmation", text='Dear %s,\n\nThank you for signing up!\n\nYou can now generate ' 'an access token for the MetaBrainz API on your profile page.' % new_user.contact_name, recipients=[new_user.contact_email], ) return redirect(url_for('.profile')) return render_template("users/signup-non-commercial.html", form=form)
def set_state(self, state): old_state = self.state self.state = state db.session.commit() if old_state != self.state: # TODO: Send additional info about new state. state_name = "ACTIVE" if self.state == STATE_ACTIVE else \ "REJECTED" if self.state == STATE_REJECTED else \ "PENDING" if self.state == STATE_PENDING else \ self.state send_mail( subject="[MetaBrainz] Your account has been updated", text='State of your MetaBrainz account has been changed to "%s".' % state_name, recipients=[self.contact_email], )
def set_state(self, state): old_state = self.state self.state = state db.session.commit() if old_state != self.state: # TODO: Send additional info about new state. state_name = "ACTIVE" if self.state == STATE_ACTIVE else \ "REJECTED" if self.state == STATE_REJECTED else \ "PENDING" if self.state == STATE_PENDING else \ "WAITING" if self.state == STATE_WAITING else \ "LIMITED" if self.state == STATE_LIMITED else \ self.state send_mail( subject="[MetaBrainz] Your account has been updated", text='State of your MetaBrainz account has been changed to "%s".' % state_name, recipients=[self.contact_email], )
def create_record(cls, access_token, ip_address): """Creates new access log record with a current timestamp. It also checks if `DIFFERENT_IP_LIMIT` is exceeded within current time and `CLEANUP_RANGE_MINUTES`, alerts admins if that's the case. Args: access_token: Access token used to access the API. ip_address: IP access used to access the API. Returns: New access log record. """ new_record = cls( token=access_token, ip_address=ip_address, ) db.session.add(new_record) db.session.commit() cls.remove_old_ip_addr_records() # Checking if HOURLY_ALERT_THRESHOLD is exceeded count = cls.query \ .distinct(cls.ip_address) \ .filter(cls.timestamp > datetime.now(pytz.utc) - timedelta(minutes=CLEANUP_RANGE_MINUTES), cls.token == access_token) \ .count() if count > DIFFERENT_IP_LIMIT: msg = ("Hourly access threshold exceeded for token %s\n\n" "This token has been used from %s different IP " "addresses during the last %s minutes.") % \ (access_token, count, CLEANUP_RANGE_MINUTES) logging.info(msg) # Checking if notification for admins about this token abuse has # been sent in the last hour. This info is kept in memcached. key = "alert_sent_%s" % access_token if not cache.get(key): send_mail( subject="[MetaBrainz] Hourly access threshold exceeded", recipients=current_app.config['NOTIFICATION_RECIPIENTS'], text=msg, ) cache.set(key, True, 3600) # 1 hour return new_record
def create_record(cls, access_token, ip_address): """Creates new access log record with a current timestamp. It also checks if `DIFFERENT_IP_LIMIT` is exceeded within current time and `CLEANUP_RANGE_MINUTES`, alerts admins if that's the case. Args: access_token: Access token used to access the API. ip_address: IP access used to access the API. Returns: New access log record. """ new_record = cls( token=access_token, ip_address=ip_address, ) db.session.add(new_record) db.session.commit() # Checking if HOURLY_ALERT_THRESHOLD is exceeded count = cls.query \ .distinct(cls.ip_address) \ .filter(cls.timestamp > datetime.now(pytz.utc) - timedelta(minutes=CLEANUP_RANGE_MINUTES), cls.token == access_token) \ .count() if count > DIFFERENT_IP_LIMIT: msg = ("Hourly access threshold exceeded for token %s\n\n" "This token has been used from %s different IP " "addresses during the last %s minutes.") % \ (access_token, count, CLEANUP_RANGE_MINUTES) logging.info(msg) # Checking if notification for admins about this token abuse has # been sent in the last hour. This info is kept in cache. key = "alert_sent_%s" % access_token if not cache.get(key): send_mail( subject="[MetaBrainz] Hourly access threshold exceeded", recipients=current_app.config['NOTIFICATION_RECIPIENTS'], text=msg, ) cache.set(key, True, 3600) # 1 hour return new_record
def send_receipt(email, date, amount, name, is_donation, editor_name=None): if is_donation: subject = "Receipt for your donation to the MetaBrainz Foundation" text = ( "Dear %s:\n\n" "Thank you very much for your donation to the MetaBrainz Foundation!\n\n" "Your donation will allow the MetaBrainz Foundation to continue operating " "and improving the MusicBrainz project and its related projects. The " "foundation depends on donations from the community and therefore deeply " "appreciates your support.\n\n" "The MetaBrainz Foundation is a United States 501(c)(3) tax-exempt public " "charity. This allows US taxpayers to deduct this donation from their " "taxes under section 170 of the Internal Revenue Service code.\n\n" "Please save a printed copy of the attached PDF receipt for your records." ) % name from_addr = 'donations@' + current_app.config['MAIL_FROM_DOMAIN'] from_name = 'Donation Manager' attachment_file_name = 'metabrainz_donation' else: subject = "Receipt for your payment to the MetaBrainz Foundation" text = ( "Dear %s:\n\n" "Thank you very much for your payment to the MetaBrainz Foundation!\n\n" "Your payment will allow the MetaBrainz Foundation to continue operating " "and improving the MusicBrainz project and its related projects. The " "foundation depends on these payments and therefore deeply appreciates " "your support.\n\n" "Please save a printed copy of the attached PDF receipt for your records." ) % name from_addr = 'payments@' + current_app.config['MAIL_FROM_DOMAIN'] from_name = 'Payment Manager' attachment_file_name = 'metabrainz_payment' send_mail( subject=subject, text=text, attachments=[(generate_recript(email, date, amount, name, is_donation, editor_name), 'pdf', '%s.pdf' % attachment_file_name)], recipients=[email], from_addr=from_addr, from_name=from_name, )
def signup_noncommercial(): """Sign up endpoint for non-commercial users.""" mb_username = session.fetch_data(SESSION_KEY_MB_USERNAME) if not mb_username: session.persist_data(**{ SESSION_KEY_ACCOUNT_TYPE: ACCOUNT_TYPE_NONCOMMERCIAL, }) return redirect(url_for(".signup")) mb_email = session.fetch_data(SESSION_KEY_MB_EMAIL) form = NonCommercialSignUpForm(default_email=mb_email) if form.validate_on_submit(): # Checking if this user already exists new_user = User.get(musicbrainz_id=mb_username) if not new_user: new_user = User.add( is_commercial=False, musicbrainz_id=mb_username, contact_name=form.contact_name.data, contact_email=form.contact_email.data, data_usage_desc=form.usage_desc.data, ) flash.success(gettext("Thanks for signing up!")) try: send_mail( subject="[MetaBrainz] Sign up confirmation", text='Dear %s,\n\nThank you for signing up!\n\nYou can now generate ' 'an access token for the MetaBrainz API on your profile page.' % new_user.contact_name, recipients=[new_user.contact_email], ) except MailException as e: logging.error(e) flash.warning(gettext( "Failed to send welcome email to you. We are looking into it. " "Sorry for inconvenience!" )) else: flash.info(gettext("You already have a MetaBrainz account!")) login_user(new_user) return redirect(url_for('.profile')) return render_template("users/signup-non-commercial.html", form=form, mb_username=mb_username)
def signup_commercial(): """Sign up endpoint for commercial users. Commercial users need to choose support tier before filling out the form. `tier_id` argument with ID of a tier of choice is required there. """ tier_id = request.args.get('tier_id') if not tier_id: flash.warn("You need to choose support tier before signing up!") return redirect(url_for('.account_type')) selected_tier = Tier.get(id=tier_id) if not selected_tier or not selected_tier.available: flash.error("You need to choose existing tier before signing up!") return redirect(url_for(".account_type")) mb_username = session.fetch_data(SESSION_KEY_MB_USERNAME) if not mb_username: session.persist_data(**{ SESSION_KEY_ACCOUNT_TYPE: ACCOUNT_TYPE_COMMERCIAL, SESSION_KEY_TIER_ID: selected_tier.id, }) return redirect(url_for(".signup")) mb_email = session.fetch_data(SESSION_KEY_MB_EMAIL) form = CommercialSignUpForm(default_email=mb_email) def custom_validation(f): if f.amount_pledged.data < selected_tier.price: flash.warning("Custom amount must be more than threshold amount" "for selected tier or equal to it!") return False # Complete address is required if payment method is invoicing if f.payment_method.data == PAYMENT_METHOD_INVOICING: if not (form.address_street.data and form.address_city.data and form.address_state.data and form.address_postcode.data and form.address_country.data): flash.warning("You need to fill in all address fields if your " "selected payment method is invoicing!") return False return True if form.validate_on_submit() and custom_validation(form): new_user = User.add( is_commercial=True, musicbrainz_id=mb_username, contact_name=form.contact_name.data, contact_email=form.contact_email.data, data_usage_desc=form.usage_desc.data, org_name=form.org_name.data, org_desc=form.org_desc.data, website_url=form.website_url.data, org_logo_url=form.logo_url.data, api_url=form.api_url.data, address_street=form.address_street.data, address_city=form.address_city.data, address_state=form.address_state.data, address_postcode=form.address_postcode.data, address_country=form.address_country.data, tier_id=tier_id, payment_method=form.payment_method.data, amount_pledged=form.amount_pledged.data, ) login_user(new_user) flash.success("Thanks for signing up! Your application will be reviewed " "soon. We will send you updates via email.") send_mail( subject="[MetaBrainz] Sign up confirmation", text="Dear %s,\n\nThank you for signing up!\n\nCurrently everyone is on " "a summer vacation until July 14. Your application will be reviewed " "as soon as we get back. We will send you updates via email. Sorry " "for the inconvenience." % new_user.contact_name, recipients=[new_user.contact_email], ) return redirect(url_for('.profile')) return render_template("users/signup-commercial.html", form=form, tier=selected_tier)
def signup_commercial(): """Sign up endpoint for commercial users. Commercial users need to choose support tier before filling out the form. `tier_id` argument with ID of a tier of choice is required there. """ tier_id = request.args.get('tier_id') if not tier_id: flash.warn("You need to choose support tier before signing up!") return redirect(url_for('.account_type')) selected_tier = Tier.get(id=tier_id) if not selected_tier or not selected_tier.available: flash.error("You need to choose existing tier before signing up!") return redirect(url_for(".account_type")) mb_username = session.fetch_data(SESSION_KEY_MB_USERNAME) if not mb_username: session.persist_data(**{ SESSION_KEY_ACCOUNT_TYPE: ACCOUNT_TYPE_COMMERCIAL, SESSION_KEY_TIER_ID: selected_tier.id, }) return redirect(url_for(".signup")) mb_email = session.fetch_data(SESSION_KEY_MB_EMAIL) form = CommercialSignUpForm(default_email=mb_email) def custom_validation(f): if f.amount_pledged.data < selected_tier.price: flash.warning("Custom amount must be more than threshold amount" "for selected tier or equal to it!") return False return True if form.validate_on_submit() and custom_validation(form): # Checking if this user already exists new_user = User.get(musicbrainz_id=mb_username) if not new_user: new_user = User.add( is_commercial=True, musicbrainz_id=mb_username, contact_name=form.contact_name.data, contact_email=form.contact_email.data, data_usage_desc=form.usage_desc.data, org_name=form.org_name.data, org_desc=form.org_desc.data, website_url=form.website_url.data, org_logo_url=form.logo_url.data, api_url=form.api_url.data, address_street=form.address_street.data, address_city=form.address_city.data, address_state=form.address_state.data, address_postcode=form.address_postcode.data, address_country=form.address_country.data, tier_id=tier_id, amount_pledged=form.amount_pledged.data, ) flash.success("Thanks for signing up! Your application will be reviewed " "soon. We will send you updates via email.") send_mail( subject="[MetaBrainz] Sign up confirmation", text='Dear %s,\n\nThank you for signing up!\n\nYour application' ' will be reviewed soon. We will send you updates via email.' % new_user.contact_name, recipients=[new_user.contact_email], ) else: flash.info("You already have a MetaBrainz account!") login_user(new_user) return redirect(url_for('.profile')) return render_template("users/signup-commercial.html", form=form, tier=selected_tier, mb_username=mb_username)
def signup_commercial(): """Sign up endpoint for commercial users. Commercial users need to choose support tier before filling out the form. `tier_id` argument with ID of a tier of choice is required there. """ tier_id = request.args.get('tier_id') if not tier_id: flash.warn( gettext("You need to choose support tier before signing up!")) return redirect(url_for('.account_type')) selected_tier = Tier.get(id=tier_id) if not selected_tier or not selected_tier.available: flash.error( gettext("You need to choose existing tier before signing up!")) return redirect(url_for(".account_type")) mb_username = session.fetch_data(SESSION_KEY_MB_USERNAME) if not mb_username: session.persist_data( **{ SESSION_KEY_ACCOUNT_TYPE: ACCOUNT_TYPE_COMMERCIAL, SESSION_KEY_TIER_ID: selected_tier.id, }) return redirect(url_for(".signup")) mb_email = session.fetch_data(SESSION_KEY_MB_EMAIL) form = CommercialSignUpForm(default_email=mb_email) def custom_validation(f): if f.amount_pledged.data < selected_tier.price: flash.warning( gettext("Custom amount must be more than threshold amount" "for selected tier or equal to it!")) return False return True if form.validate_on_submit() and custom_validation(form): # Checking if this user already exists new_user = User.get(musicbrainz_id=mb_username) if not new_user: new_user = User.add( is_commercial=True, musicbrainz_id=mb_username, contact_name=form.contact_name.data, contact_email=form.contact_email.data, data_usage_desc=form.usage_desc.data, org_name=form.org_name.data, org_desc=form.org_desc.data, website_url=form.website_url.data, org_logo_url=form.logo_url.data, api_url=form.api_url.data, address_street=form.address_street.data, address_city=form.address_city.data, address_state=form.address_state.data, address_postcode=form.address_postcode.data, address_country=form.address_country.data, tier_id=tier_id, amount_pledged=form.amount_pledged.data, ) flash.success( gettext( "Thanks for signing up! Your application will be reviewed " "soon. We will send you updates via email.")) try: send_mail( subject="[MetaBrainz] Sign up confirmation", text= 'Dear %s,\n\nThank you for signing up!\n\nYour application' ' will be reviewed soon. We will send you updates via email.' % new_user.contact_name, recipients=[new_user.contact_email], ) except MailException as e: logging.error(e) flash.warn( gettext( "Failed to send welcome email to you. We are looking into it. " "Sorry for inconvenience!")) else: flash.info(gettext("You already have a MetaBrainz account!")) login_user(new_user) return redirect(url_for('.profile')) return render_template("users/signup-commercial.html", form=form, tier=selected_tier, mb_username=mb_username)