blob: d13fde7c03cc673f9faec9bf5ea2af532d9ca3da [file]
# 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.
#
import datetime
import json
import os
import logging
import openserverless.common.response_builder as res_builder
import openserverless.couchdb.bcrypt_util as bu
from openserverless.couchdb.couchdb_util import CouchDB
from openserverless.common.kube_api_client import KubeApiClient
USER_META_DBN = "users_metadata"
class AuthService:
def __init__(self, environ=os.environ):
self._environ = environ
self.couch_db = CouchDB()
self.kube_client = KubeApiClient()
def fetch_user_data(self, login: str):
logging.info(f"searching for user {login} data")
try:
selector = {"selector": {"login": {"$eq": login}}}
response = self.couch_db.find_doc(USER_META_DBN, json.dumps(selector))
if response["docs"]:
docs = list(response["docs"])
if len(docs) > 0:
return docs[0]
logging.warning(f"OpenServerless metadata for user {login} not found!")
return None
except Exception as e:
logging.error(
f"failed to query OpenServerless metadata for user {login}. Reason: {e}"
)
return None
def env_to_dict(self, user_data, key="env"):
"""
extract env from user_data and return it as a dict
Keyword arguments:
key -- the key to extract the env from
"""
body = {}
if key in user_data:
envs = list(user_data[key])
else:
envs = []
for env in envs:
body[env['key']] = env['value']
return body
def map_data(self, user_data):
"""
Map the internal nuvolaris user_data records to the auth response
"""
resp = {}
resp["login"] = user_data["login"]
resp["email"] = user_data["email"]
if "env" in user_data:
resp["env"] = user_data["env"]
if "quota" in user_data:
resp["quota"] = user_data["quota"]
return resp
def login(self, login, password):
user_data = self.fetch_user_data(login)
if user_data:
if bu.verify_password(password, user_data["password"]):
# if(password == user_data['password']):
return res_builder.build_response_with_data(self.map_data(user_data))
else:
logging.warning(f"password mismatch for user {login}")
return res_builder.build_error_message(f"Invalid credentials", 401)
else:
logging.warning(f"no user {login} found")
return res_builder.build_error_message(f"Invalid credentials", 401)
def update_password(self, login, old_password, new_password):
user_data = self.fetch_user_data(login)
if user_data:
if bu.verify_password(old_password, user_data["password"]):
whisk_user = self.kube_client.get_whisk_user(user_data["login"])
whisk_user["spec"]["password"] = new_password
# whisk_user['spec']['password_timestamp'] = datetime.now().isoformat()
self.kube_client.update_whisk_user(whisk_user)
return res_builder.build_response_with_data(
{"status": "ok", "message": "Password updated"}
)
else:
return res_builder.build_error_message(
f"password mismatch for user {login}", 401
)
else:
return res_builder.build_error_message(f"no user {login} found", 401)