API can add and view items/images

main
Ashelyn Dawn 4 years ago
parent 502532262e
commit db6366550d

@ -0,0 +1,11 @@
const router = require('express-promise-router')()
const db = require('../db')
router.get('/:uuid/:size', async (req, res) => {
const image = await db.item.getImage(req.params.uuid, req.params.size)
res.set('Content-Type', image.mime_type)
res.end(image.file)
})
module.exports = router

@ -2,6 +2,8 @@ const router = require('express-promise-router')()
const pg = require('../db/pg')
router.use('/users/', require('./users'))
router.use('/items/', require('./items'))
router.use('/images/', require('./images'))
router.get('/', (req, res)=>{
res.json({test: true})

@ -5,34 +5,57 @@ const db = require('../db')
const {validationResult} = require('express-validator')
const validate = require('./middleware/validators')
const upload = multer({
storage: multer.memoryStorage(),
const upload = require('multer')({
storage: require('multer').memoryStorage(),
limits: {
files: 1,
fileSize: 500000
}
})
router.post('/', parseJSON, validate.urlSlugRestrictions('slug'), async (req, res) => {
router.get('/', async (req, res) => {
const items = await db.item.findAll()
res.json(items)
})
const newItemValidators = [
validate.urlSlugRestrictions,
validate.publishedBool,
validate.priceCentsInt,
validate.nameRestrictions,
validate.descriptionRestrictions
]
router.post('/', parseJSON, newItemValidators, async (req, res) => {
const errors = validationResult(req)
if(!errors.isEmpty())
return res.status(422).json({errors: errors.array()})
const item = await db.item.create(
req.body.name,
req.body.urlslug,
req.body.description,
req.body.price_cents,
req.body.published
)
// TODO: Create session
res.json(user)
res.json(item)
})
router.post('/:uuid/images', upload.single('image'), async (req, res) => {
// TODO: Use the real user when we have authentication
req.user = {
uuid: '5e17388d-612b-4ea8-b76d-620a7bb24824'
}
// Handle either image upload body or JSON body
try {
if(req.file)
await db.item.addImage(req.params.uuid, req.file.buffer)
await db.item.addImage(req.params.uuid, req.file.buffer, req.user.uuid)
else
await db.item.addImage(req.params.uuid, await b64.decode(req.body.image.split(',')[1]))
await db.item.addImage(req.params.uuid, await b64.decode(req.body.image.split(',')[1]), req.user.uuid)
} catch (error) {
error.status = 500
throw error

@ -18,5 +18,16 @@ validators.checkEmailNotUsed = body('email').custom(async email=>{
if(user) throw new Error('Email already in use')
})
validators.urlSlugRestrictions = field => body(field).isString().isLength({min: 3, max: 20}).matches(/[-a-z0-9_]*/i)
validators.urlSlugRestrictions = body('urlslug').isString().isLength({min: 3, max: 20}).matches(/^[-a-z0-9_]*$/i)
.withMessage('Slug can be between 3-20 characters long, and can include letters, numbers, dash or underscore')
validators.nameRestrictions = body('name').isString()
.withMessage('Name required. Must be a string')
validators.descriptionRestrictions = body('description').isString()
.withMessage('Description required. Must be a string')
validators.publishedBool = body('published').isBoolean()
validators.priceCentsInt = body('price_cents').isInt().custom(price => price > 0)
.withMessage('Price must be a positive integer')

@ -1,3 +1,4 @@
module.exports = {
user: require('./models/user')
user: require('./models/user'),
item: require('./models/item')
}

@ -1,3 +1,4 @@
module.exports = [
...require('./user')
...require('./user'),
...require('./item')
]

@ -22,7 +22,7 @@ module.exports = [{
'published'
],
collections: [
{name: 'images', mapId: 'imageMap', columnPrefix: 'imageColumn_'}
{name: 'images', mapId: 'imageMap', columnPrefix: 'image_'}
]
},{
mapId: 'bareImageMap',

@ -7,6 +7,15 @@ const sharp = require('sharp')
const item = module.exports = {}
item.findAll = async () => {
const query = 'select * from v_item'
debug(query);
const {rows} = await pg.query(query)
return joinjs.map(rows, mappings, 'itemMap', 'item_');
}
item.findById = async (item_uuid) => {
const query = {
text: 'select * from v_item where item_uuid = $1',
@ -37,7 +46,7 @@ item.findBySlug = async (item_slug) => {
item.create = async (name, urlslug, description, price_cents, published) => {
const query = {
text: 'select * from public.create_item($1::text, $2::citext, $2::text, $4::integer, $5::boolean)',
text: 'select * from public.create_item($1::text, $2::citext, $3::text, $4::integer, $5::boolean)',
values: [
name,
urlslug,
@ -80,20 +89,20 @@ item.addImage = async (item_uuid, image_buffer, uploader_uuid) => {
return joinjs.map(rows, mappings, 'itemMap', 'item_')
}
const queries = {
const imageSizeQueries = {
'large': 'select * from get_image_large($1)',
'thumb': 'select * from get_image_thumb($1)'
}
item.getImage = async (image_uuid, size) => {
if(!profileSizeQueries[size])
if(!imageSizeQueries[size])
throw new Error(`Cannot get unknown image size: "${size}"`)
const query = {
text: profileSizeQueries[size],
text: imageSizeQueries[size],
values: [image_uuid]
}
const {rows} = await pg.query(query)
return joinjs.map(rows, relationMaps, 'bareImageMap', 'image_')[0];
return joinjs.map(rows, mappings, 'bareImageMap', 'image_')[0];
}

@ -51,7 +51,7 @@ create table "cart_item" (
cart_item_uuid uuid primary key default uuid_generate_v4(),
cart_item_item_uuid uuid not null references "item" (item_uuid),
cart_item_cart_uuid uuid not null references "cart" (cart_uuid),
cart_item_count integer not null default 1,
cart_item_count integer not null default 1 check (cart_item_count > 0),
cart_item_time_added timestamptz not null default now()
);

@ -123,9 +123,9 @@ create or replace function public.get_image_large(_image_uuid uuid)
as $function$
begin
return query select
image_uuid,
image_mime_type,
image_large_file as image_file
"image".image_uuid,
"image".image_mime_type,
"image".image_large_file as image_file
from "image"
where "image".image_uuid = _image_uuid;
end; $function$;
@ -136,9 +136,9 @@ create or replace function public.get_image_thumb(_image_uuid uuid)
as $function$
begin
return query select
image_uuid,
image_mime_type,
image_large_thumb as image_file
"image".image_uuid,
"image".image_mime_type,
"image".image_thumb_file as image_file
from "image"
where "image".image_uuid = _image_uuid;
end; $function$;

@ -1,3 +1,4 @@
require('dotenv').config()
const express = require('express');
const next = require('next');

Loading…
Cancel
Save