Guest User

AssetReservation

a guest
Jul 9th, 2016
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.35 KB | None | 0 0
  1. from flask import Flask, render_template, url_for, flash, redirect, request, session, g
  2. from forms import LoginForm, RegistrationForm, AddAssetForm, EditReservationForm, MakeReservationForm
  3. import sqlite3, smtplib
  4. from contextlib import closing
  5. from flask_login import LoginManager, login_user, logout_user, current_user, login_required, UserMixin
  6. from datetime import date, timedelta, datetime
  7. from email.MIMEMultipart import MIMEMultipart
  8. from email.MIMEText import MIMEText
  9. from threading import Thread
  10. from string import capwords
  11.  
  12.  
  13.  
  14. #Initialization
  15. app = Flask(__name__)
  16.  
  17. #Configuration
  18.  
  19. SECRET_KEY = 'foobar'
  20. DEBUG = True
  21. DATABASE = "C:\\Python27\\asset\\asset.db"
  22. WTF_CSRF_ENABLED = True
  23. SMTP_SERVER = 'smtp.gmail.com:587'
  24. ADMIN_EMAIL = 'admin@example.com' #Put admin's email address here.
  25.  
  26. lm = LoginManager()
  27. lm.init_app(app)
  28.  
  29. #Initialization
  30. app.config.from_object(__name__)
  31.  
  32. def connect_db():
  33. return sqlite3.connect(app.config['DATABASE'])
  34.  
  35. def create_table(): #To set up database. We need a asset.db file to exist in the main folder.
  36. with closing(connect_db()) as conn:
  37. with app.open_resource('schema.sql', mode = 'r') as f:
  38. conn.cursor().executescript(f.read())
  39. conn.commit()
  40.  
  41. print('Tables created.')
  42.  
  43. def fetch_user(username):
  44. conn = connect_db()
  45. conn.row_factory = sqlite3.Row
  46. curs = conn.cursor()
  47. curs.execute('select * from user where username = (?) collate nocase', [str(username)])
  48. return curs.fetchone()
  49.  
  50. def fetch_asset(assetname):
  51. conn = connect_db()
  52. conn.row_factory = sqlite3.Row
  53. curs = conn.cursor()
  54. curs.execute('select * from asset where assetname = (?) collate nocase', [str(assetname)])
  55. return curs.fetchone()
  56.  
  57. def send_asynch(to_address, message): #Sends email asynchrously.
  58. data = MIMEMultipart()
  59. from_address = 'noreply.server995@gmail.com'
  60. data['From'] = from_address
  61. data['To'] = to_address
  62. data['Subject'] = message['subject']
  63. data.attach(MIMEText(message['body']))
  64. server = smtplib.SMTP(app.config['SMTP_SERVER'])
  65. server.ehlo()
  66. server.starttls()
  67. server.ehlo()
  68. server.login('noreply.server995', 'assetmanage')
  69. try:
  70. server.sendmail(from_address, to_address, str(data))
  71. except:
  72. print('User\'s email is not valid.')
  73. return
  74. server.quit()
  75. print('Delivered mail to %s.' % to_address)
  76.  
  77. def send_mail(to_address, message):
  78. thr = Thread(target = send_asynch, args = [to_address, message])
  79. thr.start()
  80.  
  81.  
  82. class User(UserMixin):
  83.  
  84. def __init__(self, username, password, email):
  85. self.username = capwords(username)
  86. self.password = password
  87. self.email = email
  88.  
  89. def is_authenticated():
  90. return True
  91.  
  92. def is_active():
  93. return True
  94.  
  95. def is_annonymous():
  96. return False
  97.  
  98. def is_admin():
  99. conn = connect_db()
  100. conn.row_factory = sqlite3.Row
  101. curs = conn.cursor()
  102. curs.execute('select isadmin from user where username = (?) collate nocase', [self.username])
  103. flag = curs.fetchone()[0]
  104. return flag == 1
  105.  
  106.  
  107. def get_id(self):
  108. conn = connect_db()
  109. conn.row_factory = sqlite3.Row
  110. curs = conn.cursor()
  111. curs.execute('select uid from user where username = (?) collate nocase', [self.username])
  112. return unicode(curs.fetchone()[0])
  113.  
  114. def get_username(self):
  115. return self.username
  116.  
  117. def get_email(self):
  118. return self.email
  119.  
  120. def add_db(self):
  121. curs = g.db.cursor()
  122. curs.execute('insert into user(username, password, email) values (?, ?, ?)', [self.username, self.password, self.email])
  123. g.db.commit()
  124.  
  125.  
  126. #Views
  127.  
  128. @app.route('/') #Home page of the user. Shows assets currently reserved by the user.
  129. @app.route('/index')
  130. def index():
  131. if not (g.user is not None and hasattr(g.user, 'is_authenticated') and g.user.is_authenticated):
  132. return redirect(url_for('login'))
  133. curs = g.db.cursor()
  134. g.db.row_factory = sqlite3.Row
  135. curs.execute('select * from asset where isreserved = (?) and owner = (?)', [1, g.user.get_id()])
  136. assets = curs.fetchall()
  137. return render_template('index.html', assets = assets)
  138.  
  139. @lm.user_loader
  140. def load_user(id):
  141. conn = connect_db()
  142. conn.row_factory = sqlite3.Row
  143. curs = conn.cursor()
  144. curs.execute('select * from user where uid = (?)', [id])
  145. foo = curs.fetchone()
  146. if foo is not None:
  147. return User(foo[1], foo[2], foo[3])
  148. else:
  149. return 'User not found.'
  150.  
  151. @app.route('/login', methods = ['GET', 'POST']) #Log in user.
  152. def login():
  153. if g.user is not None and hasattr(g.user, 'is_authenticated') and g.user.is_authenticated:
  154. return redirect(url_for('index'))
  155. form = LoginForm()
  156. if request.method == 'POST' and form.validate_on_submit():
  157. #session['remember_me'] = form.remember_me.data
  158. g.username = form.username.data
  159. g.password = form.password.data
  160. user_db = fetch_user(g.username)
  161. if user_db is not None:
  162. if g.password == user_db[2]:
  163. user = User(user_db[1], user_db[2], user_db[3])
  164. login_user(user, remember = form.remember_me.data)
  165. #g.user = user
  166. flash('Login successful. Welcome %s!' % user_db[1])
  167. return redirect(url_for('index'))
  168. else:
  169. flash('Incorrect password.')
  170. return redirect(url_for('login'))
  171. else:
  172. flash('No such user exists.')
  173. return redirect(url_for('login'))
  174. return render_template('login.html', title = 'Sign In', form = form)
  175.  
  176. def check_email(email): #To check if the argument email already exists in the database. Called while registering to ensure emails are not associated with multiple accounts.
  177. conn = g.db
  178. conn.row_factory = sqlite3.Row
  179. curs = conn.cursor()
  180. curs.execute('select * from user where email = (?)', [email])
  181. return len(curs.fetchall()) != 0
  182.  
  183.  
  184. @app.route('/register', methods = ['GET', 'POST']) #Create a new user account.
  185. def register():
  186. if g.user is not None and hasattr(g.user, 'is_authenticated') and g.user.is_authenticated:
  187. return redirect(url_for('index'))
  188. form = RegistrationForm()
  189. if request.method == 'POST' and form.validate_on_submit():
  190. if fetch_user(form.username.data) is not None:
  191. flash('This username already exists. Please choose another one.')
  192. return redirect(url_for('register'))
  193. elif(check_email(form.email.data)):
  194. flash('This email is already associated with an account. Please choose another one.')
  195. return redirect(url_for('register'))
  196. user = User(username = form.username.data, password = form.password.data, email = form.email.data)
  197. user.add_db()
  198. message = {'subject': 'Thank you for registering at AssetReservation!',
  199. 'body': 'Hi %s, you have successfully registered at AssetReservation.' % form.username.data}
  200. send_mail(form.email.data, message)
  201. flash('Registration successful! You may now login into your account.')
  202. return redirect(url_for('login'))
  203. return render_template('register.html', title = 'Sign Up', form = form)
  204.  
  205. @app.route('/logout') #Log out user.
  206. @login_required
  207. def logout():
  208. logout_user()
  209. flash('Logged out.')
  210. return redirect(url_for('login'))
  211.  
  212. @app.route('/addasset', methods = ['GET', 'POST']) #To create a new asset. User can reserve the new asset here itself.
  213. @login_required
  214. def add_asset():
  215. form = AddAssetForm()
  216. if request.method == 'POST' and form.validate_on_submit():
  217. if fetch_asset(form.assetname.data) is not None:
  218. flash('An asset with that name already exists. Please choose another name.')
  219. return redirect(url_for('add_asset'))
  220. else:
  221. curs = g.db.cursor()
  222. if form.reserve_it.data:
  223. release_date = str(date.today() + timedelta(days = form.days.data))
  224. owner = int(g.user.get_id())
  225. curs.execute('insert into asset(assetname, releasedate, owner, isreserved) values (?, ?, ?, ?)', [capwords(form.assetname.data), release_date, owner, 1])
  226. message = {'subject': 'An asset has been reserved.',
  227. 'body': 'User %s has reserved asset %s for %d days' % (g.user.get_username(), form.assetname.data, form.days.data)}
  228. send_mail(g.user.get_email(), message)
  229. send_mail(app.config['ADMIN_EMAIL'], message)
  230. else:
  231. curs.execute('insert into asset(assetname) values (?)', [capwords(form.assetname.data)])
  232. g.db.commit()
  233. flash('Successfully created asset named %s.' % capwords(form.assetname.data))
  234. return render_template('add asset.html', form = form)
  235. return render_template('add asset.html', form = form)
  236.  
  237. @app.route('/asset/<asset_name>') #To display asset information.
  238. def asset(asset_name):
  239. asset = fetch_asset(asset_name)
  240. if asset is None:
  241. flash('Asset not found.')
  242. return redirect(url_for('index'))
  243. curs = g.db.cursor()
  244. g.db.row_factory = sqlite3.Row
  245. curs.execute('select username from user where uid = (?)', [asset[3]])
  246. owner = str(curs.fetchone()[0])
  247. return render_template('asset.html', title = asset_name, asset = asset, owner = owner)
  248.  
  249. @app.route('/manage') #Manage Assets page where user can reserve new assets and change reservation of current assets.
  250. @login_required
  251. def manage():
  252. curs = g.db.cursor()
  253. g.db.row_factory = sqlite3.Row
  254. curs.execute('select * from asset where isreserved = (?) and owner = (?)', [1, g.user.get_id()])
  255. users_assets = curs.fetchall()
  256. curs.execute('select * from asset where isreserved = (?) and not owner = (?)', [1, g.user.get_id()])
  257. others_assets = curs.fetchall()
  258. curs.execute('select * from asset where isreserved = 0')
  259. free_assets = curs.fetchall()
  260. return render_template('manage.html', title = 'Manage Assets', users_assets = users_assets, others_assets = others_assets, free_assets = free_assets)
  261.  
  262. @app.route('/editreservation/<asset_name>', methods = ['GET', 'POST']) #To edit a current reservation. User can extend reservation or revoke it.
  263. @login_required
  264. def edit_reservation(asset_name):
  265. asset = fetch_asset(asset_name)
  266. if asset is None:
  267. flash('Asset not found.')
  268. return redirect(url_for('manage'))
  269. elif not (asset[4] == 1 and asset[3] == int(g.user.get_id())):
  270. flash('You can\'t edit reservation for this asset.')
  271. return redirect(url_for('manage'))
  272. form = EditReservationForm()
  273. if request.method == 'POST' and form.validate_on_submit():
  274. revoke = form.revoke_reservation.data
  275. curs = g.db.cursor()
  276. if revoke:
  277. curs.execute('update asset set isreserved = (?) where aid = (?)', [0, asset[0]])
  278. g.db.commit()
  279. flash('Successfully revoked reservation for asset %s.' % asset[1])
  280. return redirect(url_for('manage'))
  281. elif form.days.data != 0:
  282. release_date = str(datetime.strptime(str(asset[2]), '%Y-%m-%d').date() + timedelta(days = form.days.data))
  283. curs.execute('update asset set releasedate = (?) where aid = (?)', [release_date, asset[0]])
  284. g.db.commit()
  285. flash('Successfully updated asset %s\'s release date to %s' % (asset[1], release_date))
  286. return redirect(url_for('manage'))
  287. return render_template('edit reservation.html', date = asset[2], form = form)
  288.  
  289. @app.route('/makereservation/<asset_name>', methods = ['GET', 'POST']) #To make a new reservation.
  290. @login_required
  291. def make_reservation(asset_name):
  292. asset = fetch_asset(asset_name)
  293. if asset is None:
  294. flash('Asset not found.')
  295. return redirect(url_for('manage'))
  296. elif asset[4] == 1:
  297. flash('You can\'t reserve this asset.')
  298. return redirect(url_for('manage'))
  299. form = MakeReservationForm()
  300. if request.method == 'POST' and form.validate_on_submit():
  301. if form.days.data != 0:
  302. curs = g.db.cursor()
  303. curs.execute('update asset set isreserved = (?), owner = (?), releasedate = (?) where aid = (?)', [1, int(g.user.get_id()), str(date.today() + timedelta(days = form.days.data)), asset[0]])
  304. g.db.commit()
  305. message = {'subject': 'An asset has been reserved.',
  306. 'body': 'User %s has reserved asset %s for %d days' % (g.user.get_username(), asset_name, form.days.data)}
  307. send_mail(g.user.get_email(), message)
  308. send_mail(app.config['ADMIN_EMAIL'], message)
  309. flash('Successfully reserved asset %s for %d days' % (asset[1], form.days.data))
  310. return redirect(url_for('manage'))
  311. return render_template('make reservation.html', title = 'Make Reservation', asset = asset_name, form = form)
  312.  
  313. # @app.route('/admin', methods = ['GET', 'POST'])
  314. # @login_required
  315. # def admin():
  316. # if not g.user.is_admin():
  317. # flash('You need admin priviledges before you can visit this page.')
  318. # return redirect(url_for('index'))
  319. # return render_template('admin.html')
  320.  
  321.  
  322. @app.errorhandler(401)
  323. def unauthorized_error(error):
  324. return render_template('401.html'), 401
  325.  
  326. @app.before_request
  327. def before_request():
  328. g.db = connect_db()
  329. g.user = current_user
  330.  
  331. @app.teardown_request
  332. def teardown_request(error):
  333. if hasattr(g, 'db'):
  334. g.db.close()
  335.  
  336.  
  337. #Running
  338. if __name__ == '__main__':
  339. app.run()
Add Comment
Please, Sign In to add comment