2012-08-08 20 views
22

Tôi đang cố gắng tạo Mô hình người dùng, có một tên người dùng duy nhất. Dưới đây là đoạn code cho nó:Tôi đang làm gì sai trong quá trình xác thực lưu trước duy nhất của Mongoose này?

var mongoose = require("mongoose"); 

var Schema = mongoose.Schema; 

var UserSchema = new Schema({ 
    username: String, 
    password: String, 
}); 

UserSchema.virtual("password_confirmation").get(function() { 
    return this.pw_conf; 
}).set(function(value) { 
    this.pw_conf = value; 
}); 

UserSchema.path("username").required(true); 
UserSchema.path("password").required(true); 

UserSchema.pre("save",function(next, done) { 
    var self = this; 
    mongoose.models["User"].findOne({username : self.username},function(err, user) { 
     if(user) { 
      self.invalidate("user","username must be unique"); 
     } 
     done(); 
    }); 
    next(); 
}); 

UserSchema.pre("save",function(next) { 
    if(this.pw_conf !== this.password) { 
     next(new Error("Must specify the password confirmation")); 
    } 
    else { 
     next(); 
    } 
}); 

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

Tôi cũng đã được thử nghiệm để xem nếu các tác phẩm độc đáo:

var User = require("./users"), 
    mongoose = require("mongoose"); 
var u = new User(); 

mongoose.connect('mongodb://localhost/my_database'); 

u.username = "me"; 
u.password = "password"; 
u.password_confirmation = "password"; 
u.save(function(err) { 
    if(err) { 
     console.log(err); 
    } 
    mongoose.disconnect(); 
}); 

Vấn đề là, nó không. Mỗi lần tôi chạy mã, tôi nhận được một đối tượng mới được tạo ra. Tôi biết rằng có nhiều cách khác để đảm bảo tính độc đáo, nhưng tôi muốn làm theo cách này. Tôi có nên gọi số done sau khi xử lý kết quả của phương pháp findOne không? Tôi có gọi số next không?

Trả lời

28

Để sử dụng parallel middleware (với thông số nextdone), bạn cần phải vượt qua true làm tham số thứ hai.

Ngoài ra, có hai khả năng:

gọi self.invalidate của bạn nên được tham khảo "username" thay vì "user". Nếu điều đó không sửa chữa nó, bạn có thể thất bại thứ một cách rõ ràng bằng cách thông qua một đối tượng Lỗi để done nếu bạn muốn hủy bỏ các hoạt động tiết kiệm:

UserSchema.pre("save", true, function(next, done) { 
    var self = this; 
    mongoose.models["User"].findOne({username: self.username}, function(err, user) { 
     if(err) { 
      done(err); 
     } else if(user) { 
      self.invalidate("username", "username must be unique"); 
      done(new Error("username must be unique")); 
     } else { 
      done(); 
     } 
    }); 
    next(); 
}); 
+1

Nó hoạt động, nhưng định dạng lỗi không giống nhau vì vậy nếu bạn đang xây dựng một API và đếm định dạng đối tượng lỗi, bạn có thể sẽ gặp vấn đề với cách tiếp cận đó. Tôi đã thử nghiệm https://npmjs.org/package/mongoose-unique-validator và nó hoạt động như một sự quyến rũ đối với tôi. Đối tượng lỗi khá giống nhau. –

+0

đối với tôi, điều này không hiệu quả, tôi phải thay đổi chữ ký của hàm để chỉ có một đối số (tiếp theo) và sau đó gọi tiếp theo với lỗi hoặc tiếp theo mà không có tham số tương ứng – Matus

+0

@Matus Có hai loại 'pre' [ middleware] (http://mongoosejs.com/docs/middleware.html): song song (với tham số 'next',' done') và serial (chỉ với 'next'). – JohnnyHK

33

http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique là cách để thực hiện. Nó sử dụng các chỉ mục MongoDb thực tế để đảm bảo rằng trường của bạn là duy nhất. Không cần trung gian .pre.

Tận hưởng!

+7

Ừ nhưng không có thông báo lỗi tùy chỉnh .. Và không có cách nào để làm cho một sự khác biệt giữa 2 lỗi độc đáo khác nhau trên cùng một tài liệu. Xem https://groups.google.com/d/msg/mongoose-orm/BX7kz0BwLjk/JWuvD_p4hYcJ –

+2

+1 cho @YvesM. cho biết, và cũng theo tài liệu Mongoose: "LƯU Ý: vi phạm ràng buộc ** trả về lỗi E11000 từ MongoDB ** khi lưu, ** không phải lỗi xác thực Mongoose **." – kuzyn

3

bạn đã xem xét sử dụng một validator không đồng bộ để bắt lỗi?

UserSchema.path('username').validate(function (value, done) { 
    User.count({ username: value }, function (error, count) { 
    // Return false if an error is thrown or count > 0 
    done(!(error || count)); 
    }); 
}, 'unique'); 
5

Có một plugin thực sự tốt cho mongoose thực sự dễ cài đặt và sử dụng. Các tài liệu là tuyệt vời và nó đã làm việc cho tôi lần đầu tiên.

Nhưng có vấn đề với việc lưu lại.

https://npmjs.org/package/mongoose-unique-validator

+0

Thường chống lại việc đưa nhiều mô-đun hơn vào các dự án, nhưng tôi cũng nghĩ rằng đây là điều bắt buộc nếu bạn định thực hiện rất nhiều xác thực và nó không yêu cầu bất kỳ trình cấu trúc lại nào tích hợp – kuzyn

Các vấn đề liên quan