diff --git a/assets/index.html b/assets/index.html
index a0ad846d..c75d0c76 100644
--- a/assets/index.html
+++ b/assets/index.html
@@ -22,7 +22,7 @@
   <!-- Add to home screen for Windows -->
   <meta name="msapplication-TileImage" content="{{ .BaseURL }}/static/img/icons/msapplication-icon-144x144.png">
   <meta name="msapplication-TileColor" content="#2979ff">
-  <% for (var chunk of webpack.compilation.chunks) {
+  <% for (var chunk of webpack.chunks) {
     for (var file of chunk.files) {
       if (file.match(/\.(js|css)$/)) { %>
       <link rel="preload" href="{{ .BaseURL }}/<%= file %>" as="<%= file.match(/\.css$/)?'style':'script' %>"><% }}} %>
diff --git a/bolt/config.go b/bolt/config.go
new file mode 100644
index 00000000..6dcd0378
--- /dev/null
+++ b/bolt/config.go
@@ -0,0 +1,17 @@
+package bolt
+
+import (
+	"github.com/asdine/storm"
+)
+
+type ConfigStore struct {
+	DB *storm.DB
+}
+
+func (c ConfigStore) Get(name string, to interface{}) error {
+	return c.DB.Get("config", name, to)
+}
+
+func (c ConfigStore) Save(name string, from interface{}) error {
+	return c.DB.Set("config", name, from)
+}
diff --git a/bolt/share.go b/bolt/share.go
new file mode 100644
index 00000000..d66c08bb
--- /dev/null
+++ b/bolt/share.go
@@ -0,0 +1,36 @@
+package bolt
+
+import (
+	"github.com/asdine/storm"
+	fm "github.com/hacdias/filemanager"
+)
+
+type ShareStore struct {
+	DB *storm.DB
+}
+
+func (s ShareStore) Get(hash string) (*fm.ShareLink, error) {
+	var v *fm.ShareLink
+	err := s.DB.One("Hash", hash, &v)
+	return v, err
+}
+
+func (s ShareStore) GetByPath(hash string) ([]*fm.ShareLink, error) {
+	var v []*fm.ShareLink
+	err := s.DB.Find("Path", hash, &v)
+	return v, err
+}
+
+func (s ShareStore) Gets(hash string) ([]*fm.ShareLink, error) {
+	var v []*fm.ShareLink
+	err := s.DB.All(&v)
+	return v, err
+}
+
+func (s ShareStore) Save(l *fm.ShareLink) error {
+	return s.DB.Save(l)
+}
+
+func (s ShareStore) Delete(hash string) error {
+	return s.DB.DeleteStruct(&fm.ShareLink{Hash: hash})
+}
diff --git a/bolt/users.go b/bolt/users.go
new file mode 100644
index 00000000..880abfa1
--- /dev/null
+++ b/bolt/users.go
@@ -0,0 +1,55 @@
+package bolt
+
+import (
+	"reflect"
+
+	"github.com/asdine/storm"
+	fm "github.com/hacdias/filemanager"
+)
+
+type UsersStore struct {
+	DB *storm.DB
+}
+
+func (u UsersStore) Get(id int) (*fm.User, error) {
+	var us *fm.User
+	err := u.DB.One("ID", id, us)
+	if err == storm.ErrNotFound {
+		return nil, fm.ErrUserNotExist
+	}
+
+	if err != nil {
+		return nil, err
+	}
+
+	return &fm.User{}, nil
+}
+
+func (u UsersStore) Gets() ([]*fm.User, error) {
+	var us []*fm.User
+	err := u.DB.All(us)
+	return us, err
+}
+
+func (u UsersStore) Update(us *fm.User, fields ...string) error {
+	if len(fields) == 0 {
+		return u.Save(us)
+	}
+
+	for _, field := range fields {
+		val := reflect.ValueOf(us).Elem().FieldByName(field).Interface()
+		if err := u.DB.UpdateField(us, field, val); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (u UsersStore) Save(us *fm.User) error {
+	return u.DB.Save(us)
+}
+
+func (u UsersStore) Delete(id int) error {
+	return u.DB.DeleteStruct(&fm.User{ID: id})
+}
diff --git a/file.go b/file.go
index 8beec058..367cec66 100644
--- a/file.go
+++ b/file.go
@@ -24,12 +24,12 @@ import (
 )
 
 var (
-	errInvalidOption = errors.New("Invalid option")
+	ErrInvalidOption = errors.New("Invalid option")
 )
 
 // File contains the information about a particular file or directory.
 type File struct {
-	// Indicates the Kind of view on the front-end (listing, editor or preview).
+	// Indicates the Kind of view on the front-end (Listing, editor or preview).
 	Kind string `json:"kind"`
 	// The name of the file.
 	Name string `json:"name"`
@@ -54,19 +54,19 @@ type File struct {
 	// Stores the content of a text file.
 	Content string `json:"content,omitempty"`
 
-	*listing `json:",omitempty"`
+	*Listing `json:",omitempty"`
 
 	Metadata string `json:"metadata,omitempty"`
 	Language string `json:"language,omitempty"`
 }
 
-// A listing is the context used to fill out a template.
-type listing struct {
+// A Listing is the context used to fill out a template.
+type Listing struct {
 	// The items (files and folders) in the path.
 	Items []*File `json:"items"`
-	// The number of directories in the listing.
+	// The number of directories in the Listing.
 	NumDirs int `json:"numDirs"`
-	// The number of files (items that aren't directories) in the listing.
+	// The number of files (items that aren't directories) in the Listing.
 	NumFiles int `json:"numFiles"`
 	// Which sorting order is used.
 	Sort string `json:"sort"`
@@ -166,7 +166,7 @@ func (i *File) GetListing(u *User, r *http.Request) error {
 		fileinfos = append(fileinfos, i)
 	}
 
-	i.listing = &listing{
+	i.Listing = &Listing{
 		Items:    fileinfos,
 		NumDirs:  dirCount,
 		NumFiles: fileCount,
@@ -304,7 +304,7 @@ func (i File) Checksum(algo string) (string, error) {
 	case "sha512":
 		h = sha512.New()
 	default:
-		return "", errInvalidOption
+		return "", ErrInvalidOption
 	}
 
 	_, err = io.Copy(h, file)
@@ -321,7 +321,7 @@ func (i File) CanBeEdited() bool {
 }
 
 // ApplySort applies the sort order using .Order and .Sort
-func (l listing) ApplySort() {
+func (l Listing) ApplySort() {
 	// Check '.Order' to know how to sort
 	if l.Order == "desc" {
 		switch l.Sort {
@@ -350,10 +350,10 @@ func (l listing) ApplySort() {
 	}
 }
 
-// Implement sorting for listing
-type byName listing
-type bySize listing
-type byModified listing
+// Implement sorting for Listing
+type byName Listing
+type bySize Listing
+type byModified Listing
 
 // By Name
 func (l byName) Len() int {
diff --git a/filemanager.go b/filemanager.go
index b2489745..928a6922 100644
--- a/filemanager.go
+++ b/filemanager.go
@@ -61,6 +61,7 @@ import (
 	"os/exec"
 	"reflect"
 	"strings"
+	"time"
 
 	rice "github.com/GeertJohan/go.rice"
 	"github.com/asdine/storm"
@@ -71,17 +72,14 @@ import (
 // FileManager is a file manager instance. It should be creating using the
 // 'New' function and not directly.
 type FileManager struct {
-	// The BoltDB database for this instance.
-	db *storm.DB
+	// Job cron.
+	Cron *cron.Cron
 
 	// The key used to sign the JWT tokens.
-	key []byte
+	Key []byte
 
 	// The static assets.
-	assets *rice.Box
-
-	// Job cron.
-	cron *cron.Cron
+	Assets *rice.Box
 
 	// PrefixURL is a part of the URL that is already trimmed from the request URL before it
 	// arrives to our handlers. It may be useful when using File Manager as a middleware
@@ -103,66 +101,42 @@ type FileManager struct {
 	// The Default User needed to build the New User page.
 	DefaultUser *User
 
-	// Users is a map with the different configurations for each user.
-	Users map[string]*User
-
 	// A map of events to a slice of commands.
 	Commands map[string][]string
 
 	Store *Store
 }
 
-type Store struct {
-	Users *UsersStore
-}
-
 // Command is a command function.
 type Command func(r *http.Request, m *FileManager, u *User) error
 
-/*
-
-// New creates a new File Manager instance. If 'database' file already
-// exists, it will load the users from there. Otherwise, a new user
-// will be created using the 'base' variable. The 'base' User should
-// not have the Password field hashed.
-func New(database string, base User) (*FileManager, error) {
+func (m *FileManager) Load() error {
 	// Creates a new File Manager instance with the Users
 	// map and Assets box.
-	m := &FileManager{
-		Users:  map[string]*User{},
-		cron:   cron.New(),
-		assets: rice.MustFindBox("./assets/dist"),
-	}
-
-	// Tries to open a database on the location provided. This
-	// function will automatically create a new one if it doesn't
-	// exist.
-	db, err := storm.Open(database)
-	if err != nil {
-		return nil, err
-	}
+	m.Assets = rice.MustFindBox("./assets/dist")
+	m.Cron = cron.New()
 
 	// Tries to get the encryption key from the database.
 	// If it doesn't exist, create a new one of 256 bits.
-	err = db.Get("config", "key", &m.key)
-	if err != nil && err == storm.ErrNotFound {
+	err := m.Store.Config.Get("key", &m.Key)
+	if err != nil && err == ErrNotExist {
 		var bytes []byte
-		bytes, err = generateRandomBytes(64)
+		bytes, err = GenerateRandomBytes(64)
 		if err != nil {
-			return nil, err
+			return err
 		}
 
-		m.key = bytes
-		err = db.Set("config", "key", m.key)
+		m.Key = bytes
+		err = m.Store.Config.Save("key", m.Key)
 	}
 
 	if err != nil {
-		return nil, err
+		return err
 	}
 
 	// Tries to get the event commands from the database.
 	// If they don't exist, initialize them.
-	err = db.Get("config", "commands", &m.Commands)
+	err = m.Store.Config.Get("commands", &m.Commands)
 	if err != nil && err == storm.ErrNotFound {
 		m.Commands = map[string][]string{
 			"before_save":    {},
@@ -170,35 +144,29 @@ func New(database string, base User) (*FileManager, error) {
 			"before_publish": {},
 			"after_publish":  {},
 		}
-		err = db.Set("config", "commands", m.Commands)
+		err = m.Store.Config.Save("commands", m.Commands)
 	}
 
 	if err != nil {
-		return nil, err
+		return err
 	}
 
-	// Tries to fetch the users from the database and if there are
-	// any, add them to the current File Manager instance.
-	var users []User
-	err = db.All(&users)
+	// Tries to fetch the users from the database.
+	users, err := m.Store.Users.Gets()
 	if err != nil {
-		return nil, err
-	}
-
-	for i := range users {
-		m.Users[users[i].Username] = &users[i]
+		return err
 	}
 
 	// If there are no users in the database, it creates a new one
 	// based on 'base' User that must be provided by the function caller.
 	if len(users) == 0 {
-		u := base
+		u := *m.DefaultUser
 		u.Username = "admin"
 
 		// Hashes the password.
-		u.Password, err = hashPassword("admin")
+		u.Password, err = HashPassword("admin")
 		if err != nil {
-			return nil, err
+			return err
 		}
 
 		// The first user must be an administrator.
@@ -209,26 +177,19 @@ func New(database string, base User) (*FileManager, error) {
 		u.AllowPublish = true
 
 		// Saves the user to the database.
-		if err := db.Save(&u); err != nil {
-			return nil, err
+		if err := m.Store.Users.Save(&u); err != nil {
+			return err
 		}
-
-		m.Users[u.Username] = &u
 	}
 
-	// Attaches db to this File Manager instance.
-	m.db = db
+	m.DefaultUser.Username = ""
+	m.DefaultUser.Password = ""
 
-	// Create the default user, making a copy of the base.
-	base.Username = ""
-	base.Password = ""
-	m.DefaultUser = &base
+	m.Cron.AddFunc("@hourly", m.ShareCleaner)
+	m.Cron.Start()
 
-	m.cron.AddFunc("@hourly", m.shareCleaner)
-	m.cron.Start()
-
-	return m, nil
-} */
+	return nil
+}
 
 // RootURL returns the actual URL where
 // File Manager interface can be accessed.
@@ -291,24 +252,19 @@ func (m *FileManager) Attach(s StaticGen) error {
 
 	m.StaticGen = s
 
-	// TODO: Save...
-	/* 	err := m.db.Get("staticgen", "hugo", h)
-	if err != nil && err == storm.ErrNotFound {
-		err = m.db.Set("staticgen", "hugo", *h)
+	err = m.Store.Config.Get("staticgen_"+s.Name(), s)
+	if err == ErrNotExist {
+		return m.Store.Config.Save("staticgen_"+s.Name(), s)
 	}
-	*/
-	return nil
+
+	return err
 }
 
-/*
-
-// shareCleaner removes sharing links that are no longer active.
+// ShareCleaner removes sharing links that are no longer active.
 // This function is set to run periodically.
-func (m FileManager) shareCleaner() {
-	var links []shareLink
-
+func (m FileManager) ShareCleaner() {
 	// Get all links.
-	err := m.db.All(&links)
+	links, err := m.Store.Share.Gets()
 	if err != nil {
 		log.Print(err)
 		return
@@ -317,13 +273,13 @@ func (m FileManager) shareCleaner() {
 	// Find the expired ones.
 	for i := range links {
 		if links[i].Expires && links[i].ExpireDate.Before(time.Now()) {
-			err = m.db.DeleteStruct(&links[i])
+			err = m.Store.Share.Delete(links[i].Hash)
 			if err != nil {
 				log.Print(err)
 			}
 		}
 	}
-} */
+}
 
 // Runner runs the commands for a certain event type.
 func (m FileManager) Runner(event string, path string) error {
diff --git a/http/auth.go b/http/auth.go
index c5888e6e..ffade7ae 100644
--- a/http/auth.go
+++ b/http/auth.go
@@ -1,14 +1,11 @@
 package http
 
 import (
-	"crypto/rand"
 	"encoding/json"
 	"net/http"
 	"strings"
 	"time"
 
-	"golang.org/x/crypto/bcrypt"
-
 	jwt "github.com/dgrijalva/jwt-go"
 	"github.com/dgrijalva/jwt-go/request"
 	fm "github.com/hacdias/filemanager"
@@ -33,13 +30,13 @@ func authHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, er
 	}
 
 	// Checks if the user exists.
-	u, ok := c.Users[cred.Username]
-	if !ok {
+	u, err := c.Store.Users.Get(cred.ID)
+	if err != nil {
 		return http.StatusForbidden, nil
 	}
 
 	// Checks if the password is correct.
-	if !checkPasswordHash(cred.Password, u.Password) {
+	if !fm.CheckPasswordHash(cred.Password, u.Password) {
 		return http.StatusForbidden, nil
 	}
 
@@ -86,7 +83,7 @@ func printToken(c *fm.Context, w http.ResponseWriter) (int, error) {
 
 	// Creates the token and signs it.
 	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
-	signed, err := token.SignedString(c.key)
+	signed, err := token.SignedString(c.Key)
 
 	if err != nil {
 		return http.StatusInternalServerError, err
@@ -127,7 +124,7 @@ func validateAuth(c *fm.Context, r *http.Request) (bool, *fm.User) {
 	}
 
 	keyFunc := func(token *jwt.Token) (interface{}, error) {
-		return c.key, nil
+		return c.Key, nil
 	}
 	var claims claims
 	token, err := request.ParseFromRequestWithClaims(r,
@@ -140,38 +137,11 @@ func validateAuth(c *fm.Context, r *http.Request) (bool, *fm.User) {
 		return false, nil
 	}
 
-	u, ok := c.Users[claims.User.Username]
-	if !ok {
+	u, err := c.Store.Users.Get(claims.User.ID)
+	if err != nil {
 		return false, nil
 	}
 
 	c.User = u
 	return true, u
 }
-
-// hashPassword generates an hash from a password using bcrypt.
-func hashPassword(password string) (string, error) {
-	bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
-	return string(bytes), err
-}
-
-// checkPasswordHash compares a password with an hash to check if they match.
-func checkPasswordHash(password, hash string) bool {
-	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
-	return err == nil
-}
-
-// generateRandomBytes returns securely generated random bytes.
-// It will return an error if the system's secure random
-// number generator fails to function correctly, in which
-// case the caller should not continue.
-func generateRandomBytes(n int) ([]byte, error) {
-	b := make([]byte, n)
-	_, err := rand.Read(b)
-	// Note that err == nil only if we read len(b) bytes.
-	if err != nil {
-		return nil, err
-	}
-
-	return b, nil
-}
diff --git a/http/auth_test.go b/http/auth_test.go.txt
similarity index 97%
rename from http/auth_test.go
rename to http/auth_test.go.txt
index ee6ce8a5..fd8313ba 100644
--- a/http/auth_test.go
+++ b/http/auth_test.go.txt
@@ -45,7 +45,7 @@ func TestRenewHandler(t *testing.T) {
 	// First, we have to make an auth request to get the user authenticated,
 	r, err := http.NewRequest("POST", "/api/auth/get", strings.NewReader(defaultCredentials))
 	if err != nil {
-		t.Fatal(err)
+		t.Fatal(fm.Err)
 	}
 
 	w := httptest.NewRecorder()
@@ -60,7 +60,7 @@ func TestRenewHandler(t *testing.T) {
 	// Test renew authorization via Authorization Header.
 	r, err = http.NewRequest("GET", "/api/auth/renew", nil)
 	if err != nil {
-		t.Fatal(err)
+		t.Fatal(fm.Err)
 	}
 
 	r.Header.Set("Authorization", "Bearer "+token)
@@ -74,7 +74,7 @@ func TestRenewHandler(t *testing.T) {
 	// Test renew authorization via cookie field.
 	r, err = http.NewRequest("GET", "/api/auth/renew", nil)
 	if err != nil {
-		t.Fatal(err)
+		t.Fatal(fm.Err)
 	}
 
 	r.AddCookie(&http.Cookie{
diff --git a/http/http.go b/http/http.go
index cc2291be..23653720 100644
--- a/http/http.go
+++ b/http/http.go
@@ -2,7 +2,6 @@ package http
 
 import (
 	"encoding/json"
-	"errors"
 	"html/template"
 	"net/http"
 	"os"
@@ -13,21 +12,10 @@ import (
 	fm "github.com/hacdias/filemanager"
 )
 
-var (
-	errUserExist          = errors.New("user already exists")
-	errUserNotExist       = errors.New("user does not exist")
-	errEmptyRequest       = errors.New("request body is empty")
-	errEmptyPassword      = errors.New("password is empty")
-	errEmptyUsername      = errors.New("username is empty")
-	errEmptyScope         = errors.New("scope is empty")
-	errWrongDataType      = errors.New("wrong data type")
-	errInvalidUpdateField = errors.New("invalid field to update")
-)
-
 // ServeHTTP is the main entry point of this HTML application.
 func ServeHTTP(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
 	// Checks if the URL contains the baseURL and strips it. Otherwise, it just
-	// returns a 404 error because we're not supposed to be here!
+	// returns a 404 fm.Error because we're not supposed to be here!
 	p := strings.TrimPrefix(r.URL.Path, c.BaseURL)
 
 	if len(p) >= len(r.URL.Path) && c.BaseURL != "" {
@@ -41,7 +29,7 @@ func ServeHTTP(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, erro
 	if r.URL.Path == "/sw.js" {
 		return renderFile(
 			c, w,
-			c.assets.MustString("sw.js"),
+			c.Assets.MustString("sw.js"),
 			"application/javascript",
 		)
 	}
@@ -83,7 +71,7 @@ func ServeHTTP(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, erro
 
 	return renderFile(
 		c, w,
-		c.assets.MustString("index.html"),
+		c.Assets.MustString("index.html"),
 		"text/html",
 	)
 }
@@ -91,13 +79,13 @@ func ServeHTTP(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, erro
 // staticHandler handles the static assets path.
 func staticHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
 	if r.URL.Path != "/static/manifest.json" {
-		http.FileServer(c.assets.HTTPBox()).ServeHTTP(w, r)
+		http.FileServer(c.Assets.HTTPBox()).ServeHTTP(w, r)
 		return 0, nil
 	}
 
 	return renderFile(
 		c, w,
-		c.assets.MustString("static/manifest.json"),
+		c.Assets.MustString("static/manifest.json"),
 		"application/json",
 	)
 }
@@ -141,7 +129,7 @@ func apiHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, err
 		var err error
 		c.File, err = fm.GetInfo(r.URL, c.FileManager, c.User)
 		if err != nil {
-			return errorToHTTP(err, false), err
+			return ErrorToHTTP(err, false), err
 		}
 	}
 
@@ -177,7 +165,7 @@ func checksumHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 	query := r.URL.Query().Get("algo")
 
 	val, err := c.File.Checksum(query)
-	if err == errInvalidOption {
+	if err == fm.ErrInvalidOption {
 		return http.StatusBadRequest, err
 	} else if err != nil {
 		return http.StatusInternalServerError, err
@@ -211,7 +199,7 @@ func renderFile(c *fm.Context, w http.ResponseWriter, file string, contentType s
 
 	err := tpl.Execute(w, map[string]interface{}{
 		"BaseURL":   c.RootURL(),
-		"StaticGen": c.staticgen,
+		"StaticGen": c.StaticGen.Name(),
 	})
 	if err != nil {
 		return http.StatusInternalServerError, err
@@ -221,12 +209,11 @@ func renderFile(c *fm.Context, w http.ResponseWriter, file string, contentType s
 }
 
 func sharePage(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
-	var s shareLink
-	err := c.db.One("Hash", r.URL.Path, &s)
+	s, err := c.Store.Share.Get(r.URL.Path)
 	if err == storm.ErrNotFound {
 		return renderFile(
 			c, w,
-			c.assets.MustString("static/share/404.html"),
+			c.Assets.MustString("static/share/404.html"),
 			"text/html",
 		)
 	}
@@ -236,10 +223,10 @@ func sharePage(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, erro
 	}
 
 	if s.Expires && s.ExpireDate.Before(time.Now()) {
-		c.db.DeleteStruct(&s)
+		c.Store.Share.Delete(s.Hash)
 		return renderFile(
 			c, w,
-			c.assets.MustString("static/share/404.html"),
+			c.Assets.MustString("static/share/404.html"),
 			"text/html",
 		)
 	}
@@ -248,10 +235,10 @@ func sharePage(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, erro
 
 	info, err := os.Stat(s.Path)
 	if err != nil {
-		return errorToHTTP(err, false), err
+		return ErrorToHTTP(err, false), err
 	}
 
-	c.File = &file{
+	c.File = &fm.File{
 		Path:    s.Path,
 		Name:    info.Name(),
 		ModTime: info.ModTime(),
@@ -263,7 +250,7 @@ func sharePage(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, erro
 	dl := r.URL.Query().Get("dl")
 
 	if dl == "" || dl == "0" {
-		tpl := template.Must(template.New("file").Parse(c.assets.MustString("static/share/index.html")))
+		tpl := template.Must(template.New("file").Parse(c.Assets.MustString("static/share/index.html")))
 		w.Header().Set("Content-Type", "text/html; charset=utf-8")
 
 		err := tpl.Execute(w, map[string]interface{}{
@@ -303,8 +290,8 @@ func matchURL(first, second string) bool {
 	return strings.HasPrefix(first, second)
 }
 
-// errorToHTTP converts errors to HTTP Status Code.
-func errorToHTTP(err error, gone bool) int {
+// ErrorToHTTP converts errors to HTTP Status Code.
+func ErrorToHTTP(err error, gone bool) int {
 	switch {
 	case err == nil:
 		return http.StatusOK
diff --git a/http/resource.go b/http/resource.go
index 0a5c5271..f983f05f 100644
--- a/http/resource.go
+++ b/http/resource.go
@@ -64,9 +64,9 @@ func resourceHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 
 func resourceGetHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
 	// Gets the information of the directory/file.
-	f, err := getInfo(r.URL, c.FileManager, c.User)
+	f, err := fm.GetInfo(r.URL, c.FileManager, c.User)
 	if err != nil {
-		return errorToHTTP(err, false), err
+		return ErrorToHTTP(err, false), err
 	}
 
 	// If it's a dir and the path doesn't end with a trailing slash,
@@ -83,7 +83,7 @@ func resourceGetHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (
 
 	// Tries to get the file type.
 	if err = f.GetFileType(true); err != nil {
-		return errorToHTTP(err, true), err
+		return ErrorToHTTP(err, true), err
 	}
 
 	// Serve a preview if the file can't be edited or the
@@ -97,7 +97,7 @@ func resourceGetHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (
 	f.Kind = "editor"
 
 	// Tries to get the editor data.
-	if err = f.getEditor(); err != nil {
+	if err = f.GetEditor(); err != nil {
 		return http.StatusInternalServerError, err
 	}
 
@@ -109,11 +109,11 @@ func listingHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int,
 	f.Kind = "listing"
 
 	// Tries to get the listing data.
-	if err := f.getListing(c, r); err != nil {
-		return errorToHTTP(err, true), err
+	if err := f.GetListing(c.User, r); err != nil {
+		return ErrorToHTTP(err, true), err
 	}
 
-	listing := f.listing
+	listing := f.Listing
 
 	// Defines the cookie scope.
 	cookieScope := c.RootURL()
@@ -144,7 +144,7 @@ func resourceDeleteHandler(c *fm.Context, w http.ResponseWriter, r *http.Request
 	// Remove the file or folder.
 	err := c.User.FileSystem.RemoveAll(r.URL.Path)
 	if err != nil {
-		return errorToHTTP(err, true), err
+		return ErrorToHTTP(err, true), err
 	}
 
 	return http.StatusOK, nil
@@ -160,7 +160,7 @@ func resourcePostPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Reques
 	}
 
 	// Discard any invalid upload before returning to avoid connection
-	// reset error.
+	// reset fm.Error.
 	defer func() {
 		io.Copy(ioutil.Discard, r.Body)
 	}()
@@ -175,13 +175,13 @@ func resourcePostPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Reques
 
 		// Otherwise we try to create the directory.
 		err := c.User.FileSystem.Mkdir(r.URL.Path, 0776)
-		return errorToHTTP(err, false), err
+		return ErrorToHTTP(err, false), err
 	}
 
 	// If using POST method, we are trying to create a new file so it is not
-	// desirable to override an already existent file. Thus, we check
+	// desirable to ovfm.Erride an already existent file. Thus, we check
 	// if the file already exists. If so, we just return a 409 Conflict.
-	if r.Method == http.MethodPost && r.Header.Get("Action") != "override" {
+	if r.Method == http.MethodPost && r.Header.Get("Action") != "ovfm.Erride" {
 		if _, err := c.User.FileSystem.Stat(r.URL.Path); err == nil {
 			return http.StatusConflict, errors.New("There is already a file on that path")
 		}
@@ -190,20 +190,20 @@ func resourcePostPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Reques
 	// Create/Open the file.
 	f, err := c.User.FileSystem.OpenFile(r.URL.Path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0776)
 	if err != nil {
-		return errorToHTTP(err, false), err
+		return ErrorToHTTP(err, false), err
 	}
 	defer f.Close()
 
 	// Copies the new content for the file.
 	_, err = io.Copy(f, r.Body)
 	if err != nil {
-		return errorToHTTP(err, false), err
+		return ErrorToHTTP(err, false), err
 	}
 
 	// Gets the info about the file.
 	fi, err := f.Stat()
 	if err != nil {
-		return errorToHTTP(err, false), err
+		return ErrorToHTTP(err, false), err
 	}
 
 	// Check if this instance has a Static Generator and handles publishing
@@ -242,7 +242,7 @@ func resourcePublishSchedule(c *fm.Context, w http.ResponseWriter, r *http.Reque
 		return http.StatusInternalServerError, err
 	}
 
-	c.cron.AddFunc(t.Format("05 04 15 02 01 *"), func() {
+	c.Cron.AddFunc(t.Format("05 04 15 02 01 *"), func() {
 		_, err := resourcePublish(c, w, r)
 		if err != nil {
 			log.Print(err)
@@ -283,7 +283,7 @@ func resourcePatchHandler(c *fm.Context, w http.ResponseWriter, r *http.Request)
 	action := r.Header.Get("Action")
 	dst, err := url.QueryUnescape(dst)
 	if err != nil {
-		return errorToHTTP(err, true), err
+		return ErrorToHTTP(err, true), err
 	}
 
 	src := r.URL.Path
@@ -298,7 +298,7 @@ func resourcePatchHandler(c *fm.Context, w http.ResponseWriter, r *http.Request)
 		err = c.User.FileSystem.Rename(src, dst)
 	}
 
-	return errorToHTTP(err, true), err
+	return ErrorToHTTP(err, true), err
 }
 
 // displayMode obtains the display mode from the Cookie.
diff --git a/http/settings.go b/http/settings.go
index 887dd6d6..f0d9b2a3 100644
--- a/http/settings.go
+++ b/http/settings.go
@@ -27,7 +27,7 @@ type option struct {
 func parsePutSettingsRequest(r *http.Request) (*modifySettingsRequest, error) {
 	// Checks if the request body is empty.
 	if r.Body == nil {
-		return nil, errEmptyRequest
+		return nil, fm.ErrEmptyRequest
 	}
 
 	// Parses the request body and checks if it's well formed.
@@ -39,7 +39,7 @@ func parsePutSettingsRequest(r *http.Request) (*modifySettingsRequest, error) {
 
 	// Checks if the request type is right.
 	if mod.What != "settings" {
-		return nil, errWrongDataType
+		return nil, fm.ErrWrongDataType
 	}
 
 	return mod, nil
@@ -103,9 +103,10 @@ func settingsPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (
 	if err != nil {
 		return http.StatusBadRequest, err
 	}
+
 	// Update the commands.
 	if mod.Which == "commands" {
-		if err := c.db.Set("config", "commands", mod.Data.Commands); err != nil {
+		if err := c.Store.Config.Save("commands", mod.Data.Commands); err != nil {
 			return http.StatusInternalServerError, err
 		}
 
@@ -120,7 +121,7 @@ func settingsPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (
 			return http.StatusInternalServerError, err
 		}
 
-		err = c.db.Set("staticgen", c.staticgen, c.StaticGen)
+		err = c.Store.Config.Save("staticgen_"+c.StaticGen.Name(), c.StaticGen)
 		if err != nil {
 			return http.StatusInternalServerError, err
 		}
diff --git a/http/share.go b/http/share.go
index 8a628c48..0f9fe06e 100644
--- a/http/share.go
+++ b/http/share.go
@@ -13,13 +13,6 @@ import (
 	fm "github.com/hacdias/filemanager"
 )
 
-type shareLink struct {
-	Hash       string    `json:"hash" storm:"id,index"`
-	Path       string    `json:"path" storm:"index"`
-	Expires    bool      `json:"expires"`
-	ExpireDate time.Time `json:"expireDate"`
-}
-
 func shareHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
 	r.URL.Path = sanitizeURL(r.URL.Path)
 
@@ -36,12 +29,8 @@ func shareHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, e
 }
 
 func shareGetHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
-	var (
-		s    []*shareLink
-		path = filepath.Join(string(c.User.FileSystem), r.URL.Path)
-	)
-
-	err := c.db.Find("Path", path, &s)
+	path := filepath.Join(string(c.User.FileSystem), r.URL.Path)
+	s, err := c.Store.Share.GetByPath(path)
 	if err == storm.ErrNotFound {
 		return http.StatusNotFound, nil
 	}
@@ -52,7 +41,7 @@ func shareGetHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 
 	for i, link := range s {
 		if link.Expires && link.ExpireDate.Before(time.Now()) {
-			c.db.DeleteStruct(&shareLink{Hash: link.Hash})
+			c.Store.Share.Delete(link.Hash)
 			s = append(s[:i], s[i+1:]...)
 		}
 	}
@@ -63,7 +52,7 @@ func shareGetHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 func sharePostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
 	path := filepath.Join(string(c.User.FileSystem), r.URL.Path)
 
-	var s shareLink
+	var s fm.ShareLink
 	expire := r.URL.Query().Get("expires")
 	unit := r.URL.Query().Get("unit")
 
@@ -75,14 +64,14 @@ func sharePostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (in
 		}
 	}
 
-	bytes, err := generateRandomBytes(32)
+	bytes, err := fm.GenerateRandomBytes(32)
 	if err != nil {
 		return http.StatusInternalServerError, err
 	}
 
 	str := hex.EncodeToString(bytes)
 
-	s = shareLink{
+	s = fm.ShareLink{
 		Path:    path,
 		Hash:    str,
 		Expires: expire != "",
@@ -109,8 +98,7 @@ func sharePostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (in
 		s.ExpireDate = time.Now().Add(add)
 	}
 
-	err = c.db.Save(&s)
-	if err != nil {
+	if err := c.Store.Share.Save(&s); err != nil {
 		return http.StatusInternalServerError, err
 	}
 
@@ -118,9 +106,7 @@ func sharePostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (in
 }
 
 func shareDeleteHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
-	var s shareLink
-
-	err := c.db.One("Hash", strings.TrimPrefix(r.URL.Path, "/"), &s)
+	s, err := c.Store.Share.Get(strings.TrimPrefix(r.URL.Path, "/"))
 	if err == storm.ErrNotFound {
 		return http.StatusNotFound, nil
 	}
@@ -129,7 +115,7 @@ func shareDeleteHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (
 		return http.StatusInternalServerError, err
 	}
 
-	err = c.db.DeleteStruct(&s)
+	err = c.Store.Share.Delete(s.Hash)
 	if err != nil {
 		return http.StatusInternalServerError, err
 	}
diff --git a/http/users.go b/http/users.go
index 65384c7d..58fb0ed6 100644
--- a/http/users.go
+++ b/http/users.go
@@ -9,7 +9,6 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/asdine/storm"
 	fm "github.com/hacdias/filemanager"
 )
 
@@ -48,7 +47,7 @@ func usersHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, e
 
 // getUserID returns the id from the user which is present
 // in the request url. If the url is invalid and doesn't
-// contain a valid ID, it returns an error.
+// contain a valid ID, it returns an fm.Error.
 func getUserID(r *http.Request) (int, error) {
 	// Obtains the ID in string from the URL and converts
 	// it into an integer.
@@ -64,11 +63,11 @@ func getUserID(r *http.Request) (int, error) {
 
 // getUser returns the user which is present in the request
 // body. If the body is empty or the JSON is invalid, it
-// returns an error.
+// returns an fm.Error.
 func getUser(r *http.Request) (*fm.User, string, error) {
 	// Checks if the request body is empty.
 	if r.Body == nil {
-		return nil, "", errEmptyRequest
+		return nil, "", fm.ErrEmptyRequest
 	}
 
 	// Parses the request body and checks if it's well formed.
@@ -80,7 +79,7 @@ func getUser(r *http.Request) (*fm.User, string, error) {
 
 	// Checks if the request type is right.
 	if mod.What != "user" {
-		return nil, "", errWrongDataType
+		return nil, "", fm.ErrWrongDataType
 	}
 
 	return mod.Data, mod.Which, nil
@@ -94,15 +93,15 @@ func usersGetHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 
 	// Request for the listing of users.
 	if r.URL.Path == "/" {
-		users := []User{}
+		users, err := c.Store.Users.Gets()
+		if err != nil {
+			return http.StatusInternalServerError, err
+		}
 
-		for _, user := range c.Users {
-			// Copies the user info and removes its
-			// password so it won't be sent to the
-			// front-end.
-			u := *user
+		for _, u := range users {
+			// Removes the user password so it won't
+			// be sent to the front-end.
 			u.Password = ""
-			users = append(users, u)
 		}
 
 		sort.Slice(users, func(i, j int) bool {
@@ -117,19 +116,17 @@ func usersGetHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 		return http.StatusInternalServerError, err
 	}
 
-	// Searches for the user and prints the one who matches.
-	for _, user := range c.Users {
-		if user.ID != id {
-			continue
-		}
-
-		u := *user
-		u.Password = ""
-		return renderJSON(w, u)
+	u, err := c.Store.Users.Get(id)
+	if err == fm.ErrExist {
+		return http.StatusNotFound, err
 	}
 
-	// If there aren't any matches, return not found.
-	return http.StatusNotFound, errUserNotExist
+	if err != nil {
+		return http.StatusInternalServerError, err
+	}
+
+	u.Password = ""
+	return renderJSON(w, u)
 }
 
 func usersPostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
@@ -144,17 +141,17 @@ func usersPostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (in
 
 	// Checks if username isn't empty.
 	if u.Username == "" {
-		return http.StatusBadRequest, errEmptyUsername
+		return http.StatusBadRequest, fm.ErrEmptyUsername
 	}
 
 	// Checks if filesystem isn't empty.
 	if u.FileSystem == "" {
-		return http.StatusBadRequest, errEmptyScope
+		return http.StatusBadRequest, fm.ErrEmptyScope
 	}
 
 	// Checks if password isn't empty.
 	if u.Password == "" {
-		return http.StatusBadRequest, errEmptyPassword
+		return http.StatusBadRequest, fm.ErrEmptyPassword
 	}
 
 	// The username, password and scope cannot be empty.
@@ -164,7 +161,7 @@ func usersPostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (in
 
 	// Initialize rules if they're not initialized.
 	if u.Rules == nil {
-		u.Rules = []*Rule{}
+		u.Rules = []*fm.Rule{}
 	}
 
 	// Initialize commands if not initialized.
@@ -183,7 +180,7 @@ func usersPostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (in
 	}
 
 	// Hashes the password.
-	pw, err := hashPassword(u.Password)
+	pw, err := fm.HashPassword(u.Password)
 	if err != nil {
 		return http.StatusInternalServerError, err
 	}
@@ -191,18 +188,15 @@ func usersPostHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (in
 	u.Password = pw
 
 	// Saves the user to the database.
-	err = c.db.Save(u)
-	if err == storm.ErrAlreadyExists {
-		return http.StatusConflict, errUserExist
+	err = c.Store.Users.Save(u)
+	if err == fm.ErrExist {
+		return http.StatusConflict, err
 	}
 
 	if err != nil {
 		return http.StatusInternalServerError, err
 	}
 
-	// Saves the user to the memory.
-	c.Users[u.Username] = u
-
 	// Set the Location header and return.
 	w.Header().Set("Location", "/users/"+strconv.Itoa(u.ID))
 	w.WriteHeader(http.StatusCreated)
@@ -243,23 +237,15 @@ func usersDeleteHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (
 	}
 
 	// Deletes the user from the database.
-	err = c.db.DeleteStruct(&User{ID: id})
-	if err == storm.ErrNotFound {
-		return http.StatusNotFound, errUserNotExist
+	err = c.Store.Users.Delete(id)
+	if err == fm.ErrNotExist {
+		return http.StatusNotFound, fm.ErrNotExist
 	}
 
 	if err != nil {
 		return http.StatusInternalServerError, err
 	}
 
-	// Delete the user from the in-memory users map.
-	for _, user := range c.Users {
-		if user.ID == id {
-			delete(c.Users, user.Username)
-			break
-		}
-	}
-
 	return http.StatusOK, nil
 }
 
@@ -290,12 +276,8 @@ func usersPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 	if which == "partial" {
 		c.User.CSS = u.CSS
 		c.User.Locale = u.Locale
-		err = c.db.UpdateField(&User{ID: c.User.ID}, "CSS", u.CSS)
-		if err != nil {
-			return http.StatusInternalServerError, err
-		}
 
-		err = c.db.UpdateField(&User{ID: c.User.ID}, "Locale", u.Locale)
+		err = c.Store.Users.Update(c.User, "CSS", "Locale")
 		if err != nil {
 			return http.StatusInternalServerError, err
 		}
@@ -306,16 +288,15 @@ func usersPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 	// Updates the Password.
 	if which == "password" {
 		if u.Password == "" {
-			return http.StatusBadRequest, errEmptyPassword
+			return http.StatusBadRequest, fm.ErrEmptyPassword
 		}
 
-		pw, err := hashPassword(u.Password)
+		c.User.Password, err = fm.HashPassword(u.Password)
 		if err != nil {
 			return http.StatusInternalServerError, err
 		}
 
-		c.User.Password = pw
-		err = c.db.UpdateField(&User{ID: c.User.ID}, "Password", pw)
+		err = c.Store.Users.Update(c.User, "Password")
 		if err != nil {
 			return http.StatusInternalServerError, err
 		}
@@ -325,17 +306,17 @@ func usersPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 
 	// If can only be all.
 	if which != "all" {
-		return http.StatusBadRequest, errInvalidUpdateField
+		return http.StatusBadRequest, fm.ErrInvalidUpdateField
 	}
 
 	// Checks if username isn't empty.
 	if u.Username == "" {
-		return http.StatusBadRequest, errEmptyUsername
+		return http.StatusBadRequest, fm.ErrEmptyUsername
 	}
 
 	// Checks if filesystem isn't empty.
 	if u.FileSystem == "" {
-		return http.StatusBadRequest, errEmptyScope
+		return http.StatusBadRequest, fm.ErrEmptyScope
 	}
 
 	// Checks if the scope exists.
@@ -345,7 +326,7 @@ func usersPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 
 	// Initialize rules if they're not initialized.
 	if u.Rules == nil {
-		u.Rules = []*Rule{}
+		u.Rules = []*fm.Rule{}
 	}
 
 	// Initialize commands if not initialized.
@@ -354,22 +335,20 @@ func usersPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 	}
 
 	// Gets the current saved user from the in-memory map.
-	var suser *User
-	for _, user := range c.Users {
-		if user.ID == id {
-			suser = user
-			break
-		}
-	}
-	if suser == nil {
+	suser, err := c.Store.Users.Get(id)
+	if err == fm.ErrNotExist {
 		return http.StatusNotFound, nil
 	}
 
+	if err != nil {
+		return http.StatusInternalServerError, err
+	}
+
 	u.ID = id
 
 	// Changes the password if the request wants it.
 	if u.Password != "" {
-		pw, err := hashPassword(u.Password)
+		pw, err := fm.HashPassword(u.Password)
 		if err != nil {
 			return http.StatusInternalServerError, err
 		}
@@ -381,17 +360,10 @@ func usersPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 
 	// Updates the whole User struct because we always are supposed
 	// to send a new entire object.
-	err = c.db.Save(u)
+	err = c.Store.Users.Update(u)
 	if err != nil {
 		return http.StatusInternalServerError, err
 	}
 
-	// If the user changed the username, delete the old user
-	// from the in-memory user map.
-	if suser.Username != u.Username {
-		delete(c.Users, suser.Username)
-	}
-
-	c.Users[u.Username] = u
 	return http.StatusOK, nil
 }
diff --git a/http/websockets.go b/http/websockets.go
index c54818fe..c12cc4ba 100644
--- a/http/websockets.go
+++ b/http/websockets.go
@@ -28,7 +28,7 @@ var (
 
 // command handles the requests for VCS related commands: git, svn and mercurial
 func command(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
-	// Upgrades the connection to a websocket and checks for errors.
+	// Upgrades the connection to a websocket and checks for fm.Errors.
 	conn, err := upgrader.Upgrade(w, r, nil)
 	if err != nil {
 		return 0, err
@@ -92,7 +92,7 @@ func command(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error)
 	cmd.Stderr = buff
 	cmd.Stdout = buff
 
-	// Starts the command and checks for errors.
+	// Starts the command and checks for fm.Errors.
 	err = cmd.Start()
 	if err != nil {
 		return http.StatusInternalServerError, err
@@ -241,7 +241,7 @@ func parseSearch(value string) *searchOptions {
 
 // search searches for a file or directory.
 func search(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
-	// Upgrades the connection to a websocket and checks for errors.
+	// Upgrades the connection to a websocket and checks for fm.Errors.
 	conn, err := upgrader.Upgrade(w, r, nil)
 	if err != nil {
 		return 0, err
diff --git a/user.go b/user.go
index 3bc4ecd8..18267b21 100644
--- a/user.go
+++ b/user.go
@@ -1,12 +1,28 @@
 package filemanager
 
 import (
+	"crypto/rand"
+	"errors"
 	"regexp"
 	"strings"
+	"time"
+
+	"golang.org/x/crypto/bcrypt"
 
 	"github.com/hacdias/fileutils"
 )
 
+var (
+	ErrExist              = errors.New("the resource already exists")
+	ErrNotExist           = errors.New("the resource does not exist")
+	ErrEmptyRequest       = errors.New("request body is empty")
+	ErrEmptyPassword      = errors.New("password is empty")
+	ErrEmptyUsername      = errors.New("username is empty")
+	ErrEmptyScope         = errors.New("scope is empty")
+	ErrWrongDataType      = errors.New("wrong data type")
+	ErrInvalidUpdateField = errors.New("invalid field to update")
+)
+
 // DefaultUser is used on New, when no 'base' user is provided.
 var DefaultUser = User{
 	AllowCommands: true,
@@ -110,10 +126,24 @@ func (r *Regexp) MatchString(s string) bool {
 	return r.regexp.MatchString(s)
 }
 
+type ShareLink struct {
+	Hash       string    `json:"hash" storm:"id,index"`
+	Path       string    `json:"path" storm:"index"`
+	Expires    bool      `json:"expires"`
+	ExpireDate time.Time `json:"expireDate"`
+}
+
+type Store struct {
+	Users  UsersStore
+	Config ConfigStore
+	Share  ShareStore
+}
+
 type UsersStore interface {
 	Get(id int) (*User, error)
 	Gets() ([]*User, error)
-	Save(u *User, fields ...string) error
+	Save(u *User) error
+	Update(u *User, fields ...string) error
 	Delete(id int) error
 }
 
@@ -123,6 +153,36 @@ type ConfigStore interface {
 }
 
 type ShareStore interface {
-	Get(hash string)
-	Save()
+	Get(hash string) (*ShareLink, error)
+	GetByPath(path string) ([]*ShareLink, error)
+	Gets() ([]*ShareLink, error)
+	Save(s *ShareLink) error
+	Delete(hash string) error
+}
+
+// HashPassword generates an hash from a password using bcrypt.
+func HashPassword(password string) (string, error) {
+	bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
+	return string(bytes), err
+}
+
+// CheckPasswordHash compares a password with an hash to check if they match.
+func CheckPasswordHash(password, hash string) bool {
+	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
+	return err == nil
+}
+
+// GenerateRandomBytes returns securely generated random bytes.
+// It will return an fm.Error if the system's secure random
+// number generator fails to function correctly, in which
+// case the caller should not continue.
+func GenerateRandomBytes(n int) ([]byte, error) {
+	b := make([]byte, n)
+	_, err := rand.Read(b)
+	// Note that err == nil only if we read len(b) bytes.
+	if err != nil {
+		return nil, err
+	}
+
+	return b, nil
 }