blob: 6adda6529d9398ed07d017322a099bf3d6d8f51c [file] [log] [blame]
Fatih Degirmencic2a46012019-09-30 12:07:45 +02001import base64
2from datetime import datetime, timedelta
3import os
Fatih Degirmencic2a46012019-09-30 12:07:45 +02004
5from werkzeug.security import generate_password_hash, check_password_hash
6from flask_login import UserMixin
7
8from app import db, login
9
Fatih Degirmencic2a46012019-09-30 12:07:45 +020010@login.user_loader
11def load_user(id):
12 return User.query.get(int(id))
13
14class PaginatedAPIMixin(object):
15 @staticmethod
16 def to_collection_dict(query, page, per_page, endpoint, **kwargs):
17 resources = query.paginate(page, per_page, False)
18 data = {
19 'items': [item.to_dict() for item in resources.items],
20 '_meta': {
21 'page': page,
22 'per_page': per_page,
23 'total_pages': resources.pages,
24 'total_items': resources.total
25 },
26 }
27 return data
28
29class UserRole(db.Model):
30 id = db.Column(db.Integer, primary_key=True)
31 role_name = db.Column(db.String(32), index=True, unique=True, default='regular')
32 role_description = db.Column(db.String(128), default='Regular user with access to only base stacks')
33
34 users = db.relationship('User', backref='user_role', lazy='dynamic')
35
36 def __repr__(self):
37 return ('\tID: {}\n'
38 '\tRole name: {}\n'
39 '\tRole description: {}\n'
40 .format(self.id, self.role_name, self.role_description))
41
42class UserOrganization(db.Model):
43 id = db.Column(db.Integer, primary_key=True)
44 org_name = db.Column(db.String(32), index=True, unique=True, default='nordix')
45 org_description = db.Column(db.String(128), default='Nordix Community users')
46
47 users = db.relationship('User', backref='user_organization', lazy='dynamic')
48
49 def __repr__(self):
50 return ('\tID: {}\n'
51 '\tOrganization name: {}\n'
52 '\tOrganization description: {}\n'
53 .format(self.id, self.org_name, self.org_description))
54
55class User(PaginatedAPIMixin, UserMixin, db.Model):
56 id = db.Column(db.Integer, primary_key=True)
57 role_id = db.Column(db.Integer, db.ForeignKey('user_role.id'))
58 org_id = db.Column(db.Integer, db.ForeignKey('user_organization.id'))
59 username = db.Column(db.String(64), index=True, unique=True)
60 email = db.Column(db.String(128), index=True, unique=True)
Fatih Degirmenci0eb007f2019-09-30 14:16:48 +000061 fullname = db.Column(db.String(128))
Fatih Degirmencic2a46012019-09-30 12:07:45 +020062 password_hash = db.Column(db.String(128))
63 ssh_public_key = db.Column(db.String(1024))
64 registered_on = db.Column(db.DateTime, index=True, default=datetime.utcnow)
65 confirmed = db.Column(db.Integer, default=0)
66 last_logged_in = db.Column(db.DateTime, index=True)
67 confirmed_on = db.Column(db.DateTime, index=True)
68 updated_on = db.Column(db.DateTime, index=True, default=datetime.utcnow)
69 token = db.Column(db.String(32), index=True, unique=True)
70 token_expiration = db.Column(db.DateTime)
71
72 bookings = db.relationship('Booking', backref='user', lazy='dynamic')
73
74 def __repr__(self):
75 return ('\tID: {}\n'
76 '\tUsername: {}\n'
77 '\tFullname: {}\n'
78 '\tEmail: {}\n'
Fatih Degirmencic2a46012019-09-30 12:07:45 +020079 '\tPassword Hash: {}\n'
80 '\tSSH Public Key: {}\n'
81 '\tRegistered On: {}\n'
82 '\tConfirmed: {}\n'
83 '\tConfirmed On: {}\n'
84 '\tUpdated On: {}\n'
Fatih Degirmenci89e4ac92019-10-01 07:41:29 +000085 '\tRole ID: {}\n'
86 .format(self.id, self.username, self.fullname, self.email,
87 self.password_hash, self.ssh_public_key, self.registered_on,
88 self.confirmed, self.confirmed_on, self.updated_on, self.role_id))
Fatih Degirmencic2a46012019-09-30 12:07:45 +020089
90 def set_password(self, password):
91 self.password_hash = generate_password_hash(password)
92
93 def check_password(self, password):
94 return check_password_hash(self.password_hash, password)
95
96 def to_dict(self):
97 data = {
98 'id': self.id,
99 'role_id': self.role_id,
100 'role_name': UserRole.query.filter_by(id=self.role_id).first().role_name,
101 'org_id': self.org_id,
102 'org_name': UserOrganization.query.filter_by(id=self.org_id).first().org_name,
103 'username': self.username,
104 'email': self.email,
105 'ssh_public_key': self.ssh_public_key,
106 'registered_on': self.registered_on.isoformat(),
107 'confirmed': self.confirmed
108 }
109 return data
110
111 def from_dict(self, data, new_user=False):
112 for field in ['confirmed', 'org_id', 'role_id']:
113 if field in data:
114 setattr(self, field, data[field])
115 if new_user and 'password' in data:
116 self.set_password(data['password'])
117
118 def get_token(self, expires_in=3600):
119 now = datetime.utcnow()
120 if self.token and self.token_expiration > now + timedelta(seconds=60):
121 return self.token
122 self.token = base64.b64encode(os.urandom(24)).decode('utf-8')
123 self.token_expiration = now + timedelta(seconds=expires_in)
124 db.session.add(self)
125 return self.token
126
127 def revoke_token(self):
128 self.token_expiration = datetime.utcnow() - timedelta(seconds=1)
129
130 @staticmethod
131 def check_token(token):
132 user = User.query.filter_by(token=token).first()
133 if user is None or user.token_expiration < datetime.utcnow():
134 return None
135 return user
136
137 @staticmethod
138 def check_none_regular_user(token):
139 user = User.query.filter_by(token=token).first()
140 current_user_role_id = user.role_id
141 regular_user_role_id = UserRole.query.filter_by(role_name='regular').first().id
142 if current_user_role_id == regular_user_role_id:
143 return None
144 return user
145
146class Booking(PaginatedAPIMixin, db.Model):
147 id = db.Column(db.Integer, primary_key=True)
148 user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
149 status_id = db.Column(db.Integer, db.ForeignKey('booking_status.id'))
150 booking_length = db.Column(db.Integer)
151 created_on = db.Column(db.DateTime, index=True, default=datetime.utcnow)
152 updated_on = db.Column(db.DateTime, index=True, default=datetime.utcnow)
153 expires_on = db.Column(db.DateTime, index=True, default=datetime.utcnow)
154 heat_stack_name = db.Column(db.String(64))
155 floating_ip = db.Column(db.String(64))
156 engine_version = db.Column(db.String(64))
157 stack = db.Column(db.String(64))
158 stack_version = db.Column(db.String(64))
159 scenario = db.Column(db.String(64))
160 scenario_version = db.Column(db.String(64))
161 scenario_deploy_log_url = db.Column(db.String(256))
162
163 def __repr__(self):
164 return ('\tID: {}\n'
165 '\tUser ID: {}\n'
166 '\tStatus: {}\n'
167 '\tCreated: {}\n'
168 '\tUpdated: {}\n'
169 '\tExpires: {}\n'
170 '\tHeat Stack Name: {}\n'
171 '\tFloating IP: {}\n'
172 '\tStack Name: {}\n'
173 '\tStack Version: {}\n'
174 '\tScenario: {}\n'
175 '\tScenario Version: {}\n'
176 .format(self.id, self.user_id, self.status, self.created,
177 self.updated, self.expires, self.heat_stack_name, self.floating_ip,
178 self.engine_version, self.stack, self.stack_version, self.scenario, self.scenario_version))
179
180 def to_dict(self):
181 data = {
182 'id': self.id,
183 'user_id': self.user_id,
184 'booking_length': self.booking_length,
185 'heat_stack_name': self.heat_stack_name,
186 'scenario_deploy_log_url': self.scenario_deploy_log_url,
187 'engine_version': self.engine_version,
188 'scenario_version': self.scenario_version,
189 'floating_ip': self.floating_ip,
190 'created_on': self.created_on.isoformat(),
191 'stack': self.stack,
192 'status_text': BookingStatus.query.filter_by(id=self.status_id).first().status_text,
193 'status_id': self.status_id,
194 'scenario': self.scenario
195 }
196 return data
197
198 def from_dict(self, data, new_booking=False):
199 for field in ['status_text', 'floating_ip', 'heat_stack_name', \
200 'scenario_deploy_log_url', 'engine_version', \
201 'scenario_version']:
202 if field in data:
203 setattr(self, field, data[field])
204
205class BookingStatus(db.Model):
206 id = db.Column(db.Integer, primary_key=True)
207 status_text = db.Column(db.String(64), default='new')
208 status_description = db.Column(db.String(128), default='New booking request')
209
210 bookings = db.relationship('Booking', backref='booking_status', lazy='dynamic')
211
212 def __repr__(self):
213 return ('\tID: {}\n'
214 '\tStatus: {}\n'
215 .format(self.id, self.status))
216
217class Stack(db.Model):
218 id = db.Column(db.Integer, primary_key=True)
219 stack_name = db.Column(db.String(64), index=True, unique=True)
220 stack_description = db.Column(db.String(128), unique=True)
221 is_sandbox_enabled = db.Column(db.Boolean(8), default=False)
222
223 scenarios = db.relationship('Scenario', backref='stack', lazy='dynamic')
224
225 def __repr__(self):
226 return ('\tID: {}\n'
227 '\tStack name: {}\n'
228 '\tStack description: {}\n'
229 '\tIs sandbox enabled: {}\n'
230 .format(self.id, self.stack_name, self.stack_description, self.is_sandbox_enabled))
231
232class Scenario(db.Model):
233 id = db.Column(db.Integer, primary_key=True)
234 stack_id = db.Column(db.Integer, db.ForeignKey('stack.id'))
235 scenario_name = db.Column(db.String(64), index=True, unique=True)
236 scenario_description = db.Column(db.String(128), unique=True)
237 is_sandbox_enabled = db.Column(db.Boolean(8), default=False)
238
239 def __repr__(self):
240 return ('\tID: {}\n'
241 '\tScenario name: {}\n'
242 '\tScenario description: {}\n'
243 '\tIs sandbox enabled: {}\n'
244 .format(self.id, self.scenario_name, self.scenario_description, self.is_sandbox_enabled))