api/pages/session.py (65 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/session ######################################################################## # delete: # requestBody: # content: # application/json: # schema: # $ref: '#/components/schemas/Empty' # description: Nada # required: true # responses: # '200': # content: # application/json: # schema: # $ref: '#/components/schemas/ActionCompleted' # description: Logout successful # default: # content: # application/json: # schema: # $ref: '#/components/schemas/Error' # description: unexpected error # security: # - cookieAuth: [] # summary: Log out (remove session) # get: # responses: # '200': # content: # application/json: # schema: # $ref: '#/components/schemas/UserData' # description: 200 response # default: # content: # application/json: # schema: # $ref: '#/components/schemas/Error' # description: unexpected error # security: # - cookieAuth: [] # summary: Display your login details # put: # requestBody: # content: # application/json: # schema: # $ref: '#/components/schemas/UserCredentials' # description: User credentials # required: true # responses: # '200': # content: # application/json: # schema: # $ref: '#/components/schemas/ActionCompleted' # description: Login successful # headers: # Set-Cookie: # schema: # example: 77488a26-23c2-4e29-94a1-6a0738f6a3ff # type: string # default: # content: # application/json: # schema: # $ref: '#/components/schemas/Error' # description: unexpected error # summary: Log in # ######################################################################## """ This is the user session handler for Kibble """ import json import re import time import bcrypt import hashlib import uuid def run(API, environ, indata, session): method = environ['REQUEST_METHOD'] # Logging in? if method == "PUT": u = indata['email'] p = indata['password'] if session.DB.ES.exists(index=session.DB.dbname, doc_type='useraccount', id = u): doc = session.DB.ES.get(index=session.DB.dbname, doc_type='useraccount', id = u) hp = doc['_source']['password'] if bcrypt.hashpw(p.encode('utf-8'), hp.encode('utf-8')).decode('ascii') == hp: # If verification is enabled, make sure account is verified if session.config['accounts'].get('verify'): if doc['_source']['verified'] == False: raise API.exception(403, "Your account needs to be verified first. Check your inbox!") sessionDoc = { 'cid': u, 'id': session.cookie, 'timestamp': int(time.time()) } session.DB.ES.index(index=session.DB.dbname, doc_type='uisession', id = session.cookie, body = sessionDoc) yield json.dumps({"message": "Logged in OK!"}) return # Fall back to a 403 if username and password did not match raise API.exception(403, "Wrong username or password supplied!") # We need to be logged in for the rest of this! if not session.user: raise API.exception(403, "You must be logged in to use this API endpoint! %s") # Delete a session (log out) if method == "DELETE": session.DB.ES.delete(index=session.DB.dbname, doc_type='uisession', id = session.cookie) session.newCookie() yield json.dumps({"message": "Logged out, bye bye!"}) # Display the user data for this session if method == "GET": # Do we have an API key? If not, make one if not session.user.get('token') or indata.get('newtoken'): token = str(uuid.uuid4()) session.user['token'] = token session.DB.ES.index(index=session.DB.dbname, doc_type='useraccount', id = session.user['email'], body = session.user) # Run a quick search of all orgs we have. res = session.DB.ES.search( index=session.DB.dbname, doc_type="organisation", size = 100, body = { 'query': { 'match_all': {} } } ) orgs = [] for hit in res['hits']['hits']: doc = hit['_source'] orgs.append(doc) JSON_OUT = { 'email': session.user['email'], 'displayName': session.user['displayName'], 'defaultOrganisation': session.user['defaultOrganisation'], 'organisations': session.user['organisations'], 'ownerships': session.user['ownerships'], 'gravatar': hashlib.md5(session.user['email'].encode('utf-8')).hexdigest(), 'userlevel': session.user['userlevel'], 'token': session.user['token'] } yield json.dumps(JSON_OUT) return # Finally, if we hit a method we don't know, balk! yield API.exception(400, "I don't know this request method!!")