3de48052 by 胡边

login token and privilege check logic

1 parent c12e0da4
1 # -*- coding: utf-8 -*-
2
3
4 from flask import request
5
6 from server.database import db_adapter
7 from server.database.models import User, UserToken
8 from server.utils import get_now
9 from server.utils.api_response import unauthorized, forbidden
10
11
12 def token_required(func):
13 """
14 User must login when this decorator is enabled
15 (for both user and admin)
16 """
17 def authenticate_and_call(*args, **kwargs):
18 if not __validate_token():
19 return unauthorized("login required")
20 return func(*args, **kwargs)
21
22 # keep the original func name for API intput/output validation
23 # where original name is required
24 authenticate_and_call.original = func.__name__
25 if hasattr(func, "original"):
26 authenticate_and_call.original = func.original
27
28 return authenticate_and_call
29
30
31 def admin_privilege_required(func):
32 """
33 user must login , hackathon_name must be available,
34 and 'user' has proper admin privilege on this hackathon
35 """
36
37 def authenticate_and_call(*args, **kwargs):
38 user = __validate_token()
39 if not user:
40 return unauthorized("login required")
41
42 if not user.role == 'admin':
43 return forbidden("Permission denied need admin role")
44
45 return func(*args, **kwargs)
46
47 # keep the original func name for API intput/output
48 # validation where original name is required
49 authenticate_and_call.original = func.__name__
50 if hasattr(func, "original"):
51 authenticate_and_call.original = func.original
52
53 return authenticate_and_call
54
55
56 def __validate_token():
57 if 'token' not in request.headers:
58 return False
59
60 t = db_adapter.find_first_object_by(UserToken,
61 token=request.headers['token'])
62 if not t or t.expire_date <= get_now():
63 return False
64
65 return t.user
...@@ -19,4 +19,4 @@ Base = declarative_base() ...@@ -19,4 +19,4 @@ Base = declarative_base()
19 Base.query = db_session.query_property() 19 Base.query = db_session.query_property()
20 db_adapter = SQLAlchemyAdapter(db_session) 20 db_adapter = SQLAlchemyAdapter(db_session)
21 21
22 from models import *
...\ No newline at end of file ...\ No newline at end of file
22 from models import *
......
...@@ -6,6 +6,8 @@ from . import Base, db_adapter ...@@ -6,6 +6,8 @@ from . import Base, db_adapter
6 from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text, TypeDecorator 6 from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text, TypeDecorator
7 from sqlalchemy.orm import relation, backref 7 from sqlalchemy.orm import relation, backref
8 8
9 from server.utils import get_now
10
9 11
10 def relationship(*arg, **kw): 12 def relationship(*arg, **kw):
11 ret = relation(*arg, **kw) 13 ret = relation(*arg, **kw)
...@@ -56,78 +58,32 @@ class DBBase(Base): ...@@ -56,78 +58,32 @@ class DBBase(Base):
56 return '%s: %s' % (self.__class__.__name__, self.json()) 58 return '%s: %s' % (self.__class__.__name__, self.json())
57 59
58 60
59 class Host(DBBase): 61 class User(DBBase):
60 __tablename__ = 'host' 62 __tablename__ = 'user'
61
62 id = Column(Integer, primary_key=True)
63 hostname = Column(String(50), unique=True, nullable=False)
64 public_ip = Column(String(50), unique=True, nullable=False)
65 private_ip = Column(String(50), unique=True, nullable=False)
66 mem = Column(String(50), nullable=False)
67 cores = Column(Integer, nullable=False)
68 disk = Column(String(50), nullable=False)
69 create_time = Column(DateTime, nullable=False)
70 update_time = Column(DateTime)
71
72
73 class VM(DBBase):
74 __tablename__ = 'vm'
75 63
76 id = Column(Integer, primary_key=True) 64 id = Column(Integer, primary_key=True)
77 vm_name = Column(String(50), unique=True, nullable=False) 65 name = Column(String(64))
78 os_type = Column(String(50), nullable=False) # constants 0:linux 1:windows 66 password = Column(String(128))
79 cores = Column(Integer, nullable=False) 67 role = Column(String(16))
80 mem = Column(String(50), nullable=False) 68 status = Column(String(32))
81 capacity_g = Column(Integer, nullable=False) 69 create_time = Column(DateTime, default=get_now())
82 config = Column(String(50)) 70 last_login_time = Column(DateTime, default=get_now())
83 user = Column(String(50), nullable=False)
84 create_time = Column(DateTime, nullable=False)
85 update_time = Column(DateTime)
86
87 image_id = Column(Integer, ForeignKey('image.id', ondelete='CASCADE'))
88 image = relationship('Image', backref=backref('images_vms', lazy='dynamic'))
89
90 host_id = Column(Integer, ForeignKey('host.id', ondelete='CASCADE'))
91 host = relationship('Host', backref=backref('host_vms', lazy='dynamic'))
92
93 71
94 class Network(DBBase): 72 def __init__(self, **kwargs):
95 __tablename__ = "network" 73 super(User, self).__init__(**kwargs)
96
97 id = Column(Integer, primary_key=True)
98 mac = Column(String(50), unique=True, nullable=False)
99 type = Column(String(50), nullable=False) # constants 0:public 1:private
100 address = Column(String(50), unique=True, nullable=False)
101 device = Column(String(50), nullable=False)
102 create_time = Column(DateTime, nullable=False)
103 update_time = Column(DateTime)
104
105 vm_id = Column(Integer, ForeignKey('vm.id', ondelete='CASCADE'))
106 vm = relationship('VM', backref=backref('networks', lazy='dynamic'))
107 74
108 75
109 class Disk(DBBase): 76 class UserToken(DBBase):
110 __tablename__ = "disk" 77 __tablename__ = 'user_token'
111 78
112 id = Column(Integer, primary_key=True) 79 id = Column(Integer, primary_key=True)
113 type = Column(Integer, nullable=True) # constants 0:system 1:mounted 80 token = Column(String(64), unique=True, nullable=False)
114 capacity_g = Column(Integer, nullable=False)
115 format = Column(Integer, nullable=False) # constants 0:ntfs 1:ext4
116 path = Column(String(50), unique=True, nullable=False)
117 create_time = Column(DateTime, nullable=False)
118 update_time = Column(DateTime)
119 81
120 vm_id = Column(Integer, ForeignKey('vm.id', ondelete='CASCADE')) 82 user_id = Column(Integer, ForeignKey('user.id', ondelete='CASCADE'))
121 vm = relationship('VM', backref=backref('disks', lazy='dynamic')) 83 user = relationship('User', backref=backref('tokens', lazy='dynamic'))
122 84
85 create_time = Column(DateTime, default=get_now())
86 expire_time = Column(DateTime, nullable=False)
123 87
124 class Image(DBBase): 88 def __init__(self, **kwargs):
125 __tablename__ = "image" 89 super(UserToken, self).__init__(**kwargs)
126
127 id = Column(Integer, primary_key=True)
128 name = Column(String(50), unique=True, nullable=False)
129 type = Column(Integer, nullable=True) # constants 0:default 1:provide 2:customize
130 path = Column(String(50), unique=True, nullable=False)
131 create_by = Column(String(50))
132 create_time = Column(DateTime, nullable=False)
133 update_time = Column(DateTime)
......
1 from log import Log
2
3 log = Log()
......
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 2
3 __author__ = 'hubian'
4 3
5 import logging 4 import logging
6 from os.path import realpath, dirname 5 from os.path import realpath, dirname
7 from logging import config, DEBUG, INFO 6 from logging import config, DEBUG, INFO
8 7
8
9 class Log(object): 9 class Log(object):
10 """Wrapper of Python logging module for easier usage 10 """Wrapper of Python logging module for easier usage
11 11
...@@ -61,6 +61,9 @@ class Log(object): ...@@ -61,6 +61,9 @@ class Log(object):
61 self.logger.critical(critical) 61 self.logger.critical(critical)
62 62
63 def __init__(self): 63 def __init__(self):
64 """initialize the log wrapper through 'logging.conf' file which should be in the same dir of this file""" 64 """
65 initialize the log wrapper through 'logging.conf' file
66 which should be in the same dir of this file
67 """
65 logging.config.fileConfig("%s/logging.conf" % dirname(realpath(__file__))) 68 logging.config.fileConfig("%s/logging.conf" % dirname(realpath(__file__)))
66 self.logger = logging.getLogger("myLogger") 69 self.logger = logging.getLogger("myLogger")
...\ No newline at end of file ...\ No newline at end of file
......
1 # -*- coding: utf-8 -*-
2
3
4 import uuid
5
6 from datetime import timedelta
7 from flask import request, g
8
9 from server.database import db_adapter
10 from server.database import models
11 from server.log import log
12 from server.utils import get_now
13 from server.utils.api_response import ok, bad_request, internal_server_error
14
15
16 class UserService(object):
17
18 def logout(self, user_id):
19 pass
20
21 def login(self, username, password):
22 user = db_adapter.find_first_object_by(models.User,
23 name=username,
24 password=password)
25 if not user:
26 return bad_request("login failed")
27 else:
28 user_token = self.__generate_api_token(user)
29 return {
30 "user": user.to_dict(),
31 "token": user_token.token()
32 }
33
34 # --------------- helper private functions ---------------------#
35
36 def __generate_api_token(self, user):
37 token_issue_date = get_now()
38 token_expire_date = token_issue_date + timedelta(minutes=30)
39 user_token = models.UserToken(token=str(uuid.uuid1()),
40 user=user,
41 expire_date=token_expire_date,
42 issue_date=token_issue_date)
43 user_token.save()
44 return user_token
1 # -*- coding: utf-8 -*-
2
3 __author__ = 'hubian'
4
1 # -*- coding: utf-8 -*-
2
3 __author__ = 'hubian'
4
5
6 class VMManager():
7
8 def create_vm(self):
9 pass
10
11 def update_vm(self):
12 pass
13
14 def delete_vm(self):
15 pass
16
17 def get_vm_list(self):
18 pass
19
20 # ------------------------helper functions ---------------------- #
21
22 def __generate_vm_xml(self):
23 pass
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 2
3 3
4 from factory import factory 4 from datetime import datetime
5 5
6 from server.database import db_session
7 from server.database.db_adapters import SQLAlchemyAdapter
8 from server.log.log import Log
9 from utils import Utils
10 6
7 def get_now():
8 return datetime.now()
11 9
12 def init_factory():
13 factory.provide("util", Utils)
14 factory.provide("log", Log)
15 factory.provide("db", SQLAlchemyAdapter, db_session)
16 10
11 def get_config():
12 return None
13
14
15 def get_safe_config():
16 return None
......
1 # -*- coding: utf-8 -*-
2
3
4 from server.log import log
5
6
7 # Customize Formatted Response
8 # with status code 200 and the real status code and message in body
9
10
11 def ok(data=None, message=""):
12 return {
13 "status": "success",
14 "code": 200,
15 "data": data,
16 "message": message
17 }
18
19
20 def __response_with_code(code, message, friendly_message=""):
21 log.debug("response with code: %d and message: %s" % (code, message))
22 return {
23 "status": "failed",
24 "code": code,
25 "message": message,
26 "friendly_message": friendly_message
27 }
28
29
30 def bad_request(message="",
31 friendly_message=(
32 'Your request does not make sense'
33 )):
34 return __response_with_code(400, message, friendly_message)
35
36
37 def unauthorized(message="",
38 friendly_message=(
39 'Please login to get a valid token')):
40 return __response_with_code(401, message, friendly_message)
41
42
43 def forbidden(message="",
44 friendly_message=(
45 'You don\'t have the permission to access the request')):
46 return __response_with_code(403, message, friendly_message)
47
48
49 def not_found(message="",
50 friendly_message=(
51 'The requested URL was not found on the server.')):
52 return __response_with_code(404, message, friendly_message)
53
54
55 def internal_server_error(message="",
56 friendly_message=(
57 'Encountered an internal error ,'
58 'unable to complete your request.'
59 'Either the server is overloaded or there '
60 'is an error in the application.'
61 )):
62 return __response_with_code(500, message, friendly_message)
63
64
65
1 # -*- coding: utf-8 -*-
2
3
4 from datetime import datetime
5
6
7 def get_now():
8 return datetime.now()
9
10
11 def get_config():
12 return None
13
14
15 def get_safe_config():
16 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!