def process_login(): """ Log the user in, checking their credentials and configuring the session, and redirect them to the home page. """ password = post_param('password', template='users_login_form.tpl') email = post_param('email', template='users_login_form.tpl') user = log_in_user(email, password) if not user: abort(403, 'Login failed') return redirect(url_for('index', _external=True))
def save_contact_groups(contact_id, _user): """ Change which SubscriptionGroups a contact is in by parsing a string of keywords (like tag processing). Any new terms will create new groups; any now-empty groups will be deleted. """ contact = Contact.get(contact_id) if not contact: abort(404, 'No such contact', force_status=True) sub = _user.contact.subscribed_to(contact) if not sub: abort(400, 'Not subscribed') groups = post_param( 'groups', template='roster_edit_group.tpl', optional=True) or '' new_groups = dict( (g.name, g) for g in SubscriptionGroup.parse_line(groups, create=True, user=_user)) old_groups = dict((g.name, g) for g in sub.groups) for group_name, group in old_groups.items(): if group_name not in new_groups: other_members = [ s for s in group.subscriptions if s.to_id != contact.id ] if not other_members: db.session.delete(group) sub.groups = list(new_groups.values()) db.session.add(sub) db.session.commit() return redirect(url_for('.view', _external=True))
def rename_group(group_id, _user): """ Change the name of an existing group. """ group = SubscriptionGroup.get(group_id) if not (group) or group.user_id != _user.id: abort(404, 'No such group') group.name = post_param('name') if group.name_is_valid(group.name): db.session.add(group) db.session.commit() return redirect(url_for('.view', _external=True))
def rename_group(group_id, _user): """ Change the name of an existing group. """ group = SubscriptionGroup.get(group_id) if not(group) or group.user_id != _user.id: abort(404, 'No such group') group.name = post_param('name') if group.name_is_valid(group.name): db.session.add(group) db.session.commit() return redirect(url_for('.view', _external=True))
def create(): """ Create a new User (sign-up). """ if not _can_create_account(): abort(403, 'Disabled by site administrator') user = logged_in_user() if user: data = {} add_logged_in_user_to_data(data, user) abort(400, 'Already logged in', data) name = post_param('name', template='users_create_form.tpl') password = post_param('password', template='users_create_form.tpl') email = post_param('email', template='users_create_form.tpl') my_user = models.User() my_user.email = email my_user.contact.realname = name my_user.generate_keypair(password) db.session.commit() send_template(my_user.email, 'user_activate_email.tpl', { 'link': url_for( '.activate', user_id=my_user.id, key_hash=_hash_for_pk(my_user), _external=True ) }) data = {} add_logged_in_user_to_data(data, None) return render_response('users_created.tpl', data)
def create(): """ Create a new User (sign-up). """ if not current_app.config.get('ALLOW_CREATION', False): abort(403, 'Disabled by site administrator') user = logged_in_user() if user: data = {} add_logged_in_user_to_data(data, user) abort(400, 'Already logged in', data) name = post_param('name', template='users_create_form.tpl') password = post_param('password', template='users_create_form.tpl') email = post_param('email', template='users_create_form.tpl') my_user = models.User() my_user.email = email my_user.contact.realname = name my_user.generate_keypair(password) db.session.commit() send_template(my_user.email, 'user_activate_email.tpl', { 'link': url_for( '.activate', user_id=my_user.id, key_hash=_hash_for_pk(my_user), _external=True ) }) data = {} add_logged_in_user_to_data(data, None) return render_response('users_created.tpl', data)
def save_contact_groups(contact_id, _user): """ Change which SubscriptionGroups a contact is in by parsing a string of keywords (like tag processing). Any new terms will create new groups; any now-empty groups will be deleted. """ contact = Contact.get(contact_id) if not contact: abort(404, 'No such contact', force_status=True) sub = _user.contact.subscribed_to(contact) if not sub: abort(400, 'Not subscribed') groups = post_param( 'groups', template='roster_edit_group.tpl', optional=True ) or '' new_groups = dict( (g.name, g) for g in SubscriptionGroup.parse_line(groups, create=True, user=_user) ) old_groups = dict((g.name, g) for g in sub.groups) for group_name, group in old_groups.items(): if group_name not in new_groups: other_members = [ s for s in group.subscriptions if s.to_id != contact.id ] if not other_members: db.session.delete(group) sub.groups = list(new_groups.values()) db.session.add(sub) db.session.commit() return redirect(url_for('.view', _external=True))
def edit(_user): """ Apply the changes from the user edit form. This updates such varied things as the profile photo and bio, the email address, name, password and interests. """ from pyaspora.post.models import Post p = Post(author=_user.contact) changed = [] order = 0 notif_freq = post_param( 'notification_frequency_hours', template='users_edit.tpl', optional=True ) _user.notification_hours = int(notif_freq) if notif_freq else None email = post_param('email', optional=True) if email and email != _user.email: _user.email = email old_pw = post_param('current_password', optional=True) new_pw1 = post_param('new_password', optional=True) new_pw2 = post_param('new_password2', optional=True) if old_pw and new_pw1 and new_pw2: if new_pw1 != new_pw2: abort(400, 'New passwords do not match') try: _user.change_password(old_pw, new_pw1) except ValueError: abort(400, 'Old password is incorrect') db.session.add(_user) attachment = request.files.get('avatar', None) if attachment and attachment.filename: changed.append('avatar') order += 1 check_attachment_is_safe(attachment) if not renderer_exists(attachment.mimetype) or \ not attachment.mimetype.startswith('image/'): abort(400, 'Avatar format unsupported') attachment_part = MimePart( type=attachment.mimetype, body=attachment.stream.read(), text_preview=attachment.filename ) p.add_part(attachment_part, order=order, inline=True) _user.contact.avatar = attachment_part name = post_param('name', template='users_edit.tpl', optional=True) if name and name != _user.contact.realname: _user.contact.realname = name changed.append('name') bio = post_param('bio', template='users_edit.tpl', optional=True) if bio: bio = bio.encode('utf-8') else: bio = b'' if bio and (not _user.contact.bio or _user.contact.bio.body != bio): changed.append('bio') order += 1 bio_part = MimePart(body=bio, type='text/plain', text_preview=None) p.add_part( order=order, inline=True, mime_part=bio_part ) _user.contact.bio = bio_part tags = post_param('tags', optional=True) if tags is not None: tag_objects = Tag.parse_line(tags, create=True) old_tags = set([t.id for t in _user.contact.interests]) new_tags = set([t.id for t in tag_objects]) if old_tags != new_tags: changed.append('tags') _user.contact.interests = tag_objects p.add_part( order=0, inline=True, mime_part=MimePart( body=json_dumps({ 'fields_changed': changed }).encode('utf-8'), type='application/x-pyaspora-profile-update', text_preview='updated their profile' ) ) if changed: db.session.add(p) db.session.add(_user.contact) p.share_with([_user.contact]) p.thread_modified() db.session.commit() return redirect(url_for('contacts.profile', contact_id=_user.contact.id))
def create(_user): """ Create a new Post and Share it with the selected Contacts. """ body = post_param('body') relationship = { 'type': post_param('relationship_type', optional=True), 'id': post_param('relationship_id', optional=True), } target = { 'type': post_param('target_type'), 'id': post_param('target_id', optional=True), } assert (target['type'] in targets_by_name) # Loathe inflexible HTML forms if target['id'] is None: target['id'] = post_param('target_%s_id' % target['type'], optional=True) if relationship['type']: post = Post.get(relationship['id']) if not post: abort(404, 'No such post', force_status=True) if not post.has_permission_to_view(_user.contact): abort(403, 'Forbidden') relationship['post'] = post shared = None post = Post(author=_user.contact) body_part = MimePart(type='text/x-markdown', body=body.encode('utf-8'), text_preview=None) topics = post_param('tags', optional=True) if topics: post.tags = Tag.parse_line(topics, create=True) if relationship['type'] == 'comment': post.parent = relationship['post'] post.add_part(body_part, order=0, inline=True) elif relationship['type'] == 'share': shared = relationship['post'] share_part = MimePart(type='application/x-pyaspora-share', body=dumps({ 'post': { 'id': shared.id }, 'author': { 'id': shared.author_id, 'name': shared.author.realname, } }).encode('utf-8'), text_preview=u"shared {0}'s post".format( shared.author.realname)) post.add_part(share_part, order=0, inline=True) post.add_part(body_part, order=1, inline=True) order = 1 for part in shared.parts: if part.mime_part.type != 'application/x-pyaspora-share': order += 1 post.add_part(part.mime_part, inline=part.inline, order=order) if not post.tags: post.tags = shared.tags else: # Naked post post.add_part(body_part, order=0, inline=True) attachment = request.files.get('attachment', None) if attachment and attachment.filename: check_attachment_is_safe(attachment) attachment_part = MimePart(type=attachment.mimetype, body=attachment.stream.read(), text_preview=attachment.filename) post.add_part(attachment_part, order=1, inline=bool(renderer_exists(attachment.mimetype))) post.thread_modified() # Sigh, need an ID for the post for making shares db.session.add(post) db.session.commit() targets_by_name[target['type']].make_shares(post, target['id'], reshare_of=shared) db.session.commit() data = json_post(post) return redirect(url_for('feed.view', _external=True), data_structure=data)
def create(_user): """ Create a new Post and Share it with the selected Contacts. """ body = post_param('body') relationship = { 'type': post_param('relationship_type', optional=True), 'id': post_param('relationship_id', optional=True), } target = { 'type': post_param('target_type'), 'id': post_param('target_id', optional=True), } assert(target['type'] in targets_by_name) # Loathe inflexible HTML forms if target['id'] is None: target['id'] = post_param( 'target_%s_id' % target['type'], optional=True) if relationship['type']: post = Post.get(relationship['id']) if not post: abort(404, 'No such post', force_status=True) if not post.has_permission_to_view(_user.contact): abort(403, 'Forbidden') relationship['post'] = post post = Post(author=_user.contact) body_part = MimePart(type='text/x-markdown', body=body.encode('utf-8'), text_preview=None) topics = post_param('tags', optional=True) if topics: post.tags = Tag.parse_line(topics, create=True) if relationship['type'] == 'comment': post.parent = relationship['post'] post.add_part(body_part, order=0, inline=True) elif relationship['type'] == 'share': shared = relationship['post'] share_part = MimePart( type='application/x-pyaspora-share', body=dumps({ 'post': {'id': shared.id}, 'author': { 'id': shared.author_id, 'name': shared.author.realname, } }).encode('utf-8'), text_preview="shared {0}'s post".format(shared.author.realname) ) post.add_part(share_part, order=0, inline=True) post.add_part(body_part, order=1, inline=True) order = 1 for part in shared.parts: if part.mime_part.type != 'application/x-pyaspora-share': order += 1 post.add_part(part.mime_part, inline=part.inline, order=order) if not post.tags: post.tags = shared.tags else: # Naked post post.add_part(body_part, order=0, inline=True) attachment = request.files.get('attachment', None) if attachment and attachment.filename: check_attachment_is_safe(attachment) attachment_part = MimePart( type=attachment.mimetype, body=attachment.stream.read(), text_preview=attachment.filename ) post.add_part(attachment_part, order=1, inline=bool(renderer_exists(attachment.mimetype))) post.thread_modified() # Sigh, need an ID for the post for making shares db.session.add(post) db.session.commit() targets_by_name[target['type']].make_shares(post, target['id']) db.session.commit() data = json_post(post) return redirect(url_for('feed.view', _external=True), data_structure=data)