Go and a base database model
Instead of working with large or small ORM libraries, sometimes all you need is a little pattern and you’re good to go. This is a simple one that I’ve developed for use in my projects who use mgo and MongoDB.
It’s an Account model and includes a few basic functions. This snippet assumes you have a package or other way of retrieving an *mgo.Session.
package account
import (
“code.google.com/p/go.crypto/bcrypt”
“github.com/me/db”
“gopkg.in/mgo.v2"
“gopkg.in/mgo.v2/bson”
)
func C() (*mgo.Collection, error) {
session, err := db.GetSession()
if err != nil {
return nil, err
}collection := session.DB(“”).C(“accounts”)
collection.EnsureIndex(mgo.Index{
Key: []string{“email”},
Unique: true,
Background: true,
Sparse: true,
})
return collection, nil
}
type Account struct {
Id bson.ObjectId “_id”
Email string “email”
Hash []byte “hash”
Name string “name”
}func FindEmail(email string) (*Account, error) {
collection, err := C()
if err != nil {
return nil, err
}var account *Account
err = collection.Find(bson.M{“email”: email}).One(&account)
return account, err
}
func FindEmailAuth(email, pw string) (*Account, error) {
account, err := FindEmail(email)
if err != nil {
return nil, err
}err = bcrypt.CompareHashAndPassword(account.Hash, []byte(pw))
if err != nil {
return nil, err
}
return account, nil
}
func CreateAccount(email, pw, name string) error {
cost := bcrypt.DefaultCost
hash, err := bcrypt.GenerateFromPassword([]byte(pw), cost)
if err != nil {
return err
}collection, err := C()
if err != nil {
return err
}
return collection.Insert(bson.M{
“email”: email,
“hash”: hash,
“name”: name,
})
}func (account *Account) UpdateProfile(name string) error {
collection, err := C()
if err != nil {
return err
} return collection.UpdateId(account.Id, bson.M{
“$set”: bson.M{
“name”: name,
},
})
}With this base model you have the ability to find an account using email, you can verify that an account exists and that it has a certain password associated with it, all safely and securely stored and compared using bcrypt. You can create a new account and update the profile of the account, in our case, just the name.
If you need to access the underlying collection, just use C() and you can use *mgo.Collection just like you other wise would.