api/pages/org/members.py (105 lines of code) (raw):

#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ######################################################################## # OPENAPI-URI: /api/org/members ######################################################################## # get: # responses: # '200': # content: # application/json: # schema: # $ref: '#/components/schemas/OrgMembers' # description: 200 Response # default: # content: # application/json: # schema: # $ref: '#/components/schemas/Error' # description: unexpected error # security: # - cookieAuth: [] # summary: Lists the members of an organisation # post: # requestBody: # content: # application/json: # schema: # $ref: '#/components/schemas/defaultWidgetArgs' # description: Nothing... # required: true # responses: # '200': # content: # application/json: # schema: # type: array # items: # $ref: '#/components/schemas/OrgMembers' # description: 200 Response # default: # content: # application/json: # schema: # $ref: '#/components/schemas/Error' # description: unexpected error # security: # - cookieAuth: [] # summary: Lists the members of an organisation # put: # requestBody: # content: # application/json: # schema: # $ref: '#/components/schemas/UserAccountEdit' # required: true # responses: # '200': # content: # application/json: # schema: # $ref: '#/components/schemas/ActionCompleted' # description: 200 Response # default: # content: # application/json: # schema: # $ref: '#/components/schemas/Error' # description: unexpected error # security: # - cookieAuth: [] # summary: Invite a person to an organisation # delete: # requestBody: # content: # application/json: # schema: # $ref: '#/components/schemas/UserAccountEdit' # required: true # responses: # '200': # content: # application/json: # schema: # $ref: '#/components/schemas/ActionCompleted' # description: 200 Response # default: # content: # application/json: # schema: # $ref: '#/components/schemas/Error' # description: unexpected error # security: # - cookieAuth: [] # summary: Remove a person from an organisation # ######################################################################## """ This is the Org list renderer for Kibble """ import json import time import hashlib def canInvite(session): """ Determine if the user can edit sources in this org """ if session.user['userlevel'] == 'admin': return True dOrg = session.user['defaultOrganisation'] or "apache" if session.DB.ES.exists(index=session.DB.dbname, doc_type="organisation", id= dOrg): xorg = session.DB.ES.get(index=session.DB.dbname, doc_type="organisation", id= dOrg)['_source'] if session.user['email'] in xorg['admins']: return True def run(API, environ, indata, session): now = time.time() # We need to be logged in for this! if not session.user: raise API.exception(403, "You must be logged in to use this API endpoint!") method = environ['REQUEST_METHOD'] ################################################# # Inviting a new member? # ################################################# if method == "PUT": if canInvite(session): newmember = indata.get('email') isadmin = indata.get('admin', False) orgid = session.user['defaultOrganisation'] or "apache" # Make sure the org exists if not session.DB.ES.exists(index=session.DB.dbname, doc_type='organisation', id = orgid): raise API.exception(403, "No such organisation!") # make sure the user account exists if not session.DB.ES.exists(index=session.DB.dbname, doc_type='useraccount', id = newmember): raise API.exception(403, "No such user!") # Modify user account doc = session.DB.ES.get(index=session.DB.dbname, doc_type='useraccount', id = newmember) if orgid not in doc['_source']['organisations']: # No duplicates, please doc['_source']['organisations'].append(orgid) session.DB.ES.index(index=session.DB.dbname, doc_type='useraccount', id = newmember, body = doc['_source']) # Get org doc from ES doc = session.DB.ES.get(index=session.DB.dbname, doc_type='organisation', id = orgid) if isadmin: if newmember not in doc['_source']['admins']: doc['_source']['admins'].append(newmember) # Override old doc session.DB.ES.index(index=session.DB.dbname, doc_type='organisation', id = orgid, body = doc['_source']) time.sleep(1) # Bleh!! # If an admin, and not us, and reinvited, we purge the admin bit elif newmember in doc['_source']['admins']: if newmember == session.user['email']: raise API.exception(403, "You can't remove yourself from an organisation.") doc['_source']['admins'].remove(newmember) # Override old doc session.DB.ES.index(index=session.DB.dbname, doc_type='organisation', id = orgid, body = doc['_source']) time.sleep(1) # Bleh!! yield json.dumps({"okay": True, "message": "Member invited!!"}) return else: raise API.exception(403, "Only administrators or organisation owners can invite new members.") ################################################# # DELETE: Remove a member # ################################################# if method == "DELETE": if canInvite(session): memberid = indata.get('email') isadmin = indata.get('admin', False) orgid = session.user['defaultOrganisation'] or "apache" # We can't remove ourselves! if memberid == session.user['email']: raise API.exception(403, "You can't remove yourself from an organisation.") # Make sure the org exists if not session.DB.ES.exists(index=session.DB.dbname, doc_type='organisation', id = orgid): raise API.exception(403, "No such organisation!") # make sure the user account exists if not session.DB.ES.exists(index=session.DB.dbname, doc_type='useraccount', id = memberid): raise API.exception(403, "No such user!") # Modify user account doc = session.DB.ES.get(index=session.DB.dbname, doc_type='useraccount', id = memberid) if orgid in doc['_source']['organisations']: # No duplicates, please doc['_source']['organisations'].remove(orgid) session.DB.ES.index(index=session.DB.dbname, doc_type='useraccount', id = memberid, body = doc['_source']) # Check is user is admin and remove if so # Get org doc from ES doc = session.DB.ES.get(index=session.DB.dbname, doc_type='organisation', id = orgid) if memberid in doc['_source']['admins']: doc['_source']['admins'].remove(memberid) # Override old doc session.DB.ES.index(index=session.DB.dbname, doc_type='organisation', id = orgid, body = doc['_source']) time.sleep(1) # Bleh!! yield json.dumps({"okay": True, "message": "Member removed!"}) return else: raise API.exception(403, "Only administrators or organisation owners can invite new members.") ################################################# # GET/POST: Display members # ################################################# if method in ["GET", "POST"]: orgid = session.user['defaultOrganisation'] or "apache" if not session.DB.ES.exists(index=session.DB.dbname, doc_type='organisation', id = orgid): raise API.exception(403, "No such organisation!") # Only admins should be able to view this! if not canInvite(session): raise API.exception(403, "Only organisation owners can view this list.") # Find everyone affiliated with this org query = { 'query': { 'bool': { 'must': [ { 'term': { 'organisations': orgid } } ] } } } res = session.DB.ES.search( index=session.DB.dbname, doc_type="useraccount", size = 5000, # TO-DO: make this a scroll?? body = query ) members = [] for doc in res['hits']['hits']: members.append(doc['_id']) # Get org doc from ES doc = session.DB.ES.get(index=session.DB.dbname, doc_type='organisation', id = orgid) JSON_OUT = { 'members': members, 'admins': doc['_source']['admins'], 'okay': True, 'responseTime': time.time() - now } yield json.dumps(JSON_OUT)