Ho un servizio RESTful molto semplice scritto usando lo stack MEAN (MongoDb, Express.js, Angular.js, Node.js) e utilizzando l'ODM Mongoose.
Product
schema
var productSchema = new mongoose.Schema({
name: {type: String, required: true, maxlength: 250},
_prices: [{
amount: {type: Number,required: true,min: 0.0},
date: {type: Date, required: true, default: Date.now}
}]
});
productSchema
.virtual('price')
.get(function () {
var price = this._prices[this._prices.length - 1];
return price !== undefined ? price.amount : undefined;
});
productSchema.methods.setPrice = function (amount) {
this._prices.push({amount: amount});
};
Lo scopo della matrice _prices
e della proprietà virtuale price
è che voglio salvare una traccia di controllo della cronologia dei prezzi.
Ho un'interfaccia RESTful per /products
che supporta il solito GET
, POST
, PUT
e DELETE
.
Nel mio sistema, gli amministratori sono autorizzati a POST
, PUT
e DELETE
, il che è ovvio, tuttavia il problema si pone per l'accesso anonimo. Gli utenti anonimi sono autorizzati solo a GET
, ma la risposta GET
non deve includere il campo _prices
, in quanto solo gli amministratori possono visualizzare la cronologia.
As anonimo
{
name: "Widget",
price: "5.99"
}
Come amministratore
{
name: "Widget",
price: "5.99",
_prices: [
{price: "7.25", date: "2015-02-28"},
{price: "5.99", date: "2016-01-09"}
]
}
La maggior parte delle esercitazioni che ho letto sullo stack MEAN mostrano sempre la restituzione del modello di mangusta direttamente.
exports.getAll = function(request, response) {
Product.find({}, '-_prices', function (err, products) {
res.json(200, products);
});
};
Questo è molto semplice da aggirare dal controller products
, tuttavia, trovo che sia molto mal riposto dato che questa logica di filtraggio è nel controller e fragile in quanto se aggiungo nuovi campi al mio schema, devo torna al controller per assicurarti di non esporre i campi in futuro.
Ho anche domande sull'andare dall'altra parte, facendo la convalida della richiesta. Sembra che la maggior parte delle esercitazioni abbia accettato l'input dell'utente così com'è e che la convalida di Mangusta abbia esito negativo.
exports.post = function(request, response) {
var product = new Product(request.body)
product.save(function(error, product) {
if (error) {
return response.json(422, error);
}
response.send(201);
});
};
Essendo stato utilizzato per ASP.NET WebApi, le mie opinioni su questo sono leggermente distorte. Avrei probabilmente creato modelli di visualizzazione separati per la richiesta e diversi modelli di visualizzazione per la risposta (a seconda che io sia autenticato o meno), eseguo la convalida dell'input sul modello di visualizzazione richiesta e ho solo la validazione invariabile all'interno della mia entità. Tuttavia, voglio assicurarmi che stia facendo il modo stack MEAN.
Le mie domande sono le seguenti:
-
Devo fare affidamento esclusivamente sulla convalida della mangusta per la convalida dell'input, o dovrei scrivere la mia prima che arrivi anche a mangusta?
-
Per il filtro di output, dovrei creare un modulo di sicurezza / filtro che accetti un
Product
e restituisca un modello di visualizzazione in base al contesto dell'utente, a seconda che si tratti di un amministratore oppure no? -
Devo sovrascrivere il comportamento di
toJSON
(che è estensibile in mangusta, comunque) per fare il filtraggio? -
Devo creare un livello di astrazione tra i miei controller e mangusta?
Il mio pensiero iniziale è che la stessa mangusta ha troppe responsabilità, ma non voglio evitare di usarla se è l'approccio migliore.