Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
github.com/dsmontoya/marango
marango is an ODM (Object Document Mapper) for MongoDB written in Go. It is written on top of the mgo library. marango doesn't try to replace mgo, but rather simply augments it.
####Why do I we need an ODM? You don't. Though, it is nice to have.. specially in the context of a web application. It allows you to couple your business logic with your data. But it is only useful as long as it doesn't get in your way, and you can drop down the to the DB driver any time.
Populate - MongoDB doesn't have JOINs, but we still want to query based on relationships. marango makes this task easy. Relationships are mapped via tags in the model definition. marango can run populate on a single ObjectId or a slice of them. And it can even run queries on these relationships! For example, lets say you have a social networking site and a user has 200 friends, you can run a query on those friends to only return the friends that are older than 30, sort them by their ages, and limit it to 5 results
Hooks - The hooks functionality allows you to register functions to be called before or after an action has taken place on the document. Ex: PreSave(), PreRemove()
. Use these to consolidate your business logic in one place. See bellow for a full list of supported hooks
Virtuals - Store computed and temporary data along with your document. These values live only for the lifetime of the document, and are not persisted to the database.
Extends mgo.Collection - marango extends mgo's Collection struct. Reimplements operations that take just a bson.ObjectId to also accept string, because often times we only have a string representation of the ObjectId and we can let marango handle the conversion. Mgo's Query struct is replaced with one that understands the populate functions.
Convenience methods - All documents get methods such as Save(), Remove(), Apply(), Populate(), PopulateQuery()
The docs include lots of detailed explainations and examples:
In all of its glory: http://godoc.org/github.com/mansoor-s/marango
marango suppresses mgo's ErrNotFound error and instead provides the method IsValid() on every document. It returns true if the document was found, otherwise returns false
Define your Model:
package Models
type User struct {
marango.Document `bson:"-"` //This is important! All models must have an anonymous composition of marango.Document
Id bson.ObjectId `bson:"_id"` //Nothing different from mgo here
Email string
Password string
Friends []bson.ObjectId `model:"User"` //define relationship - other Users
}
//This is an optional hook implemented to be called when the document is retrieved from the DB
func (u *User) OnResult() {
u.Virtual.SetInt("totalFriends", len(u.Friends))
}
func (u *User) MySuperDuperMethod() {
//do cool stuff
}
Implementation:
package main
import (
"github.com/dsmontoya/marango"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
func main() {
//Business as usual.. dial up the DB
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
//Create new marango instance
mago := marango.New(session, "MY_DB_NAME")
//All models must be registered with marango
//It expects an instance of the schema and the collection name that it represents documents in
// and returns a pointer to a Model representing the mongodb collection
User := mago.Register(User{}, "MY_COLLECTION_NAME")
/////////////////////////
//// Ready to rock! ////
/////////////////////////
user := &User{}
//marango can infer the model to use from the type of the pointer we passed to Exec()
//We can pass in both types "string" and "bson.ObjectId"
err = mago.FindId("5232171fc081671e81000001").Exec(user)
if err != nil {
//do stuff
}
if !user.IsValid() {
//user not found!
}
// We can also explictly call Find on the model pointer that we got back from marango.Register()
// Also showing how to handle multiple results
users := []*User{}
User.Find(bson.M{"age": 40, "planet": "Earth"}).Sort("firstname", "-lastname").Limit(10).Exec(&users)
//Using Populate()
//A populate operation can either be part of a query or can be performed on an existing document
//////////////////
//Using Populate In a query:
//////////////////
users := []*User{}
User.Find(bson.M{"age": 40}).Sort("firstname").Limit(10).Populate("Friends").Exec(&users)
//In this example, lets assume that we got back 10 results. For all of those 10 results, marango just populated the references
//made in its "Friends" field
//To access a populated field:
theFirstUser := users[0]
thisUsersFriends := []*User{}
theFirstUser.Populated("Friends", thisUsersFriends)
// THAT WAS EASY!!!
///////////////////
//Using Populate on an existing document ... say one that you queried from the DB earlier
//////////////////
//This example will also show the PopulateQuery method, which allows you to further filter and sort your relationships!
friends := []*User{}
popQuery := User.Find(bson.M{"age": bson.M{"$gt": 30}}).Sort("age").Limit(5)
err := myDoc.PopulateQuery(popQuery, friends)
//The model inherits from the mgo.C struct that it represents. For instance, even though marango.Model does not implement
// an EnsureIndex() method, when called, the underlying mgo.C.EnsureIndex() method is called.
User.EnsureIndex(.....)
//or
User.UpdateAll(.....)
//or
User.Count()
}
###Hooks (Hooks are optional):
PreSave()
PostSave()
PreRemove()
PostRemove()
OnCreate()
OnResult()
Implement these methods in your schema and they will be called when triggered.
Look at the API docs for marango.Document for more info
###Virtuals Example Usage:
//get the document from DB here..
//Setting virtuals:
myDoc.Virtual.SetString("stringVal", "ABCDEF")
//Store an arbitrary type:
//myIds := []bson.ObjectId{...........}
myDoc.Virtual.Set("myIds", myIds)
//Getting arbitrary typed values
idsInterface, ok := myDoc.Virtual.Get("myIds")
if !ok {
//handle not found here
}
//assert it back to the type we want
myIds := idsInterface.([]bson.ObjectId)
FAQs
Unknown package
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.