Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Sync API #965

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8cd9b33
just return bookmarks after specific timestamp
Monirzadeh Aug 17, 2024
89bea5b
send modified and deleted item in database
Monirzadeh Aug 17, 2024
caac394
make swagger
Monirzadeh Aug 17, 2024
b3abc95
Merge branch 'master' into sync
Monirzadeh Sep 13, 2024
939b6cc
pagginate for sync request
Monirzadeh Sep 16, 2024
7412ca3
make swagger
Monirzadeh Sep 16, 2024
8e70402
if ids be empty than just return modified bookmarks
Monirzadeh Sep 16, 2024
ed0926c
show deletd bookmark once and just in first page
Monirzadeh Sep 16, 2024
3b73f02
update filter for LastSync and deleted function for postgress
Monirzadeh Sep 16, 2024
760c920
test autentication for sync endpoint
Monirzadeh Sep 16, 2024
246a6d1
fix method in unittest
Monirzadeh Sep 16, 2024
a1c3bc3
add unittest for invalid id in sync request
Monirzadeh Sep 16, 2024
4774b5a
fix typo
Monirzadeh Sep 16, 2024
0f8eb28
unittest sync api return expected id
Monirzadeh Sep 17, 2024
03df459
get correct modified bookmark in sync api
Monirzadeh Sep 17, 2024
33f91a2
fix unittest discription
Monirzadeh Sep 17, 2024
92307dc
first database LastSync unittest
Monirzadeh Sep 18, 2024
d4ea048
Merge branch 'master' into sync
Monirzadeh Sep 24, 2024
5eda5f6
add mysql logic
Monirzadeh Sep 24, 2024
4322edb
unittest for deleted bookmark
Monirzadeh Sep 24, 2024
d76009d
use correct payload
Monirzadeh Sep 24, 2024
01cb7ef
fix deleted bookamrks in unittest
Monirzadeh Sep 24, 2024
e16ea20
deletedBookarksIDs unittest
Monirzadeh Sep 24, 2024
16bdf2e
add missing swagger payload
Monirzadeh Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions docs/swagger/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,39 @@ const docTemplate = `{
}
}
},
"/api/v1/bookmarks/sync": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Get List of bookmark and last time of sync response bookmark change after that time and deleted bookmark.",
"parameters": [
{
"description": "Bookmarks id in client side and last sync timestamp and page for pagination",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/api_v1.syncPayload"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api_v1.syncResponseMessage"
}
},
"403": {
"description": "Token not provided/invalid"
}
}
}
},
"/api/v1/system/info": {
"get": {
"description": "Get general system information like Shiori version, database, and OS",
Expand Down Expand Up @@ -251,6 +284,23 @@ const docTemplate = `{
}
},
"definitions": {
"api_v1.bookmarksModifiedResponse": {
"type": "object",
"properties": {
"bookmarks": {
"type": "array",
"items": {
"$ref": "#/definitions/model.BookmarkDTO"
}
},
"maxPage": {
"type": "integer"
},
"page": {
"type": "integer"
}
}
},
"api_v1.infoResponse": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -329,6 +379,40 @@ const docTemplate = `{
}
}
},
"api_v1.syncPayload": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "integer"
}
},
"last_sync": {
"type": "integer"
},
"page": {
"type": "integer"
}
}
},
"api_v1.syncResponseMessage": {
"type": "object",
"properties": {
"deleted": {
"type": "array",
"items": {
"type": "integer"
}
},
"modified": {
"$ref": "#/definitions/api_v1.bookmarksModifiedResponse"
}
}
},
"api_v1.updateCachePayload": {
"type": "object",
"required": [
Expand Down
84 changes: 84 additions & 0 deletions docs/swagger/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,39 @@
}
}
},
"/api/v1/bookmarks/sync": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Get List of bookmark and last time of sync response bookmark change after that time and deleted bookmark.",
"parameters": [
{
"description": "Bookmarks id in client side and last sync timestamp and page for pagination",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/api_v1.syncPayload"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api_v1.syncResponseMessage"
}
},
"403": {
"description": "Token not provided/invalid"
}
}
}
},
"/api/v1/system/info": {
"get": {
"description": "Get general system information like Shiori version, database, and OS",
Expand Down Expand Up @@ -240,6 +273,23 @@
}
},
"definitions": {
"api_v1.bookmarksModifiedResponse": {
"type": "object",
"properties": {
"bookmarks": {
"type": "array",
"items": {
"$ref": "#/definitions/model.BookmarkDTO"
}
},
"maxPage": {
"type": "integer"
},
"page": {
"type": "integer"
}
}
},
"api_v1.infoResponse": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -318,6 +368,40 @@
}
}
},
"api_v1.syncPayload": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "integer"
}
},
"last_sync": {
"type": "integer"
},
"page": {
"type": "integer"
}
}
},
"api_v1.syncResponseMessage": {
"type": "object",
"properties": {
"deleted": {
"type": "array",
"items": {
"type": "integer"
}
},
"modified": {
"$ref": "#/definitions/api_v1.bookmarksModifiedResponse"
}
}
},
"api_v1.updateCachePayload": {
"type": "object",
"required": [
Expand Down
56 changes: 56 additions & 0 deletions docs/swagger/swagger.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
definitions:
api_v1.bookmarksModifiedResponse:
properties:
bookmarks:
items:
$ref: '#/definitions/model.BookmarkDTO'
type: array
maxPage:
type: integer
page:
type: integer
type: object
api_v1.infoResponse:
properties:
database:
Expand Down Expand Up @@ -50,6 +61,28 @@ definitions:
config:
$ref: '#/definitions/model.UserConfig'
type: object
api_v1.syncPayload:
properties:
ids:
items:
type: integer
type: array
last_sync:
type: integer
page:
type: integer
required:
- ids
type: object
api_v1.syncResponseMessage:
properties:
deleted:
items:
type: integer
type: array
modified:
$ref: '#/definitions/api_v1.bookmarksModifiedResponse'
type: object
api_v1.updateCachePayload:
properties:
create_archive:
Expand Down Expand Up @@ -257,6 +290,29 @@ paths:
summary: Get readable version of bookmark.
tags:
- Auth
/api/v1/bookmarks/sync:
post:
parameters:
- description: Bookmarks id in client side and last sync timestamp and page
for pagination
in: body
name: payload
required: true
schema:
$ref: '#/definitions/api_v1.syncPayload'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/api_v1.syncResponseMessage'
"403":
description: Token not provided/invalid
summary: Get List of bookmark and last time of sync response bookmark change
after that time and deleted bookmark.
tags:
- Auth
/api/v1/system/info:
get:
description: Get general system information like Shiori version, database, and
Expand Down
5 changes: 5 additions & 0 deletions internal/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ type GetBookmarksOptions struct {
IDs []int
Tags []string
ExcludedTags []string
IsDeleted []int
Keyword string
LastSync string
WithContent bool
OrderMethod OrderMethod
Limit int
Expand Down Expand Up @@ -79,6 +81,9 @@ type DB interface {
// SaveBookmarks saves bookmarks data to database.
SaveBookmarks(ctx context.Context, create bool, bookmarks ...model.BookmarkDTO) ([]model.BookmarkDTO, error)

// GetDeletedBookmarks fetch list of bookmarks based on submitted options.
GetDeletedBookmarks(ctx context.Context, opts GetBookmarksOptions) ([]int, error)

// GetBookmarks fetch list of bookmarks based on submitted options.
GetBookmarks(ctx context.Context, opts GetBookmarksOptions) ([]model.BookmarkDTO, error)

Expand Down
44 changes: 44 additions & 0 deletions internal/database/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func testDatabase(t *testing.T, dbFactory testDatabaseFactory) {
"testSaveAccountSetting": testSaveAccountSettings,
"testGetAccount": testGetAccount,
"testGetAccounts": testGetAccounts,
// Sync
"testSync": testSync,
}

for testName, testCase := range tests {
Expand Down Expand Up @@ -516,3 +518,45 @@ func testGetBoomarksWithTimeFilters(t *testing.T, db DB) {
// Second id should be 2 if order them by id
assert.Equal(t, booksOrderById[1].ID, 2)
}

func testSync(t *testing.T, db DB) {
ctx := context.TODO()

// First Bookmark
book1 := model.BookmarkDTO{
URL: "https://github.com/go-shiori/shiori/one",
Title: "first bookmark",
}

_, err := db.SaveBookmarks(ctx, true, book1)
assert.NoError(t, err, "Save bookmarks must not fail")

// Second bookmark
unixTimestampOneSecondLater := time.Now().UTC().Add(2 * time.Second).Unix()
book2 := model.BookmarkDTO{
URL: "https://github.com/go-shiori/shiori/second",
Title: "second bookmark",
ModifiedAt: time.Unix(unixTimestampOneSecondLater, 0).UTC().Format(model.DatabaseDateFormat),
}

_, err = db.SaveBookmarks(ctx, true, book2)
assert.NoError(t, err, "Save bookmarks must not fail")

t.Run("get correct bookmarks based on LastSync", func(t *testing.T) {
booksAfterSpecificDate, err := db.GetBookmarks(ctx, GetBookmarksOptions{
LastSync: book2.ModifiedAt,
})
assert.NoError(t, err, "Get bookmarks must not fail")
assert.Equal(t, booksAfterSpecificDate[0].ID, 2)
assert.Len(t, booksAfterSpecificDate, 1)
})

t.Run("get deleted bookmarks id", func(t *testing.T) {
deletedBookarksIDs, err := db.GetDeletedBookmarks(ctx, GetBookmarksOptions{
IsDeleted: []int{1, 5, 10},
})
assert.NoError(t, err, "Get deleted bookmarks must not fail")
assert.Equal(t, deletedBookarksIDs, []int{5, 10})
assert.Len(t, deletedBookarksIDs, 2)
})
}
Loading
Loading