diff options
author | Frédéric Guillot <fred@miniflux.net> | 2017-11-19 21:10:04 -0800 |
---|---|---|
committer | Frédéric Guillot <fred@miniflux.net> | 2017-11-19 22:01:46 -0800 |
commit | 8ffb773f43c8dc54801ca1d111854e7e881c93c9 (patch) | |
tree | 38133a2fc612597a75fed1d13e5b4042f58a2b7e /model |
First commit
Diffstat (limited to 'model')
-rw-r--r-- | model/category.go | 51 | ||||
-rw-r--r-- | model/enclosure.go | 18 | ||||
-rw-r--r-- | model/entry.go | 71 | ||||
-rw-r--r-- | model/feed.go | 66 | ||||
-rw-r--r-- | model/icon.go | 19 | ||||
-rw-r--r-- | model/job.go | 10 | ||||
-rw-r--r-- | model/session.go | 23 | ||||
-rw-r--r-- | model/theme.go | 13 | ||||
-rw-r--r-- | model/user.go | 96 |
9 files changed, 367 insertions, 0 deletions
diff --git a/model/category.go b/model/category.go new file mode 100644 index 0000000..76f254f --- /dev/null +++ b/model/category.go @@ -0,0 +1,51 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +import ( + "errors" + "fmt" +) + +type Category struct { + ID int64 `json:"id,omitempty"` + Title string `json:"title,omitempty"` + UserID int64 `json:"user_id,omitempty"` + FeedCount int `json:"nb_feeds,omitempty"` +} + +func (c *Category) String() string { + return fmt.Sprintf("ID=%d, UserID=%d, Title=%s", c.ID, c.UserID, c.Title) +} + +func (c Category) ValidateCategoryCreation() error { + if c.Title == "" { + return errors.New("The title is mandatory") + } + + if c.UserID == 0 { + return errors.New("The userID is mandatory") + } + + return nil +} + +func (c Category) ValidateCategoryModification() error { + if c.Title == "" { + return errors.New("The title is mandatory") + } + + if c.UserID == 0 { + return errors.New("The userID is mandatory") + } + + if c.ID == 0 { + return errors.New("The ID is mandatory") + } + + return nil +} + +type Categories []*Category diff --git a/model/enclosure.go b/model/enclosure.go new file mode 100644 index 0000000..5a52f78 --- /dev/null +++ b/model/enclosure.go @@ -0,0 +1,18 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +// Enclosure represents an attachment. +type Enclosure struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + EntryID int64 `json:"entry_id"` + URL string `json:"url"` + MimeType string `json:"mime_type"` + Size int `json:"size"` +} + +// EnclosureList represents a list of attachments. +type EnclosureList []*Enclosure diff --git a/model/entry.go b/model/entry.go new file mode 100644 index 0000000..6858935 --- /dev/null +++ b/model/entry.go @@ -0,0 +1,71 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +import ( + "fmt" + "time" +) + +const ( + EntryStatusUnread = "unread" + EntryStatusRead = "read" + EntryStatusRemoved = "removed" + DefaultSortingOrder = "published_at" + DefaultSortingDirection = "desc" +) + +type Entry struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + FeedID int64 `json:"feed_id"` + Status string `json:"status"` + Hash string `json:"hash"` + Title string `json:"title"` + URL string `json:"url"` + Date time.Time `json:"published_at"` + Content string `json:"content"` + Author string `json:"author"` + Enclosures EnclosureList `json:"enclosures,omitempty"` + Feed *Feed `json:"feed,omitempty"` + Category *Category `json:"category,omitempty"` +} + +type Entries []*Entry + +func ValidateEntryStatus(status string) error { + switch status { + case EntryStatusRead, EntryStatusUnread, EntryStatusRemoved: + return nil + } + + return fmt.Errorf(`Invalid entry status, valid status values are: "%s", "%s" and "%s"`, EntryStatusRead, EntryStatusUnread, EntryStatusRemoved) +} + +func ValidateEntryOrder(order string) error { + switch order { + case "id", "status", "published_at", "category_title", "category_id": + return nil + } + + return fmt.Errorf(`Invalid entry order, valid order values are: "id", "status", "published_at", "category_title", "category_id"`) +} + +func ValidateDirection(direction string) error { + switch direction { + case "asc", "desc": + return nil + } + + return fmt.Errorf(`Invalid direction, valid direction values are: "asc" or "desc"`) +} + +func GetOppositeDirection(direction string) string { + if direction == "asc" { + return "desc" + } + + return "asc" +} diff --git a/model/feed.go b/model/feed.go new file mode 100644 index 0000000..17a9b25 --- /dev/null +++ b/model/feed.go @@ -0,0 +1,66 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +import ( + "fmt" + "reflect" + "time" +) + +// Feed represents a feed in the database +type Feed struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + FeedURL string `json:"feed_url"` + SiteURL string `json:"site_url"` + Title string `json:"title"` + CheckedAt time.Time `json:"checked_at,omitempty"` + EtagHeader string `json:"etag_header,omitempty"` + LastModifiedHeader string `json:"last_modified_header,omitempty"` + ParsingErrorMsg string `json:"parsing_error_message,omitempty"` + ParsingErrorCount int `json:"parsing_error_count,omitempty"` + Category *Category `json:"category,omitempty"` + Entries Entries `json:"entries,omitempty"` + Icon *FeedIcon `json:"icon,omitempty"` +} + +func (f *Feed) String() string { + return fmt.Sprintf("ID=%d, UserID=%d, FeedURL=%s, SiteURL=%s, Title=%s, Category={%s}", + f.ID, + f.UserID, + f.FeedURL, + f.SiteURL, + f.Title, + f.Category, + ) +} + +// Merge combine src to the current struct +func (f *Feed) Merge(src *Feed) { + src.ID = f.ID + src.UserID = f.UserID + + new := reflect.ValueOf(src).Elem() + for i := 0; i < new.NumField(); i++ { + field := new.Field(i) + + switch field.Interface().(type) { + case int64: + value := field.Int() + if value != 0 { + reflect.ValueOf(f).Elem().Field(i).SetInt(value) + } + case string: + value := field.String() + if value != "" { + reflect.ValueOf(f).Elem().Field(i).SetString(value) + } + } + } +} + +// Feeds is a list of feed +type Feeds []*Feed diff --git a/model/icon.go b/model/icon.go new file mode 100644 index 0000000..7bf12bf --- /dev/null +++ b/model/icon.go @@ -0,0 +1,19 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +// Icon represents a website icon (favicon) +type Icon struct { + ID int64 `json:"id"` + Hash string `json:"hash"` + MimeType string `json:"mime_type"` + Content []byte `json:"content"` +} + +// FeedIcon is a jonction table between feeds and icons +type FeedIcon struct { + FeedID int64 `json:"feed_id"` + IconID int64 `json:"icon_id"` +} diff --git a/model/job.go b/model/job.go new file mode 100644 index 0000000..ed3ef5e --- /dev/null +++ b/model/job.go @@ -0,0 +1,10 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +type Job struct { + UserID int64 + FeedID int64 +} diff --git a/model/session.go b/model/session.go new file mode 100644 index 0000000..ba62d8a --- /dev/null +++ b/model/session.go @@ -0,0 +1,23 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +import "time" +import "fmt" + +type Session struct { + ID int64 + UserID int64 + Token string + CreatedAt time.Time + UserAgent string + IP string +} + +func (s *Session) String() string { + return fmt.Sprintf("ID=%d, UserID=%d, IP=%s", s.ID, s.UserID, s.IP) +} + +type Sessions []*Session diff --git a/model/theme.go b/model/theme.go new file mode 100644 index 0000000..bcbb23a --- /dev/null +++ b/model/theme.go @@ -0,0 +1,13 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +// GetThemes returns the list of available themes. +func GetThemes() map[string]string { + return map[string]string{ + "default": "Default", + "black": "Black", + } +} diff --git a/model/user.go b/model/user.go new file mode 100644 index 0000000..26bf6c9 --- /dev/null +++ b/model/user.go @@ -0,0 +1,96 @@ +// Copyright 2017 Frédéric Guillot. All rights reserved. +// Use of this source code is governed by the Apache 2.0 +// license that can be found in the LICENSE file. + +package model + +import ( + "errors" + "time" +) + +// User represents a user in the system. +type User struct { + ID int64 `json:"id"` + Username string `json:"username"` + Password string `json:"password,omitempty"` + IsAdmin bool `json:"is_admin"` + Theme string `json:"theme"` + Language string `json:"language"` + Timezone string `json:"timezone"` + LastLoginAt *time.Time `json:"last_login_at"` +} + +func (u User) ValidateUserCreation() error { + if err := u.ValidateUserLogin(); err != nil { + return err + } + + if err := u.ValidatePassword(); err != nil { + return err + } + + return nil +} + +func (u User) ValidateUserModification() error { + if u.Username == "" { + return errors.New("The username is mandatory") + } + + if err := u.ValidatePassword(); err != nil { + return err + } + + return nil +} + +func (u User) ValidateUserLogin() error { + if u.Username == "" { + return errors.New("The username is mandatory") + } + + if u.Password == "" { + return errors.New("The password is mandatory") + } + + return nil +} + +func (u User) ValidatePassword() error { + if u.Password != "" && len(u.Password) < 6 { + return errors.New("The password must have at least 6 characters") + } + + return nil +} + +// Merge update the current user with another user. +func (u *User) Merge(override *User) { + if u.Username != override.Username { + u.Username = override.Username + } + + if u.Password != override.Password { + u.Password = override.Password + } + + if u.IsAdmin != override.IsAdmin { + u.IsAdmin = override.IsAdmin + } + + if u.Theme != override.Theme { + u.Theme = override.Theme + } + + if u.Language != override.Language { + u.Language = override.Language + } + + if u.Timezone != override.Timezone { + u.Timezone = override.Timezone + } +} + +// Users represents a list of users. +type Users []*User |