| #!/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. |
| |
| """ |
| This is the session library for Apache Kibble. |
| It handles setting/getting cookies and user prefs |
| """ |
| |
| |
| # Main imports |
| import re |
| import sys |
| import traceback |
| import http.cookies |
| import uuid |
| import elasticsearch |
| import time |
| |
| class KibbleSession(object): |
| |
| def getView(self, viewID): |
| if self.DB.ES.exists(index=self.DB.dbname, doc_type="view", id = viewID): |
| view = self.DB.ES.get(index=self.DB.dbname, doc_type="view", id = viewID) |
| return view['_source']['sourceList'] |
| return [] |
| |
| def subFilter(self, subfilter, view = []): |
| if len(subfilter) == 0: |
| return view |
| dOrg = self.user['defaultOrganisation'] or "apache" |
| res = self.DB.ES.search( |
| index=self.DB.dbname, |
| doc_type="source", |
| size = 10000, |
| _source_include = ['sourceURL', 'sourceID'], |
| body = { |
| 'query': { |
| 'bool': { |
| 'must': [ |
| {'term': { |
| 'organisation': dOrg |
| } |
| }] |
| } |
| |
| } |
| } |
| ) |
| sources = [] |
| for doc in res['hits']['hits']: |
| sid = doc['_source']['sourceID'] |
| m = re.search(subfilter, doc['_source']['sourceURL'], re.IGNORECASE) |
| if m and ((not view) or (sid in view)): |
| sources.append(sid) |
| if not sources: |
| sources = ['x'] # blank return to not show eeeeverything |
| return sources |
| |
| def subType(self, stype, view = []): |
| if len(stype) == 0: |
| return view |
| if type(stype) is str: |
| stype = [stype] |
| dOrg = self.user['defaultOrganisation'] or "apache" |
| res = self.DB.ES.search( |
| index=self.DB.dbname, |
| doc_type="source", |
| size = 10000, |
| _source_include = ['sourceURL', 'sourceID', 'type'], |
| body = { |
| 'query': { |
| 'bool': { |
| 'must': [ |
| {'term': { |
| 'organisation': dOrg |
| } |
| }, |
| {'terms': { |
| 'type': stype |
| } |
| } |
| ] |
| } |
| |
| } |
| } |
| ) |
| sources = [] |
| for doc in res['hits']['hits']: |
| sid = doc['_source']['sourceID'] |
| m = doc['_source']['type'] in stype |
| if m and ((not view) or (sid in view)): |
| sources.append(sid) |
| if not sources: |
| sources = ['x'] # blank return to not show eeeeverything |
| return sources |
| |
| def logout(self): |
| """Log out user and wipe cookie""" |
| if self.user and self.cookie: |
| cookies = http.cookies.SimpleCookie() |
| cookies['kibble_session'] = "null" |
| self.headers.append(('Set-Cookie', cookies['kibble_session'].OutputString())) |
| try: |
| self.DB.ES.delete(index=self.DB.dbname, doc_type='uisession', id = self.cookie) |
| self.cookie = None |
| self.user = None |
| except: |
| pass |
| |
| def newCookie(self): |
| cookie = uuid.uuid4() |
| cookies = http.cookies.SimpleCookie() |
| cookies['kibble_session'] = cookie |
| cookies['kibble_session']['expires'] = 86400 * 365 # Expire one year from now |
| cookies['kibble_session']['HttpOnly'] = True; # no js write exposure |
| # cookies['kibble_session']['secure'] = True; # more secure |
| self.headers.append(('Set-Cookie', cookies['kibble_session'].OutputString())) |
| if __debug__: |
| print("headers ", ( self.headers) ) |
| return cookie |
| |
| def __init__(self, DB, environ, config): |
| """ |
| Loads the current user session or initiates a new session if |
| none was found. |
| """ |
| self.config = config |
| self.user = None |
| self.DB = DB |
| self.headers = [('Content-Type', 'application/json; charset=utf-8')] |
| self.cookie = None |
| |
| # Construct the URL we're visiting |
| self.url = "%s://%s" % (environ['wsgi.url_scheme'], environ.get('HTTP_HOST', environ.get('SERVER_NAME'))) |
| self.url += environ.get('SCRIPT_NAME', '/') |
| |
| # Get Kibble cookie |
| cookie = None |
| cookies = None |
| if 'HTTP_KIBBLE_TOKEN' in environ: |
| token = environ.get('HTTP_KIBBLE_TOKEN') |
| if re.match(r"^[-a-f0-9]+$", token): # Validate token, must follow UUID4 specs |
| res = self.DB.ES.search(index=self.DB.dbname, doc_type='useraccount', body = {"query": { "match": { "token": token}}}) |
| if res['hits']['hits']: |
| self.user = res['hits']['hits'][0]['_source'] |
| self.newCookie() |
| else: |
| if 'HTTP_COOKIE' in environ: |
| cookies = http.cookies.SimpleCookie(environ['HTTP_COOKIE']) |
| if cookies and 'kibble_session' in cookies: |
| cookie = cookies['kibble_session'].value |
| try: |
| if re.match(r"^[-a-f0-9]+$", cookie): # Validate cookie, must follow UUID4 specs |
| doc = None |
| sdoc = self.DB.ES.get(index=self.DB.dbname, doc_type='uisession', id = cookie) |
| if sdoc and 'cid' in sdoc['_source']: |
| doc = self.DB.ES.get(index=self.DB.dbname, doc_type='useraccount', id = sdoc['_source']['cid']) |
| if doc and '_source' in doc: |
| # Make sure this cookie has been used in the past 7 days, else nullify it. |
| # Further more, run an update of the session if >1 hour ago since last update. |
| age = time.time() - sdoc['_source']['timestamp'] |
| if age > (7*86400): |
| self.DB.ES.delete(index=self.DB.dbname, doc_type='uisession', id = cookie) |
| sdoc['_source'] = None # Wipe it! |
| doc = None |
| elif age > 3600: |
| sdoc['_source']['timestamp'] = int(time.time()) # Update timestamp in session DB |
| self.DB.ES.update(index=self.DB.dbname, doc_type='uisession', id = cookie, body = {'doc':sdoc['_source']}) |
| if doc: |
| self.user = doc['_source'] |
| else: |
| cookie = None |
| except Exception as err: |
| print(err) |
| if not cookie: |
| cookie = self.newCookie() |
| self.cookie = cookie |
| if __debug__: |
| print("cookie found/set ", (cookie) ) |
| |