const models = require('./models');
const express = require('express');
const uuidv4 = require('uuid/v4');
const bcrypt = require('bcrypt');
const asyncHandler = require('express-async-handler');
const error = require('./utils').appThrow;
const bodyParser = express.urlencoded({extended: true});
var app = express();

var requireUser = asyncHandler(async (req, res, next) => {
  var userId = req.body.id;
  var token = req.body.token;
  var user = await models.user.findOne({where: {'id': userId}});
  if (!user) {
    error(403, "user");
    return;
  }
  if (!await bcrypt.compare(token, user.token)) {
    error(403, "user");
    return;
  }
  req.user = user;
  next();
});
app.get('/users', asyncHandler(async (req, res) => {
  var users = await models.user.findAll();
  res.send(JSON.stringify(users));
}));
app.post('/users/new', asyncHandler(async (req, res) => {
  var rawToken = uuidv4();
  var token = await bcrypt.hash(rawToken, 10);
  var user = await models.user.create({token: token});
  res.send(JSON.stringify({id: user.id, token: rawToken}));
}));
app.get('/mai/:nickname', asyncHandler(async (req, res) => {
  var nickname = req.params.nickname;
  var player = await models.laundryPlayer.findOne({where: {'nickname': nickname}});
  if (!player) {
    error(404, "not_found");
  }
}));
app.post('/mai/', bodyParser, requireUser, asyncHandler(async (req, res) => {
  var nickname = req.body.nickname;
  var privacy = req.body.privacy;
  var user = req.user;
  var player = await models.laundryPlayer.findOne({where: {'nickname': nickname}});
  if (player) {
    error(400, "exists");
    return;
  }
  var newPlayer = await models.laundryPlayer.create({'nickname': nickname, 'userId': user.id, 'privacy': privacy});
  res.send(JSON.stringify({}));
}));

app.post('/mai/:nickname', bodyParser, requireUser, asyncHandler(async (req, res) => {
  var nickname = req.params.nickname;
  var user = req.user;
  var player = await models.laundryPlayer.findOne({where: {'nickname': nickname}});
  if (!player) {
    error(404, "not_exists");
    return;
  }
  if (player.userId != user.id) {
    error(403, "forbidden");
    return;
  }
}));

app.use(function(err, req, res, next) {
  if (!err.exposed) {
    console.log(err);
    res.status(500).send(JSON.stringify({"err": "internal"}));
  } else {
    res.status(err.status).send(JSON.stringify({"err": err.message}));
  }
});

app.listen(8585);

@@ -185,24 +185,167 @@
 -handler');%0A
+const %7B check, validationResult %7D = require('express-validator/check');%0Aconst %7B matchedData, sanitize %7D = require('express-validator/filter');%0A
 const error 
@@ -1487,42 +1487,317 @@
 er, 
-asyncHandler(async (req, res) =%3E %7B
+%5B%0A  check('nickname').matches(/%5B0-9a-z%5C-%5C_%5D/),%0A  check('privacy').matches(/%5E(public%7Canonymous%7Cprivate)$/)%0A%5D, asyncHandler(async (req, res) =%3E %7B%0A  const errors = validationResult(req);%0A  if (!errors.isEmpty()) %7B%0A    console.log(errors.mapped());%0A    error(422, %22validation%22);%0A  %7D%0A  var data = matchedData(req);
 %0A  v
@@ -1810,24 +1810,20 @@
 kname = 
-req.body
+data
 .nicknam
@@ -1841,24 +1841,20 @@
 ivacy = 
-req.body
+data
 .privacy

Add validation.