diff --git a/.gitignore b/.gitignore index d1005e5..65bb228 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -trantor +trantor.git tools/adduser/adduser tools/update/update tools/togridfs/togridfs diff --git a/admin.go b/admin.go index a7b4b90..48355ec 100644 --- a/admin.go +++ b/admin.go @@ -3,6 +3,7 @@ package main import log "github.com/cihub/seelog" import ( + "git.gitorious.org/trantor/trantor.git/database" "github.com/gorilla/mux" "labix.org/v2/mgo/bson" "net/http" @@ -25,14 +26,14 @@ func deleteHandler(h handler) { } id := bson.ObjectIdHex(idStr) - books, _, err := h.db.GetBooks(bson.M{"_id": id}) + books, _, err := h.db.GetBooks(bson.M{"_id": id}, 0, 0) if err != nil { h.sess.Notify("Book not found!", "The book with id '"+idStr+"' is not there", "error") continue } book := books[0] DeleteBook(book, h.db) - h.db.RemoveBook(id) + h.db.DeleteBook(id) if !book.Active { isNew = true @@ -57,7 +58,7 @@ func editHandler(h handler) { return } id := bson.ObjectIdHex(idStr) - books, _, err := h.db.GetBooks(bson.M{"_id": id}) + books, _, err := h.db.GetBooks(bson.M{"_id": id}, 0, 0) if err != nil { notFound(h) return @@ -120,7 +121,7 @@ func saveHandler(h handler) { type newBook struct { TitleFound int AuthorFound int - B Book + B database.Book } type newData struct { S Status @@ -161,8 +162,8 @@ func newHandler(h handler) { } for i, b := range res { data.Books[i].B = b - _, data.Books[i].TitleFound, _ = h.db.GetBooks(buildQuery("title:"+b.Title), 1) - _, data.Books[i].AuthorFound, _ = h.db.GetBooks(buildQuery("author:"+strings.Join(b.Author, " author:")), 1) + _, data.Books[i].TitleFound, _ = h.db.GetBooks(buildQuery("title:"+b.Title), 1, 0) + _, data.Books[i].AuthorFound, _ = h.db.GetBooks(buildQuery("author:"+strings.Join(b.Author, " author:")), 1, 0) } data.Page = page + 1 if num > (page+1)*NEW_ITEMS_PAGE { @@ -188,7 +189,7 @@ func storeHandler(h handler) { } id := bson.ObjectIdHex(idStr) - books, _, err := h.db.GetBooks(bson.M{"_id": id}) + books, _, err := h.db.GetBooks(bson.M{"_id": id}, 0, 0) if err != nil { h.sess.Notify("Book not found!", "The book with id '"+idStr+"' is not there", "error") continue diff --git a/config.go b/config.go index e172e9c..902dcc4 100644 --- a/config.go +++ b/config.go @@ -3,24 +3,11 @@ package main const ( PORT = "8080" - DB_IP = "127.0.0.1" - DB_NAME = "trantor" - META_COLL = "meta" - BOOKS_COLL = "books" - TAGS_COLL = "tags" - VISITED_COLL = "visited" - DOWNLOADED_COLL = "downloaded" - HOURLY_VISITS_COLL = "visits.hourly" - DAILY_VISITS_COLL = "visits.daily" - MONTHLY_VISITS_COLL = "visits.monthly" - HOURLY_DOWNLOADS_COLL = "downloads.hourly" - DAILY_DOWNLOADS_COLL = "downloads.daily" - MONTHLY_DOWNLOADS_COLL = "downloads.monthly" - USERS_COLL = "users" - NEWS_COLL = "news" - STATS_COLL = "statistics" - FS_BOOKS = "fs_books" - FS_IMGS = "fs_imgs" + DB_IP = "127.0.0.1" + DB_NAME = "trantor" + META_COLL = "meta" + FS_BOOKS = "fs_books" + FS_IMGS = "fs_imgs" PASS_SALT = "ImperialLibSalt" MINUTES_UPDATE_TAGS = 11 @@ -33,7 +20,6 @@ const ( MINUTES_UPDATE_DAILY_D = 60*12 + 13 MINUTES_UPDATE_MONTHLY_D = 60*24 + 17 MINUTES_UPDATE_LOGGER = 5 - TAGS_DISPLAY = 50 BOOKS_FRONT_PAGE = 6 SEARCH_ITEMS_PAGE = 20 NEW_ITEMS_PAGE = 50 diff --git a/cover.go b/cover.go index c6e3bae..20b0daa 100644 --- a/cover.go +++ b/cover.go @@ -8,6 +8,7 @@ import _ "image/gif" import ( "bytes" "git.gitorious.org/go-pkg/epubgo.git" + "git.gitorious.org/trantor/trantor.git/database" "github.com/gorilla/mux" "github.com/nfnt/resize" "image" @@ -27,7 +28,7 @@ func coverHandler(h handler) { return } id := bson.ObjectIdHex(vars["id"]) - books, _, err := h.db.GetBooks(bson.M{"_id": id}) + books, _, err := h.db.GetBooks(bson.M{"_id": id}, 0, 0) if err != nil || len(books) == 0 { notFound(h) return @@ -61,7 +62,7 @@ func coverHandler(h handler) { io.Copy(h.w, f) } -func GetCover(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bson.ObjectId) { +func GetCover(e *epubgo.Epub, title string, db *database.DB) (bson.ObjectId, bson.ObjectId) { imgId, smallId := coverFromMetadata(e, title, db) if imgId != "" { return imgId, smallId @@ -116,7 +117,7 @@ func GetCover(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bson.ObjectI return "", "" } -func coverFromMetadata(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bson.ObjectId) { +func coverFromMetadata(e *epubgo.Epub, title string, db *database.DB) (bson.ObjectId, bson.ObjectId) { metaList, _ := e.MetadataAttr("meta") for _, meta := range metaList { if meta["name"] == "cover" { @@ -130,7 +131,7 @@ func coverFromMetadata(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bso return "", "" } -func searchCommonCoverNames(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bson.ObjectId) { +func searchCommonCoverNames(e *epubgo.Epub, title string, db *database.DB) (bson.ObjectId, bson.ObjectId) { for _, p := range []string{"cover.jpg", "Images/cover.jpg", "images/cover.jpg", "cover.jpeg", "cover1.jpg", "cover1.jpeg"} { img, err := e.OpenFile(p) if err == nil { @@ -141,7 +142,7 @@ func searchCommonCoverNames(e *epubgo.Epub, title string, db *DB) (bson.ObjectId return "", "" } -func storeImg(img io.Reader, title string, db *DB) (bson.ObjectId, bson.ObjectId) { +func storeImg(img io.Reader, title string, db *database.DB) (bson.ObjectId, bson.ObjectId) { /* open the files */ fBig, err := createCoverFile(title, db) if err != nil { @@ -187,7 +188,7 @@ func storeImg(img io.Reader, title string, db *DB) (bson.ObjectId, bson.ObjectId return idBig, idSmall } -func createCoverFile(title string, db *DB) (*mgo.GridFile, error) { +func createCoverFile(title string, db *database.DB) (*mgo.GridFile, error) { fs := db.GetFS(FS_IMGS) return fs.Create(title + ".jpg") } diff --git a/database.go b/database.go deleted file mode 100644 index 348e9af..0000000 --- a/database.go +++ /dev/null @@ -1,345 +0,0 @@ -package main - -import log "github.com/cihub/seelog" - -import ( - "crypto/md5" - "errors" - "labix.org/v2/mgo" - "labix.org/v2/mgo/bson" - "os" - "time" -) - -type Book struct { - Id string `bson:"_id"` - Title string - Author []string - Contributor string - Publisher string - Description string - Subject []string - Date string - Lang []string - Isbn string - Type string - Format string - Source string - Relation string - Coverage string - Rights string - Meta string - File bson.ObjectId - FileSize int - Cover bson.ObjectId - CoverSmall bson.ObjectId - Active bool - Keywords []string -} - -type News struct { - Date time.Time - Text string -} - -type DB struct { - session *mgo.Session -} - -func initDB() *DB { - var err error - d := new(DB) - d.session, err = mgo.Dial(DB_IP) - if err != nil { - log.Critical(err) - os.Exit(1) - } - return d -} - -func (d *DB) Close() { - d.session.Close() -} - -func (d *DB) Copy() *DB { - dbCopy := new(DB) - dbCopy.session = d.session.Copy() - return dbCopy -} - -func md5Pass(pass string) []byte { - h := md5.New() - hash := h.Sum(([]byte)(PASS_SALT + pass)) - return hash -} - -func (d *DB) SetPassword(user string, pass string) error { - hash := md5Pass(pass) - userColl := d.session.DB(DB_NAME).C(USERS_COLL) - return userColl.Update(bson.M{"user": user}, bson.M{"$set": bson.M{"pass": hash}}) -} - -func (d *DB) UserValid(user string, pass string) bool { - hash := md5Pass(pass) - userColl := d.session.DB(DB_NAME).C(USERS_COLL) - n, err := userColl.Find(bson.M{"user": user, "pass": hash}).Count() - if err != nil { - return false - } - return n != 0 -} - -func (d *DB) AddUser(user string, pass string) error { - hash := md5Pass(pass) - userColl := d.session.DB(DB_NAME).C(USERS_COLL) - return userColl.Insert(bson.M{"user": user, "pass": hash, "role": ""}) -} - -func (d *DB) UserRole(user string) string { - type result struct { - Role string - } - res := result{} - userColl := d.session.DB(DB_NAME).C(USERS_COLL) - err := userColl.Find(bson.M{"user": user}).One(&res) - if err != nil { - return "" - } - return res.Role -} - -func (d *DB) AddNews(text string) error { - var news News - news.Text = text - news.Date = time.Now() - newsColl := d.session.DB(DB_NAME).C(NEWS_COLL) - return newsColl.Insert(news) -} - -func (d *DB) GetNews(num int, days int) (news []News, err error) { - query := bson.M{} - if days != 0 { - duration := time.Duration(-24*days) * time.Hour - date := time.Now().Add(duration) - query = bson.M{"date": bson.M{"$gt": date}} - } - newsColl := d.session.DB(DB_NAME).C(NEWS_COLL) - q := newsColl.Find(query).Sort("-date").Limit(num) - err = q.All(&news) - return -} - -func (d *DB) InsertStats(stats interface{}) error { - statsColl := d.session.DB(DB_NAME).C(STATS_COLL) - return statsColl.Insert(stats) -} - -func (d *DB) InsertBook(book interface{}) error { - booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL) - return booksColl.Insert(book) -} - -func (d *DB) RemoveBook(id bson.ObjectId) error { - booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL) - return booksColl.Remove(bson.M{"_id": id}) -} - -func (d *DB) UpdateBook(id bson.ObjectId, data interface{}) error { - booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL) - return booksColl.Update(bson.M{"_id": id}, bson.M{"$set": data}) -} - -/* optional parameters: length and start index - * - * Returns: list of books, number found and err - */ -func (d *DB) GetBooks(query bson.M, r ...int) (books []Book, num int, err error) { - var start, length int - if len(r) > 0 { - length = r[0] - if len(r) > 1 { - start = r[1] - } - } - booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL) - q := booksColl.Find(query).Sort("-_id") - num, err = q.Count() - if err != nil { - return - } - if start != 0 { - q = q.Skip(start) - } - if length != 0 { - q = q.Limit(length) - } - - err = q.All(&books) - for i, b := range books { - books[i].Id = bson.ObjectId(b.Id).Hex() - } - return -} - -/* Get the most visited books - */ -func (d *DB) GetVisitedBooks() (books []Book, err error) { - visitedColl := d.session.DB(DB_NAME).C(VISITED_COLL) - bookId, err := GetBooksVisited(visitedColl) - if err != nil { - return nil, err - } - - books = make([]Book, len(bookId)) - for i, id := range bookId { - booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL) - booksColl.Find(bson.M{"_id": id}).One(&books[i]) - books[i].Id = bson.ObjectId(books[i].Id).Hex() - } - return -} - -func (d *DB) UpdateMostVisited() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(STATS_COLL) - u.dst = d.session.DB(DB_NAME).C(VISITED_COLL) - return u.UpdateMostBooks("book") -} - -/* Get the most downloaded books - */ -func (d *DB) GetDownloadedBooks() (books []Book, err error) { - downloadedColl := d.session.DB(DB_NAME).C(DOWNLOADED_COLL) - bookId, err := GetBooksVisited(downloadedColl) - if err != nil { - return nil, err - } - - books = make([]Book, len(bookId)) - for i, id := range bookId { - booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL) - booksColl.Find(bson.M{"_id": id}).One(&books[i]) - books[i].Id = bson.ObjectId(books[i].Id).Hex() - } - return -} - -func (d *DB) UpdateDownloadedBooks() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(STATS_COLL) - u.dst = d.session.DB(DB_NAME).C(DOWNLOADED_COLL) - return u.UpdateMostBooks("download") -} - -/* optional parameters: length and start index - * - * Returns: list of books, number found and err - */ -func (d *DB) GetNewBooks(r ...int) (books []Book, num int, err error) { - return d.GetBooks(bson.M{"$nor": []bson.M{{"active": true}}}, r...) -} - -func (d *DB) BookActive(id bson.ObjectId) bool { - var book Book - booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL) - err := booksColl.Find(bson.M{"_id": id}).One(&book) - if err != nil { - return false - } - return book.Active -} - -func (d *DB) GetFS(prefix string) *mgo.GridFS { - return d.session.DB(DB_NAME).GridFS(prefix) -} - -func (d *DB) GetTags() ([]string, error) { - tagsColl := d.session.DB(DB_NAME).C(TAGS_COLL) - return GetTags(tagsColl) -} - -func (d *DB) UpdateTags() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(BOOKS_COLL) - u.dst = d.session.DB(DB_NAME).C(TAGS_COLL) - return u.UpdateTags() -} - -type VisitType int - -const ( - hourly_visits = iota - daily_visits - monthly_visits - hourly_downloads - daily_downloads - monthly_downloads -) - -type Visits struct { - Date time.Time "date" - Count int "count" -} - -func (d *DB) GetVisits(visitType VisitType) ([]Visits, error) { - var coll *mgo.Collection - switch visitType { - case hourly_visits: - coll = d.session.DB(DB_NAME).C(HOURLY_VISITS_COLL) - case daily_visits: - coll = d.session.DB(DB_NAME).C(DAILY_VISITS_COLL) - case monthly_visits: - coll = d.session.DB(DB_NAME).C(MONTHLY_VISITS_COLL) - case hourly_downloads: - coll = d.session.DB(DB_NAME).C(HOURLY_DOWNLOADS_COLL) - case daily_downloads: - coll = d.session.DB(DB_NAME).C(DAILY_DOWNLOADS_COLL) - case monthly_downloads: - coll = d.session.DB(DB_NAME).C(MONTHLY_DOWNLOADS_COLL) - default: - return nil, errors.New("Not valid VisitType") - } - return GetVisits(coll) -} - -func (d *DB) UpdateHourVisits() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(STATS_COLL) - u.dst = d.session.DB(DB_NAME).C(HOURLY_VISITS_COLL) - return u.UpdateHourVisits(false) -} - -func (d *DB) UpdateDayVisits() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(STATS_COLL) - u.dst = d.session.DB(DB_NAME).C(DAILY_VISITS_COLL) - return u.UpdateDayVisits(false) -} - -func (d *DB) UpdateMonthVisits() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(STATS_COLL) - u.dst = d.session.DB(DB_NAME).C(MONTHLY_VISITS_COLL) - return u.UpdateMonthVisits(false) -} - -func (d *DB) UpdateHourDownloads() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(STATS_COLL) - u.dst = d.session.DB(DB_NAME).C(HOURLY_DOWNLOADS_COLL) - return u.UpdateHourVisits(true) -} - -func (d *DB) UpdateDayDownloads() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(STATS_COLL) - u.dst = d.session.DB(DB_NAME).C(DAILY_DOWNLOADS_COLL) - return u.UpdateDayVisits(true) -} - -func (d *DB) UpdateMonthDownloads() error { - var u DBUpdate - u.src = d.session.DB(DB_NAME).C(STATS_COLL) - u.dst = d.session.DB(DB_NAME).C(MONTHLY_DOWNLOADS_COLL) - return u.UpdateMonthVisits(true) -} diff --git a/database/books.go b/database/books.go new file mode 100644 index 0000000..358aaf3 --- /dev/null +++ b/database/books.go @@ -0,0 +1,77 @@ +package database + +import ( + "labix.org/v2/mgo" + "labix.org/v2/mgo/bson" +) + +const ( + books_coll = "books" +) + +type Book struct { + Id string `bson:"_id"` + Title string + Author []string + Contributor string + Publisher string + Description string + Subject []string + Date string + Lang []string + Isbn string + Type string + Format string + Source string + Relation string + Coverage string + Rights string + Meta string + File bson.ObjectId + FileSize int + Cover bson.ObjectId + CoverSmall bson.ObjectId + Active bool + Keywords []string +} + +func addBook(coll *mgo.Collection, book interface{}) error { + return coll.Insert(book) +} + +func getBooks(coll *mgo.Collection, query bson.M, length int, start int) (books []Book, num int, err error) { + q := coll.Find(query).Sort("-_id") + num, err = q.Count() + if err != nil { + return + } + if start != 0 { + q = q.Skip(start) + } + if length != 0 { + q = q.Limit(length) + } + + err = q.All(&books) + for i, b := range books { + books[i].Id = bson.ObjectId(b.Id).Hex() + } + return +} + +func deleteBook(coll *mgo.Collection, id bson.ObjectId) error { + return coll.Remove(bson.M{"_id": id}) +} + +func updateBook(coll *mgo.Collection, id bson.ObjectId, data interface{}) error { + return coll.Update(bson.M{"_id": id}, bson.M{"$set": data}) +} + +func bookActive(coll *mgo.Collection, id bson.ObjectId) bool { + var book Book + err := coll.Find(bson.M{"_id": id}).One(&book) + if err != nil { + return false + } + return book.Active +} diff --git a/database/books_test.go b/database/books_test.go new file mode 100644 index 0000000..f07bf3f --- /dev/null +++ b/database/books_test.go @@ -0,0 +1,40 @@ +package database + +import "testing" + +import ( + "labix.org/v2/mgo/bson" +) + +var book = map[string]interface{}{ + "title": "some title", + "author": []string{"Alice", "Bob"}, +} + +func TestAddBook(t *testing.T) { + db := Init(test_host, test_coll) + defer db.del() + + tAddBook(t, db) + + books, num, err := db.GetBooks(bson.M{}, 1, 0) + if err != nil { + t.Fatalf("db.GetBooks() return an error: ", err) + } + if num < 1 { + t.Fatalf("db.GetBooks() didn't find any result.") + } + if len(books) < 1 { + t.Fatalf("db.GetBooks() didn't return any result.") + } + if books[0].Title != book["title"] { + t.Errorf("Book title don't match : '", books[0].Title, "' <=> '", book["title"], "'") + } +} + +func tAddBook(t *testing.T, db *DB) { + err := db.AddBook(book) + if err != nil { + t.Errorf("db.AddBook(", book, ") return an error: ", err) + } +} diff --git a/database/database.go b/database/database.go new file mode 100644 index 0000000..bff4a40 --- /dev/null +++ b/database/database.go @@ -0,0 +1,236 @@ +package database + +import log "github.com/cihub/seelog" + +import ( + "errors" + "labix.org/v2/mgo" + "labix.org/v2/mgo/bson" + "os" +) + +const ( + visited_coll = "visited" + downloaded_coll = "downloaded" + tags_coll = "tags" +) + +type DB struct { + session *mgo.Session + name string +} + +func Init(host string, name string) *DB { + var err error + db := new(DB) + db.session, err = mgo.Dial(host) + if err != nil { + log.Critical(err) + os.Exit(1) + } + db.name = name + return db +} + +func (db *DB) Close() { + db.session.Close() +} + +func (db *DB) Copy() *DB { + dbCopy := new(DB) + dbCopy.session = db.session.Copy() + dbCopy.name = db.name + return dbCopy +} + +func (db *DB) AddBook(book interface{}) error { + booksColl := db.session.DB(db.name).C(books_coll) + return addBook(booksColl, book) +} + +// FIXME: don't export bson data +func (db *DB) GetBooks(query bson.M, length int, start int) (books []Book, num int, err error) { + booksColl := db.session.DB(db.name).C(books_coll) + return getBooks(booksColl, query, length, start) +} + +func (db *DB) DeleteBook(id bson.ObjectId) error { + booksColl := db.session.DB(db.name).C(books_coll) + return deleteBook(booksColl, id) +} + +func (db *DB) UpdateBook(id bson.ObjectId, data interface{}) error { + booksColl := db.session.DB(db.name).C(books_coll) + return updateBook(booksColl, id, data) +} + +func (db *DB) GetNewBooks(length int, start int) (books []Book, num int, err error) { + booksColl := db.session.DB(db.name).C(books_coll) + return getBooks(booksColl, bson.M{"$nor": []bson.M{{"active": true}}}, length, start) +} + +func (db *DB) BookActive(id bson.ObjectId) bool { + booksColl := db.session.DB(db.name).C(books_coll) + return bookActive(booksColl, id) +} + +func (db *DB) User(name string) *User { + userColl := db.session.DB(db.name).C(user_coll) + return getUser(userColl, name) +} + +func (db *DB) AddUser(name string, pass string) error { + userColl := db.session.DB(db.name).C(user_coll) + return addUser(userColl, name, pass) +} + +func (db *DB) AddNews(text string) error { + newsColl := db.session.DB(db.name).C(news_coll) + return addNews(newsColl, text) +} + +func (db *DB) GetNews(num int, days int) (news []News, err error) { + newsColl := db.session.DB(db.name).C(news_coll) + return getNews(newsColl, num, days) +} + +// TODO: split code in files +func (db *DB) AddStats(stats interface{}) error { + statsColl := db.session.DB(db.name).C(stats_coll) + return statsColl.Insert(stats) +} + +/* Get the most visited books + */ +func (db *DB) GetVisitedBooks() (books []Book, err error) { + visitedColl := db.session.DB(db.name).C(visited_coll) + bookId, err := GetBooksVisited(visitedColl) + if err != nil { + return nil, err + } + + books = make([]Book, len(bookId)) + for i, id := range bookId { + booksColl := db.session.DB(db.name).C(books_coll) + booksColl.Find(bson.M{"_id": id}).One(&books[i]) + books[i].Id = bson.ObjectId(books[i].Id).Hex() + } + return +} + +func (db *DB) UpdateMostVisited() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(stats_coll) + u.dst = db.session.DB(db.name).C(visited_coll) + return u.UpdateMostBooks("book") +} + +/* Get the most downloaded books + */ +func (db *DB) GetDownloadedBooks() (books []Book, err error) { + downloadedColl := db.session.DB(db.name).C(downloaded_coll) + bookId, err := GetBooksVisited(downloadedColl) + if err != nil { + return nil, err + } + + books = make([]Book, len(bookId)) + for i, id := range bookId { + booksColl := db.session.DB(db.name).C(books_coll) + booksColl.Find(bson.M{"_id": id}).One(&books[i]) + books[i].Id = bson.ObjectId(books[i].Id).Hex() + } + return +} + +func (db *DB) UpdateDownloadedBooks() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(stats_coll) + u.dst = db.session.DB(db.name).C(downloaded_coll) + return u.UpdateMostBooks("download") +} + +func (db *DB) GetFS(prefix string) *mgo.GridFS { + return db.session.DB(db.name).GridFS(prefix) +} + +func (db *DB) GetTags() ([]string, error) { + tagsColl := db.session.DB(db.name).C(tags_coll) + return GetTags(tagsColl) +} + +func (db *DB) UpdateTags() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(books_coll) + u.dst = db.session.DB(db.name).C(tags_coll) + return u.UpdateTags() +} + +func (db *DB) GetVisits(visitType VisitType) ([]Visits, error) { + var coll *mgo.Collection + switch visitType { + case Hourly_visits: + coll = db.session.DB(db.name).C(hourly_visits_coll) + case Daily_visits: + coll = db.session.DB(db.name).C(daily_visits_coll) + case Monthly_visits: + coll = db.session.DB(db.name).C(monthly_visits_coll) + case Hourly_downloads: + coll = db.session.DB(db.name).C(hourly_downloads_coll) + case Daily_downloads: + coll = db.session.DB(db.name).C(daily_downloads_coll) + case Monthly_downloads: + coll = db.session.DB(db.name).C(monthly_downloads_coll) + default: + return nil, errors.New("Not valid VisitType") + } + return GetVisits(coll) +} + +func (db *DB) UpdateHourVisits() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(stats_coll) + u.dst = db.session.DB(db.name).C(hourly_visits_coll) + return u.UpdateHourVisits(false) +} + +func (db *DB) UpdateDayVisits() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(stats_coll) + u.dst = db.session.DB(db.name).C(daily_visits_coll) + return u.UpdateDayVisits(false) +} + +func (db *DB) UpdateMonthVisits() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(stats_coll) + u.dst = db.session.DB(db.name).C(monthly_visits_coll) + return u.UpdateMonthVisits(false) +} + +func (db *DB) UpdateHourDownloads() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(stats_coll) + u.dst = db.session.DB(db.name).C(hourly_downloads_coll) + return u.UpdateHourVisits(true) +} + +func (db *DB) UpdateDayDownloads() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(stats_coll) + u.dst = db.session.DB(db.name).C(daily_downloads_coll) + return u.UpdateDayVisits(true) +} + +func (db *DB) UpdateMonthDownloads() error { + var u dbUpdate + u.src = db.session.DB(db.name).C(stats_coll) + u.dst = db.session.DB(db.name).C(monthly_downloads_coll) + return u.UpdateMonthVisits(true) +} + +// function defined for the tests +func (db *DB) del() { + defer db.Close() + db.session.DB(db.name).DropDatabase() +} diff --git a/database/database_test.go b/database/database_test.go new file mode 100644 index 0000000..f62d51e --- /dev/null +++ b/database/database_test.go @@ -0,0 +1,40 @@ +package database + +import "testing" + +const ( + test_coll = "test_trantor" + test_host = "127.0.0.1" +) + +func TestInit(t *testing.T) { + db := Init(test_host, test_coll) + defer db.Close() +} + +func TestCopy(t *testing.T) { + db := Init(test_host, test_coll) + defer db.del() + + db2 := db.Copy() + + if db.name != db2.name { + t.Errorf("Names don't match") + } + names1, err := db.session.DatabaseNames() + if err != nil { + t.Errorf("Error on db1: ", err) + } + names2, err := db2.session.DatabaseNames() + if err != nil { + t.Errorf("Error on db1: ", err) + } + if len(names1) != len(names2) { + t.Errorf("len(names) don't match") + } + for i, _ := range names1 { + if names1[i] != names2[i] { + t.Errorf("Names don't match") + } + } +} diff --git a/database/news.go b/database/news.go new file mode 100644 index 0000000..853196c --- /dev/null +++ b/database/news.go @@ -0,0 +1,35 @@ +package database + +import ( + "labix.org/v2/mgo" + "labix.org/v2/mgo/bson" + "time" +) + +const ( + news_coll = "news" +) + +type News struct { + Date time.Time + Text string +} + +func addNews(coll *mgo.Collection, text string) error { + var news News + news.Text = text + news.Date = time.Now() + return coll.Insert(news) +} + +func getNews(coll *mgo.Collection, num int, days int) (news []News, err error) { + query := bson.M{} + if days != 0 { + duration := time.Duration(-24*days) * time.Hour + date := time.Now().Add(duration) + query = bson.M{"date": bson.M{"$gt": date}} + } + q := coll.Find(query).Sort("-date").Limit(num) + err = q.All(&news) + return +} diff --git a/database/news_test.go b/database/news_test.go new file mode 100644 index 0000000..0c91034 --- /dev/null +++ b/database/news_test.go @@ -0,0 +1,26 @@ +package database + +import "testing" + +func TestNews(t *testing.T) { + const text = "Some news text" + + db := Init(test_host, test_coll) + defer db.del() + + err := db.AddNews(text) + if err != nil { + t.Errorf("db.News(", text, ") return an error: ", err) + } + + news, err := db.GetNews(1, 1) + if err != nil { + t.Fatalf("db.GetNews() return an error: ", err) + } + if len(news) < 1 { + t.Fatalf("No news found.") + } + if news[0].Text != text { + t.Errorf("News text don't match : '", news[0].Text, "' <=> '", text, "'") + } +} diff --git a/db_stats.go b/database/stats.go similarity index 76% rename from db_stats.go rename to database/stats.go index 986cdf6..e8f43d2 100644 --- a/db_stats.go +++ b/database/stats.go @@ -1,4 +1,4 @@ -package main +package database import ( "labix.org/v2/mgo" @@ -6,11 +6,41 @@ import ( "time" ) -type DBUpdate struct { +const ( + stats_coll = "statistics" + hourly_visits_coll = "visits.hourly" + daily_visits_coll = "visits.daily" + monthly_visits_coll = "visits.monthly" + hourly_downloads_coll = "downloads.hourly" + daily_downloads_coll = "downloads.daily" + monthly_downloads_coll = "downloads.monthly" + + // FIXME: this should return to the config.go + TAGS_DISPLAY = 50 + BOOKS_FRONT_PAGE = 6 +) + +type dbUpdate struct { src *mgo.Collection dst *mgo.Collection } +type VisitType int + +const ( + Hourly_visits = iota + Daily_visits + Monthly_visits + Hourly_downloads + Daily_downloads + Monthly_downloads +) + +type Visits struct { + Date time.Time "date" + Count int "count" +} + func GetTags(tagsColl *mgo.Collection) ([]string, error) { var result []struct { Tag string "_id" @@ -49,7 +79,7 @@ func GetVisits(visitsColl *mgo.Collection) ([]Visits, error) { return result, err } -func (u *DBUpdate) UpdateTags() error { +func (u *dbUpdate) UpdateTags() error { var tags []struct { Tag string "_id" Count int "count" @@ -75,7 +105,7 @@ func (u *DBUpdate) UpdateTags() error { return nil } -func (u *DBUpdate) UpdateMostBooks(section string) error { +func (u *dbUpdate) UpdateMostBooks(section string) error { const numDays = 30 start := time.Now().UTC().Add(-numDays * 24 * time.Hour) @@ -104,19 +134,19 @@ func (u *DBUpdate) UpdateMostBooks(section string) error { return nil } -func (u *DBUpdate) UpdateHourVisits(isDownloads bool) error { +func (u *dbUpdate) UpdateHourVisits(isDownloads bool) error { const numDays = 2 spanStore := numDays * 24 * time.Hour return u.updateVisits(hourInc, spanStore, isDownloads) } -func (u *DBUpdate) UpdateDayVisits(isDownloads bool) error { +func (u *dbUpdate) UpdateDayVisits(isDownloads bool) error { const numDays = 30 spanStore := numDays * 24 * time.Hour return u.updateVisits(dayInc, spanStore, isDownloads) } -func (u *DBUpdate) UpdateMonthVisits(isDownloads bool) error { +func (u *dbUpdate) UpdateMonthVisits(isDownloads bool) error { const numDays = 365 spanStore := numDays * 24 * time.Hour return u.updateVisits(monthInc, spanStore, isDownloads) @@ -137,7 +167,7 @@ func monthInc(date time.Time) time.Time { return date.AddDate(0, 1, 1-date.Day()).Truncate(span) } -func (u *DBUpdate) updateVisits(incTime func(time.Time) time.Time, spanStore time.Duration, isDownloads bool) error { +func (u *dbUpdate) updateVisits(incTime func(time.Time) time.Time, spanStore time.Duration, isDownloads bool) error { start := u.calculateStart(spanStore) for start.Before(time.Now().UTC()) { stop := incTime(start) @@ -165,7 +195,7 @@ func (u *DBUpdate) updateVisits(incTime func(time.Time) time.Time, spanStore tim return err } -func (u *DBUpdate) calculateStart(spanStore time.Duration) time.Time { +func (u *dbUpdate) calculateStart(spanStore time.Duration) time.Time { var date struct { Id bson.ObjectId `bson:"_id"` Date time.Time `bson:"date"` @@ -178,7 +208,7 @@ func (u *DBUpdate) calculateStart(spanStore time.Duration) time.Time { return time.Now().UTC().Add(-spanStore).Truncate(time.Hour) } -func (u *DBUpdate) countVisits(start time.Time, stop time.Time) int { +func (u *dbUpdate) countVisits(start time.Time, stop time.Time) int { var result struct { Count int "count" } @@ -194,7 +224,7 @@ func (u *DBUpdate) countVisits(start time.Time, stop time.Time) int { return result.Count } -func (u *DBUpdate) countDownloads(start time.Time, stop time.Time) (int, error) { +func (u *dbUpdate) countDownloads(start time.Time, stop time.Time) (int, error) { query := bson.M{"date": bson.M{"$gte": start, "$lt": stop}, "section": "download"} return u.src.Find(query).Count() } diff --git a/database/users.go b/database/users.go new file mode 100644 index 0000000..e547a28 --- /dev/null +++ b/database/users.go @@ -0,0 +1,96 @@ +package database + +import log "github.com/cihub/seelog" + +import ( + "bytes" + "crypto/md5" + "errors" + "labix.org/v2/mgo" + "labix.org/v2/mgo/bson" +) + +const ( + user_coll = "users" + pass_salt = "ImperialLibSalt" +) + +type User struct { + user db_user + err error + coll *mgo.Collection +} + +type db_user struct { + User string + Pass []byte + Role string +} + +func getUser(coll *mgo.Collection, name string) *User { + u := new(User) + if !validUserName(name) { + u.err = errors.New("Invalid username") + return u + } + + u.coll = coll + err := u.coll.Find(bson.M{"user": name}).One(&u.user) + if err != nil { + log.Warn("Error on database checking user ", name, ": ", err) + u.err = errors.New("User not found") + return u + } + return u +} + +func addUser(coll *mgo.Collection, name string, pass string) error { + if !validUserName(name) { + return errors.New("Invalid user name") + } + num, err := coll.Find(bson.M{"user": name}).Count() + if err != nil { + log.Error("Error on database checking user ", name, ": ", err) + return errors.New("An error happen on the database") + } + if num != 0 { + return errors.New("User name already exist") + } + + var user db_user + user.Pass = md5Pass(pass) + user.User = name + user.Role = "" + return coll.Insert(user) +} + +func validUserName(name string) bool { + return name != "" +} + +func (u User) Valid(pass string) bool { + if u.err != nil { + return false + } + hash := md5Pass(pass) + return bytes.Compare(u.user.Pass, hash) == 0 +} + +func (u User) Role() string { + return u.user.Role +} + +func (u *User) SetPassword(pass string) error { + if u.err != nil { + return u.err + } + hash := md5Pass(pass) + return u.coll.Update(bson.M{"user": u.user.User}, bson.M{"$set": bson.M{"pass": hash}}) +} + +// FIXME: use a proper salting algorithm +func md5Pass(pass string) []byte { + h := md5.New() + hash := h.Sum(([]byte)(pass_salt + pass)) + return hash +} diff --git a/database/users_test.go b/database/users_test.go new file mode 100644 index 0000000..79ca366 --- /dev/null +++ b/database/users_test.go @@ -0,0 +1,43 @@ +package database + +import "testing" + +const ( + name, pass = "user", "mypass" +) + +func TestUserEmpty(t *testing.T) { + db := Init(test_host, test_coll) + defer db.del() + + if db.User("").Valid("") { + t.Errorf("user.Valid() with an empty password return true") + } +} + +func TestAddUser(t *testing.T) { + db := Init(test_host, test_coll) + defer db.del() + + tAddUser(t, db) + if !db.User(name).Valid(pass) { + t.Errorf("user.Valid() return false for a valid user") + } +} + +func TestEmptyUsername(t *testing.T) { + db := Init(test_host, test_coll) + defer db.del() + + tAddUser(t, db) + if db.User("").Valid(pass) { + t.Errorf("user.Valid() return true for an invalid user") + } +} + +func tAddUser(t *testing.T, db *DB) { + err := db.AddUser(name, pass) + if err != nil { + t.Errorf("db.Adduser(", name, ", ", pass, ") return an error: ", err) + } +} diff --git a/news.go b/news.go index 3f37cc3..964dff0 100644 --- a/news.go +++ b/news.go @@ -1,6 +1,7 @@ package main import ( + "git.gitorious.org/trantor/trantor.git/database" "net/http" ) @@ -57,7 +58,7 @@ func postNewsHandler(h handler) { http.Redirect(h.w, h.r, "/news/", http.StatusFound) } -func getNews(num int, days int, db *DB) []newsEntry { +func getNews(num int, days int, db *database.DB) []newsEntry { dbnews, _ := db.GetNews(num, days) news := make([]newsEntry, len(dbnews)) for i, n := range dbnews { diff --git a/reader.go b/reader.go index 902ac9a..0faa7c8 100644 --- a/reader.go +++ b/reader.go @@ -2,6 +2,7 @@ package main import ( "git.gitorious.org/go-pkg/epubgo.git" + "git.gitorious.org/trantor/trantor.git/database" "github.com/gorilla/mux" "io" "labix.org/v2/mgo/bson" @@ -21,7 +22,7 @@ type chapter struct { type readData struct { S Status - Book Book + Book database.Book Content string Chapters []chapter Next string @@ -171,13 +172,13 @@ func readHandler(h handler) { loadTemplate(h.w, "read", data) } -func openReadEpub(h handler) (*epubgo.Epub, Book) { - var book Book +func openReadEpub(h handler) (*epubgo.Epub, database.Book) { + var book database.Book id := mux.Vars(h.r)["id"] if !bson.IsObjectIdHex(id) { return nil, book } - books, _, err := h.db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)}) + books, _, err := h.db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)}, 0, 0) if err != nil || len(books) == 0 { return nil, book } @@ -204,7 +205,7 @@ func contentHandler(h handler) { return } - books, _, err := h.db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)}) + books, _, err := h.db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)}, 0, 0) if err != nil || len(books) == 0 { notFound(h) return diff --git a/search.go b/search.go index 9f94543..baaa582 100644 --- a/search.go +++ b/search.go @@ -1,6 +1,7 @@ package main import ( + "git.gitorious.org/trantor/trantor.git/database" "labix.org/v2/mgo/bson" "net/http" "strconv" @@ -28,7 +29,7 @@ func buildQuery(q string) bson.M { type searchData struct { S Status Found int - Books []Book + Books []database.Book ItemsPage int Page int Next string diff --git a/session.go b/session.go index e958cdc..0f22e2f 100644 --- a/session.go +++ b/session.go @@ -2,6 +2,7 @@ package main import ( "encoding/hex" + "git.gitorious.org/trantor/trantor.git/database" "github.com/gorilla/securecookie" "github.com/gorilla/sessions" "net/http" @@ -21,13 +22,13 @@ type Session struct { S *sessions.Session } -func GetSession(r *http.Request, db *DB) (s *Session) { +func GetSession(r *http.Request, db *database.DB) (s *Session) { s = new(Session) var err error s.S, err = sesStore.Get(r, "session") if err == nil && !s.S.IsNew { s.User, _ = s.S.Values["user"].(string) - s.Role = db.UserRole(s.User) + s.Role = db.User(s.User).Role() } if s.S.IsNew { diff --git a/stats.go b/stats.go index d6e48cd..e2552c7 100644 --- a/stats.go +++ b/stats.go @@ -3,6 +3,7 @@ package main import log "github.com/cihub/seelog" import ( + "git.gitorious.org/trantor/trantor.git/database" "github.com/gorilla/mux" "labix.org/v2/mgo/bson" "net/http" @@ -15,15 +16,15 @@ type handler struct { w http.ResponseWriter r *http.Request sess *Session - db *DB + db *database.DB } -func InitStats(database *DB) { +func InitStats(database *database.DB) { statsChannel = make(chan statsRequest, CHAN_SIZE) go statsWorker(database) } -func GatherStats(function func(handler), database *DB) func(http.ResponseWriter, *http.Request) { +func GatherStats(function func(handler), database *database.DB) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { log.Info("Query ", r.Method, " ", r.RequestURI) @@ -49,7 +50,7 @@ type statsRequest struct { r *http.Request } -func statsWorker(database *DB) { +func statsWorker(database *database.DB) { db := database.Copy() defer db.Close() @@ -61,7 +62,7 @@ func statsWorker(database *DB) { appendSession(req.sess, stats) stats["method"] = req.r.Method stats["date"] = req.date - db.InsertStats(stats) + db.AddStats(stats) } } @@ -69,12 +70,12 @@ func statsHandler(h handler) { var data statsData data.S = GetStatus(h) data.S.Stats = true - data.HVisits = getVisits(hourlyLabel, h.db, hourly_visits) - data.DVisits = getVisits(dailyLabel, h.db, daily_visits) - data.MVisits = getVisits(monthlyLabel, h.db, monthly_visits) - data.HDownloads = getVisits(hourlyLabel, h.db, hourly_downloads) - data.DDownloads = getVisits(dailyLabel, h.db, daily_downloads) - data.MDownloads = getVisits(monthlyLabel, h.db, monthly_downloads) + data.HVisits = getVisits(hourlyLabel, h.db, database.Hourly_visits) + data.DVisits = getVisits(dailyLabel, h.db, database.Daily_visits) + data.MVisits = getVisits(monthlyLabel, h.db, database.Monthly_visits) + data.HDownloads = getVisits(hourlyLabel, h.db, database.Hourly_downloads) + data.DDownloads = getVisits(dailyLabel, h.db, database.Daily_downloads) + data.MDownloads = getVisits(monthlyLabel, h.db, database.Monthly_downloads) loadTemplate(h.w, "stats", data) } @@ -106,7 +107,7 @@ func monthlyLabel(date time.Time) string { return date.Month().String() } -func getVisits(funcLabel func(time.Time) string, db *DB, visitType VisitType) []visitData { +func getVisits(funcLabel func(time.Time) string, db *database.DB, visitType database.VisitType) []visitData { var visits []visitData visit, err := db.GetVisits(visitType) diff --git a/store.go b/store.go index 5b0ee8c..3b70a34 100644 --- a/store.go +++ b/store.go @@ -3,6 +3,7 @@ package main import ( "bytes" "git.gitorious.org/go-pkg/epubgo.git" + "git.gitorious.org/trantor/trantor.git/database" "io" "io/ioutil" "labix.org/v2/mgo/bson" @@ -10,7 +11,7 @@ import ( "strings" ) -func OpenBook(id bson.ObjectId, db *DB) (*epubgo.Epub, error) { +func OpenBook(id bson.ObjectId, db *database.DB) (*epubgo.Epub, error) { fs := db.GetFS(FS_BOOKS) f, err := fs.OpenId(id) if err != nil { @@ -24,7 +25,7 @@ func OpenBook(id bson.ObjectId, db *DB) (*epubgo.Epub, error) { return epubgo.Load(reader, int64(len(buff))) } -func StoreNewFile(name string, file io.Reader, db *DB) (bson.ObjectId, int64, error) { +func StoreNewFile(name string, file io.Reader, db *database.DB) (bson.ObjectId, int64, error) { fs := db.GetFS(FS_BOOKS) fw, err := fs.Create(name) if err != nil { @@ -37,17 +38,17 @@ func StoreNewFile(name string, file io.Reader, db *DB) (bson.ObjectId, int64, er return id, size, err } -func DeleteFile(id bson.ObjectId, db *DB) error { +func DeleteFile(id bson.ObjectId, db *database.DB) error { fs := db.GetFS(FS_BOOKS) return fs.RemoveId(id) } -func DeleteCover(id bson.ObjectId, db *DB) error { +func DeleteCover(id bson.ObjectId, db *database.DB) error { fs := db.GetFS(FS_IMGS) return fs.RemoveId(id) } -func DeleteBook(book Book, db *DB) { +func DeleteBook(book database.Book, db *database.DB) { if book.Cover != "" { DeleteCover(book.Cover, db) } diff --git a/tasker.go b/tasker.go index e057874..b5e7d9d 100644 --- a/tasker.go +++ b/tasker.go @@ -3,10 +3,11 @@ package main import log "github.com/cihub/seelog" import ( + "git.gitorious.org/trantor/trantor.git/database" "time" ) -func InitTasks(db *DB) { +func InitTasks(db *database.DB) { periodicTask(updateLogger, MINUTES_UPDATE_LOGGER*time.Minute) periodicTask(db.UpdateTags, MINUTES_UPDATE_TAGS*time.Minute) periodicTask(db.UpdateMostVisited, MINUTES_UPDATE_VISITED*time.Minute) diff --git a/trantor.go b/trantor.go index f974c40..dcd5216 100644 --- a/trantor.go +++ b/trantor.go @@ -3,6 +3,7 @@ package main import log "github.com/cihub/seelog" import ( + "git.gitorious.org/trantor/trantor.git/database" "github.com/gorilla/mux" "io" "labix.org/v2/mgo/bson" @@ -38,7 +39,7 @@ func logoutHandler(h handler) { type bookData struct { S Status - Book Book + Book database.Book Description []string } @@ -52,7 +53,7 @@ func bookHandler(h handler) { var data bookData data.S = GetStatus(h) id := bson.ObjectIdHex(idStr) - books, _, err := h.db.GetBooks(bson.M{"_id": id}) + books, _, err := h.db.GetBooks(bson.M{"_id": id}, 0, 0) if err != nil || len(books) == 0 { notFound(h) return @@ -70,7 +71,7 @@ func downloadHandler(h handler) { } id := bson.ObjectIdHex(idStr) - books, _, err := h.db.GetBooks(bson.M{"_id": id}) + books, _, err := h.db.GetBooks(bson.M{"_id": id}, 0, 0) if err != nil || len(books) == 0 { notFound(h) return @@ -101,9 +102,9 @@ func downloadHandler(h handler) { type indexData struct { S Status - Books []Book - VisitedBooks []Book - DownloadedBooks []Book + Books []database.Book + VisitedBooks []database.Book + DownloadedBooks []database.Book Count int Tags []string News []newsEntry @@ -115,7 +116,7 @@ func indexHandler(h handler) { data.Tags, _ = h.db.GetTags() data.S = GetStatus(h) data.S.Home = true - data.Books, data.Count, _ = h.db.GetBooks(bson.M{"active": true}, BOOKS_FRONT_PAGE) + data.Books, data.Count, _ = h.db.GetBooks(bson.M{"active": true}, BOOKS_FRONT_PAGE, 0) data.VisitedBooks, _ = h.db.GetVisitedBooks() data.DownloadedBooks, _ = h.db.GetDownloadedBooks() data.News = getNews(1, DAYS_NEWS_INDEXPAGE, h.db) @@ -147,7 +148,7 @@ func main() { } log.Info("Start the imperial library of trantor") - db := initDB() + db := database.Init(DB_IP, DB_NAME) defer db.Close() InitTasks(db) @@ -158,7 +159,7 @@ func main() { log.Error(http.ListenAndServe(":"+PORT, nil)) } -func initRouter(db *DB) { +func initRouter(db *database.DB) { r := mux.NewRouter() var notFoundHandler http.HandlerFunc notFoundHandler = GatherStats(notFound, db) diff --git a/upload.go b/upload.go index 8f05f0a..d155e76 100644 --- a/upload.go +++ b/upload.go @@ -5,12 +5,13 @@ import log "github.com/cihub/seelog" import ( "bytes" "git.gitorious.org/go-pkg/epubgo.git" + "git.gitorious.org/trantor/trantor.git/database" "io/ioutil" "mime/multipart" "strings" ) -func InitUpload(database *DB) { +func InitUpload(database *database.DB) { uploadChannel = make(chan uploadRequest, CHAN_SIZE) go uploadWorker(database) } @@ -22,7 +23,7 @@ type uploadRequest struct { filename string } -func uploadWorker(database *DB) { +func uploadWorker(database *database.DB) { db := database.Copy() defer db.Close() @@ -31,7 +32,7 @@ func uploadWorker(database *DB) { } } -func processFile(req uploadRequest, db *DB) { +func processFile(req uploadRequest, db *database.DB) { defer req.file.Close() epub, err := openMultipartEpub(req.file) @@ -52,7 +53,7 @@ func processFile(req uploadRequest, db *DB) { book["file"] = id book["filesize"] = size - err = db.InsertBook(book) + err = db.AddBook(book) if err != nil { log.Error("Error storing metadata (", title, "): ", err) return @@ -103,7 +104,7 @@ func openMultipartEpub(file multipart.File) (*epubgo.Epub, error) { return epubgo.Load(reader, int64(len(buff))) } -func parseFile(epub *epubgo.Epub, db *DB) map[string]interface{} { +func parseFile(epub *epubgo.Epub, db *database.DB) map[string]interface{} { book := map[string]interface{}{} for _, m := range epub.MetadataFields() { data, err := epub.Metadata(m) diff --git a/user.go b/user.go index dcecb38..43a78df 100644 --- a/user.go +++ b/user.go @@ -1,7 +1,8 @@ package main +import log "github.com/cihub/seelog" + import ( - "log" "net/http" ) @@ -19,12 +20,12 @@ func loginHandler(h handler) { func loginPostHandler(h handler) { user := h.r.FormValue("user") pass := h.r.FormValue("pass") - if h.db.UserValid(user, pass) { - log.Println("User", user, "log in") + if h.db.User(user).Valid(pass) { + log.Info("User ", user, " log in") h.sess.LogIn(user) h.sess.Notify("Successful login!", "Welcome "+user, "success") } else { - log.Println("User", user, "bad user or password") + log.Warn("User ", user, " bad user or password") h.sess.Notify("Invalid login!", "user or password invalid", "error") } h.sess.Save(h.w, h.r) @@ -71,12 +72,12 @@ func settingsHandler(h handler) { pass1 := h.r.FormValue("password1") pass2 := h.r.FormValue("password2") switch { - case !h.db.UserValid(h.sess.User, current_pass): + case !h.db.User(h.sess.User).Valid(current_pass): h.sess.Notify("Password error!", "The current password given don't match with the user password. Try again", "error") case pass1 != pass2: h.sess.Notify("Passwords don't match!", "The new password and the confirmation password don't match. Try again", "error") default: - h.db.SetPassword(h.sess.User, pass1) + h.db.User(h.sess.User).SetPassword(pass1) h.sess.Notify("Password updated!", "Your new password is correctly set.", "success") } h.sess.Save(h.w, h.r)