aboutsummaryrefslogtreecommitdiffhomepage
path: root/model
diff options
context:
space:
mode:
authorGravatar Frédéric Guillot <fred@miniflux.net>2017-11-19 21:10:04 -0800
committerGravatar Frédéric Guillot <fred@miniflux.net>2017-11-19 22:01:46 -0800
commit8ffb773f43c8dc54801ca1d111854e7e881c93c9 (patch)
tree38133a2fc612597a75fed1d13e5b4042f58a2b7e /model
First commit
Diffstat (limited to 'model')
-rw-r--r--model/category.go51
-rw-r--r--model/enclosure.go18
-rw-r--r--model/entry.go71
-rw-r--r--model/feed.go66
-rw-r--r--model/icon.go19
-rw-r--r--model/job.go10
-rw-r--r--model/session.go23
-rw-r--r--model/theme.go13
-rw-r--r--model/user.go96
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