首页 > 解决方案 > “路径中的值 1,1 转换为数字失败”

问题描述

我正在尝试构建具有某些特权的用户模型。

架构如下所示:

var mongoose = require("mongoose"), 
    passportLocalMongoose = require("passport-local-mongoose");

let userSchema = new mongoose.Schema({
    username:
    {type: String,
    unique: true
    },
    password: String,
    privileges:
    [{
            region: { type: Number, unique: true },
            read: Number,
            write: Number,
            edit: Number
    }]
});

userSchema.plugin(passportLocalMongoose);

module.exports = mongoose.model("User", userSchema);

POST 路线看起来像这样。

router.post('/register', function(req, res)
{
    console.log(req.body);
    User.register(new User({
        username: req.body.username,
        privileges:{
            region: req.body.privileges['region'],
            read: req.body.privileges['read'],
            write: req.body.privileges['write'],
            edit: req.body.privileges['edit']
        }
    }), req.body.password, function(err)
    {
        if(err)
        {
            console.log(err);
            res.redirect("/register");
        }
        else
        {
            console.log("fine");
            passport.authenticate('local', {
                successRedirect: '/',
                failureRedirect: '/login'
            })
        }
    })
});

<form action="/register" method="POST">
    <input type="text" name="username"><br/>
    <input type="password" name="password"><br/>
    <input type="text" name="privileges[region]"><br/>
    <input type="text" name="privileges[read]"><br/>
    <input type="text" name="privileges[write]"><br/>
    <input type="text" name="privileges[edit]"><br/>
    <input type="text" name="privileges[delete]"><br/>
    <button>Submit</button>
</form>

基本上,它应该像这样工作:从表单中我应该获得一系列特权。现在,当我在这样的字段中输入数据时:test 1234 1 2 1 1 1 1 1 1 (test - username, 1234 - password, 1 2 region array, 1 1 - read array, 1 1 write array, 1 1 edit array ) 我得到这个错误: 点击

现在我明白了原因 - 特权[编辑] 是 type="text",它不能作为数字解析到数据库中。但为什么它只发生在编辑?我觉得很奇怪。

我尝试将输入类型更改为数字,但之后我无法再输入数组。

我想我可能需要一个将文本转换为数字的中间件。我对吗?如果是这样,它应该怎么做?它应该单独转换数组的每个元素还是整个数组?

谢谢。

标签: javascriptnode.jsmongodbmongoose

解决方案


在为 定义的架构中Userprivileges是具有此架构的子文档数组。

{
    region: { type: Number, unique: true },
    read: Number,
    write: Number,
    edit: Number
}

设置此字段时,提供的数据需要与该架构匹配。例如

new User({
  username: req.body.username,
  privileges: [
    {
      region: ":region_value",
      read: ":read_value",
      write: ":write_value",
      edit: ":edit_value"
    },
    {
      region: ":region_value",
      read: ":read_value",
      write: ":write_value",
      edit: ":edit_value"
    },
    //....
  ],
})

我假设特权设计是故意以这种方式完成的,以允许用户拥有许多特权。

设置权限的一种直接方法是适当地设计表单。表单字段可以允许设置多个权限。例如,要设置两个权限,您可以通过以下方式编写标记来实现:

<input type="text" name="privileges[0][region]"><br/>
<input type="text" name="privileges[0][read]"><br/>
<input type="text" name="privileges[0][write]"><br/>
<input type="text" name="privileges[0][edit]"><br/>
<input type="text" name="privileges[0][delete]"><br/>

<input type="text" name="privileges[1][region]"><br/>
<input type="text" name="privileges[1][read]"><br/>
<input type="text" name="privileges[1][write]"><br/>
<input type="text" name="privileges[1][edit]"><br/>
<input type="text" name="privileges[1][delete]"><br/>

这种方式中的特权req.body将具有正确的格式,例如

{ privileges:
  [ { region: '1', read: '2', write: '2', edit: '2', delete: '4' },
    { region: '2', read: '4', write: '4', edit: '4', delete: '4' } ] }

这样你就可以简单地写

new User({
  username: req.body.username, 
  privileges: req.body.privileges
})

确保客户端传递正确的数据比尝试在事后处理数据更直接。

以这种方式设计表单的限制意味着必须提前确定用户可以拥有的权限数量。解决此问题的方法是动态构建表单并让用户控制以根据情况添加更多权限。请参阅以下示例以了解如何进行操作:

function addPrivilege(e) {
  e.preventDefault();
  const privileges =  $('.privileges');
  const lastCount = privileges.length;
  console.log($(this).data('template').replace(/:x:/g, lastCount))
  const template = $(this).data('template').replace(':x:', lastCount);
  
  privileges.after($('<div class="privileges"></div>').append(template))
}


$(document).ready(function () {

  $("#addPrivilegeBtn").on('click', addPrivilege);
});
.privileges {
  background: #ccc;
  padding: 8px 16px;
  margin: 4px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
  <div class="privileges">
    <input type="text" name="privileges[0][region]"><br/>
    <input type="text" name="privileges[0][read]"><br/>
    <input type="text" name="privileges[0][write]"><br/>
    <input type="text" name="privileges[0][edit]"><br/>
    <input type="text" name="privileges[0][delete]"><br/>
  </div>

  <button 
    id="addPrivilegeBtn"
    data-template='<input type="text"name="privileges[:x:][region]"><br/>
    <input type="text" name="privileges[:x:][read]"><br/>
    <input type="text" name="privileges[:x:][write]"><br/>
    <input type="text" name="privileges[:x:][edit]"><br/>
    <input type="text" name="privileges[:x:][delete]"><br/>'
  >Add privilege</button>
</form>


推荐阅读