diff --git a/Gopkg.lock b/Gopkg.lock index ca51c391..50067ee5 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -45,7 +45,7 @@ branch = "master" name = "github.com/miniflux/miniflux-go" packages = ["."] - revision = "ec30672607d4dd72470f4c156bd36ba07d9a9a2a" + revision = "cfb76c59831603c2b57e03356e9241facfa9834e" [[projects]] name = "github.com/tdewolff/minify" diff --git a/api/feed.go b/api/feed.go index 351457f7..b7c46ea1 100644 --- a/api/feed.go +++ b/api/feed.go @@ -97,7 +97,7 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) { return } - newFeed, err := decodeFeedModificationPayload(r.Body) + feedChanges, err := decodeFeedModificationPayload(r.Body) if err != nil { json.BadRequest(w, err) return @@ -106,11 +106,6 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) { ctx := context.New(r) userID := ctx.UserID() - if newFeed.Category != nil && newFeed.Category.ID != 0 && !c.store.CategoryExists(userID, newFeed.Category.ID) { - json.BadRequest(w, errors.New("This category_id doesn't exists or doesn't belongs to this user")) - return - } - originalFeed, err := c.store.FeedByID(userID, feedID) if err != nil { json.NotFound(w, errors.New("Unable to find this feed")) @@ -122,7 +117,13 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) { return } - originalFeed.Merge(newFeed) + feedChanges.Update(originalFeed) + + if !c.store.CategoryExists(userID, originalFeed.Category.ID) { + json.BadRequest(w, errors.New("This category_id doesn't exists or doesn't belongs to this user")) + return + } + if err := c.store.UpdateFeed(originalFeed); err != nil { json.ServerError(w, errors.New("Unable to update this feed")) return diff --git a/api/payload.go b/api/payload.go index 45cb826a..ed5255a0 100644 --- a/api/payload.go +++ b/api/payload.go @@ -37,13 +37,115 @@ type subscriptionDiscovery struct { Password string `json:"password"` } -func decodeUserPayload(r io.ReadCloser) (*model.User, error) { - var user model.User +type feedModification struct { + FeedURL *string `json:"feed_url"` + SiteURL *string `json:"site_url"` + Title *string `json:"title"` + ScraperRules *string `json:"scraper_rules"` + RewriteRules *string `json:"rewrite_rules"` + Crawler *bool `json:"crawler"` + Username *string `json:"username"` + Password *string `json:"password"` + CategoryID *int64 `json:"category_id"` +} - decoder := json.NewDecoder(r) +func (f *feedModification) Update(feed *model.Feed) { + if f.FeedURL != nil && *f.FeedURL != "" { + feed.FeedURL = *f.FeedURL + } + + if f.SiteURL != nil && *f.SiteURL != "" { + feed.SiteURL = *f.SiteURL + } + + if f.Title != nil && *f.Title != "" { + feed.Title = *f.Title + } + + if f.ScraperRules != nil { + feed.ScraperRules = *f.ScraperRules + } + + if f.RewriteRules != nil { + feed.RewriteRules = *f.RewriteRules + } + + if f.Crawler != nil { + feed.Crawler = *f.Crawler + } + + if f.Username != nil { + feed.Username = *f.Username + } + + if f.Password != nil { + feed.Password = *f.Password + } + + if f.CategoryID != nil && *f.CategoryID > 0 { + feed.Category.ID = *f.CategoryID + } +} + +type userModification struct { + Username *string `json:"username"` + Password *string `json:"password"` + IsAdmin *bool `json:"is_admin"` + Theme *string `json:"theme"` + Language *string `json:"language"` + Timezone *string `json:"timezone"` + EntryDirection *string `json:"entry_sorting_direction"` +} + +func (u *userModification) Update(user *model.User) { + if u.Username != nil { + user.Username = *u.Username + } + + if u.Password != nil { + user.Password = *u.Password + } + + if u.IsAdmin != nil { + user.IsAdmin = *u.IsAdmin + } + + if u.Theme != nil { + user.Theme = *u.Theme + } + + if u.Language != nil { + user.Language = *u.Language + } + + if u.Timezone != nil { + user.Timezone = *u.Timezone + } + + if u.EntryDirection != nil { + user.EntryDirection = *u.EntryDirection + } +} + +func decodeUserModificationPayload(r io.ReadCloser) (*userModification, error) { defer r.Close() + + var user userModification + decoder := json.NewDecoder(r) if err := decoder.Decode(&user); err != nil { - return nil, fmt.Errorf("Unable to decode user JSON object: %v", err) + return nil, fmt.Errorf("Unable to decode user modification JSON object: %v", err) + } + + return &user, nil +} + +func decodeUserCreationPayload(r io.ReadCloser) (*model.User, error) { + defer r.Close() + + var user model.User + decoder := json.NewDecoder(r) + if err := decoder.Decode(&user); err != nil { + return nil, fmt.Errorf("Unable to decode user modification JSON object: %v", err) } return &user, nil @@ -89,13 +191,13 @@ func decodeFeedCreationPayload(r io.ReadCloser) (*feedCreation, error) { return &fc, nil } -func decodeFeedModificationPayload(r io.ReadCloser) (*model.Feed, error) { - var feed model.Feed - - decoder := json.NewDecoder(r) +func decodeFeedModificationPayload(r io.ReadCloser) (*feedModification, error) { defer r.Close() + + var feed feedModification + decoder := json.NewDecoder(r) if err := decoder.Decode(&feed); err != nil { - return nil, fmt.Errorf("Unable to decode feed JSON object: %v", err) + return nil, fmt.Errorf("Unable to decode feed modification JSON object: %v", err) } return &feed, nil diff --git a/api/payload_test.go b/api/payload_test.go new file mode 100644 index 00000000..debf897e --- /dev/null +++ b/api/payload_test.go @@ -0,0 +1,192 @@ +// Copyright 2018 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 api + +import ( + "testing" + + "github.com/miniflux/miniflux/model" +) + +func TestUpdateFeedURL(t *testing.T) { + feedURL := "http://example.com/" + changes := &feedModification{FeedURL: &feedURL} + feed := &model.Feed{FeedURL: "http://example.org/"} + changes.Update(feed) + + if feed.FeedURL != feedURL { + t.Fatalf(`Unexpected value, got %q instead of %q`, feed.FeedURL, feedURL) + } +} + +func TestUpdateFeedURLWithEmptyString(t *testing.T) { + feedURL := "" + changes := &feedModification{FeedURL: &feedURL} + feed := &model.Feed{FeedURL: "http://example.org/"} + changes.Update(feed) + + if feed.FeedURL == feedURL { + t.Fatal(`The FeedURL should not be modified`) + } +} + +func TestUpdateFeedURLWhenNotSet(t *testing.T) { + changes := &feedModification{} + feed := &model.Feed{FeedURL: "http://example.org/"} + changes.Update(feed) + + if feed.FeedURL != "http://example.org/" { + t.Fatal(`The FeedURL should not be modified`) + } +} + +func TestUpdateFeedSiteURL(t *testing.T) { + siteURL := "http://example.com/" + changes := &feedModification{SiteURL: &siteURL} + feed := &model.Feed{SiteURL: "http://example.org/"} + changes.Update(feed) + + if feed.SiteURL != siteURL { + t.Fatalf(`Unexpected value, got %q instead of %q`, feed.SiteURL, siteURL) + } +} + +func TestUpdateFeedSiteURLWithEmptyString(t *testing.T) { + siteURL := "" + changes := &feedModification{FeedURL: &siteURL} + feed := &model.Feed{SiteURL: "http://example.org/"} + changes.Update(feed) + + if feed.SiteURL == siteURL { + t.Fatal(`The FeedURL should not be modified`) + } +} + +func TestUpdateFeedSiteURLWhenNotSet(t *testing.T) { + changes := &feedModification{} + feed := &model.Feed{SiteURL: "http://example.org/"} + changes.Update(feed) + + if feed.SiteURL != "http://example.org/" { + t.Fatal(`The SiteURL should not be modified`) + } +} + +func TestUpdateFeedTitle(t *testing.T) { + title := "Example 2" + changes := &feedModification{Title: &title} + feed := &model.Feed{Title: "Example"} + changes.Update(feed) + + if feed.Title != title { + t.Fatalf(`Unexpected value, got %q instead of %q`, feed.Title, title) + } +} + +func TestUpdateFeedTitleWithEmptyString(t *testing.T) { + title := "" + changes := &feedModification{Title: &title} + feed := &model.Feed{Title: "Example"} + changes.Update(feed) + + if feed.Title == title { + t.Fatal(`The Title should not be modified`) + } +} + +func TestUpdateFeedTitleWhenNotSet(t *testing.T) { + changes := &feedModification{} + feed := &model.Feed{Title: "Example"} + changes.Update(feed) + + if feed.Title != "Example" { + t.Fatal(`The Title should not be modified`) + } +} + +func TestUpdateFeedUsername(t *testing.T) { + username := "Alice" + changes := &feedModification{Username: &username} + feed := &model.Feed{Username: "Bob"} + changes.Update(feed) + + if feed.Username != username { + t.Fatalf(`Unexpected value, got %q instead of %q`, feed.Username, username) + } +} + +func TestUpdateFeedUsernameWithEmptyString(t *testing.T) { + username := "" + changes := &feedModification{Username: &username} + feed := &model.Feed{Username: "Bob"} + changes.Update(feed) + + if feed.Username != "" { + t.Fatal(`The Username should be empty now`) + } +} + +func TestUpdateFeedUsernameWhenNotSet(t *testing.T) { + changes := &feedModification{} + feed := &model.Feed{Username: "Alice"} + changes.Update(feed) + + if feed.Username != "Alice" { + t.Fatal(`The Username should not be modified`) + } +} + +func TestUpdateFeedCategory(t *testing.T) { + categoryID := int64(1) + changes := &feedModification{CategoryID: &categoryID} + feed := &model.Feed{Category: &model.Category{ID: 42}} + changes.Update(feed) + + if feed.Category.ID != categoryID { + t.Fatalf(`Unexpected value, got %q instead of %q`, feed.Username, categoryID) + } +} + +func TestUpdateFeedCategoryWithZero(t *testing.T) { + categoryID := int64(0) + changes := &feedModification{CategoryID: &categoryID} + feed := &model.Feed{Category: &model.Category{ID: 42}} + changes.Update(feed) + + if feed.Category.ID != 42 { + t.Fatal(`The CategoryID should not be modified`) + } +} + +func TestUpdateFeedCategoryWhenNotSet(t *testing.T) { + changes := &feedModification{} + feed := &model.Feed{Category: &model.Category{ID: 42}} + changes.Update(feed) + + if feed.Category.ID != 42 { + t.Fatal(`The CategoryID should not be modified`) + } +} + +func TestUpdateUserTheme(t *testing.T) { + theme := "Example 2" + changes := &userModification{Theme: &theme} + user := &model.User{Theme: "Example"} + changes.Update(user) + + if user.Theme != theme { + t.Fatalf(`Unexpected value, got %q instead of %q`, user.Theme, theme) + } +} + +func TestUserThemeWhenNotSet(t *testing.T) { + changes := &userModification{} + user := &model.User{Theme: "Example"} + changes.Update(user) + + if user.Theme != "Example" { + t.Fatal(`The user Theme should not be modified`) + } +} diff --git a/api/user.go b/api/user.go index a231e8ce..4e5fa828 100644 --- a/api/user.go +++ b/api/user.go @@ -33,7 +33,7 @@ func (c *Controller) CreateUser(w http.ResponseWriter, r *http.Request) { return } - user, err := decodeUserPayload(r.Body) + user, err := decodeUserCreationPayload(r.Body) if err != nil { json.BadRequest(w, err) return @@ -73,17 +73,12 @@ func (c *Controller) UpdateUser(w http.ResponseWriter, r *http.Request) { return } - user, err := decodeUserPayload(r.Body) + userChanges, err := decodeUserModificationPayload(r.Body) if err != nil { json.BadRequest(w, err) return } - if err := user.ValidateUserModification(); err != nil { - json.BadRequest(w, err) - return - } - originalUser, err := c.store.UserByID(userID) if err != nil { json.BadRequest(w, errors.New("Unable to fetch this user from the database")) @@ -95,7 +90,12 @@ func (c *Controller) UpdateUser(w http.ResponseWriter, r *http.Request) { return } - originalUser.Merge(user) + userChanges.Update(originalUser) + if err := originalUser.ValidateUserModification(); err != nil { + json.BadRequest(w, err) + return + } + if err = c.store.UpdateUser(originalUser); err != nil { json.ServerError(w, errors.New("Unable to update this user")) return diff --git a/integration_test.go b/integration_test.go index 40505eeb..30758a93 100644 --- a/integration_test.go +++ b/integration_test.go @@ -42,6 +42,10 @@ func TestWithWrongCredentials(t *testing.T) { if err == nil { t.Fatal(`Using bad credentials should raise an error`) } + + if err != miniflux.ErrNotAuthorized { + t.Fatal(`A "Not Authorized" error should be raised`) + } } func TestGetCurrentLoggedUser(t *testing.T) { @@ -256,7 +260,7 @@ func TestGetUserByUsername(t *testing.T) { } } -func TestUpdateUser(t *testing.T) { +func TestUpdateUserTheme(t *testing.T) { username := getRandomUsername() client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) user, err := client.CreateUser(username, testStandardPassword, false) @@ -265,18 +269,17 @@ func TestUpdateUser(t *testing.T) { } theme := "black" - user.Theme = theme - user, err = client.UpdateUser(user) + user, err = client.UpdateUser(user.ID, &miniflux.UserModification{Theme: &theme}) if err != nil { t.Fatal(err) } if user.Theme != theme { - t.Fatalf(`Unable to update user: got "%v" instead of "%v"`, user.Theme, theme) + t.Fatalf(`Unable to update user Theme: got "%v" instead of "%v"`, user.Theme, theme) } } -func TestUpdateUserWithInvalidValue(t *testing.T) { +func TestUpdateUserThemeWithInvalidValue(t *testing.T) { username := getRandomUsername() client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) user, err := client.CreateUser(username, testStandardPassword, false) @@ -285,10 +288,9 @@ func TestUpdateUserWithInvalidValue(t *testing.T) { } theme := "something that doesn't exists" - user.Theme = theme - _, err = client.UpdateUser(user) + _, err = client.UpdateUser(user.ID, &miniflux.UserModification{Theme: &theme}) if err == nil { - t.Fatal(`Updating a user with an invalid value should raise an error`) + t.Fatal(`Updating a user Theme with an invalid value should raise an error`) } } @@ -319,6 +321,10 @@ func TestCannotListUsersAsNonAdmin(t *testing.T) { if err == nil { t.Fatal(`Standard users should not be able to list any users`) } + + if err != miniflux.ErrForbidden { + t.Fatal(`A "Forbidden" error should be raised`) + } } func TestCannotGetUserAsNonAdmin(t *testing.T) { @@ -334,6 +340,10 @@ func TestCannotGetUserAsNonAdmin(t *testing.T) { if err == nil { t.Fatal(`Standard users should not be able to get any users`) } + + if err != miniflux.ErrForbidden { + t.Fatal(`A "Forbidden" error should be raised`) + } } func TestCannotUpdateUserAsNonAdmin(t *testing.T) { @@ -345,10 +355,14 @@ func TestCannotUpdateUserAsNonAdmin(t *testing.T) { } client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - _, err = client.UpdateUser(user) + _, err = client.UpdateUser(user.ID, &miniflux.UserModification{}) if err == nil { t.Fatal(`Standard users should not be able to update any users`) } + + if err != miniflux.ErrForbidden { + t.Fatal(`A "Forbidden" error should be raised`) + } } func TestCannotCreateUserAsNonAdmin(t *testing.T) { @@ -364,6 +378,10 @@ func TestCannotCreateUserAsNonAdmin(t *testing.T) { if err == nil { t.Fatal(`Standard users should not be able to create users`) } + + if err != miniflux.ErrForbidden { + t.Fatal(`A "Forbidden" error should be raised`) + } } func TestCannotDeleteUserAsNonAdmin(t *testing.T) { @@ -375,9 +393,14 @@ func TestCannotDeleteUserAsNonAdmin(t *testing.T) { } client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - if err := client.DeleteUser(user.ID); err == nil { + err = client.DeleteUser(user.ID) + if err == nil { t.Fatal(`Standard users should not be able to remove any users`) } + + if err != miniflux.ErrForbidden { + t.Fatal(`A "Forbidden" error should be raised`) + } } func TestCreateCategory(t *testing.T) { @@ -417,16 +440,10 @@ func TestCreateCategoryWithEmptyTitle(t *testing.T) { } func TestCannotCreateDuplicatedCategory(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } + client := createClient(t) categoryName := "My category" - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - _, err = client.CreateCategory(categoryName) + _, err := client.CreateCategory(categoryName) if err != nil { t.Fatal(err) } @@ -521,14 +538,8 @@ func TestListCategories(t *testing.T) { } func TestDeleteCategory(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } + client := createClient(t) - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) category, err := client.CreateCategory("My category") if err != nil { t.Fatal(err) @@ -585,82 +596,36 @@ func TestDiscoverSubscriptions(t *testing.T) { } func TestCreateFeed(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + feed, _ := createFeed(t, client) - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } - - if feedID == 0 { - t.Fatalf(`Invalid feed ID, got "%v"`, feedID) + if feed.ID == 0 { + t.Fatalf(`Invalid feed ID, got %q`, feed.ID) } } func TestCannotCreateDuplicatedFeed(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + feed, category := createFeed(t, client) - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } - - if feedID == 0 { - t.Fatalf(`Invalid feed ID, got "%v"`, feedID) - } - - _, err = client.CreateFeed(testFeedURL, categories[0].ID) + _, err := client.CreateFeed(feed.FeedURL, category.ID) if err == nil { t.Fatal(`Duplicated feeds should not be allowed`) } } func TestCreateFeedWithInexistingCategory(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } + client := createClient(t) - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - _, err = client.CreateFeed(testFeedURL, -1) + _, err := client.CreateFeed(testFeedURL, -1) if err == nil { t.Fatal(`Feeds should not be created with inexisting category`) } } func TestExport(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } + client := createClient(t) - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) output, err := client.Export() if err != nil { t.Fatal(err) @@ -672,14 +637,7 @@ func TestExport(t *testing.T) { } func TestImport(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) + client := createClient(t) data := ` @@ -691,125 +649,264 @@ func TestImport(t *testing.T) { ` b := bytes.NewReader([]byte(data)) - err = client.Import(ioutil.NopCloser(b)) + err := client.Import(ioutil.NopCloser(b)) if err != nil { t.Fatal(err) } } -func TestUpdateFeed(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) +func TestUpdateFeedURL(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + + url := "test" + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{FeedURL: &url}) if err != nil { t.Fatal(err) } - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() + if updatedFeed.FeedURL != url { + t.Fatalf(`Wrong FeedURL, got %q instead of %q`, updatedFeed.FeedURL, url) + } + + url = "" + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{FeedURL: &url}) if err != nil { t.Fatal(err) } - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) + if updatedFeed.FeedURL == "" { + t.Fatalf(`The FeedURL should not be empty`) + } +} + +func TestUpdateFeedSiteURL(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + + url := "test" + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{SiteURL: &url}) if err != nil { t.Fatal(err) } - if feedID == 0 { - t.Fatalf(`Invalid feed ID, got "%v"`, feedID) + if updatedFeed.SiteURL != url { + t.Fatalf(`Wrong SiteURL, got %q instead of %q`, updatedFeed.SiteURL, url) } - feed, err := client.Feed(feedID) + url = "" + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{SiteURL: &url}) if err != nil { t.Fatal(err) } + if updatedFeed.SiteURL == "" { + t.Fatalf(`The SiteURL should not be empty`) + } +} + +func TestUpdateFeedTitle(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + newTitle := "My new feed" - feed.Title = newTitle - feed, err = client.UpdateFeed(feed) + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{Title: &newTitle}) if err != nil { t.Fatal(err) } - if feed.Title != newTitle { - t.Errorf(`Wrong title, got "%v" instead of "%v"`, feed.Title, newTitle) + if updatedFeed.Title != newTitle { + t.Fatalf(`Wrong title, got %q instead of %q`, updatedFeed.Title, newTitle) + } + + newTitle = "" + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{Title: &newTitle}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Title == "" { + t.Fatalf(`The Title should not be empty`) + } +} + +func TestUpdateFeedCrawler(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + + crawler := true + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{Crawler: &crawler}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Crawler != crawler { + t.Fatalf(`Wrong crawler value, got "%v" instead of "%v"`, updatedFeed.Crawler, crawler) + } + + if updatedFeed.Title != feed.Title { + t.Fatalf(`The titles should be the same after update`) + } + + crawler = false + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{Crawler: &crawler}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Crawler != crawler { + t.Fatalf(`Wrong crawler value, got "%v" instead of "%v"`, updatedFeed.Crawler, crawler) + } +} + +func TestUpdateFeedScraperRules(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + + scraperRules := "test" + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{ScraperRules: &scraperRules}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.ScraperRules != scraperRules { + t.Fatalf(`Wrong ScraperRules value, got "%v" instead of "%v"`, updatedFeed.ScraperRules, scraperRules) + } + + scraperRules = "" + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{ScraperRules: &scraperRules}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.ScraperRules != scraperRules { + t.Fatalf(`Wrong ScraperRules value, got "%v" instead of "%v"`, updatedFeed.ScraperRules, scraperRules) + } +} + +func TestUpdateFeedRewriteRules(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + + rewriteRules := "test" + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{RewriteRules: &rewriteRules}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.RewriteRules != rewriteRules { + t.Fatalf(`Wrong RewriteRules value, got "%v" instead of "%v"`, updatedFeed.RewriteRules, rewriteRules) + } + + rewriteRules = "" + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{RewriteRules: &rewriteRules}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.RewriteRules != rewriteRules { + t.Fatalf(`Wrong RewriteRules value, got "%v" instead of "%v"`, updatedFeed.RewriteRules, rewriteRules) + } +} + +func TestUpdateFeedUsername(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + + username := "test" + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{Username: &username}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Username != username { + t.Fatalf(`Wrong Username value, got "%v" instead of "%v"`, updatedFeed.Username, username) + } + + username = "" + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{Username: &username}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Username != username { + t.Fatalf(`Wrong Username value, got "%v" instead of "%v"`, updatedFeed.Username, username) + } +} + +func TestUpdateFeedPassword(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + + password := "test" + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{Password: &password}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Password != password { + t.Fatalf(`Wrong Password value, got "%v" instead of "%v"`, updatedFeed.Password, password) + } + + password = "" + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{Password: &password}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Password != password { + t.Fatalf(`Wrong Password value, got "%v" instead of "%v"`, updatedFeed.Password, password) + } +} + +func TestUpdateFeedCategory(t *testing.T) { + client := createClient(t) + feed, _ := createFeed(t, client) + + newCategory, err := client.CreateCategory("my new category") + if err != nil { + t.Fatal(err) + } + + updatedFeed, err := client.UpdateFeed(feed.ID, &miniflux.FeedModification{CategoryID: &newCategory.ID}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Category.ID != newCategory.ID { + t.Fatalf(`Wrong CategoryID value, got "%v" instead of "%v"`, updatedFeed.Category.ID, newCategory.ID) + } + + categoryID := int64(0) + updatedFeed, err = client.UpdateFeed(feed.ID, &miniflux.FeedModification{CategoryID: &categoryID}) + if err != nil { + t.Fatal(err) + } + + if updatedFeed.Category.ID == 0 { + t.Fatalf(`The CategoryID must defined`) } } func TestDeleteFeed(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } - - err = client.DeleteFeed(feedID) - if err != nil { + client := createClient(t) + feed, _ := createFeed(t, client) + if err := client.DeleteFeed(feed.ID); err != nil { t.Fatal(err) } } func TestRefreshFeed(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } - - err = client.RefreshFeed(feedID) - if err != nil { + client := createClient(t) + feed, _ := createFeed(t, client) + if err := client.RefreshFeed(feed.ID); err != nil { t.Fatal(err) } } func TestGetFeed(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } - - feed, err := client.Feed(feedID) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + feed, category := createFeed(t, client) if feed.Title != testFeedTitle { t.Fatalf(`Invalid feed title, got "%v" instead of "%v"`, feed.Title, testFeedTitle) @@ -823,39 +920,23 @@ func TestGetFeed(t *testing.T) { t.Fatalf(`Invalid feed URL, got "%v" instead of "%v"`, feed.FeedURL, testFeedURL) } - if feed.Category.ID != categories[0].ID { - t.Fatalf(`Invalid feed category ID, got "%v" instead of "%v"`, feed.Category.ID, categories[0].ID) + if feed.Category.ID != category.ID { + t.Fatalf(`Invalid feed category ID, got "%v" instead of "%v"`, feed.Category.ID, category.ID) } - if feed.Category.UserID != categories[0].UserID { - t.Fatalf(`Invalid feed category user ID, got "%v" instead of "%v"`, feed.Category.UserID, categories[0].UserID) + if feed.Category.UserID != category.UserID { + t.Fatalf(`Invalid feed category user ID, got "%v" instead of "%v"`, feed.Category.UserID, category.UserID) } - if feed.Category.Title != categories[0].Title { - t.Fatalf(`Invalid feed category title, got "%v" instead of "%v"`, feed.Category.Title, categories[0].Title) + if feed.Category.Title != category.Title { + t.Fatalf(`Invalid feed category title, got "%v" instead of "%v"`, feed.Category.Title, category.Title) } } func TestGetFeedIcon(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } - - feedIcon, err := client.FeedIcon(feedID) + client := createClient(t) + feed, _ := createFeed(t, client) + feedIcon, err := client.FeedIcon(feed.ID) if err != nil { t.Fatal(err) } @@ -888,23 +969,8 @@ func TestGetFeedIconNotFound(t *testing.T) { } func TestGetFeeds(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + feed, category := createFeed(t, client) feeds, err := client.Feeds() if err != nil { @@ -915,8 +981,8 @@ func TestGetFeeds(t *testing.T) { t.Fatalf(`Invalid number of feeds`) } - if feeds[0].ID != feedID { - t.Fatalf(`Invalid feed ID, got "%v" instead of "%v"`, feeds[0].ID, feedID) + if feeds[0].ID != feed.ID { + t.Fatalf(`Invalid feed ID, got "%v" instead of "%v"`, feeds[0].ID, feed.ID) } if feeds[0].Title != testFeedTitle { @@ -931,39 +997,24 @@ func TestGetFeeds(t *testing.T) { t.Fatalf(`Invalid feed URL, got "%v" instead of "%v"`, feeds[0].FeedURL, testFeedURL) } - if feeds[0].Category.ID != categories[0].ID { - t.Fatalf(`Invalid feed category ID, got "%v" instead of "%v"`, feeds[0].Category.ID, categories[0].ID) + if feeds[0].Category.ID != category.ID { + t.Fatalf(`Invalid feed category ID, got "%v" instead of "%v"`, feeds[0].Category.ID, category.ID) } - if feeds[0].Category.UserID != categories[0].UserID { - t.Fatalf(`Invalid feed category user ID, got "%v" instead of "%v"`, feeds[0].Category.UserID, categories[0].UserID) + if feeds[0].Category.UserID != category.UserID { + t.Fatalf(`Invalid feed category user ID, got "%v" instead of "%v"`, feeds[0].Category.UserID, category.UserID) } - if feeds[0].Category.Title != categories[0].Title { - t.Fatalf(`Invalid feed category title, got "%v" instead of "%v"`, feeds[0].Category.Title, categories[0].Title) + if feeds[0].Category.Title != category.Title { + t.Fatalf(`Invalid feed category title, got "%v" instead of "%v"`, feeds[0].Category.Title, category.Title) } } func TestGetAllFeedEntries(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + feed, _ := createFeed(t, client) - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } - - allResults, err := client.FeedEntries(feedID, nil) + allResults, err := client.FeedEntries(feed.ID, nil) if err != nil { t.Fatal(err) } @@ -976,7 +1027,7 @@ func TestGetAllFeedEntries(t *testing.T) { t.Fatal(`Invalid entry title`) } - filteredResults, err := client.FeedEntries(feedID, &miniflux.Filter{Limit: 1, Offset: 5}) + filteredResults, err := client.FeedEntries(feed.ID, &miniflux.Filter{Limit: 1, Offset: 5}) if err != nil { t.Fatal(err) } @@ -989,7 +1040,7 @@ func TestGetAllFeedEntries(t *testing.T) { t.Fatal(`Filtered entries should be different than previous results`) } - filteredResultsByEntryID, err := client.FeedEntries(feedID, &miniflux.Filter{BeforeEntryID: allResults.Entries[0].ID}) + filteredResultsByEntryID, err := client.FeedEntries(feed.ID, &miniflux.Filter{BeforeEntryID: allResults.Entries[0].ID}) if err != nil { t.Fatal(err) } @@ -1000,23 +1051,8 @@ func TestGetAllFeedEntries(t *testing.T) { } func TestGetAllEntries(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - _, err = client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + createFeed(t, client) resultWithoutSorting, err := client.Entries(nil) if err != nil { @@ -1056,25 +1092,10 @@ func TestGetAllEntries(t *testing.T) { } func TestInvalidFilters(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + createFeed(t, client) - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - _, err = client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } - - _, err = client.Entries(&miniflux.Filter{Status: "invalid"}) + _, err := client.Entries(&miniflux.Filter{Status: "invalid"}) if err == nil { t.Fatal(`Using invalid status should raise an error`) } @@ -1091,23 +1112,8 @@ func TestInvalidFilters(t *testing.T) { } func TestGetEntry(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - _, err = client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + createFeed(t, client) result, err := client.Entries(&miniflux.Filter{Limit: 1}) if err != nil { @@ -1134,23 +1140,8 @@ func TestGetEntry(t *testing.T) { } func TestUpdateStatus(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - _, err = client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + createFeed(t, client) result, err := client.Entries(&miniflux.Filter{Limit: 1}) if err != nil { @@ -1178,23 +1169,8 @@ func TestUpdateStatus(t *testing.T) { } func TestToggleBookmark(t *testing.T) { - username := getRandomUsername() - client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) - _, err := client.CreateUser(username, testStandardPassword, false) - if err != nil { - t.Fatal(err) - } - - client = miniflux.NewClient(testBaseURL, username, testStandardPassword) - categories, err := client.Categories() - if err != nil { - t.Fatal(err) - } - - _, err = client.CreateFeed(testFeedURL, categories[0].ID) - if err != nil { - t.Fatal(err) - } + client := createClient(t) + createFeed(t, client) result, err := client.Entries(&miniflux.Filter{Limit: 1}) if err != nil { @@ -1228,3 +1204,37 @@ func getRandomUsername() string { } return "user" + strings.Join(suffix, "") } + +func createClient(t *testing.T) *miniflux.Client { + username := getRandomUsername() + client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword) + _, err := client.CreateUser(username, testStandardPassword, false) + if err != nil { + t.Fatal(err) + } + + return miniflux.NewClient(testBaseURL, username, testStandardPassword) +} + +func createFeed(t *testing.T, client *miniflux.Client) (*miniflux.Feed, *miniflux.Category) { + categories, err := client.Categories() + if err != nil { + t.Fatal(err) + } + + feedID, err := client.CreateFeed(testFeedURL, categories[0].ID) + if err != nil { + t.Fatal(err) + } + + if feedID == 0 { + t.Fatalf(`Invalid feed ID, got %q`, feedID) + } + + feed, err := client.Feed(feedID) + if err != nil { + t.Fatal(err) + } + + return feed, categories[0] +} diff --git a/model/feed.go b/model/feed.go index 9c7eccab..d019eeb8 100644 --- a/model/feed.go +++ b/model/feed.go @@ -42,44 +42,5 @@ func (f *Feed) String() string { ) } -// Merge combine override to the current struct -func (f *Feed) Merge(override *Feed) { - if override.Title != "" && override.Title != f.Title { - f.Title = override.Title - } - - if override.SiteURL != "" && override.SiteURL != f.SiteURL { - f.SiteURL = override.SiteURL - } - - if override.FeedURL != "" && override.FeedURL != f.FeedURL { - f.FeedURL = override.FeedURL - } - - if override.ScraperRules != "" && override.ScraperRules != f.ScraperRules { - f.ScraperRules = override.ScraperRules - } - - if override.RewriteRules != "" && override.RewriteRules != f.RewriteRules { - f.RewriteRules = override.RewriteRules - } - - if override.Crawler != f.Crawler { - f.Crawler = override.Crawler - } - - if override.Category != nil && override.Category.ID != 0 && override.Category.ID != f.Category.ID { - f.Category.ID = override.Category.ID - } - - if override.Username != f.Username { - f.Username = override.Username - } - - if override.Password != f.Password { - f.Password = override.Password - } -} - // Feeds is a list of feed type Feeds []*Feed diff --git a/model/feed_test.go b/model/feed_test.go deleted file mode 100644 index 138949df..00000000 --- a/model/feed_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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 "testing" - -func TestMergeFeedTitle(t *testing.T) { - feed1 := &Feed{Title: "Feed 1"} - feed2 := &Feed{Title: "Feed 2"} - feed1.Merge(feed2) - - if feed1.Title != "Feed 2" { - t.Fatal(`The title of feed1 should be merged`) - } - - feed1 = &Feed{Title: "Feed 1"} - feed2 = &Feed{} - feed1.Merge(feed2) - - if feed1.Title != "Feed 1" { - t.Fatal(`The title of feed1 should not be merged`) - } - - feed1 = &Feed{Title: "Feed 1"} - feed2 = &Feed{Title: "Feed 1"} - feed1.Merge(feed2) - - if feed1.Title != "Feed 1" { - t.Fatal(`The title of feed1 should not be changed`) - } -} - -func TestMergeFeedCategory(t *testing.T) { - feed1 := &Feed{Category: &Category{ID: 222}} - feed2 := &Feed{Category: &Category{ID: 333}} - feed1.Merge(feed2) - - if feed1.Category.ID != 333 { - t.Fatal(`The category of feed1 should be merged`) - } - - feed1 = &Feed{Category: &Category{ID: 222}} - feed2 = &Feed{} - feed1.Merge(feed2) - - if feed1.Category.ID != 222 { - t.Fatal(`The category of feed1 should not be merged`) - } - - feed1 = &Feed{Category: &Category{ID: 222}} - feed2 = &Feed{Category: &Category{ID: 0}} - feed1.Merge(feed2) - - if feed1.Category.ID != 222 { - t.Fatal(`The category of feed1 should not be merged`) - } -} diff --git a/model/user.go b/model/user.go index d2283f1a..6a985e3a 100644 --- a/model/user.go +++ b/model/user.go @@ -74,33 +74,6 @@ func (u User) ValidatePassword() error { return nil } -// Merge update the current user with another user. -func (u *User) Merge(override *User) { - if override.Username != "" && u.Username != override.Username { - u.Username = override.Username - } - - if override.Password != "" && u.Password != override.Password { - u.Password = override.Password - } - - if u.IsAdmin != override.IsAdmin { - u.IsAdmin = override.IsAdmin - } - - if override.Theme != "" && u.Theme != override.Theme { - u.Theme = override.Theme - } - - if override.Language != "" && u.Language != override.Language { - u.Language = override.Language - } - - if override.Timezone != "" && u.Timezone != override.Timezone { - u.Timezone = override.Timezone - } -} - // UseTimezone converts last login date to the given timezone. func (u *User) UseTimezone(tz string) { if u.LastLoginAt != nil { diff --git a/model/user_test.go b/model/user_test.go index ac075a83..e7bcb1e3 100644 --- a/model/user_test.go +++ b/model/user_test.go @@ -59,35 +59,3 @@ func TestValidateUserModification(t *testing.T) { t.Error(`An invalid password should generate an error`) } } - -func TestMergeUsername(t *testing.T) { - user1 := &User{ID: 42, Username: "user1", Password: "secret", Theme: "default"} - user2 := &User{ID: 42, Username: "user2"} - user1.Merge(user2) - - if user1.Username != "user2" { - t.Fatal(`The username should be merged into user1`) - } - - if user1.Theme != "default" { - t.Fatal(`The theme should not be merged into user1`) - } -} - -func TestMergeIsAdmin(t *testing.T) { - user1 := &User{ID: 42, Username: "user1", Password: "secret", Theme: "default"} - user2 := &User{ID: 42, IsAdmin: true} - user1.Merge(user2) - - if !user1.IsAdmin { - t.Fatal(`The is_admin flag should be merged into user1`) - } - - user1 = &User{ID: 42, Username: "user1", Password: "secret", Theme: "default"} - user2 = &User{ID: 42} - user1.Merge(user2) - - if user1.IsAdmin { - t.Fatal(`The is_admin flag should not be merged into user1`) - } -} diff --git a/vendor/github.com/miniflux/miniflux-go/client.go b/vendor/github.com/miniflux/miniflux-go/client.go index efc2a03d..924fe49c 100644 --- a/vendor/github.com/miniflux/miniflux-go/client.go +++ b/vendor/github.com/miniflux/miniflux-go/client.go @@ -104,8 +104,8 @@ func (c *Client) CreateUser(username, password string, isAdmin bool) (*User, err } // UpdateUser updates a user in the system. -func (c *Client) UpdateUser(user *User) (*User, error) { - body, err := c.request.Put(fmt.Sprintf("/v1/users/%d", user.ID), user) +func (c *Client) UpdateUser(userID int64, userChanges *UserModification) (*User, error) { + body, err := c.request.Put(fmt.Sprintf("/v1/users/%d", userID), userChanges) if err != nil { return nil, err } @@ -296,8 +296,8 @@ func (c *Client) CreateFeed(url string, categoryID int64) (int64, error) { } // UpdateFeed updates a feed. -func (c *Client) UpdateFeed(feed *Feed) (*Feed, error) { - body, err := c.request.Put(fmt.Sprintf("/v1/feeds/%d", feed.ID), feed) +func (c *Client) UpdateFeed(feedID int64, feedChanges *FeedModification) (*Feed, error) { + body, err := c.request.Put(fmt.Sprintf("/v1/feeds/%d", feedID), feedChanges) if err != nil { return nil, err } diff --git a/vendor/github.com/miniflux/miniflux-go/miniflux.go b/vendor/github.com/miniflux/miniflux-go/miniflux.go index 9d08a654..08e4d558 100644 --- a/vendor/github.com/miniflux/miniflux-go/miniflux.go +++ b/vendor/github.com/miniflux/miniflux-go/miniflux.go @@ -34,6 +34,17 @@ func (u User) String() string { return fmt.Sprintf("#%d - %s (admin=%v)", u.ID, u.Username, u.IsAdmin) } +// UserModification is used to update a user. +type UserModification struct { + Username *string `json:"username"` + Password *string `json:"password"` + IsAdmin *bool `json:"is_admin"` + Theme *string `json:"theme"` + Language *string `json:"language"` + Timezone *string `json:"timezone"` + EntryDirection *string `json:"entry_sorting_direction"` +} + // Users represents a list of users. type Users []User @@ -77,10 +88,28 @@ type Feed struct { LastModifiedHeader string `json:"last_modified_header,omitempty"` ParsingErrorMsg string `json:"parsing_error_message,omitempty"` ParsingErrorCount int `json:"parsing_error_count,omitempty"` + ScraperRules string `json:"scraper_rules"` + RewriteRules string `json:"rewrite_rules"` + Crawler bool `json:"crawler"` + Username string `json:"username"` + Password string `json:"password"` Category *Category `json:"category,omitempty"` Entries Entries `json:"entries,omitempty"` } +// FeedModification represents changes for a feed. +type FeedModification struct { + FeedURL *string `json:"feed_url"` + SiteURL *string `json:"site_url"` + Title *string `json:"title"` + ScraperRules *string `json:"scraper_rules"` + RewriteRules *string `json:"rewrite_rules"` + Crawler *bool `json:"crawler"` + Username *string `json:"username"` + Password *string `json:"password"` + CategoryID *int64 `json:"category_id"` +} + // FeedIcon represents the feed icon. type FeedIcon struct { ID int64 `json:"id"`