def watch_canary(sigid_base64): canary = get_canary(sigid_base64) if canary is None: return page_not_found('canary') if request.method == 'GET': return dict(canary=canary) if request.method == 'POST': try: email = request.form['email'] except KeyError: flash(err_messages['incomplete_form'], 'error') return dict(canary=canary) except Exception as e: flash(err_messages['generic'], 'error') app.logger.error(e) return dict(canary=canary) if not re.search('@', email) or len(email) > 254: flash(err_messages['invalid_email'], 'error') return dict(canary=canary) alerts = request.form.getlist('alerts') on_publish = 'onPublish' in alerts on_overdue = 'onOverdue' in alerts # on_delete = list['onDelete'] delay_days = 0 if on_overdue: delay = int(request.form['delay']) delay_type = request.form['delayType'] if not delay or not delay_type: on_overdue = False allowed_delays = 'day', 'week', 'month' in_range = 1 <= delay <= 100 if delay_type not in allowed_delays or not in_range: flash(err_messages['incomplete_form'], 'error') return dict(canary=canary) # Get the delay in days delay_days = days(delay, delay_type) # TODO: notify watchers when an canary is deleted # on_delete = request.form.get('onDelete') or False if not (on_publish or on_overdue): flash(err_messages['incomplete_form'], 'error') return dict(canary=canary) secret = os.urandom(16).encode('hex') alert = Alert(email, canary, False, on_overdue, on_publish, delay_days, secret) db_session.add(alert) db_session.commit() # Send verification email send_verification_email.delay(alert, canary) return redirect(url_for('canary', sigid_base64=sigid_base64))
def edit_canary(sigid_base64): if not logged_in(): return redirect(url_for('login')) canary = get_canary(sigid_base64) if canary is None: return page_not_found('canary') if logged_in and canary.user.fingerprint == session['fp']: freq_num = request.form['frequencyNum'] freq = request.form['frequency'] canary.freq_type = freq canary.frequency = days(freq_num, freq) canary.active = True db_session.commit() flash(messages['canary_updated'], 'message') return redirect(url_for('canary', sigid_base64=sigid_base64)) else: abort(403)
def new_canary(): if request.method == 'GET': return None if request.method == 'POST': try: signed = request.form['signedMessage'] frequency_num = int(request.form['frequencyNum']) frequency_type = request.form['frequency'] except KeyError: flash(err_messages['incomplete_form'], 'error') return None allowed_freqs = 'day', 'week', 'month' in_range = 1 <= frequency_num <= 100 if frequency_type not in allowed_freqs or not in_range: flash(err_messages['invalid_freq'], 'error') return None # Get the frequency in days frequency = days(frequency_num, frequency_type) verified, err = gpg.verify(signed) # Start over if the message wasn't verified. if err and not verified: flash(err, 'error') return None fp = verified.fingerprint sigid_base64 = base64.urlsafe_b64encode(verified.signature_id) try: canary = Canary(sigid_base64, frequency, frequency_type) db_session.add(canary) db_session.commit() except IntegrityError: # Throw an error if a canary with that sigid already exists db_session.rollback() db_session.flush() flash(err_messages['dupe_canary'], 'error') return redirect(url_for('new_canary')) except Exception as e: db_session.rollback() db_session.flush() app.logger.error(e) """An unexpected database error should not reveal any error details to the user.""" flash(err_messages['generic'], 'error') return None ciphertext = Challenge.generate(canary, fp) # TODO: This is sloppy. session['canary'] = dict(fp=verified.fingerprint.lower(), text=signed, uid=verified.username, keyid=verified.key_id, sigid_base64=sigid_base64, frequency=frequency, freq_type=frequency_type, ciphertext=str(ciphertext)) flash(messages['verified'], 'message') return dict(canary=session['canary'])