3de48052 by 胡边

login token and privilege check logic

1 parent c12e0da4
# -*- coding: utf-8 -*-
from flask import request
from server.database import db_adapter
from server.database.models import User, UserToken
from server.utils import get_now
from server.utils.api_response import unauthorized, forbidden
def token_required(func):
"""
User must login when this decorator is enabled
(for both user and admin)
"""
def authenticate_and_call(*args, **kwargs):
if not __validate_token():
return unauthorized("login required")
return func(*args, **kwargs)
# keep the original func name for API intput/output validation
# where original name is required
authenticate_and_call.original = func.__name__
if hasattr(func, "original"):
authenticate_and_call.original = func.original
return authenticate_and_call
def admin_privilege_required(func):
"""
user must login , hackathon_name must be available,
and 'user' has proper admin privilege on this hackathon
"""
def authenticate_and_call(*args, **kwargs):
user = __validate_token()
if not user:
return unauthorized("login required")
if not user.role == 'admin':
return forbidden("Permission denied need admin role")
return func(*args, **kwargs)
# keep the original func name for API intput/output
# validation where original name is required
authenticate_and_call.original = func.__name__
if hasattr(func, "original"):
authenticate_and_call.original = func.original
return authenticate_and_call
def __validate_token():
if 'token' not in request.headers:
return False
t = db_adapter.find_first_object_by(UserToken,
token=request.headers['token'])
if not t or t.expire_date <= get_now():
return False
return t.user
......@@ -6,6 +6,8 @@ from . import Base, db_adapter
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text, TypeDecorator
from sqlalchemy.orm import relation, backref
from server.utils import get_now
def relationship(*arg, **kw):
ret = relation(*arg, **kw)
......@@ -56,78 +58,32 @@ class DBBase(Base):
return '%s: %s' % (self.__class__.__name__, self.json())
class Host(DBBase):
__tablename__ = 'host'
id = Column(Integer, primary_key=True)
hostname = Column(String(50), unique=True, nullable=False)
public_ip = Column(String(50), unique=True, nullable=False)
private_ip = Column(String(50), unique=True, nullable=False)
mem = Column(String(50), nullable=False)
cores = Column(Integer, nullable=False)
disk = Column(String(50), nullable=False)
create_time = Column(DateTime, nullable=False)
update_time = Column(DateTime)
class VM(DBBase):
__tablename__ = 'vm'
class User(DBBase):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
vm_name = Column(String(50), unique=True, nullable=False)
os_type = Column(String(50), nullable=False) # constants 0:linux 1:windows
cores = Column(Integer, nullable=False)
mem = Column(String(50), nullable=False)
capacity_g = Column(Integer, nullable=False)
config = Column(String(50))
user = Column(String(50), nullable=False)
create_time = Column(DateTime, nullable=False)
update_time = Column(DateTime)
image_id = Column(Integer, ForeignKey('image.id', ondelete='CASCADE'))
image = relationship('Image', backref=backref('images_vms', lazy='dynamic'))
host_id = Column(Integer, ForeignKey('host.id', ondelete='CASCADE'))
host = relationship('Host', backref=backref('host_vms', lazy='dynamic'))
name = Column(String(64))
password = Column(String(128))
role = Column(String(16))
status = Column(String(32))
create_time = Column(DateTime, default=get_now())
last_login_time = Column(DateTime, default=get_now())
class Network(DBBase):
__tablename__ = "network"
id = Column(Integer, primary_key=True)
mac = Column(String(50), unique=True, nullable=False)
type = Column(String(50), nullable=False) # constants 0:public 1:private
address = Column(String(50), unique=True, nullable=False)
device = Column(String(50), nullable=False)
create_time = Column(DateTime, nullable=False)
update_time = Column(DateTime)
vm_id = Column(Integer, ForeignKey('vm.id', ondelete='CASCADE'))
vm = relationship('VM', backref=backref('networks', lazy='dynamic'))
def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
class Disk(DBBase):
__tablename__ = "disk"
class UserToken(DBBase):
__tablename__ = 'user_token'
id = Column(Integer, primary_key=True)
type = Column(Integer, nullable=True) # constants 0:system 1:mounted
capacity_g = Column(Integer, nullable=False)
format = Column(Integer, nullable=False) # constants 0:ntfs 1:ext4
path = Column(String(50), unique=True, nullable=False)
create_time = Column(DateTime, nullable=False)
update_time = Column(DateTime)
token = Column(String(64), unique=True, nullable=False)
vm_id = Column(Integer, ForeignKey('vm.id', ondelete='CASCADE'))
vm = relationship('VM', backref=backref('disks', lazy='dynamic'))
user_id = Column(Integer, ForeignKey('user.id', ondelete='CASCADE'))
user = relationship('User', backref=backref('tokens', lazy='dynamic'))
create_time = Column(DateTime, default=get_now())
expire_time = Column(DateTime, nullable=False)
class Image(DBBase):
__tablename__ = "image"
id = Column(Integer, primary_key=True)
name = Column(String(50), unique=True, nullable=False)
type = Column(Integer, nullable=True) # constants 0:default 1:provide 2:customize
path = Column(String(50), unique=True, nullable=False)
create_by = Column(String(50))
create_time = Column(DateTime, nullable=False)
update_time = Column(DateTime)
def __init__(self, **kwargs):
super(UserToken, self).__init__(**kwargs)
......
from log import Log
log = Log()
......
# -*- coding: utf-8 -*-
__author__ = 'hubian'
import logging
from os.path import realpath, dirname
from logging import config, DEBUG, INFO
class Log(object):
"""Wrapper of Python logging module for easier usage
......@@ -61,6 +61,9 @@ class Log(object):
self.logger.critical(critical)
def __init__(self):
"""initialize the log wrapper through 'logging.conf' file which should be in the same dir of this file"""
"""
initialize the log wrapper through 'logging.conf' file
which should be in the same dir of this file
"""
logging.config.fileConfig("%s/logging.conf" % dirname(realpath(__file__)))
self.logger = logging.getLogger("myLogger")
\ No newline at end of file
......
# -*- coding: utf-8 -*-
import uuid
from datetime import timedelta
from flask import request, g
from server.database import db_adapter
from server.database import models
from server.log import log
from server.utils import get_now
from server.utils.api_response import ok, bad_request, internal_server_error
class UserService(object):
def logout(self, user_id):
pass
def login(self, username, password):
user = db_adapter.find_first_object_by(models.User,
name=username,
password=password)
if not user:
return bad_request("login failed")
else:
user_token = self.__generate_api_token(user)
return {
"user": user.to_dict(),
"token": user_token.token()
}
# --------------- helper private functions ---------------------#
def __generate_api_token(self, user):
token_issue_date = get_now()
token_expire_date = token_issue_date + timedelta(minutes=30)
user_token = models.UserToken(token=str(uuid.uuid1()),
user=user,
expire_date=token_expire_date,
issue_date=token_issue_date)
user_token.save()
return user_token
# -*- coding: utf-8 -*-
__author__ = 'hubian'
# -*- coding: utf-8 -*-
__author__ = 'hubian'
class VMManager():
def create_vm(self):
pass
def update_vm(self):
pass
def delete_vm(self):
pass
def get_vm_list(self):
pass
# ------------------------helper functions ---------------------- #
def __generate_vm_xml(self):
pass
# -*- coding: utf-8 -*-
from factory import factory
from datetime import datetime
from server.database import db_session
from server.database.db_adapters import SQLAlchemyAdapter
from server.log.log import Log
from utils import Utils
def get_now():
return datetime.now()
def init_factory():
factory.provide("util", Utils)
factory.provide("log", Log)
factory.provide("db", SQLAlchemyAdapter, db_session)
def get_config():
return None
def get_safe_config():
return None
......
# -*- coding: utf-8 -*-
from server.log import log
# Customize Formatted Response
# with status code 200 and the real status code and message in body
def ok(data=None, message=""):
return {
"status": "success",
"code": 200,
"data": data,
"message": message
}
def __response_with_code(code, message, friendly_message=""):
log.debug("response with code: %d and message: %s" % (code, message))
return {
"status": "failed",
"code": code,
"message": message,
"friendly_message": friendly_message
}
def bad_request(message="",
friendly_message=(
'Your request does not make sense'
)):
return __response_with_code(400, message, friendly_message)
def unauthorized(message="",
friendly_message=(
'Please login to get a valid token')):
return __response_with_code(401, message, friendly_message)
def forbidden(message="",
friendly_message=(
'You don\'t have the permission to access the request')):
return __response_with_code(403, message, friendly_message)
def not_found(message="",
friendly_message=(
'The requested URL was not found on the server.')):
return __response_with_code(404, message, friendly_message)
def internal_server_error(message="",
friendly_message=(
'Encountered an internal error ,'
'unable to complete your request.'
'Either the server is overloaded or there '
'is an error in the application.'
)):
return __response_with_code(500, message, friendly_message)
# -*- coding: utf-8 -*-
from datetime import datetime
def get_now():
return datetime.now()
def get_config():
return None
def get_safe_config():
return None
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!