@ -7,7 +7,7 @@ from functools import wraps
from sqlalchemy . sql import select
from sqlalchemy . sql import select
from sqlalchemy . sql import text
from sqlalchemy . sql import text
from flask import Flask
from flask import Flask
from flask import render_template , send_from_directory , request , Response , send_file , session
from flask import render_template , send_from_directory , request , Response , send_file , session , jsonify
from PIL import Image , ImageDraw
from PIL import Image , ImageDraw
from io import BytesIO
from io import BytesIO
from os import listdir
from os import listdir
@ -30,20 +30,22 @@ with open('taglines.txt', 'r') as infile:
def getContainers ( ) :
def getContainers ( ) :
query = " select id, name from containers order by UPPER(name); "
query = " select id, name from containers order by UPPER(name); "
r = db_engine . execute ( text ( query ) )
# r = db_engine.execute(text(query))
containers = [ ]
# containers = []
for row in r :
# for row in r:
containers . append ( dict ( row ) )
# containers.append(dict(row))
r . close ( )
# r.close()
with db_engine . connect ( ) as conn :
r = conn . execute ( text ( query ) )
containers = r . mappings ( ) . all ( )
return containers
return containers
def check_auth ( username , password ) :
def check_auth ( username , password ) :
query = " select id, password from users where username=:usrnm; "
query = " select id, password from users where username=:usrnm; "
r = db_engine . execute ( text ( query ) , usrnm = username )
#r = db_engine.execute(text(query), usrnm=username) #SQLalchemy 1.x
results = [ ]
with db_engine . connect ( ) as conn :
for row in r :
r = conn . execute ( text ( query ) )
results . append ( dict ( row ) )
results = r . mappings ( ) . all ( )
r . close ( )
if len ( results ) != 1 :
if len ( results ) != 1 :
return False ;
return False ;
@ -79,99 +81,151 @@ def index():
@app.route ( baseURL + ' /getlocationsInContainer/<containerID> ' )
@app.route ( baseURL + ' /getlocationsInContainer/<containerID> ' )
def get_locations_in_container ( containerID ) :
def get_locations_in_container ( containerID ) :
s = ' select id, name from locations where container_id = :id order by name; '
s = ' select id, name from locations where container_id = :id order by name; '
r = db_engine . execute ( text ( s ) , id = containerID )
# r = db_engine.execute(text(s), id=containerID)
l = { }
# l={}
for row in r :
# for row in r:
l [ str ( row [ 0 ] ) ] = row [ 1 ] ;
# l[str(row[0])]= row[1];
r . close ( )
# r.close()
return json . dumps ( l )
# return json.dumps(l)
with db_engine . connect ( ) as conn :
r = conn . execute ( text ( s ) , { " id " : containerID } )
l = { str ( row . id ) : row . name for row in r }
return jsonify ( l )
@app.route ( baseURL + ' /getlocationURL/<locationID> ' )
@app.route ( baseURL + ' /getlocationURL/<locationID> ' )
def get_locationURL ( locationID ) :
def get_locationURL ( locationID ) :
s = ' select map from locations where id = :id; '
s = ' select map from locations where id = :id; '
r = db_engine . execute ( text ( s ) , id = locationID )
# r = db_engine.execute(text(s), id=locationID)
l = [ ] ;
# l=[];
for row in r :
# for row in r:
l . append ( row ) ;
# l.append(row);
r . close ( )
# r.close()
return l [ 0 ] [ 0 ]
# return l[0][0]
with db_engine . connect ( ) as conn :
result = conn . execute ( text ( s ) , { " id " : locationID } ) . fetchone ( )
if result is None :
return " "
return result [ 0 ]
@app.route ( baseURL + ' /locationEditor ' )
@app.route ( baseURL + ' /locationEditor ' )
def locationEditor ( ) :
def locationEditor ( ) :
query = ' select c.name as container, l.name as name, l.id, c.id as container_id from locations as l inner join containers as c on l.container_id = c.id order by container, name; '
query = ' select c.name as container, l.name as name, l.id, c.id as container_id from locations as l inner join containers as c on l.container_id = c.id order by container, name; '
r = db_engine . execute ( text ( query ) )
# r = db_engine.execute(text(query))
locations = [ ]
# locations = []
for row in r :
# for row in r:
locations . append ( dict ( row ) )
# locations.append(dict(row))
r . close ( )
# r.close()
return render_template ( ' locationEditor.html ' , locations = locations , containers = getContainers ( ) , baseURL = baseURL )
# return render_template('locationEditor.html', locations=locations, containers=getContainers(),baseURL=baseURL)
with db_engine . connect ( ) as conn :
result = conn . execute ( text ( query ) )
locations = [ dict ( row . _mapping ) for row in result ]
return render_template (
' locationEditor.html ' ,
locations = locations ,
containers = getContainers ( ) ,
baseURL = baseURL
)
@app.route ( baseURL + ' /userEditor ' )
@app.route ( baseURL + ' /userEditor ' )
def userEditor ( ) :
def userEditor ( ) :
query = ' select c.name as container, l.name as name, l.id, c.id as container_id from locations as l inner join containers as c on l.container_id = c.id order by container, name; '
query = ' select id, username from users; '
query = ' select id, username from users; '
r = db_engine . execute ( text ( query ) )
# r = db_engine.execute(text(query))
users = [ ]
# users = []
for row in r :
# for row in r:
users . append ( dict ( row ) )
# users.append(dict(row))
r . close ( )
# r.close()
with db_engine . connect ( ) as conn :
result = conn . execute ( text ( query ) )
users = [ dict ( row . _mapping ) for row in result ]
return render_template ( ' userEditor.html ' , users = users , containers = getContainers ( ) , baseURL = baseURL )
return render_template ( ' userEditor.html ' , users = users , containers = getContainers ( ) , baseURL = baseURL )
@app.route ( baseURL + ' /alterLocation/<locationID> ' , methods = [ ' POST ' ] )
@app.route ( baseURL + ' /alterLocation/<locationID> ' , methods = [ ' POST ' ] )
@requires_auth
@requires_auth
def alterLocation ( locationID ) :
def alterLocation ( locationID ) :
locationID = int ( locationID )
locationID = int ( locationID )
s = ' '
if locationID < 0 :
if locationID < 0 :
# New entry
# New entry
s = ' insert into locations (name, container_id) '
query = text ( """
s + = ' values (:name, :container); '
insert into locations ( name , container_id )
s = text ( s )
values ( : name , : container )
r = db_engine . execute ( s , name = request . form [ ' name ' ] , container = request . form [ ' container ' ] ) ;
""" )
r . close ( )
return ' { " status " : " ok " } '
with db_engine . begin ( ) as conn :
conn . execute ( query , {
" name " : request . form [ ' name ' ] ,
" container " : request . form [ ' container ' ]
} )
return jsonify ( status = " ok " )
else :
else :
# Modify entry
# Modify entry
s = ' update locations '
query = text ( """
s + = ' set name=:name, container_id=:container '
update locations
s + = ' where id=:locationID; '
set name = : name ,
s = text ( s )
container_id = : container
r = db_engine . execute ( s , name = request . form [ ' name ' ] , container = request . form [ ' container ' ] , locationID = locationID ) ;
where id = : locationID
r . close ( )
""" )
return ' { " status " : " ok " } '
@app.route ( baseURL + ' /alterUser/<userID> ' , methods = [ ' POST ' ] )
with db_engine . begin ( ) as conn :
conn . execute ( query , {
" name " : request . form [ ' name ' ] ,
" container " : request . form [ ' container ' ] ,
" locationID " : locationID
} )
return jsonify ( status = " ok " )
@app.route ( baseURL + ' /alterUser/<userID> ' , methods = [ ' POST ' ] )
@requires_auth
@requires_auth
def alterUser ( userID ) :
def alterUser ( userID ) :
userID = int ( userID )
userID = int ( userID )
s = ' '
if userID < 0 :
if userID < 0 :
# New entry
# New entry
s = ' insert into users (username, password) '
query = text ( """
s + = ' values (:name, :password); '
insert into users ( username , password )
s = text ( s )
values ( : name , : password )
r = db_engine . execute ( s , name = request . form [ ' name ' ] , password = request . form [ ' password ' ] ) ;
""" )
r . close ( )
return ' { " status " : " ok " } '
with db_engine . begin ( ) as conn :
conn . execute ( query , {
" name " : request . form [ ' name ' ] ,
" password " : request . form [ ' password ' ]
} )
return jsonify ( status = " ok " )
else :
else :
# Modify entry
# Modify entry
s = ' update users '
query = text ( """
s + = ' set username=:name, password=:password '
update users
s + = ' where id=:userID; '
set username = : name , password = : password
s = text ( s )
where id = : userID
r = db_engine . execute ( s , name = request . form [ ' name ' ] , password = request . form [ ' password ' ] , userID = userID ) ;
""" )
r . close ( )
return ' { " status " : " ok " } '
with db_engine . begin ( ) as conn :
conn . execute ( query , {
" name " : request . form [ ' name ' ] ,
" password " : request . form [ ' password ' ] ,
" userID " : userID
} )
return jsonify ( status = " ok " )
@app.route ( baseURL + ' /getpartinfo/<partID> ' )
@app.route ( baseURL + ' /getpartinfo/<partID> ' )
def get_part_info ( partID ) :
def get_part_info ( partID ) :
s = ' select p.id,partno,description,notes, c.name || l.name as location_descriptor, location_id, container_id, datasheet from parts as p inner join locations as l on p.location_id = l.id inner join containers as c on l.container_id = c.id where p.id = :id; '
s = ' select p.id,partno,description,notes, c.name || l.name as location_descriptor, location_id, container_id, datasheet from parts as p inner join locations as l on p.location_id = l.id inner join containers as c on l.container_id = c.id where p.id = :id; '
r = db_engine . execute ( text ( s ) , id = partID )
with db_engine . connect ( ) as conn :
l = [ ]
result = conn . execute ( text ( s ) , { " id " : partID } )
for row in r :
row = result . mappings ( ) . first ( )
l . append ( dict ( row ) )
r . close ( )
return json . dumps ( l [ 0 ] )
return jsonify ( dict ( row ) if row else { } )
@app.route ( baseURL + ' /query/<filter_dummy>/<query> ' ) # TODO: maybe change AND to OR or maybe not
@app.route ( baseURL + ' /query/<filter_dummy>/<query> ' ) # TODO: maybe change AND to OR or maybe not
def query ( filter_dummy , query ) :
def query ( filter_dummy , query ) :
filter = request . args . to_dict ( )
filter = request . args . to_dict ( )
@ -203,24 +257,24 @@ def query(filter_dummy, query):
s = s [ : - 5 ]
s = s [ : - 5 ]
s + = ' ) OR '
s + = ' ) OR '
s = s [ : - 4 ] + ' ; '
s = s [ : - 4 ] + ' ; '
s = text ( s )
# s = text(s)
r = db_engine . execute ( s , kw_dict )
# r = db_engine.execute(s, kw_dict)
l = [ ]
# l = []
for row in r :
# for row in r:
l . append ( dict ( row ) )
# l.append(dict(row))
r . close ( )
# r.close()
with db_engine . connect ( ) as conn :
l = [ dict ( row ) for row in conn . execute ( text ( s ) , kw_dict ) . mappings ( ) ]
return json . dumps ( l )
return json . dumps ( l )
@app.route ( baseURL + ' /map/<containerID> ' )
@app.route ( baseURL + ' /map/<containerID> ' )
@app.route ( baseURL + ' /map/<containerID>/<annotate> ' )
@app.route ( baseURL + ' /map/<containerID>/<annotate> ' )
def getMap ( containerID , annotate = None ) :
def getMap ( containerID , annotate = None ) :
s = ' select map, overlay from containers where id = :id; '
s = ' select map, overlay from containers where id = :id; '
r = db_engine . execute ( text ( s ) , id = containerID )
with db_engine . connect ( ) as conn :
l = [ ]
row = conn . execute ( text ( s ) , { " id " : containerID } ) . mappings ( ) . first ( )
for row in r :
mapFile = row [ ' map ' ]
l . append ( dict ( row ) )
overlayFile = row [ ' overlay ' ]
mapFile = l [ 0 ] [ ' map ' ]
overlayFile = l [ 0 ] [ ' overlay ' ]
try :
try :
mapImage = Image . open ( ' maps/ ' + mapFile ) . convert ( " RGBA " )
mapImage = Image . open ( ' maps/ ' + mapFile ) . convert ( " RGBA " )
overlayImage = Image . open ( ' maps/overlays/ ' + overlayFile ) . convert ( " RGBA " )
overlayImage = Image . open ( ' maps/overlays/ ' + overlayFile ) . convert ( " RGBA " )
@ -246,109 +300,134 @@ def getMap(containerID, annotate=None):
@app.route ( baseURL + ' /getfile/<filename> ' )
@app.route ( baseURL + ' /getfile/<filename> ' )
def getfile ( filename ) :
def getfile ( filename ) :
if ( re . match ( ' ^[ \ w \ -_]+.[p|P][d|D][f|F]$ ' , filename ) == None ) :
# if(re.match('^[\w\-_]+.[p|P][d|D][f|F]$', filename) == None):
if ( re . match ( r ' ^[ \ w-]+ \ .pdf$ ' , filename , re . IGNORECASE ) == None ) :
return ' No injections pls. '
return ' No injections pls. '
return send_from_directory ( ' /srv/datasheets/ ' , filename )
return send_from_directory ( ' /srv/datasheets/ ' , filename )
@app.route ( baseURL + ' /alter/<partID> ' , methods = [ ' POST ' ] )
@app.route ( baseURL + ' /alter/<partID> ' , methods = [ ' POST ' ] )
@requires_auth
@requires_auth
def alter ( partID ) :
def alter ( partID ) :
partID = int ( partID )
partID = int ( partID )
s = ' '
r = { }
# -------------------------
# HANDLE FILE UPLOAD
# -------------------------
if len ( request . files ) != 0 :
datasheet_file = request . files [ ' datasheet-file ' ]
datasheet_filename = secure_filename ( datasheet_file . filename )
i = 1
while os . path . isfile ( ' /srv/datasheets/ ' + datasheet_filename ) :
datasheet_filename = datasheet_filename [ : - 4 ] + str ( i ) + ' .pdf '
i + = 1
datasheet_file . save ( ' /srv/datasheets/ ' + datasheet_filename )
datasheet_filename = ' http://elab.kth.se/parts/getfile/ ' + datasheet_filename
else :
try :
datasheet_filename = request . form [ ' datasheet-url ' ]
except :
datasheet_filename = None
# -------------------------
# INSERT
# -------------------------
if partID < 0 :
if partID < 0 :
# New entry
query = text ( """
s = ' insert into parts (partno, description, datasheet, location_id, whoadded, notes) '
insert into parts
s + = ' values (:partno, :description, :datasheet, :location_id, :user_id, :notes) returning id; '
( partno , description , datasheet , location_id , whoadded , notes )
s = text ( s )
values
if len ( request . files ) != 0 :
( : partno , : description , : datasheet , : location_id , : user_id , : notes )
datasheet_file = request . files [ ' datasheet-file ' ]
returning id
datasheet_filename = secure_filename ( datasheet_file . filename )
""" )
i = 1
while os . path . isfile ( ' /srv/datasheets/ ' + datasheet_filename ) :
with db_engine . begin ( ) as conn :
datasheet_filename = datasheet_filename [ : - 4 ] + str ( i ) + ' .pdf '
result = conn . execute ( query , {
i + = 1
" partno " : request . form [ ' partno ' ] ,
datasheet_file . save ( ' /srv/datasheets/ ' + datasheet_filename )
" description " : request . form [ ' description ' ] ,
datasheet_filename = ' http://elab.kth.se/parts/getfile/ ' + datasheet_filename
" datasheet " : datasheet_filename ,
# elif request.form.has_key('datasheet-url'):
" location_id " : request . form [ ' location_id ' ] ,
# datasheet_filename = request.form['datasheet-url']
" notes " : request . form [ ' notes ' ] ,
else :
" user_id " : session [ ' uid ' ]
try :
} )
datasheet_filename = request . form [ ' datasheet-url ' ]
except :
new_id = result . mappings ( ) . first ( ) [ " id " ]
datasheet_filename = None
r = db_engine . execute ( s , partno = request . form [ ' partno ' ] ,
return jsonify ( status = " ok " , part_id = new_id )
description = request . form [ ' description ' ] ,
datasheet = datasheet_filename ,
# -------------------------
location_id = request . form [ ' location_id ' ] ,
# UPDATE
notes = request . form [ ' notes ' ] ,
# -------------------------
user_id = session [ ' uid ' ] )
else :
else :
# Modify entry
query = text ( """
r = db_engine . execute ( text ( ' select * from parts where id=:id; ' ) , id = partID )
update parts
l = [ ]
set partno = : partno ,
for row in r :
description = : description ,
l . append ( dict ( row ) )
datasheet = : datasheet ,
r . close ( )
location_id = : location_id ,
s = ' update parts '
notes = : notes
s + = ' set partno=:partno, description=:description, datasheet=:datasheet, location_id=:location_id, notes=:notes '
where id = : id
if len ( request . files ) != 0 :
returning id
datasheet_file = request . files [ ' datasheet-file ' ]
""" )
datasheet_filename = secure_filename ( datasheet_file . filename )
i = 1
with db_engine . begin ( ) as conn :
while os . path . isfile ( ' /srv/datasheets/ ' + datasheet_filename ) :
result = conn . execute ( query , {
datasheet_filename = datasheet_filename [ : - 4 ] + str ( i ) + ' .pdf '
" partno " : request . form [ ' partno ' ] ,
i + = 1
" description " : request . form [ ' description ' ] ,
datasheet_file . save ( ' /srv/datasheets/ ' + datasheet_filename )
" datasheet " : datasheet_filename ,
datasheet_filename = ' http://elab.kth.se/parts/getfile/ ' + datasheet_filename
" location_id " : request . form [ ' location_id ' ] ,
if l [ 0 ] [ ' datasheet ' ] != None :
" notes " : request . form [ ' notes ' ] ,
whole_url = l [ 0 ] [ ' datasheet ' ]
" id " : partID
actual_filename = whole_url [ whole_url . rfind ( ' / ' ) + 1 : ]
} )
os . remove ( ' /srv/datasheets/ ' + actual_filename )
else :
new_id = result . mappings ( ) . first ( ) [ " id " ]
try :
datasheet_filename = request . form [ ' datasheet-url ' ]
return jsonify ( status = " ok " , part_id = new_id )
except :
@app.route ( baseURL + ' /delete/<partID> ' )
datasheet_filename = l [ 0 ] [ ' datasheet ' ]
s + = ' where id=:id returning id; '
s = text ( s )
r = db_engine . execute ( s , partno = request . form [ ' partno ' ] ,
description = request . form [ ' description ' ] ,
datasheet = datasheet_filename ,
location_id = request . form [ ' location_id ' ] ,
id = partID ,
notes = request . form [ ' notes ' ] )
new_id = r . fetchone ( ) [ 0 ]
r . close ( )
return ' { " status " : " ok " , " part_id " : ' + str ( new_id ) + ' } '
@app.route ( baseURL + ' /delete/<partID> ' )
@requires_auth
@requires_auth
def delete ( partID ) :
def delete ( partID ) :
if int ( partID ) < 0 :
partID = int ( partID )
if partID < 0 :
abort ( 400 )
abort ( 400 )
s = text ( ' delete from parts where id=:id; ' )
r = db_engine . execute ( s , id = partID )
return ' { " status " : " ok " } '
@app.route ( baseURL + ' /deleteLocation/<locationID> ' )
query = text ( ' delete from parts where id=:id ' )
with db_engine . begin ( ) as conn :
conn . execute ( query , { " id " : partID } )
return jsonify ( status = " ok " )
@app.route ( baseURL + ' /deleteLocation/<locationID> ' )
@requires_auth
@requires_auth
def deleteLocation ( locationID ) :
def deleteLocation ( locationID ) :
if int ( locationID ) < 0 :
locationID = int ( locationID )
if locationID < 0 :
abort ( 400 )
abort ( 400 )
s = text ( ' delete from locations where id=:id; ' )
r = db_engine . execute ( s , id = locationID )
query = text ( ' delete from locations where id=:id ' )
return ' { " status " : " ok " } '
@app.route ( baseURL + ' /deleteUser/<userID> ' )
with db_engine . begin ( ) as conn :
conn . execute ( query , { " id " : locationID } )
return jsonify ( status = " ok " )
@app.route ( baseURL + ' /deleteUser/<userID> ' )
@requires_auth
@requires_auth
def deleteUser ( userID ) :
def deleteUser ( userID ) :
if int ( userID ) < 0 :
userID = int ( userID )
if userID < 0 :
abort ( 400 )
abort ( 400 )
s = text ( ' delete from users where id=:id; ' )
r = db_engine . execute ( s , id = userID )
query = text ( ' delete from users where id=:id ' )
return ' { " status " : " ok " } '
with db_engine . begin ( ) as conn :
conn . execute ( query , { " id " : userID } )
return jsonify ( status = " ok " )
@app.route ( baseURL + ' /fetchOctopartSnippet/<searchTerm> ' )
@app.route ( baseURL + ' /fetchOctopartSnippet/<searchTerm> ' )
def fetchOctopartSnippet ( searchTerm ) :
def fetchOctopartSnippet ( searchTerm ) :
@ -380,8 +459,8 @@ def connect(user, password, db, host='localhost', port=5432):
con = sqlalchemy . create_engine ( url , client_encoding = ' utf8 ' )
con = sqlalchemy . create_engine ( url , client_encoding = ' utf8 ' )
# We then bind the connection to MetaData()
# We then bind the connection to MetaData()
meta = sqlalchemy . MetaData ( bind = con )
meta = sqlalchemy . MetaData ( )
meta . reflect ( bind= con)
meta . reflect ( con)
return con , meta
return con , meta
@ -395,7 +474,7 @@ if __name__ == '__main__':
try :
try :
with open ( ' octopartAPIkey.json ' ) as f :
with open ( ' octopartAPIkey.json ' ) as f :
j = json . load ( f ) ;
j = json . load ( f ) ;
if j [ ' key ' ] is not ' ' :
if j [ ' key ' ] != ' ' :
octopartURL = j [ ' URL ' ] + j [ ' key ' ]
octopartURL = j [ ' URL ' ] + j [ ' key ' ]
print ( " Octopart credentials loaded. " )
print ( " Octopart credentials loaded. " )
else :
else :
@ -404,6 +483,7 @@ if __name__ == '__main__':
print ( " NO OCTOPART KEY FOUND. ABANDONING THAT PART " )
print ( " NO OCTOPART KEY FOUND. ABANDONING THAT PART " )
# Example query
# Example query
''' s = select([parts]).where(parts.c.notes != ' ' )
''' s = select([parts]).where(parts.c.notes != ' ' )
for row in db_engine . execute ( s ) :
with db_engine . connect ( ) as conn :
print row '''
r = conn . execute ( text ( query ) )
app . run ( host = ' 127.0.0.1 ' , port = ' 5000 ' , debug = False )
'''
app . run ( host = ' 127.0.0.1 ' , port = ' 5000 ' , debug = False )