Sybren A. Stüvel 47474ac936 Replaced Gravatar with self-hosted avatars
Avatars are now obtained from Blender ID. They are downloaded from
Blender ID and stored in the users' home project storage.

Avatars can be synced via Celery and triggered from a webhook.

The avatar can be obtained from the current user object in Python, or
via pillar.api.users.avatar.url(user_dict).

Avatars can be shown in the web frontend by:

- an explicit image (like before but with a non-Gravatar URL)
- a Vue.js component `user-avatar`
- a Vue.js component `current-user-avatar`

The latter is the most efficient for the current user, as it uses user
info that's already injected into the webpage (so requires no extra
queries).
2019-05-31 16:49:24 +02:00

94 lines
3.1 KiB
Python

import logging
from flask import Blueprint, render_template, request, url_for
import flask_wtf.csrf
from flask_login import current_user
import pillar.flask_extra
from pillar import current_app
import pillar.api.users.avatar
from pillar.api.utils import authorization, str2id, jsonify
from pillar.web.system_util import pillar_api
from pillarsdk import Organization, User
log = logging.getLogger(__name__)
blueprint = Blueprint('pillar.web.organizations', __name__, url_prefix='/organizations')
@blueprint.route('/', endpoint='index')
def index(organization_id: str = None):
api = pillar_api()
organizations = Organization.all(api=api)
if not organization_id and organizations['_items']:
organization_id = organizations['_items'][0]._id
can_create_organization = current_user.has_cap('create-organization')
return render_template('organizations/index.html',
can_create_organization=can_create_organization,
organizations=organizations,
open_organization_id=organization_id)
@blueprint.route('/<organization_id>')
@pillar.flask_extra.vary_xhr()
def view_embed(organization_id: str):
if not request.is_xhr:
return index(organization_id)
api = pillar_api()
organization: Organization = Organization.find(organization_id, api=api)
om = current_app.org_manager
organization_oid = str2id(organization_id)
members = om.org_members(organization.members)
for member in members:
member['avatar'] = pillar.api.users.avatar.url(member)
member['_id'] = str(member['_id'])
admin_user = User.find(organization.admin_uid, api=api)
# Make sure it's never None
organization.unknown_members = organization.unknown_members or []
organization.human_ip_ranges = [ipr['human'] for ipr in (organization.ip_ranges or [])]
can_super_edit = current_user.has_cap('admin')
can_edit = can_super_edit or om.user_is_admin(organization_oid)
csrf = flask_wtf.csrf.generate_csrf()
return render_template('organizations/view_embed.html',
organization=organization,
admin_user=admin_user,
members=members,
can_edit=can_edit,
can_super_edit=can_super_edit,
seats_used=len(members) + len(organization.unknown_members),
csrf=csrf)
@blueprint.route('/create-new', methods=['POST'])
@authorization.require_login(require_cap='create-organization')
def create_new():
"""Creates a new Organization, owned by the currently logged-in user."""
user_id = current_user.user_id
log.info('Creating new organization for user %s', user_id)
name = request.form['name']
seat_count = int(request.form['seat_count'], 10)
org_doc = current_app.org_manager.create_new_org(name, user_id, seat_count)
org_id = str(org_doc['_id'])
url = url_for('.view_embed', organization_id=org_id)
resp = jsonify({'_id': org_id, 'location': url})
resp.headers['Location'] = url
return resp, 201