You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
847 lines
29 KiB
Lua
847 lines
29 KiB
Lua
--local xxhash = require( "xxhash" )
|
|
--local uuid = require( 'resty.jit-uuid' )
|
|
local uuid = require( 'lua_uuid' )
|
|
local DB = require( "./piazza-lmdb" )
|
|
local db = DB.init()
|
|
|
|
local user = require'./models/user'
|
|
local item = require'./models/item'
|
|
local image = require'./models/image'
|
|
local thumbnail = require'./models/thumbnail'
|
|
local cart = require'./models/cart'
|
|
local lineitem = require'./models/lineitem'
|
|
local order = require'./models/order'
|
|
local customprice = require'./models/customprice'
|
|
local application = require'./models/application'
|
|
|
|
local util = require( './piazza-util' )
|
|
|
|
local models = {user, item, image, thumbnail, cart, lineitem, order, customprice, application}
|
|
for _, model in ipairs(models) do
|
|
model.setdb(db)
|
|
end
|
|
|
|
-- password hash:
|
|
local hash = util.hash
|
|
|
|
local sessions = {} -- keys are session_hashes, values are whatever the server wants to store
|
|
|
|
local validate = util.validate
|
|
|
|
local api = {};
|
|
api.post = function()
|
|
return {message="I did a post."}
|
|
end
|
|
|
|
api.attemptlogin = function(req)
|
|
local validation_errors = validate(req, {
|
|
username = {'string', required=true},
|
|
password = {'string', required=true}
|
|
})
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local user_record = db:findOne(function(record)
|
|
return record.type == 'user' and record.username == req.username
|
|
end)
|
|
if user_record == nil then
|
|
return {success = false, error="no such user"}
|
|
elseif user_record.password_hash ~= hash(req.password) then
|
|
return {success = false, error="wrong password"}
|
|
-- TODO: add 'elseif' to make sure user isn't already logged-in, so two sessions aren't made for the same user who clicked 'login' button twice; although this will make it impossible to sign-in from two different computers
|
|
else
|
|
local session_hash = uuid()
|
|
sessions[session_hash] = {user_id = user_record.id}
|
|
if user_record.current_cart_id == nil then
|
|
cart.newForUser(user_record)
|
|
end
|
|
return {
|
|
success = true,
|
|
-- user = db:preparecopy(user_record, {'password_hash'}),
|
|
-- cart = db:preparecopy(user_record.current_cart),
|
|
user = user_record:copyandtransform({
|
|
id = 'copy',
|
|
username = 'copy',
|
|
firstname = 'copy',
|
|
tier = 'copy',
|
|
is_admin = 'copy'
|
|
}),
|
|
cart = db:getrecord(user_record.current_cart_id):copyandtransform({
|
|
id = 'copy',
|
|
lineitem_ids = {'list', {
|
|
id = 'copy',
|
|
quantity = 'copy',
|
|
price = 'copy',
|
|
item_id = {
|
|
id = 'copy',
|
|
name = 'copy',
|
|
brand = 'copy',
|
|
model = 'copy',
|
|
color = 'copy'
|
|
}
|
|
}}
|
|
}),
|
|
session_hash = session_hash
|
|
}
|
|
end
|
|
end
|
|
end
|
|
|
|
api.logout = function(req)
|
|
local session_hash = req.session_hash
|
|
if session_hash ~= nil and sessions[session_hash] ~= nil then
|
|
sessions[session_hash] = nil
|
|
return {success=true}
|
|
else
|
|
return {error="no such session_hash"} -- TODO: this could happen if user logged-in, then fastcgi was restarted (thus clearing the sessions table), and then logged-out
|
|
end
|
|
end
|
|
|
|
api.getone = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true},
|
|
['type'] = {'string', required=true},
|
|
id = {'db_ref', to=req['type'], required=true, load_as='record'},
|
|
structure = {'table', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local record_copy = loaded_records.record:copyandtransform(req.structure)
|
|
return {success = true, record = record_copy}
|
|
end
|
|
end
|
|
|
|
--[[ -- too big of a security concern. it could return the whole DB to a clever attacker
|
|
api.getall = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true},
|
|
filter = {'table', required=true}, -- TODO: ensure 'filter' is a non-empty table, for security reasons, because then the whole DB will be returned
|
|
structure = {'table', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local records = db:findByStructure(req.filter)
|
|
local record_copies = db:copyandtransformall(records, req.structure)
|
|
return {success=true, records = record_copies}
|
|
end
|
|
end
|
|
]]
|
|
|
|
api.setproperty = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
record_type = {'string', required=true},
|
|
record_id = {'db_ref', to=req.record_type, required=true, load_as='record'},
|
|
key = {'string', required=true}
|
|
-- value = {'string', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local record = loaded_records.record
|
|
record[req.key] = req.value
|
|
record:save()
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
api.insertrecord = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true},
|
|
record = {'table', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local id = db:insertrecord(req.record)
|
|
return {success=true, id = id}
|
|
end
|
|
end
|
|
|
|
|
|
-- admin function: add item
|
|
api.additem = function(req)
|
|
local validation_errors = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
item = {'table', required=true}
|
|
}, nil, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
item.new(req.item)
|
|
-- if saving succeeds, return success message
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
-- admin function: delete item
|
|
api.deleteitem = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
item_id = {'db_ref', to='item', required=true, load_as='item_record'}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
-- delete item
|
|
--loaded_records.item_record:delete()
|
|
loaded_records.item_record.deleted = true
|
|
loaded_records.item_record:save()
|
|
-- if deletion succeeds, return success message
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
-- admin function: update item
|
|
-- session_hash, item_id, properties_to_update
|
|
api.updateitem = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
item_id = {'db_ref', to='item', required=true, load_as='item_record'},
|
|
properties_to_update = {'table', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
util.merge(loaded_records.item_record, req.properties_to_update)
|
|
loaded_records.item_record:save()
|
|
--db:update(loaded_records.item_record, req.properties_to_update)
|
|
-- if update succeeds, reply with success
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
api.fulliteminfo = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
item_id = {'db_ref', to='item', required=true, load_as='item_record'}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local item_record_copy = loaded_records.item_record:copyandtransform({
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
description_short = 'copy',
|
|
size = 'copy',
|
|
material = 'copy',
|
|
color_description = 'copy'
|
|
})
|
|
-- if update succeeds, reply with success
|
|
return {success=true, item=item_record_copy}
|
|
end
|
|
end
|
|
|
|
--[[
|
|
api.newimage = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
image_base64 = {'base64', required=true, load_as = 'image_base64'},
|
|
original_filename = {'string', required=true} -- so we can tell for which frame it is in retrospect
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
image.new_from_base64(loaded_records.image_base64, req.original_filename, db)
|
|
return {success=true}
|
|
end
|
|
end
|
|
]]
|
|
|
|
-- admin function: create new empty frame record
|
|
-- session_hash
|
|
api.createnewframe = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local new_frame_record = item.new({
|
|
subtype='frame',
|
|
brand='',
|
|
model='',
|
|
color = '',
|
|
color_description = '',
|
|
name = '',
|
|
description_short = '',
|
|
size = '',
|
|
material = '',
|
|
price_silver = 0,
|
|
price_gold = 0,
|
|
inventory = 0
|
|
})
|
|
local new_frame_record_copy = new_frame_record:copyandtransform({
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
subtype = 'copy',
|
|
brand = 'copy',
|
|
model = 'copy',
|
|
color = 'copy',
|
|
color_description = 'copy',
|
|
name = 'copy',
|
|
description_short = 'copy',
|
|
size = 'copy',
|
|
material = 'copy',
|
|
price_silver = 'copy',
|
|
price_gold = 'copy',
|
|
inventory = 'copy'
|
|
})
|
|
-- if update succeeds, reply with success
|
|
return {success=true, new_frame=new_frame_record_copy}
|
|
end
|
|
end
|
|
|
|
-- admin function: add image to item
|
|
-- session_hash, item_id, image_base64, original_filename
|
|
api.addimagetoitem = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
item_id = {'db_ref', to='item', required=true, load_as='item_record'},
|
|
image_base64 = {'base64', required=true, load_as='image_base64'},
|
|
original_filename = {'string', required=true} -- so we can tell for which frame it is in retrospect
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local image_record = image.new_from_base64(loaded_records.image_base64, req.original_filename)
|
|
local item_record = loaded_records.item_record
|
|
-- image_record.item = item_record -- not all images have a `.item` property, so we should rather link the image to the item by `item.images`
|
|
if item_record.image_ids == nil then item_record.image_ids = {} end
|
|
table.insert(item_record.image_ids, image_record.id)
|
|
item_record:save()
|
|
local image_record_copy = image_record:copyandtransform({
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
original_filename = 'copy',
|
|
thumbnail_960_id = 'copy',
|
|
thumbnail_180_id = 'copy',
|
|
thumbnail_original_id = 'copy'
|
|
})
|
|
-- if update succeeds, reply with success
|
|
return {success=true, image=image_record_copy}
|
|
end
|
|
end
|
|
|
|
api.deleteitemimage = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
item_id = {'db_ref', to='item', required=true, load_as='item_record'},
|
|
image_id = {'db_ref', to='image', required=true, load_as='image_record'}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local image_record = loaded_records.image_record
|
|
local item_record = loaded_records.item_record
|
|
-- image_record.item = item_record -- not all images have a `.item` property, so we should rather link the image to the item by `item.images`
|
|
if item_record.image_ids == nil then item_record.image_ids = {} end
|
|
local image_index = 0
|
|
repeat
|
|
image_index = image_index + 1
|
|
until item_record.image_ids[image_index] == image_record.id or item_record.image_ids[image_index] == nil
|
|
|
|
table.remove(item_record.image_ids, image_index)
|
|
item_record:save()
|
|
-- also delete the image_record, and the files it points to
|
|
image_record:delete()
|
|
|
|
db:delete(image_record.thumbnail_original_id)
|
|
db:delete(image_record.thumbnail_960_id)
|
|
db:delete(image_record.thumbnail_180_id)
|
|
|
|
-- if update succeeds, reply with success
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
api.itemsbystring = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true},
|
|
search_string = {'string', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local item_records = db:findAll(function(record)
|
|
return record.type == 'item' and string.find(record.model, req.search_string) ~= nil
|
|
end)
|
|
item_records = db:copyandtransformall(item_records, {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
brand = 'copy',
|
|
model = 'copy',
|
|
color = 'copy'
|
|
})
|
|
return {success=true, results = item_records}
|
|
end
|
|
end
|
|
|
|
api.framesbystring = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true},
|
|
search_string = {'string', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local item_records = db:findAll(function(record)
|
|
return record.subtype == 'frame' and string.find(record.model, req.search_string) ~= nil
|
|
end)
|
|
item_records = db:copyandtransformall(item_records, {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
subtype = 'copy',
|
|
name = 'copy',
|
|
brand = 'copy',
|
|
model = 'copy',
|
|
color = 'copy',
|
|
color_description = 'copy',
|
|
description_short = 'copy',
|
|
size = 'copy',
|
|
material = 'copy',
|
|
price_silver = 'copy',
|
|
price_gold = 'copy',
|
|
inventory = 'copy'
|
|
})
|
|
return {success=true, results = item_records}
|
|
end
|
|
end
|
|
|
|
api.itemimages = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
--session_hash = {'session', required=true},
|
|
item_id = {'db_ref', to='item', required=true, load_as='item_record'}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local item_record = loaded_records.item_record
|
|
if item_record.image_ids == nil then
|
|
item_record.image_ids = {}
|
|
item_record:save()
|
|
end
|
|
local image_records = db:copyandtransformall(item_record.image_ids, {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
original_filename = 'copy',
|
|
thumbnail_960_id = 'copy',
|
|
thumbnail_180_id = 'copy',
|
|
thumbnail_original_id = 'copy'
|
|
})
|
|
return {success=true, images = image_records}
|
|
end
|
|
end
|
|
|
|
-- admin function: change user's tier
|
|
-- session_hash, user_id, tier
|
|
api.changeusertier = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
user_id = {'db_ref', to='user', required=true, load_as='user_record'},
|
|
tier = {'string', required=true, is_any_of={'gold','silver'}}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
--db:update(loaded_records.user_record, {tier=req.tier})
|
|
loaded_records.user_record.tier = req.tier
|
|
loaded_records.user_record:save()
|
|
-- if update succeeds, reply with success
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
-- admin function: give custom price to user for certain item
|
|
-- session_hash, user_id, item_id, price
|
|
api.setuseritemprice = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
user_id = {'db_ref', to='user', required=true, load_as='user_record'},
|
|
item_id = {'db_ref', to='item', required=true, load_as='item_record'},
|
|
price = {'number', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
-- find previously-existing special price between this user and this item
|
|
local custom_price_record = db:findOne(function(record) return record.type == 'custom_price' and record.user_id == loaded_records.user_record.id and record.item_id == loaded_records.item_record_id end)
|
|
-- if no existing special price is found, insert one into DB
|
|
if custom_price_record == nil then
|
|
customprice.new({user_id=loaded_records.user_record.id, item_id=loaded_records.item_record.id, price=req.price})
|
|
-- if insert succeeds, reply with success
|
|
return {success=true}
|
|
-- if insert fails, reply with error
|
|
-- if existing special price is found, update it
|
|
else
|
|
--db:update(custom_price_record, {price = req.price})
|
|
custom_price_record.price = req.price
|
|
custom_price_record:save()
|
|
-- if update succeeds, reply with success
|
|
return {success=true}
|
|
-- if update fails, reply with error
|
|
end
|
|
end
|
|
end
|
|
|
|
-- function: update item quantity in current cart; if zero, remove; if was zero, add to cart
|
|
api.updateitemquantityincart = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true},
|
|
item_id = {'db_ref', to='item', required=true, load_as='item_record'},
|
|
quantity = {'number', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
-- find cart based on session_hash
|
|
local current_user_record = db:getrecord( loaded_records.session.user_id )
|
|
local cart_record = db:getrecord(current_user_record.current_cart_id)
|
|
-- if cart not found, create one
|
|
if cart_record == nil then
|
|
cart_record = cart.newForUser(current_user_record)
|
|
end
|
|
-- find lineitem for this item in cart
|
|
local lineitem_record_id = util.findOne(cart_record.lineitem_ids, function(lineitem_id)
|
|
local lineitem = db:getrecord(lineitem_id)
|
|
return lineitem.item_id == loaded_records.item_record.id
|
|
end)
|
|
local lineitem_record
|
|
-- if lineitem not found, create one
|
|
if lineitem_record_id == nil then
|
|
if req.quantity > 0 then
|
|
lineitem_record = lineitem.new({cart=cart_record, item=loaded_records.item_record, quantity=req.quantity})
|
|
end
|
|
else
|
|
lineitem_record = db:getrecord(lineitem_record_id)
|
|
if req.quantity > 0 then
|
|
-- update quantity in lineitem
|
|
--db:update(lineitem_record, {quantity = req.quantity})
|
|
lineitem_record.quantity = req.quantity
|
|
lineitem_record:save()
|
|
-- if the item is being removed from the cart
|
|
elseif req.quantity == 0 then
|
|
-- remove item from cart
|
|
util.removefromtable(cart_record.lineitem_ids, lineitem_record.id)
|
|
--db:remove(lineitem_record)
|
|
lineitem_record:delete()
|
|
cart_record:save()
|
|
end
|
|
end
|
|
local lineitem_records_copy = db:copyandtransformall(cart_record.lineitem_ids, {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
item_id = {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
name = 'copy',
|
|
brand = 'copy',
|
|
model = 'copy',
|
|
color = 'copy',
|
|
price_silver = 'copy',
|
|
price_gold = 'copy',
|
|
inventory = 'copy',
|
|
price = 'copy',
|
|
},
|
|
quantity = 'copy',
|
|
price = 'copy'
|
|
})
|
|
return {success=true, lineitems = lineitem_records_copy}
|
|
end
|
|
end
|
|
|
|
-- function: place order (i.e. current cart)
|
|
api.placeorder = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
-- find cart based on session_hash
|
|
local current_user_record = db:getrecord( loaded_records.session.user_id )
|
|
local cart_record = db:getrecord( current_user_record.current_cart_id )
|
|
-- if cart not found, reply with error
|
|
if cart_record == nil then
|
|
return {error="No cart for current user."}
|
|
elseif #cart_record.lineitem_ids == 0 then
|
|
return {error="Cart is empty."}
|
|
else
|
|
-- if cart found, create order out of it
|
|
local order_record = order.new({cart=cart_record})
|
|
-- if order creation successful, create new empty cart for user and reply with success
|
|
for _, lineitem_id in ipairs(cart_record.lineitem_ids) do
|
|
local lineitem_record = db:getrecord(lineitem_id)
|
|
local item_record = db:getrecord(lineitem_record.item_id)
|
|
item_record.inventory = item_record.inventory - lineitem_record.quantity
|
|
item_record:save()
|
|
end
|
|
local new_cart_record = cart.newForUser(current_user_record)
|
|
return {success=true, order_id = order_record.id, new_cart_record = new_cart_record}
|
|
end
|
|
end
|
|
end
|
|
|
|
-- admin function: list open orders
|
|
api.listopenorders = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
-- find open orders
|
|
local open_order_records = db:findAll(function(record)
|
|
return record.type == 'order' and record.status == 'open'
|
|
end)
|
|
-- local open_orders = db:preparecopies(open_order_records)
|
|
local open_orders = db:copyandtransformall(open_order_records, {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
cart_id = 'copy',
|
|
user_id = {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
firstname = 'copy',
|
|
lastname = 'copy',
|
|
store = 'copy'
|
|
},
|
|
date_ordered = 'copy',
|
|
status = 'copy',
|
|
progress = 'copy'
|
|
})
|
|
return {success=true, orders=open_orders}
|
|
end
|
|
end
|
|
|
|
-- admin function: list open orders
|
|
api.loadorder = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
order_id = {'db_ref', to='order', load_as='order_record'}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local order_record_copy = loaded_records.order_record:copyandtransform({
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
progress = 'copy',
|
|
cart_id = {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
lineitem_ids = {
|
|
'list',
|
|
{
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
price = 'copy',
|
|
quantity = 'copy',
|
|
item_id = {
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
name = 'copy'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
return {success=true, order=order_record_copy}
|
|
end
|
|
end
|
|
|
|
-- admin function: mark order as packed, shipped, and delivered
|
|
api.updateorderstatus = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
order_id = {'db_ref', to='order', required=true, load_as='order_record'},
|
|
status = {'string', required=true, is_any_of={'open','packed','shipped','paid'}}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
-- if order found, update status
|
|
--db:update(loaded_records.order_record, {status = req.status})
|
|
loaded_records.order_record.status = req.status
|
|
loaded_records.order_record:save()
|
|
-- if update succeeds, reply with success
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
-- function: find items according to privileges and characteristics
|
|
api.itemsbyfilter = function(req)
|
|
local filter = req.filter
|
|
local item_records = db:findAll(function(record)
|
|
if record.type ~= 'item' then return false end
|
|
--if record.inventory == nil then record.inventory = 0; record:save() end
|
|
if record.inventory < 1 then return false end
|
|
-- if user is not signed-in, he cannot see all items:
|
|
if req.session_hash == nil then
|
|
for k,v in pairs(filter) do
|
|
if record[k] ~= v then return false end
|
|
if item.restricted == true then return false end
|
|
end
|
|
-- if user is signed-in, he may see all items:
|
|
else
|
|
for k,v in pairs(filter) do
|
|
if record[k] ~= v then return false end
|
|
end
|
|
end
|
|
return true
|
|
end)
|
|
local item_records_copy = db:copyandtransformall(item_records, {
|
|
id = 'copy',
|
|
name = 'copy',
|
|
brand = 'copy',
|
|
model = 'copy',
|
|
color = 'copy',
|
|
color_description = 'copy',
|
|
size = 'copy',
|
|
material = 'copy',
|
|
description_short = 'copy',
|
|
price_gold = 'copy',
|
|
price_silver = 'copy',
|
|
inventory = 'copy',
|
|
image_ids = {
|
|
'list',
|
|
{
|
|
id = 'copy',
|
|
['type'] = 'copy',
|
|
thumbnail_180_id = 'copy',
|
|
thumbnail_960_id = 'copy',
|
|
thumbnail_original_id = 'copy'
|
|
}
|
|
}
|
|
})
|
|
-- TODO: only send the price for each item according to the user's tier, or his own special pricing. don't send price_silver and price_gold
|
|
return {success=true, items = item_records_copy}
|
|
end
|
|
|
|
-- function: submit new user application, to be accepted or declined by admin
|
|
api.submitnewuserapplication = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
username = {'string', required=true},
|
|
salutation = {'string', required=true, is_any_of={'mr','ms','mrs','dr'}},
|
|
firstname = {'string', required=true},
|
|
lastname = {'string', required=true},
|
|
position = {'string', required=true},
|
|
store = {'string', required=true},
|
|
address = {'string', required=true},
|
|
practice_type = {'string', required=true},
|
|
phone_office = {'string', required=true},
|
|
phone_cell = {'string', required=true},
|
|
email = {'string', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
application.new({
|
|
['type'] = 'application',
|
|
username = req.username,
|
|
salutation = req.salutation,
|
|
firstname = req.firstname,
|
|
lastname = req.lastname,
|
|
position = req.position,
|
|
store = req.store,
|
|
address = req.address,
|
|
practice_type = req.practice_type,
|
|
phone_office = req.phone_office,
|
|
phone_cell = req.phone_cell,
|
|
email = req.email
|
|
})
|
|
-- if update succeeds, reply with success
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
api.acceptnewuserapplication = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
application_id = {'db_ref', to='application', required=true, load_as='application_record'},
|
|
password = {'string', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
local application_record = loaded_records.application_record
|
|
user.new({
|
|
password = req.password,
|
|
username = application_record.username,
|
|
salutation = application_record.salutation,
|
|
firstname = application_record.firstname,
|
|
lastname = application_record.lastname,
|
|
position = application_record.position,
|
|
store = application_record.store,
|
|
address = application_record.address,
|
|
practice_type = application_record.practice_type,
|
|
phone_office = application_record.phone_office,
|
|
phone_cell = application_record.phone_cell,
|
|
email = application_record.email,
|
|
tier='silver'
|
|
})
|
|
--db:update(application_record, {status = 'accepted', accepted_at = os.time()})
|
|
application_record.status = 'accepted'
|
|
application_record.accepted_at = os.time()
|
|
application_record:save()
|
|
-- if update succeeds, reply with success
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
-- admin function: list open application records
|
|
api.listnewuserapplications = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
-- find open applications
|
|
local open_application_records = db:findAll(function(record) return record.type == 'application' and record.status == 'open' end)
|
|
local open_applications = db:copyandtransformall(open_application_records, {
|
|
id='copy',
|
|
['type'] = 'copy',
|
|
username = 'copy',
|
|
salutation = 'copy',
|
|
firstname = 'copy',
|
|
lastname = 'copy',
|
|
position = 'copy',
|
|
store = 'copy',
|
|
address = 'copy',
|
|
practice_type = 'copy',
|
|
phone_office = 'copy',
|
|
phone_cell = 'copy',
|
|
email = 'copy',
|
|
submitted_at = 'copy'
|
|
})
|
|
return {success=true, open_applications=open_applications}
|
|
end
|
|
end
|
|
|
|
api.declinenewuserapplication = function(req)
|
|
local validation_errors, loaded_records = validate(req, {
|
|
session_hash = {'session', required=true, is_admin=true},
|
|
application_id = {'db_ref', to='application', required=true, load_as='application_record'},
|
|
password = {'string', required=true}
|
|
}, db, sessions)
|
|
if #validation_errors > 0 then
|
|
return {errors=validation_errors}
|
|
else
|
|
--db:update(loaded_records.application_record, {status = 'declined', declined_at = os.time()})
|
|
local application_record = loaded_records.application_record
|
|
application_record.status = 'declined'
|
|
application_record.declined_at = os.time()
|
|
application_record:save()
|
|
-- if update succeeds, reply with success
|
|
return {success=true}
|
|
end
|
|
end
|
|
|
|
api.getthumbnail = function(thumbnail_id)
|
|
return db:getrecord(thumbnail_id).src
|
|
end
|
|
|
|
return api
|