blob: d3f4bdedfb1bfc338d42e3a3457566e7c5d8d34b [file] [log] [blame]
#!/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 Warble
"""
import json
import re
import time
import bcrypt
import hashlib
def run(API, environ, indata, session):
method = environ['REQUEST_METHOD']
# Logging in?
if method == "PUT":
u = indata['username']
p = indata['password']
if session.DB.dbtype == 'sqlite':
session_conn = session.DB.sqlite.open('sessions.db')
account_conn = session.DB.sqlite.open('accounts.db')
sc = session_conn.cursor()
ac = account_conn.cursor()
ac.execute("SELECT * FROM `accounts` WHERE `userid` = ? LIMIT 1", (u,))
sdoc = ac.fetchone()
if sdoc:
mypass = sdoc['password']
theirpass = bcrypt.hashpw(p.encode('utf-8'), mypass.encode('utf-8')).decode('ascii')
if mypass == theirpass:
sc.execute("INSERT INTO `sessions` (`userid`, `cookie`, `timestamp`) VALUES (?, ?, ?)",
(u, session.cookie, int(time.time())))
session_conn.commit()
session_conn.close()
account_conn.close()
yield json.dumps({"message": "Logged in OK!"}, indent = 2)
return
# Fall back to a 403 if username and password did not match
raise API.exception(403, "Wrong username or password supplied!")
elif session.DB.dbtype == 'elasticsearch':
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!")
# Delete a session (log out)
if method == "DELETE":
if session.DB.dbtype == 'sqlite':
c = self.DB.sqlite.open('sessions.db')
cur = c.cursor()
cur.execute("DELETE FROM `sessions` WHERE `cookie` = ? LIMIT 1", (session.cookie,))
c.commit()
c.close()
elif session.DB.dbtype == 'elasticsearch':
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":
JSON_OUT = {
'userid': session.user['userid'],
'userlevel': session.user['userlevel']
}
yield json.dumps(JSON_OUT, indent = 2)
return
# Finally, if we hit a method we don't know, balk!
yield API.exception(400, "I don't know this request method!!")