Commit 69777235 authored by Daniele Venzano's avatar Daniele Venzano

Start implementing REST API for users

parent 5bc41fe3
......@@ -194,6 +194,22 @@ class APIEndpoint:
return services_info, endpoints
def user_by_name(self, username):
def user_by_name(self, username) -> zoe_lib.state.User:
"""Finds a user in the database looking it up by its username."""
return self.sql.user.select(only_one=True, **{'username': username})
def user_by_id(self, user: zoe_lib.state.User, user_id: int) -> zoe_lib.state.User:
"""Finds a user in the database looking it up by its username."""
if user.id == user_id:
return user
if not user.role.can_operate_others:
raise zoe_api.exceptions.ZoeAuthException()
return self.sql.user.select(only_one=True, id=user_id)
def user_delete(self, user: zoe_lib.state.User, user_id: int):
"""Deletes the user identified by the ID."""
if not user.role.can_change_config:
raise zoe_api.exceptions.ZoeAuthException()
self.sql.user.delete(user_id)
......@@ -30,7 +30,12 @@ class ZoeException(Exception):
class ZoeAuthException(ZoeException):
"""An authentication error."""
pass
def __init__(self, message=None):
super().__init__()
if message is None:
self.message = 'Unauthorized'
else:
self.message = message
class ZoeNotFoundException(ZoeException):
......
......@@ -21,7 +21,7 @@ import tornado.web
from zoe_api.rest_api.execution import ExecutionAPI, ExecutionCollectionAPI, ExecutionDeleteAPI, ExecutionEndpointsAPI
from zoe_api.rest_api.info import InfoAPI
from zoe_api.rest_api.userinfo import UserInfoAPI
from zoe_api.rest_api.userinfo import UserAPI, UserCollectionAPI
from zoe_api.rest_api.service import ServiceAPI, ServiceLogsAPI
from zoe_api.rest_api.discovery import DiscoveryAPI
from zoe_api.rest_api.statistics import SchedulerStatsAPI
......@@ -42,9 +42,11 @@ def api_init(api_endpoint) -> List[tornado.web.URLSpec]:
api_routes = [
tornado.web.url(API_PATH + r'/info', InfoAPI, route_args),
tornado.web.url(API_PATH + r'/login', LoginAPI, route_args),
tornado.web.url(API_PATH + r'/userinfo', UserInfoAPI, route_args),
tornado.web.url(API_PATH + r'/zapp_validate', ZAppValidateAPI, route_args),
tornado.web.url(API_PATH + r'/user/([0-9]+)', UserAPI, route_args),
tornado.web.url(API_PATH + r'/user', UserCollectionAPI, route_args),
tornado.web.url(API_PATH + r'/execution/([0-9]+)', ExecutionAPI, route_args),
tornado.web.url(API_PATH + r'/execution/delete/([0-9]+)', ExecutionDeleteAPI, route_args),
tornado.web.url(API_PATH + r'/execution/endpoints/([0-9]+)', ExecutionEndpointsAPI, route_args),
......
# Copyright (c) 2016, Quang-Nhat Hoang-Xuan
# Copyright (c) 2018, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -13,21 +13,58 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""The User Info API endpoint."""
"""The User API endpoints."""
from zoe_api.rest_api.request_handler import ZoeAPIRequestHandler
from zoe_api.exceptions import ZoeAuthException
class UserInfoAPI(ZoeAPIRequestHandler):
"""The UserInfo API endpoint."""
class UserAPI(ZoeAPIRequestHandler):
"""The User API endpoint. Ops on a single user."""
def get(self):
def get(self, user_id):
"""HTTP GET method."""
if self.current_user is None:
return
ret = {
'user': self.current_user
}
if user_id == self.current_user.id:
ret = {
'user': self.current_user.serialize()
}
else:
user = self.api_endpoint.user_by_id(self.current_user, user_id)
ret = {
'user': user.serialize()
}
self.write(ret)
def post(self, user_id):
"""HTTP POST method."""
if self.current_user is None:
return
def delete(self, user_id: int):
"""HTTP DELETE method."""
if self.current_user is None:
return
try:
self.api_endpoint.user_delete(self.current_user, user_id)
except ZoeAuthException as e:
self.set_status(401, e.message)
self.set_status(204)
class UserCollectionAPI(ZoeAPIRequestHandler):
"""The UserCollection API. Ops that interact with the User collection."""
def get(self):
"""HTTP GET method"""
if self.current_user is None:
return
def post(self):
"""HTTP POST method."""
if self.current_user is None:
return
......@@ -106,20 +106,6 @@ class QuotaTable(BaseTable):
else:
return [Quota(x, self.sql_manager) for x in self.cursor]
def update(self, record_id, **kwargs):
"""Update the state of an existing quota."""
arg_list = []
value_list = []
for key, value in kwargs.items():
arg_list.append('{} = %s'.format(key))
value_list.append(value)
set_q = ", ".join(arg_list)
value_list.append(record_id)
q_base = 'UPDATE quota SET ' + set_q + ' WHERE id=%s'
query = self.cursor.mogrify(q_base, value_list)
self.cursor.execute(query)
self.sql_manager.commit()
def insert(self, name, concurrent_executions, memory, cores):
"""Adds a new quota to the state."""
query = self.cursor.mogrify('INSERT INTO quota (id, name, concurrent_executions, memory, cores) VALUES (DEFAULT, %s, %s, %s, %s) RETURNING id', (name, concurrent_executions, memory, cores))
......
......@@ -102,20 +102,6 @@ class RoleTable(BaseTable):
else:
return [Role(x, self.sql_manager) for x in self.cursor]
def update(self, record_id, **kwargs):
"""Update the state of an existing role."""
arg_list = []
value_list = []
for key, value in kwargs.items():
arg_list.append('{} = %s'.format(key))
value_list.append(value)
set_q = ", ".join(arg_list)
value_list.append(record_id)
q_base = 'UPDATE role SET ' + set_q + ' WHERE id=%s'
query = self.cursor.mogrify(q_base, value_list)
self.cursor.execute(query)
self.sql_manager.commit()
def insert(self, name):
"""Adds a new role to the state."""
query = self.cursor.mogrify('INSERT INTO role (id, name) VALUES (DEFAULT, %s) RETURNING id', (name,))
......
......@@ -138,23 +138,17 @@ class UserTable(BaseTable):
else:
return [User(x, self.sql_manager) for x in self.cursor]
def update(self, port_id, **kwargs):
"""Update the state of an user port."""
arg_list = []
value_list = []
for key, value in kwargs.items():
arg_list.append('{} = %s'.format(key))
value_list.append(value)
set_q = ", ".join(arg_list)
value_list.append(port_id)
q_base = 'UPDATE "user" SET ' + set_q + ' WHERE id=%s'
query = self.cursor.mogrify(q_base, value_list)
self.cursor.execute(query)
self.sql_manager.commit()
def insert(self, username, fs_uid, role, auth_source):
"""Adds a new user to the state."""
query = self.cursor.mogrify('INSERT INTO "user" (id, username, fs_uid, email, priority, enabled, auth_source, role_id, quota_id) VALUES (DEFAULT, %s, %s, NULL, DEFAULT, DEFAULT, %s, (SELECT id FROM role WHERE name=%s), (SELECT id FROM quota WHERE name=\'default\')) RETURNING id', (username, fs_uid, auth_source, role))
self.cursor.execute(query)
self.sql_manager.commit()
return self.cursor.fetchone()[0]
def delete(self, user_id):
"""Delete a user from the state."""
query = 'DELETE FROM execution WHERE user_id=%s'
self.cursor.execute(query, (user_id,))
query = 'DELETE FROM "user" WHERE id = %s'
self.cursor.execute(query, (user_id,))
self.sql_manager.commit()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment