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: allow per-user settings and store them in database #639

Merged
merged 68 commits into from Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
3d5778f
create needed field in sqlite database
Monirzadeh Jul 9, 2023
c574a7e
update account model
Monirzadeh Jul 10, 2023
53314e5
update Account struct for save Account options
Monirzadeh Jul 10, 2023
ab0b922
update sqlite database return account settings
Monirzadeh Jul 10, 2023
c6fdddc
save configure in sqlite as text and return that
Monirzadeh Jul 16, 2023
8d68fb5
read configure from user account and defualt configure for shiori
Monirzadeh Jul 16, 2023
f32dfd8
add api/ui for update settings in database user can save settings in …
Monirzadeh Jul 16, 2023
c106749
check configures be in json format before save in database
Monirzadeh Jul 17, 2023
440a125
support MariaDB
Monirzadeh Jul 17, 2023
b872736
fix wrong comment
Monirzadeh Jul 17, 2023
e950ff4
support PostgreSQL
Monirzadeh Jul 17, 2023
fcaa29b
revert unneeded change in new logic
Monirzadeh Jul 17, 2023
a77fe7e
change configures to config
Monirzadeh Jul 18, 2023
3c2a961
change SaveAccount to SaveAccountSettings
Monirzadeh Jul 18, 2023
741af23
add migrate database scripts
Monirzadeh Jul 18, 2023
353b10b
change default in migration scrtipts
Monirzadeh Jul 19, 2023
dbe0773
update model
Monirzadeh Jul 19, 2023
e7ca00a
read config field as json from database
Monirzadeh Jul 22, 2023
17854a2
fix parse value config value & update config update
Monirzadeh Jul 22, 2023
e215a58
update default value for new user
Monirzadeh Jul 22, 2023
8e8ab72
update settings variable name to reflect database value in UI
Monirzadeh Jul 22, 2023
f0fd7a9
fix typo
Monirzadeh Jul 22, 2023
e880efb
not panic if user not exist and update worng comment
Monirzadeh Jul 22, 2023
463684e
visitor user can update there settings now
Monirzadeh Jul 22, 2023
d4a2449
remove unneeded loading dialog
Monirzadeh Jul 22, 2023
b17a3b3
fix typo
Monirzadeh Jul 22, 2023
75777dd
update function for pg and mysql
Monirzadeh Jul 22, 2023
3e0519e
remove IsJson
Monirzadeh Jul 22, 2023
7a37dcb
move scan method to model
Monirzadeh Jul 22, 2023
5a9bb0b
simplify jsonify
Monirzadeh Jul 22, 2023
039be53
simplify assignees value to account.Config
Monirzadeh Jul 22, 2023
1398279
missing part of function
Monirzadeh Jul 22, 2023
0f4df09
fix some typo and unneeded field in struct
Monirzadeh Jul 23, 2023
c70dd9d
add down migrate script for all database
Monirzadeh Jul 23, 2023
0121f62
change createEbook to CreateEbook
Monirzadeh Jul 23, 2023
e4ec3f2
use json instead of text in mysql and postgres
Monirzadeh Jul 23, 2023
006f52c
implement
Monirzadeh Jul 23, 2023
80a84c3
remove unneeded part
Monirzadeh Jul 23, 2023
26f7232
remove unneeded jsonify in code
Monirzadeh Jul 23, 2023
30f75b3
return SelectContext and GetContext
Monirzadeh Jul 23, 2023
7eba991
remove defualt config in reques for new user it will be set in backend
Monirzadeh Jul 23, 2023
04299a0
merge with master and resolved conflict
Monirzadeh Jul 24, 2023
a06e8a2
New API
Monirzadeh Jul 24, 2023
c108f25
remove legacy API
Monirzadeh Jul 24, 2023
ec72e75
remove validateSessionWithoutOwnerStatus
Monirzadeh Jul 24, 2023
465abde
remove Jsonify function don't need that anymore
Monirzadeh Jul 24, 2023
f6d06b7
add unit test for database
Monirzadeh Jul 24, 2023
567a376
update migrate script name
Monirzadeh Jul 25, 2023
84ab1fc
change put to patch
Monirzadeh Jul 25, 2023
6bdb106
return PUT
Monirzadeh Jul 25, 2023
93d4cd7
fix Patch problem and now use PATCH instead of PUT
Monirzadeh Jul 25, 2023
cb186e7
remove unneeded retuen
Monirzadeh Jul 25, 2023
9c57905
more cleaner code for request new settings
Monirzadeh Jul 26, 2023
34c7426
fix bug to handle string in Scan method thanks to fmartingr
Monirzadeh Jul 26, 2023
5043acb
fix Authorization & use GetAccount & remove username from request
Monirzadeh Aug 1, 2023
0b611ad
shiori-settings remove and it read from shiori-account
Monirzadeh Aug 1, 2023
f9c60e2
add swagger documentation
Monirzadeh Aug 1, 2023
bce2321
API unit test
Monirzadeh Aug 1, 2023
3f60ad5
fix typo
Monirzadeh Aug 1, 2023
f9c91be
remove unneeded coment
Monirzadeh Aug 12, 2023
9f62b1e
better Documentation
Monirzadeh Aug 12, 2023
f6314ae
shiori-toke remove on logout
Monirzadeh Aug 12, 2023
f256392
fix typo
Monirzadeh Aug 12, 2023
8f564cd
add unit test check update config in database
Monirzadeh Aug 14, 2023
4a3b07b
update swag documentation
Monirzadeh Aug 14, 2023
c2572b5
Merge branch 'master' into settings-per-user
Monirzadeh Aug 14, 2023
aa1b558
fix swag formaing error
Monirzadeh Aug 14, 2023
f268858
Merge branch 'master' into settings-per-user
Monirzadeh Oct 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 72 additions & 0 deletions docs/swagger/docs.go
Expand Up @@ -15,6 +15,38 @@ const docTemplate = `{
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/api/v1/auth/account": {
"patch": {
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Perform actions on the currently logged-in user.",
"parameters": [
{
"description": "Config data",
"name": "payload",
"in": "body",
"schema": {
"$ref": "#/definitions/api_v1.settingRequestPayload"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/model.Account"
}
},
"403": {
"description": "Token not provided/invalid"
}
}
}
},
"/api/v1/auth/login": {
"post": {
"consumes": [
Expand Down Expand Up @@ -175,9 +207,20 @@ const docTemplate = `{
}
}
},
"api_v1.settingRequestPayload": {
"type": "object",
"properties": {
"config": {
"$ref": "#/definitions/model.UserConfig"
}
}
},
"model.Account": {
"type": "object",
"properties": {
"config": {
"$ref": "#/definitions/model.UserConfig"
},
"id": {
"type": "integer"
},
Expand Down Expand Up @@ -205,6 +248,35 @@ const docTemplate = `{
"type": "string"
}
}
},
"model.UserConfig": {
"type": "object",
"properties": {
"HideExcerpt": {
"type": "boolean"
},
"HideThumbnail": {
"type": "boolean"
},
"KeepMetadata": {
"type": "boolean"
},
"ListMode": {
"type": "boolean"
},
"MakePublic": {
"type": "boolean"
},
"NightMode": {
"type": "boolean"
},
"ShowId": {
"type": "boolean"
},
"UseArchive": {
"type": "boolean"
}
}
}
}
}`
Expand Down
72 changes: 72 additions & 0 deletions docs/swagger/swagger.json
Expand Up @@ -4,6 +4,38 @@
"contact": {}
},
"paths": {
"/api/v1/auth/account": {
"patch": {
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Perform actions on the currently logged-in user.",
"parameters": [
{
"description": "Config data",
"name": "payload",
"in": "body",
"schema": {
"$ref": "#/definitions/api_v1.settingRequestPayload"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/model.Account"
}
},
"403": {
"description": "Token not provided/invalid"
}
}
}
},
"/api/v1/auth/login": {
"post": {
"consumes": [
Expand Down Expand Up @@ -164,9 +196,20 @@
}
}
},
"api_v1.settingRequestPayload": {
"type": "object",
"properties": {
"config": {
"$ref": "#/definitions/model.UserConfig"
}
}
},
"model.Account": {
"type": "object",
"properties": {
"config": {
"$ref": "#/definitions/model.UserConfig"
},
"id": {
"type": "integer"
},
Expand Down Expand Up @@ -194,6 +237,35 @@
"type": "string"
}
}
},
"model.UserConfig": {
"type": "object",
"properties": {
"HideExcerpt": {
"type": "boolean"
},
"HideThumbnail": {
"type": "boolean"
},
"KeepMetadata": {
"type": "boolean"
},
"ListMode": {
"type": "boolean"
},
"MakePublic": {
"type": "boolean"
},
"NightMode": {
"type": "boolean"
},
"ShowId": {
"type": "boolean"
},
"UseArchive": {
"type": "boolean"
}
}
}
}
}
46 changes: 46 additions & 0 deletions docs/swagger/swagger.yaml
Expand Up @@ -22,8 +22,15 @@ definitions:
token:
type: string
type: object
api_v1.settingRequestPayload:
properties:
config:
$ref: '#/definitions/model.UserConfig'
type: object
model.Account:
properties:
config:
$ref: '#/definitions/model.UserConfig'
id:
type: integer
owner:
Expand All @@ -42,9 +49,48 @@ definitions:
name:
type: string
type: object
model.UserConfig:
properties:
HideExcerpt:
type: boolean
HideThumbnail:
type: boolean
KeepMetadata:
type: boolean
ListMode:
type: boolean
MakePublic:
type: boolean
NightMode:
type: boolean
ShowId:
type: boolean
UseArchive:
type: boolean
type: object
info:
contact: {}
paths:
/api/v1/auth/account:
patch:
parameters:
- description: Config data
in: body
name: payload
schema:
$ref: '#/definitions/api_v1.settingRequestPayload'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/model.Account'
"403":
description: Token not provided/invalid
summary: Perform actions on the currently logged-in user.
tags:
- Auth
/api/v1/auth/login:
post:
consumes:
Expand Down
3 changes: 3 additions & 0 deletions internal/database/database.go
Expand Up @@ -89,6 +89,9 @@ type DB interface {
// SaveAccount saves new account in database
SaveAccount(ctx context.Context, a model.Account) error

// SaveAccountSettings saves settings for specific user in database
SaveAccountSettings(ctx context.Context, a model.Account) error

// GetAccounts fetch list of account (without its password) with matching keyword.
GetAccounts(ctx context.Context, opts GetAccountsOptions) ([]model.Account, error)

Expand Down
8 changes: 4 additions & 4 deletions internal/database/migrations/mysql/0001_initial.up.sql
@@ -1,8 +1,8 @@
CREATE TABLE IF NOT EXISTS account(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(250) NOT NULL,
password BINARY(80) NOT NULL,
owner TINYINT(1) NOT NULL DEFAULT '0',
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(250) NOT NULL,
password BINARY(80) NOT NULL,
owner TINYINT(1) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
UNIQUE KEY account_username_UNIQUE (username))
CHARACTER SET utf8mb4;
1 change: 1 addition & 0 deletions internal/database/migrations/mysql/0005_config.down.sql
@@ -0,0 +1 @@
ALTER TABLE account DROP COLUMN config;
2 changes: 2 additions & 0 deletions internal/database/migrations/mysql/0005_config.up.sql
@@ -0,0 +1,2 @@
ALTER TABLE account
Monirzadeh marked this conversation as resolved.
Show resolved Hide resolved
ADD COLUMN config JSON NOT NULL DEFAULT '{}';
2 changes: 1 addition & 1 deletion internal/database/migrations/postgres/0001_initial.up.sql
Expand Up @@ -33,4 +33,4 @@ CREATE TABLE IF NOT EXISTS bookmark_tag(
CONSTRAINT bookmark_tag_tag_id_FK FOREIGN KEY (tag_id) REFERENCES tag (id));

CREATE INDEX IF NOT EXISTS bookmark_tag_bookmark_id_FK ON bookmark_tag (bookmark_id);
CREATE INDEX IF NOT EXISTS bookmark_tag_tag_id_FK ON bookmark_tag (tag_id);
CREATE INDEX IF NOT EXISTS bookmark_tag_tag_id_FK ON bookmark_tag (tag_id);
1 change: 1 addition & 0 deletions internal/database/migrations/postgres/0002_config.down.sql
@@ -0,0 +1 @@
ALTER TABLE account DROP COLUMN config;
2 changes: 2 additions & 0 deletions internal/database/migrations/postgres/0002_config.up.sql
@@ -0,0 +1,2 @@
ALTER TABLE account
Monirzadeh marked this conversation as resolved.
Show resolved Hide resolved
ADD COLUMN config JSONB NOT NULL DEFAULT '{}';
1 change: 1 addition & 0 deletions internal/database/migrations/sqlite/0003_config.down.sql
@@ -0,0 +1 @@
ALTER TABLE account DROP COLUMN config;
3 changes: 3 additions & 0 deletions internal/database/migrations/sqlite/0003_config.up.sql
@@ -0,0 +1,3 @@
ALTER TABLE account
Monirzadeh marked this conversation as resolved.
Show resolved Hide resolved
ADD config JSON NOT NULL DEFAULT '{}';

Monirzadeh marked this conversation as resolved.
Show resolved Hide resolved
19 changes: 15 additions & 4 deletions internal/database/mysql.go
Expand Up @@ -532,11 +532,22 @@ func (db *MySQLDatabase) SaveAccount(ctx context.Context, account model.Account)

// Insert account to database
_, err = db.ExecContext(ctx, `INSERT INTO account
(username, password, owner) VALUES (?, ?, ?)
(username, password, owner, config) VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
password = VALUES(password),
owner = VALUES(owner)`,
account.Username, hashedPassword, account.Owner)
account.Username, hashedPassword, account.Owner, account.Config)

return errors.WithStack(err)
}

// SaveAccountSettings update settings for specific account in database. Returns error if any happened
func (db *MySQLDatabase) SaveAccountSettings(ctx context.Context, account model.Account) (err error) {
// Update account config in database for specific user
_, err = db.ExecContext(ctx, `UPDATE account
SET config = ?
WHERE username = ?`,
account.Config, account.Username)

return errors.WithStack(err)
}
Expand All @@ -545,7 +556,7 @@ func (db *MySQLDatabase) SaveAccount(ctx context.Context, account model.Account)
func (db *MySQLDatabase) GetAccounts(ctx context.Context, opts GetAccountsOptions) ([]model.Account, error) {
// Create query
args := []interface{}{}
query := `SELECT id, username, owner FROM account WHERE 1`
query := `SELECT id, username, owner, config FROM account WHERE 1`

if opts.Keyword != "" {
query += " AND username LIKE ?"
Expand Down Expand Up @@ -573,7 +584,7 @@ func (db *MySQLDatabase) GetAccounts(ctx context.Context, opts GetAccountsOption
func (db *MySQLDatabase) GetAccount(ctx context.Context, username string) (model.Account, bool, error) {
account := model.Account{}
if err := db.GetContext(ctx, &account, `SELECT
id, username, password, owner FROM account WHERE username = ?`,
id, username, password, owner, config FROM account WHERE username = ?`,
username,
); err != nil {
return account, false, errors.WithStack(err)
Expand Down