def resource_action_delete(client, resource, action): return render_delete_sqla(action, db, title=_("Confirm delete"), message=_(u"Delete action ‘{action}’ from resource ‘{resource}’ of app ‘{client}’?").format( action=action.title, resource=resource.title, client=client.title), success=_(u"You have deleted action ‘{action}’ on resource ‘{resource}’ of app ‘{client}’").format( action=action.title, resource=resource.title, client=client.title), next=url_for('.client_info', key=client.key))
def proposal_edit(space, proposal): form = ProposalForm(obj=proposal, model=Proposal, parent=space) if not proposal.session_type: del form.session_type # Remove this if we're editing a proposal that had no session type form.section.query = ProposalSpaceSection.query.filter_by(proposal_space=space, public=True).order_by('title') if len(list(form.section.query.all())) == 0: # Don't bother with sections when there aren't any del form.section if proposal.user != g.user: del form.speaking elif request.method == 'GET': form.speaking.data = proposal.speaker == g.user if form.validate_on_submit(): form.populate_obj(proposal) proposal.name = make_name(proposal.title) if proposal.user == g.user: # Only allow the speaker to change this status if form.speaking.data: proposal.speaker = g.user else: if proposal.speaker == g.user: proposal.speaker = None proposal.edited_at = datetime.utcnow() db.session.commit() flash(_("Your changes have been saved"), 'info') return redirect(proposal.url_for(), code=303) return render_template('baseframe/autoform.html', form=form, title=_("Edit session proposal"), submit=_("Save changes"), breadcrumbs=[(space.url_for(), space.title), (proposal.url_for(), proposal.title)], message=Markup( _('This form uses <a href="http://daringfireball.net/projects/markdown/">Markdown</a> for formatting.')))
def proposal_edit(profile, space, proposal): form = ProposalForm(obj=proposal.formdata, model=Proposal, parent=space) if not proposal.session_type: del form.session_type # Remove this if we're editing a proposal that had no session type form.section.query = ProposalSpaceSection.query.filter_by(proposal_space=space, public=True).order_by("title") if len(list(form.section.query.all())) == 0: # Don't bother with sections when there aren't any del form.section if proposal.user != g.user: del form.speaking if form.validate_on_submit(): form.populate_obj(proposal.formdata) proposal.name = make_name(proposal.title) proposal.edited_at = datetime.utcnow() db.session.commit() flash(_("Your changes have been saved"), "info") return redirect(proposal.url_for(), code=303) return render_form( form=form, title=_("Edit session proposal"), submit=_("Save changes"), message=Markup( _('This form uses <a href="http://daringfireball.net/projects/markdown/">Markdown</a> for formatting.') ), )
def resource_delete(client, resource): return render_delete_sqla(resource, db, title=_(u"Confirm delete"), message=_(u"Delete resource ‘{resource}’ from app ‘{client}’?").format( resource=resource.title, client=client.title), success=_(u"You have deleted resource ‘{resource}’ on app ‘{client}’").format( resource=resource.title, client=client.title), next=url_for('.client_info', key=client.key))
def usergroup_edit(profile, space, kwargs): group = kwargs.get('group') form = UserGroupForm(model=UserGroup, parent=space) if group is not None: usergroup = UserGroup.query.filter_by(name=group, proposal_space=space).first_or_404() form.edit_id = usergroup.id if request.method == 'GET': form.name.data = usergroup.name form.title.data = usergroup.title form.users.data = '\r\n'.join([u.email or u.username or '' for u in usergroup.users]) if form.validate_on_submit(): if group is None: usergroup = UserGroup(proposal_space=space) usergroup.name = form.name.data usergroup.title = form.title.data formdata = [line.strip() for line in form.users.data.replace('\r', '\n').replace(',', '\n').split('\n') if line] usersdata = lastuser.getusers(names=formdata) users = [] for userdata in usersdata or []: user = User.query.filter_by(userid=userdata['userid']).first() if user is None: user = User(userid=userdata['userid'], fullname=userdata['title']) db.session.add(user) users.append(user) usergroup.users = users db.session.commit() return redirect(usergroup.url_for(), code=303) if group is None: return render_form(form=form, title=_("New user group"), submit=_("Create user group")) else: return render_form(form=form, title=_("Edit user group"), submit=_("Save changes"))
def video_new(channel, playlist): """ Add a new video """ form = VideoAddForm() if request.method == 'GET': if playlist is None: cancel_url = channel.url_for() else: cancel_url = playlist.url_for() html_form = render_form(form=form, title=_("New Video"), submit=_("Add"), cancel_url=cancel_url, ajax=False, with_chrome=False) return {'channel': dict(channel.current_access()), 'playlist': dict(playlist.current_access()), 'form': html_form} if form.validate_on_submit(): stream_playlist = channel.playlist_for_stream(create=True) video = Video(playlist=playlist if playlist is not None else stream_playlist) form.populate_obj(video) try: process_video(video, new=True) process_slides(video) except (DataProcessingError, ValueError) as e: return {'status': 'error', 'errors': {'video_url': [e.message]}}, 400 video.make_name() if playlist is not None and video not in playlist.videos: playlist.videos.append(video) if video not in stream_playlist.videos: stream_playlist.videos.append(video) db.session.commit() return {'status': 'ok', 'doc': _("Added video {title}.".format(title=video.title)), 'result': {'new_video_edit_url': video.url_for('edit')}}, 201 else: return {'status': 'error', 'errors': form.errors}, 400
def report_smsgupshup(): externalId = request.args.get('externalId') deliveredTS = request.args.get('deliveredTS') status = request.args.get('status') phoneNo = request.args.get('phoneNo') cause = request.args.get('cause') # Find a corresponding message and ensure the parameters match msg = SMSMessage.query.filter_by(transaction_id=externalId).first() if not msg: return _("No such message"), 404 elif msg.phone_number != '+' + phoneNo: return _("Incorrect phone number"), 404 else: if status == 'SUCCESS': msg.status = SMS_STATUS.DELIVERED elif status == 'FAIL': msg.status = SMS_STATUS.FAILED else: msg.status == SMS_STATUS.UNKNOWN msg.fail_reason = cause if deliveredTS: deliveredTS = float(deliveredTS) / 1000.0 # This delivery time is in IST, GMT+0530 # Convert this into a naive UTC timestamp before saving local_status_at = datetime.fromtimestamp(deliveredTS) msg.status_at = local_status_at - SMSGUPSHUP_TIMEZONE.utcoffset(local_status_at) db.session.commit() return _("Status updated")
def status_label(self): if self.status == POSTSTATUS.DRAFT: return _("Draft") elif self.status == POSTSTATUS.PENDING: return _("Pending") elif self.is_new(): return _("New!")
def proposal_delete(space, proposal): form = ConfirmDeleteForm() if form.validate_on_submit(): if "delete" in request.form: comments = Comment.query.filter_by(commentspace=proposal.comments).order_by("created_at").all() for comment in comments: db.session.delete(comment) db.session.delete(proposal.comments) votes = Vote.query.filter_by(votespace=proposal.votes).all() for vote in votes: db.session.delete(vote) db.session.delete(proposal.votes) db.session.delete(proposal) db.session.commit() flash(_("Your proposal has been deleted"), "info") return redirect(space.url_for()) else: return redirect(proposal.url_for()) return render_template( "delete.html", form=form, title=_(u"Confirm delete"), message=_( u"Do you really wish to delete your proposal ‘{title}’? " u"This will remove all votes and comments as well. This operation " u"is permanent and cannot be undone." ).format(title=proposal.title), )
def proposal_new(profile, space): form = ProposalForm(model=Proposal, parent=space) del form.session_type # We don't use this anymore form.section.query = ProposalSpaceSection.query.filter_by(proposal_space=space, public=True).order_by("title") if len(list(form.section.query.all())) == 0: # Don't bother with sections when there aren't any del form.section if request.method == "GET": form.email.data = g.user.email form.phone.data = g.user.phone if form.validate_on_submit(): proposal = Proposal(user=g.user, proposal_space=space) with db.session.no_autoflush: proposal.votes.vote(g.user) # Vote up your own proposal by default form.populate_obj(proposal.formdata) proposal.name = make_name(proposal.title) db.session.add(proposal) db.session.commit() flash(_("Your new session has been saved"), "info") return redirect(proposal.url_for(), code=303) return render_form( form=form, title=_("Submit a session proposal"), submit=_("Submit proposal"), message=Markup( _('This form uses <a href="http://daringfireball.net/projects/markdown/">Markdown</a> for formatting.') ), )
def client_edit(client): form = RegisterClientForm(obj=client, model=Client) form.edit_user = current_auth.user form.client_owner.choices = available_client_owners() if request.method == 'GET': if client.user: form.client_owner.data = client.user.buid else: form.client_owner.data = client.org.buid if form.validate_on_submit(): if client.user != form.user or client.org != form.org: # Ownership has changed. Remove existing permission assignments for perm in UserClientPermissions.query.filter_by(client=client).all(): db.session.delete(perm) for perm in TeamClientPermissions.query.filter_by(client=client).all(): db.session.delete(perm) flash(_(u"This application’s owner has changed, so all previously assigned permissions " "have been revoked"), 'warning') form.populate_obj(client) client.user = form.user client.org = form.org if not client.team_access: # This client does not have access to teams in organizations. Remove all existing assignments for cta in ClientTeamAccess.query.filter_by(client=client).all(): db.session.delete(cta) db.session.commit() return render_redirect(url_for('.client_info', key=client.key), code=303) return render_form(form=form, title=_("Edit application"), formid='client_edit', submit=_("Save changes"), ajax=True)
def location_new(): if not (lastuser.has_permission('siteadmin') or (g.board and g.board.owner_is(g.user))): abort(403) now = datetime.utcnow() geonames = OrderedDict([(r.geonameid, None) for r in db.session.query(JobLocation.geonameid, db.func.count(JobLocation.geonameid).label('count')).join( JobPost).filter(JobPost.status.in_(POSTSTATUS.LISTED), JobPost.datetime > now - agelimit, ~JobLocation.geonameid.in_(db.session.query(Location.id).filter(Location.board == g.board)) ).group_by(JobLocation.geonameid).order_by(db.text('count DESC')).limit(100)]) data = location_geodata(geonames.keys()) for row in data.values(): geonames[row['geonameid']] = row choices = [('%s/%s' % (row['geonameid'], row['name']), row['picker_title']) for row in geonames.values()] form = NewLocationForm() form.geoname.choices = choices if form.validate_on_submit(): geonameid, name = form.geoname.data.split('/', 1) geonameid = int(geonameid) title = geonames[geonameid]['use_title'] location = Location(id=geonameid, board=g.board, name=name, title=title) db.session.add(location) db.session.commit() return redirect(location.url_for('edit'), code=303) return render_form(form=form, title=_("Add a location"), submit=_("Next"))
def verify_phone(phoneclaim): if phoneclaim.verification_expired: flash(_("You provided an incorrect verification code too many times"), 'danger') # Block attempts to verify this number, but also keep the claim so that a new # claim cannot be made. A periodic sweep to delete old claims is needed. return render_redirect(url_for('.account'), code=303) form = VerifyPhoneForm() form.phoneclaim = phoneclaim if form.validate_on_submit(): if UserPhone.get(phoneclaim.phone) is None: if not current_auth.user.phones: primary = True else: primary = False userphone = UserPhone(user=current_auth.user, phone=phoneclaim.phone, gets_text=True) userphone.primary = primary db.session.add(userphone) db.session.delete(phoneclaim) db.session.commit() flash(_("Your phone number has been verified"), 'success') user_data_changed.send(current_auth.user, changes=['phone']) return render_redirect(url_for('.account'), code=303) else: db.session.delete(phoneclaim) db.session.commit() flash(_("This phone number has already been claimed by another user"), 'danger') elif request.method == 'POST': phoneclaim.verification_attempts += 1 db.session.commit() return render_form(form=form, title=_("Verify phone number"), formid='phone_verify', submit=_("Verify"), ajax=True)
def callback(self): if 'google_callback' in session: callback_url = session.pop('google_callback') else: raise LoginCallbackError(_(u"Duplicate callback. Did you go back in your browser history?")) if request.args.get('error'): if request.args['error'] == 'access_denied': raise LoginCallbackError(_(u"You denied the Google login request")) else: raise LoginCallbackError(_(u"Unknown failure")) code = request.args.get('code', None) try: credentials = self.flow(callback_url).step2_exchange(code) response = requests.get(self.info_url, headers={'Authorization': credentials.token_response['token_type'] + ' ' + credentials.access_token}).json() except Exception as e: raise LoginCallbackError(_(u"Unable to authenticate via Google. Internal details: {error}").format(error=e)) if response.get('error'): raise LoginCallbackError(_(u"Unable to login via Google: {error}").format( error=response['error'].get('message', u''))) return {'email': credentials.id_token['email'], 'userid': credentials.id_token['email'], 'username': credentials.id_token['email'], 'fullname': response.get('name', ''), 'avatar_url': response.get('picture'), 'oauth_token': credentials.access_token, 'oauth_token_secret': None, # OAuth 2 doesn't need token secrets 'oauth_token_type': credentials.token_response['token_type'] }
def validate(self): rv = super(PermissionForm, self).validate() if not rv: return False if not valid_username(self.name.data): self.name.errors.append(_("Name contains invalid characters")) return False existing = Permission.get(name=self.name.data, allusers=True) if existing and existing.id != self.edit_id: self.name.errors.append(_("A global permission with that name already exists")) return False if self.context.data == self.edit_user.buid: existing = Permission.get(name=self.name.data, user=self.edit_user) else: org = Organization.get(buid=self.context.data) if org: existing = Permission.get(name=self.name.data, org=org) else: existing = None if existing and existing.id != self.edit_id: self.name.errors.append(_("You have another permission with the same name")) return False return True
def proposal_new(space): form = ProposalForm(model=Proposal, parent=space) # del form.session_type # We don't use this anymore # But The Goa Project still does, so commented out form.section.query = ProposalSpaceSection.query.filter_by(proposal_space=space, public=True).order_by('title') if len(list(form.section.query.all())) == 0: # Don't bother with sections when there aren't any del form.section if request.method == 'GET': form.email.data = g.user.email form.phone.data = g.user.phone if form.validate_on_submit(): proposal = Proposal(user=g.user, proposal_space=space) if form.speaking.data: proposal.speaker = g.user else: proposal.speaker = None with db.session.no_autoflush: proposal.votes.vote(g.user) # Vote up your own proposal by default form.populate_obj(proposal) proposal.name = make_name(proposal.title) db.session.add(proposal) db.session.commit() flash(_("Your new session has been saved"), 'info') return redirect(proposal.url_for(), code=303) return render_template('baseframe/autoform.html', form=form, title=_("Submit a session proposal"), submit=_("Submit proposal"), breadcrumbs=[(space.url_for(), space.title)], message=Markup( _('This form uses <a href="http://daringfireball.net/projects/markdown/">Markdown</a> for formatting.')))
def validate_name(self, field): field.data = field.data.lower() if not valid_username(field.data): raise forms.ValidationError(_("Name contains invalid characters")) existing = self.edit_resource.get_action(field.data) if existing and existing.id != self.edit_id: raise forms.ValidationError(_("An action with that name already exists for this resource"))
def validate_username(self, field): if field.data in current_app.config['RESERVED_USERNAMES']: raise forms.ValidationError, _("This name is reserved") if not valid_username(field.data): raise forms.ValidationError(_(u"Invalid characters in name. Names must be made of ‘a-z’, ‘0-9’ and ‘-’, without trailing dashes")) existing = User.get(username=field.data) if existing is not None: raise forms.ValidationError(_("This username is taken"))
def event_edit(profile, space, event): form = EventForm(obj=event, model=Event) if form.validate_on_submit(): form.populate_obj(event) db.session.commit() flash(_(u"Your changes have been saved"), 'info') return redirect(space.url_for('admin'), code=303) return render_form(form=form, title=_(u"Edit event"), submit=_(u"Save changes"))
def ticket_client_edit(profile, project, ticket_client): form = TicketClientForm(obj=ticket_client, model=TicketClient) if form.validate_on_submit(): form.populate_obj(ticket_client) db.session.commit() flash(_(u"Your changes have been saved"), 'info') return redirect(project.url_for('admin'), code=303) return render_form(form=form, title=_(u"Edit ticket client"), submit=_(u"Save changes"))
def delete(self): return render_delete_sqla(self.obj, db, title=_(u"Confirm delete"), message=_(u"Do you really wish to delete your proposal ‘{title}’? " u"This will remove all votes and comments as well. This operation " u"is permanent and cannot be undone.").format(title=self.obj.title), success=_("Your proposal has been deleted"), next=self.obj.project.url_for(), cancel_url=self.obj.url_for())
def edit(self): form = SectionForm(obj=self.obj, model=Section, parent=self.obj.parent) if form.validate_on_submit(): form.populate_obj(self.obj) db.session.commit() flash(_("Your section has been edited"), 'info') return redirect(self.obj.project.url_for('sections'), code=303) return render_form(form=form, title=_("Edit section"), submit=_("Save changes"))
def team_delete(org, team): if team == org.owners or team == org.members: abort(403) if request.method == 'POST': team_data_changed.send(team, changes=['delete'], user=g.user) return render_delete_sqla(team, db, title=_(u"Confirm delete"), message=_(u"Delete team {title}?").format(title=team.title), success=_(u"You have deleted team ‘{team}’ from organization ‘{org}’").format(team=team.title, org=org.title), next=url_for('.org_info', name=org.name))
def proposal_delete(profile, space, proposal): return render_delete_sqla(proposal, db, title=_(u"Confirm delete"), message=_(u"Do you really wish to delete your proposal ‘{title}’? " u"This will remove all votes and comments as well. This operation " u"is permanent and cannot be undone.").format(title=proposal.title), success=_("Your proposal has been deleted"), next=space.url_for(), cancel_url=proposal.url_for())
def delete(self): if self.obj == self.obj.project.primary_venue: flash(_(u"You can not delete the primary venue"), 'danger') return render_redirect(self.obj.project.url_for('venues'), code=303) return render_delete_sqla(self.obj, db, title=u"Confirm delete", message=_(u"Delete venue “{title}”? This cannot be undone".format(title=self.obj.title)), success=_(u"You have deleted venue “{title}”".format(title=self.obj.title)), next=self.obj.project.url_for('venues'))
def space_edit(space): form = ProposalSpaceForm(obj=space, model=ProposalSpace) if form.validate_on_submit(): form.populate_obj(space) db.session.commit() flash(_("Your changes have been saved"), 'info') return redirect(space.url_for(), code=303) return render_template('baseframe/autoform.html', form=form, title=_("Edit proposal space"), submit=_("Save changes"))
def validate_job_location(form, field): if QUOTES_RE.search(field.data) is not None: raise forms.ValidationError(_(u"Don’t use quotes in the location name")) caps = len(CAPS_RE.findall(field.data)) small = len(SMALL_RE.findall(field.data)) if small == 0 or caps / float(small) > 0.5: raise forms.ValidationError(_("Surely this location isn't named in uppercase?"))
def video_edit(channel, playlist, video): """ Edit video """ current_speakers = [speaker.userid for speaker in video.speakers] form = VideoEditForm(obj=video) if request.method == 'GET': html_form = render_form(form=form, title=_("Edit Video"), submit=_("Save"), cancel_url=video.url_for(), ajax=False, with_chrome=False) return {'video': dict(video.current_access()), 'form': html_form} if form.validate(): form.populate_obj(video) if not video.name: video.make_name() if video.video_url != form.video_url.data: try: process_video(video, new=False) except (DataProcessingError, ValueError) as e: return {'status': 'error', 'errors': {'video_url': [e.message]}}, 400 if video.slides_url != form.slides_url.data: try: process_slides(video) if video.video_slides_mapping: video.video_slides_mapping_json = make_presentz_json(video, json.loads(video.video_slides_mapping)) except (DataProcessingError, ValueError) as e: return {'status': 'error', 'errors': {'slides_url': [e.message]}}, 400 new_speakers = [new_speaker.userid for new_speaker in form.speakers.data] for current_speaker in current_speakers: # Remove speaker if current_speaker not in new_speakers: speaker_channel = Channel.query.filter_by(userid=current_speaker).first() if speaker_channel: speaker_playlist = speaker_channel.playlist_for_speaking_in() if speaker_playlist: speaker_playlist.videos.remove(video) for new_speaker in new_speakers: # Add speaker if new_speaker not in current_speakers: userinfo = lastuser.getuser_by_userid(new_speaker) if userinfo: speaker_channel = Channel.query.filter_by(userid=new_speaker).first() if speaker_channel is None: # Create a channel for this speaker. They have never logged in to hasgeek.tv # at this point, but when they do, the channel will be waiting for them speaker_channel = Channel(userid=userinfo['userid'], name=userinfo['name'] or userinfo['userid'], title=userinfo['title'], type=CHANNEL_TYPE.PERSON) db.session.add(speaker_channel) else: speaker_channel.title = userinfo['title'] speaker_channel.name = userinfo['name'] or userinfo['userid'] speaker_playlist = speaker_channel.playlist_for_speaking_in(create=True) if video not in speaker_playlist.videos: speaker_playlist.videos.append(video) else: return {'status': 'error', 'errors': ['Could not find a user matching that name or email address']}, 400 db.session.commit() return {'status': 'ok', 'doc': _("Edited video {title}.".format(title=video.title)), 'result': {}}, 201 return {'status': 'error', 'errors': form.errors}, 400
def venueroom_delete(space, venue, room): return render_delete_sqla( room, db, title=u"Confirm delete", message=_(u"Delete room “{title}”? This cannot be undone".format(title=room.title)), success=_(u"You have deleted room “{title}”".format(title=room.title)), next=space.url_for("venues"), )
def venue_delete(space, venue): return render_delete_sqla( venue, db, title=u"Confirm delete", message=_(u"Delete venue “{title}”? This cannot be undone".format(title=venue.title)), success=_(u"You have deleted venue “{title}”".format(title=venue.title)), next=space.url_for("venues"), )
def client_new(): form = RegisterClientForm(model=Client) form.edit_user = g.user form.client_owner.choices = available_client_owners() if request.method == 'GET': form.client_owner.data = g.user.userid if form.validate_on_submit(): client = Client() form.populate_obj(client) client.user = form.user client.org = form.org client.trusted = False db.session.add(client) db.session.commit() return render_redirect(url_for('.client_info', key=client.key), code=303) return render_form(form=form, title=_("Register a new client application"), formid='client_new', submit=_("Register application"), ajax=True)
def validate_job_pay_cash_max(form, field): if form.job_pay_type.data in (PAY_TYPE.ONETIME, PAY_TYPE.RECURRING): data = string_to_number(field.data.strip()) if data is None: raise forms.ValidationError( _("Unrecognised value %%s") % field.data) else: field.data = data else: field.data = None
def validate_job_pay_equity_min(form, field): if form.job_pay_equity.data: data = field.data.strip() if data: if not data[-1].isdigit(): data = field.data[:-1] # Remove % symbol data = data.replace(',', '').strip() # Remove thousands separator try: field.data = Decimal(data) except InvalidOperation: raise forms.ValidationError( _("Please enter a percentage between 0%% and 100%%")) else: raise forms.ValidationError( _("Unrecognised value %%s") % field.data) else: # Discard submission if equity checkbox is unchecked field.data = None
def do(self, callback_url): try: return self.twitter.authorize(callback=callback_url) except (OAuthException, BadStatusLine, SSLError, socket_error, gaierror) as e: raise LoginInitError(e) except KeyError: # As above, the lack of a Content-Type header in a 404 response breaks Flask-OAuth. Catch it. raise LoginInitError( _("Twitter had an intermittent error. Please try again") )
def report_spam(self): csrf_form = forms.Form() if request.method == 'POST': if csrf_form.validate(): report = CommentModeratorReport.submit( actor=current_auth.user, comment=self.obj ) db.session.commit() dispatch_notification( CommentReportReceivedNotification( document=self.obj, fragment=report ) ) return { 'status': 'ok', 'message': _("The comment has been reported as spam"), 'comments': self.obj.commentset.views.json_comments(), } else: flash( _("There was an issue reporting this comment. Please try again"), 'error', ) return ( { 'status': 'error', 'error_code': 'report_spam_error', 'error_description': _( "There was an issue reporting this comment. Please try again" ), 'error_details': csrf_form.errors, }, 400, ) reportspamform_html = render_form( form=csrf_form, title='Do you want to mark this comment as spam?', submit=_("Confirm"), ajax=False, with_chrome=False, ) return {'form': reportspamform_html}
def permission_user_new(client): if client.user: available_perms = Permission.query.filter(db.or_( Permission.allusers == True, Permission.user == current_auth.user)).order_by('name').all() # NOQA form = UserPermissionAssignForm() elif client.org: available_perms = Permission.query.filter(db.or_( Permission.allusers == True, Permission.org == client.org)).order_by('name').all() # NOQA form = TeamPermissionAssignForm() form.org = client.org form.team_id.choices = [(team.buid, team.title) for team in client.org.teams] else: abort(403) # This should never happen. Clients always have an owner. form.perms.choices = [(ap.name, _(u"{name} – {title}").format(name=ap.name, title=ap.title)) for ap in available_perms] if form.validate_on_submit(): perms = set() if client.user: permassign = UserClientPermissions.query.filter_by(user=form.user.data, client=client).first() if permassign: perms.update(permassign.access_permissions.split(u' ')) else: permassign = UserClientPermissions(user=form.user.data, client=client) db.session.add(permassign) else: permassign = TeamClientPermissions.query.filter_by(team=form.team, client=client).first() if permassign: perms.update(permassign.access_permissions.split(u' ')) else: permassign = TeamClientPermissions(team=form.team, client=client) db.session.add(permassign) perms.update(form.perms.data) permassign.access_permissions = u' '.join(sorted(perms)) db.session.commit() if client.user: flash(_(u"Permissions have been assigned to user {pname}").format(pname=form.user.data.pickername), 'success') else: flash(_(u"Permissions have been assigned to team ‘{pname}’").format(pname=permassign.team.pickername), 'success') return render_redirect(url_for('.client_info', key=client.key), code=303) return render_form(form=form, title=_("Assign permissions"), formid='perm_assign', submit=_("Assign permissions"))
def usergroup_edit(profile, space, kwargs): group = kwargs.get('group') form = UserGroupForm(model=UserGroup, parent=space) if group is not None: usergroup = UserGroup.query.filter_by( name=group, proposal_space=space).first_or_404() form.edit_id = usergroup.id if request.method == 'GET': form.name.data = usergroup.name form.title.data = usergroup.title form.users.data = '\r\n'.join( [u.email or u.username or '' for u in usergroup.users]) if form.validate_on_submit(): if group is None: usergroup = UserGroup(proposal_space=space) usergroup.name = form.name.data usergroup.title = form.title.data formdata = [ line.strip() for line in form.users.data.replace( '\r', '\n').replace(',', '\n').split('\n') if line ] usersdata = lastuser.getusers(names=formdata) users = [] for userdata in usersdata or []: user = User.query.filter_by(userid=userdata['userid']).first() if user is None: user = User(userid=userdata['userid'], fullname=userdata['title']) db.session.add(user) users.append(user) usergroup.users = users db.session.commit() return redirect(usergroup.url_for(), code=303) if group is None: return render_form(form=form, title=_("New user group"), submit=_("Create user group")) else: return render_form(form=form, title=_("Edit user group"), submit=_("Save changes"))
def __call__(self, form, field): # Get actor (from existing obj, or current_auth.actor) actor = None if hasattr(form, 'edit_obj'): obj = form.edit_obj if obj and hasattr(obj, '__email_for__'): actor = getattr(obj, obj.__email_for__) if not actor: actor = current_auth.actor # Call validator is_valid = EmailAddress.validate_for(actor, field.data, check_dns=True, new=self.purpose != 'use') # Interpret code if not is_valid: if actor: raise forms.validators.StopValidation( _("This email address has been claimed by someone else")) raise forms.validators.StopValidation( _("This email address is already registered. You may want to try" " logging in or resetting your password")) elif is_valid == 'invalid': raise forms.validators.StopValidation( _("This does not appear to be a valid email address.")) elif is_valid == 'nomx': raise forms.validators.StopValidation( _("The domain name of this email address is missing a DNS MX record." " We require an MX record as missing MX is a strong indicator of" " spam. Please ask your tech person to add MX to DNS.")) elif is_valid == 'not_new' and self.purpose == 'register': raise forms.validators.StopValidation( _("You or someone else has made an account with this email address" " but not confirmed it. Do you need to reset your password?") ) elif is_valid == 'not_new' and self.purpose == 'claim': raise forms.validators.StopValidation( _("You have already registered this email address")) elif is_valid == 'soft_fail': # XXX: In the absence of support for warnings in WTForms, we can only use # flash messages to communicate flash( _("This email address appears to be having temporary problems with" " receiving email. Please use another if necessary"), 'warning', ) elif is_valid == 'hard_fail': raise forms.validators.StopValidation( _("This email address is no longer valid. If you believe this to be" " in error, please email us at [email protected]"))
def comment_votedown(profile, space, proposal, comment): csrf_form = forms.Form() if not csrf_form.validate_on_submit(): abort(403) comment.votes.vote(g.user, votedown=True) db.session.commit() message = _("Your vote has been recorded") if request.is_xhr: return jsonify(message=message, code=200) flash(message, 'info') return redirect(comment.url_for(proposal=proposal), code=303)
def funnelapp_login(cookietest=False): # 1. Create a login nonce (single use, unlike CSRF) session['login_nonce'] = str(uuid.uuid4()) if not cookietest: # Reconstruct current URL with ?cookietest=1 or &cookietest=1 appended if request.query_string: return redirect(request.url + '&cookietest=1') return redirect(request.url + '?cookietest=1') if 'login_nonce' not in session: # No support for cookies. Abort login return render_message( title=_("Cookies required"), message=_("Please enable cookies in your browser."), ) # 2. Nonce has been set. Create a request code request_code = talkfunnel_serializer().dumps( {'nonce': session['login_nonce']}) # 3. Redirect user return redirect(app_url_for(app, 'login_talkfunnel', code=request_code))
def __init__(self, *args, **kwargs): super(ApplicationForm, self).__init__(*args, **kwargs) self.apply_email.choices = [] if g.user: self.apply_email.description = Markup( _( 'Add new email addresses from <a href="{}" target="_blank">your profile</a>' ).format(g.user.profile_url) ) try: self.apply_email.choices = [ (e, e) for e in lastuser.user_emails(g.user) ] except LastuserResourceException: self.apply_email.choices = [(g.user.email, g.user.email)] # If choices is [] or [(None, None)] if not self.apply_email.choices or not self.apply_email.choices[0][0]: self.apply_email.choices = [ ('', Markup(_("<em>You have not verified your email address</em>"))) ]
def labels(self): form = forms.Form() if form.validate_on_submit(): namelist = [abort_null(x) for x in request.values.getlist('name')] for idx, lname in enumerate(namelist, start=1): lbl = Label.query.filter_by(project=self.obj, name=lname).first() if lbl is not None: lbl.seq = idx db.session.commit() flash(_("Your changes have been saved"), category='success') return {'project': self.obj, 'labels': self.obj.labels, 'form': form}
def validate_job_headline(form, field): if simplify_text(field.data) in ( 'awesome coder wanted at awesome company', 'pragmatic programmer wanted at outstanding organisation', 'pragmatic programmer wanted at outstanding organization') or ( g.board and g.board.newjob_headline and simplify_text( field.data) == simplify_text(g.board.newjob_headline)): raise forms.ValidationError( _(u"Come on, write your own headline. You aren’t just another run-of-the-mill employer, right?" )) caps = len(CAPS_RE.findall(field.data)) small = len(SMALL_RE.findall(field.data)) if small == 0 or caps / float(small) > 1.0: raise forms.ValidationError( _("No shouting, please. Reduce the number of capital letters in your headline" )) for word_list, message in app.config.get('BANNED_WORDS', []): for word in word_list: if word in field.data.lower(): raise forms.ValidationError(message)
def remove_email(md5sum): useremail = UserEmail.query.filter_by(md5sum=md5sum, user=g.user).first() if not useremail: useremail = UserEmailClaim.query.filter_by(md5sum=md5sum, user=g.user).first_or_404() if isinstance(useremail, UserEmail) and useremail.primary: flash(_("You cannot remove your primary email address"), 'error') return render_redirect(url_for('.profile'), code=303) if request.method == 'POST': # FIXME: Confirm validation success user_data_changed.send(g.user, changes=['email-delete']) return render_delete_sqla( useremail, db, title=_(u"Confirm removal"), message=_(u"Remove email address {email}?").format( email=useremail.email), success=_(u"You have removed your email address {email}").format( email=useremail.email), next=url_for('.profile'))
def validate_password(self, field): if not self.username.data: # Can't validate password without a user return user = getuser(self.username.data) if user and not user.pw_hash: raise LoginPasswordResetException() if user is None or not user.password_is(field.data): if not self.username.errors: raise forms.ValidationError(_("Incorrect password")) self.user = user
def change_password(): if not current_auth.user.pw_hash: form = PasswordResetForm() form.edit_user = current_auth.user del form.username else: form = PasswordChangeForm() form.edit_user = current_auth.user if form.validate_on_submit(): current_auth.user.password = form.password.data db.session.commit() flash(_("Your new password has been saved"), category='success') return render_redirect(url_for('.account'), code=303) return render_form( form=form, title=_("Change password"), formid='changepassword', submit=_("Change password"), ajax=True, )
def edit_banner_image_url(self): form = ProfileBannerForm(obj=self.obj) if request.method == 'POST': if form.validate_on_submit(): form.populate_obj(self.obj) db.session.commit() flash(_("Your changes have been saved"), 'info') return render_redirect(self.obj.url_for(), code=303) else: return render_form(form=form, title="", submit=_("Save banner"), ajax=True) return render_form( form=form, title="", submit=_("Save banner"), ajax=True, template='img_upload_formlayout.html.jinja2', )
def rsvp_transition(self): form = RsvpTransitionForm() if form.validate_on_submit(): rsvp = Rsvp.get_for(self.obj, current_auth.user, create=True) transition = getattr(rsvp, form.transition.data) transition() db.session.commit() flash(transition.data['message'], 'success') else: flash(_("This response is not valid"), 'error') return redirect(self.obj.url_for(), code=303)
def proposal_cancelvote(profile, space, proposal): csrf_form = forms.Form() if not csrf_form.validate_on_submit(): abort(403) proposal.votes.cancelvote(g.user) db.session.commit() message = _("Your vote has been withdrawn") if request.is_xhr: return jsonify(message=message, code=200) flash(message, 'info') return redirect(proposal.url_for(), code=303)
def add_email(): form = NewEmailAddressForm() if form.validate_on_submit(): useremail = UserEmailClaim.get(user=current_auth.user, email=form.email.data) if useremail is None: useremail = UserEmailClaim(user=current_auth.user, email=form.email.data, type=form.type.data) db.session.add(useremail) db.session.commit() send_email_verify_link(useremail) flash(_("We sent you an email to confirm your address"), 'success') user_data_changed.send(current_auth.user, changes=['email-claim']) return render_redirect(url_for('.account'), code=303) return render_form(form=form, title=_("Add an email address"), formid='email_add', submit=_("Add email"), ajax=True)
def validate_company_name(self, field): if len(field.data) > 6: caps = len(CAPS_RE.findall(field.data)) # small = len(SMALL_RE.findall(field.data)) # deprecated on 30-11-2018 # if small == 0 or caps / float(small) > 0.8: # deprecated on 30-11-2018 # For now, only 6 capital letters are allowed in company name if caps > 6: raise forms.ValidationError( _("Surely your organization isn’t named in uppercase?"))
def proposal_edit(profile, space, proposal): form = ProposalForm(obj=proposal.formdata, model=Proposal, parent=space) if not proposal.session_type: del form.session_type # Remove this if we're editing a proposal that had no session type form.section.query = ProposalSpaceSection.query.filter_by(proposal_space=space, public=True).order_by('title') if len(list(form.section.query.all())) == 0: # Don't bother with sections when there aren't any del form.section if proposal.user != g.user: del form.speaking if form.validate_on_submit(): form.populate_obj(proposal.formdata) proposal.name = make_name(proposal.title) proposal.edited_at = datetime.utcnow() db.session.commit() flash(_("Your changes have been saved"), 'info') return redirect(proposal.url_for(), code=303) return render_form(form=form, title=_("Edit session proposal"), submit=_("Save changes"), message=Markup( _('This form uses <a href="http://daringfireball.net/projects/markdown/">Markdown</a> for formatting.')))
def delete(self): form = forms.Form() if form.validate_on_submit(): self.obj.delete(actor=current_auth.user) db.session.commit() flash(_("The update has been deleted"), 'success') return redirect(self.obj.project.url_for('updates')) return render_form( form=form, title=_("Confirm delete"), message=_( "Delete this draft update? This operation is permanent and cannot be" " undone.") if self.obj.state.UNPUBLISHED else _("Delete this update? This update’s number (#{number}) will be skipped" " for the next update.").format(number=self.obj.number), submit=_("Delete"), cancel_url=self.obj.url_for(), )
def new(self): form = OrganizationForm() form.name.description = current_app.config.get('ORG_NAME_REASON') form.title.description = current_app.config.get('ORG_TITLE_REASON') if form.validate_on_submit(): org = Organization() form.populate_obj(org) if current_auth.user not in org.owners.users: org.owners.users.append(current_auth.user) if current_auth.user not in org.members.users: org.members.users.append(current_auth.user) db.session.add(org) db.session.commit() org_data_changed.send(org, changes=['new'], user=current_auth.user) return render_redirect(org.url_for('view'), code=303) return render_form(form=form, title=_("New organization"), formid='org_new', submit=_("Create"), ajax=False)
def delete_vote(self): csrf_form = forms.Form() if not csrf_form.validate_on_submit(): abort(403) self.obj.voteset.cancelvote(current_auth.user) db.session.commit() message = _("Your vote has been withdrawn") if request_is_xhr(): return jsonify(message=message, code=200) flash(message, 'info') return redirect(self.obj.url_for(), code=303)
def votedown(self): csrf_form = forms.Form() if not csrf_form.validate_on_submit(): abort(403) self.obj.voteset.vote(current_auth.user, votedown=True) db.session.commit() message = _("Your vote has been recorded") if request_is_xhr(): return jsonify(message=message, code=200) flash(message, 'info') return redirect(self.obj.url_for(), code=303)
def login(): # If user is already logged in, send them back if current_auth.is_authenticated: return redirect(get_next_url(referrer=True), code=303) loginform = LoginForm() service_forms = {} for service, provider in login_registry.items(): if provider.at_login and provider.form is not None: service_forms[service] = provider.get_form() loginmethod = None if request.method == 'GET': loginmethod = request.cookies.get('login') formid = request.form.get('form.id') if request.method == 'POST' and formid == 'passwordlogin': try: if loginform.validate(): user = loginform.user login_internal(user) db.session.commit() flash(_("You are now logged in"), category='success') return set_loginmethod_cookie(render_redirect(get_next_url(session=True), code=303), 'password') except LoginPasswordResetException: flash(_(u"Your account does not have a password set. Please enter your username " "or email address to request a reset code and set a new password"), category='danger') return render_redirect(url_for('.reset', username=loginform.username.data)) elif request.method == 'POST' and formid in service_forms: form = service_forms[formid]['form'] if form.validate(): return set_loginmethod_cookie(login_registry[formid].do(form=form), formid) elif request.method == 'POST': abort(500) iframe_block = {'X-Frame-Options': 'SAMEORIGIN'} if request.is_xhr and formid == 'passwordlogin': return render_template('loginform.html.jinja2', loginform=loginform, Markup=Markup), 200, iframe_block else: return render_template('login.html.jinja2', loginform=loginform, lastused=loginmethod, service_forms=service_forms, Markup=Markup, login_registry=login_registry), 200, iframe_block
def callback(self): if 'google_callback' in session: callback_url = session.pop('google_callback') else: raise LoginCallbackError( _(u"Duplicate callback. Did you go back in your browser history?" )) if request.args.get('error'): if request.args['error'] == 'access_denied': raise LoginCallbackError( _(u"You denied the Google login request")) else: raise LoginCallbackError(_(u"Unknown failure")) code = request.args.get('code', None) try: credentials = self.flow(callback_url).step2_exchange(code) response = requests.get( self.info_url, headers={ 'Authorization': credentials.token_response['token_type'] + ' ' + credentials.access_token }).json() except Exception as e: raise LoginCallbackError( _(u"Unable to authenticate via Google. Internal details: {error}" ).format(error=e)) if response.get('error'): raise LoginCallbackError( _(u"Unable to login via Google: {error}").format( error=response['error'].get('message', u''))) return { 'email': credentials.id_token['email'], 'userid': credentials.id_token['email'], 'username': credentials.id_token['email'], 'fullname': response['name'], 'avatar_url': response['picture'], 'oauth_token': credentials.access_token, 'oauth_token_secret': None, # OAuth 2 doesn't need token secrets 'oauth_token_type': credentials.token_response['token_type'] }
def account_edit(newprofile=False): form = ProfileForm(obj=current_auth.user) form.edit_user = current_auth.user form.fullname.description = current_app.config.get('FULLNAME_REASON') form.email.description = current_app.config.get('EMAIL_REASON') form.username.description = current_app.config.get('USERNAME_REASON') form.timezone.description = current_app.config.get('TIMEZONE_REASON') if current_auth.user.email or newprofile is False: del form.email if form.validate_on_submit(): # Can't auto-populate here because user.email is read-only current_auth.user.fullname = form.fullname.data current_auth.user.username = form.username.data current_auth.user.timezone = form.timezone.data if newprofile and not current_auth.user.email: useremail = UserEmailClaim.get(user=current_auth.user, email=form.email.data) if useremail is None: useremail = UserEmailClaim(user=current_auth.user, email=form.email.data) db.session.add(useremail) send_email_verify_link(useremail) db.session.commit() user_data_changed.send(current_auth.user, changes=['profile', 'email-claim']) flash(_( "Your profile has been updated. We sent you an email to confirm your address" ), category='success') else: db.session.commit() user_data_changed.send(current_auth.user, changes=['profile']) flash(_("Your profile has been updated"), category='success') if newprofile: return render_redirect(get_next_url(), code=303) else: return render_redirect(url_for('account'), code=303) if newprofile: return render_form( form, title=_("Update profile"), formid='account_new', submit=_("Continue"), message=Markup( _(u"Hello, <strong>{fullname}</strong>. Please spare a minute to fill out your profile" ).format(fullname=escape(current_auth.user.fullname))), ajax=True) else: return render_form(form, title=_("Edit profile"), formid='account_edit', submit=_("Save changes"), ajax=True)
def permission_edit(perm): form = PermissionForm(obj=perm) form.edit_user = current_auth.user form.context.choices = available_client_owners() if request.method == 'GET': if perm.user: form.context.data = perm.user.buid else: form.context.data = perm.org.buid if form.validate_on_submit(): form.populate_obj(perm) perm.user = form.user perm.org = form.org db.session.commit() flash(_("Your permission has been saved"), 'success') return render_redirect(url_for('.permission_list'), code=303) return render_form(form=form, title=_("Edit permission"), formid='perm_edit', submit=_("Save changes"), ajax=True)