Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
bc22f69a
Commit
bc22f69a
authored
May 19, 2022
by
boojack
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: raw struct for store
parent
0b50122a
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
687 additions
and
188 deletions
+687
-188
api.go
api/api.go
+21
-0
memo.go
api/memo.go
+12
-8
memo_organizer.go
api/memo_organizer.go
+21
-0
shortcut.go
api/shortcut.go
+5
-5
user.go
api/user.go
+19
-2
auth.go
server/auth.go
+2
-0
basic_auth.go
server/basic_auth.go
+2
-0
memo.go
server/memo.go
+46
-1
user.go
server/user.go
+50
-13
webhook.go
server/webhook.go
+1
-1
memo.go
store/memo.go
+110
-37
memo_organizer.go
store/memo_organizer.go
+117
-0
10000__reset.sql
store/migration/10000__reset.sql
+1
-0
10001__schema.sql
store/migration/10001__schema.sql
+23
-7
resource.go
store/resource.go
+70
-30
10000__reset.sql
store/seed/10000__reset.sql
+1
-0
10001__user.sql
store/seed/10001__user.sql
+1
-1
10002__memo.sql
store/seed/10002__memo.sql
+6
-4
10003__memo_organizer.sql
store/seed/10003__memo_organizer.sql
+12
-0
10004__shortcut.sql
store/seed/10004__shortcut.sql
+0
-0
shortcut.go
store/shortcut.go
+76
-36
user.go
store/user.go
+91
-43
No files found.
api/api.go
0 → 100644
View file @
bc22f69a
package
api
// RowStatus is the status for a row.
type
RowStatus
string
const
(
// Normal is the status for a normal row.
Normal
RowStatus
=
"NORMAL"
// Archived is the status for an archived row.
Archived
RowStatus
=
"ARCHIVED"
)
func
(
e
RowStatus
)
String
()
string
{
switch
e
{
case
Normal
:
return
"NORMAL"
case
Archived
:
return
"ARCHIVED"
}
return
""
}
api/memo.go
View file @
bc22f69a
...
@@ -4,13 +4,14 @@ type Memo struct {
...
@@ -4,13 +4,14 @@ type Memo struct {
ID
int
`json:"id"`
ID
int
`json:"id"`
// Standard fields
// Standard fields
CreatedTs
int64
`json:"createdTs"`
RowStatus
RowStatus
`json:"rowStatus"`
UpdatedTs
int64
`json:"updatedTs"`
CreatorID
int
`json:"creatorId"`
RowStatus
string
`json:"rowStatus"`
CreatedTs
int64
`json:"createdTs"`
UpdatedTs
int64
`json:"updatedTs"`
// Domain specific fields
// Domain specific fields
Content
string
`json:"content"`
Content
string
`json:"content"`
CreatorID
int
`json:"creatorI
d"`
Pinned
bool
`json:"pinne
d"`
}
}
type
MemoCreate
struct
{
type
MemoCreate
struct
{
...
@@ -27,7 +28,7 @@ type MemoPatch struct {
...
@@ -27,7 +28,7 @@ type MemoPatch struct {
ID
int
ID
int
// Standard fields
// Standard fields
RowStatus
*
string
`json:"rowStatus"`
RowStatus
*
RowStatus
`json:"rowStatus"`
// Domain specific fields
// Domain specific fields
Content
*
string
`json:"content"`
Content
*
string
`json:"content"`
...
@@ -37,8 +38,11 @@ type MemoFind struct {
...
@@ -37,8 +38,11 @@ type MemoFind struct {
ID
*
int
`json:"id"`
ID
*
int
`json:"id"`
// Standard fields
// Standard fields
CreatorID
*
int
`json:"creatorId"`
RowStatus
*
RowStatus
`json:"rowStatus"`
RowStatus
*
string
`json:"rowStatus"`
CreatorID
*
int
`json:"creatorId"`
// Domain specific fields
Pinned
*
bool
}
}
type
MemoDelete
struct
{
type
MemoDelete
struct
{
...
...
api/memo_organizer.go
0 → 100644
View file @
bc22f69a
package
api
type
MemoOrganizer
struct
{
ID
int
// Domain specific fields
MemoID
int
UserID
int
Pinned
bool
}
type
MemoOrganizerFind
struct
{
MemoID
int
UserID
int
}
type
MemoOrganizerUpsert
struct
{
MemoID
int
UserID
int
Pinned
bool
`json:"pinned"`
}
api/shortcut.go
View file @
bc22f69a
...
@@ -4,10 +4,10 @@ type Shortcut struct {
...
@@ -4,10 +4,10 @@ type Shortcut struct {
ID
int
`json:"id"`
ID
int
`json:"id"`
// Standard fields
// Standard fields
CreatorID
int
RowStatus
RowStatus
`json:"rowStatus"`
Creat
edTs
int64
`json:"createdTs
"`
Creat
orID
int
`json:"creatorId
"`
UpdatedTs
int64
`json:"upd
atedTs"`
CreatedTs
int64
`json:"cre
atedTs"`
RowStatus
string
`json:"rowStatu
s"`
UpdatedTs
int64
`json:"updatedT
s"`
// Domain specific fields
// Domain specific fields
Title
string
`json:"title"`
Title
string
`json:"title"`
...
@@ -27,7 +27,7 @@ type ShortcutPatch struct {
...
@@ -27,7 +27,7 @@ type ShortcutPatch struct {
ID
int
ID
int
// Standard fields
// Standard fields
RowStatus
*
string
`json:"rowStatus"`
RowStatus
*
RowStatus
`json:"rowStatus"`
// Domain specific fields
// Domain specific fields
Title
*
string
`json:"title"`
Title
*
string
`json:"title"`
...
...
api/user.go
View file @
bc22f69a
...
@@ -10,12 +10,23 @@ const (
...
@@ -10,12 +10,23 @@ const (
NormalUser
Role
=
"USER"
NormalUser
Role
=
"USER"
)
)
func
(
e
Role
)
String
()
string
{
switch
e
{
case
Owner
:
return
"OWNER"
case
NormalUser
:
return
"USER"
}
return
"USER"
}
type
User
struct
{
type
User
struct
{
ID
int
`json:"id"`
ID
int
`json:"id"`
// Standard fields
// Standard fields
CreatedTs
int64
`json:"createdTs"`
RowStatus
RowStatus
`json:"rowStatus"`
UpdatedTs
int64
`json:"updatedTs"`
CreatedTs
int64
`json:"createdTs"`
UpdatedTs
int64
`json:"updatedTs"`
// Domain specific fields
// Domain specific fields
Email
string
`json:"email"`
Email
string
`json:"email"`
...
@@ -38,6 +49,9 @@ type UserCreate struct {
...
@@ -38,6 +49,9 @@ type UserCreate struct {
type
UserPatch
struct
{
type
UserPatch
struct
{
ID
int
ID
int
// Standard fields
RowStatus
*
RowStatus
`json:"rowStatus"`
// Domain specific fields
// Domain specific fields
Email
*
string
`json:"email"`
Email
*
string
`json:"email"`
Name
*
string
`json:"name"`
Name
*
string
`json:"name"`
...
@@ -50,6 +64,9 @@ type UserPatch struct {
...
@@ -50,6 +64,9 @@ type UserPatch struct {
type
UserFind
struct
{
type
UserFind
struct
{
ID
*
int
`json:"id"`
ID
*
int
`json:"id"`
// Standard fields
RowStatus
*
RowStatus
`json:"rowStatus"`
// Domain specific fields
// Domain specific fields
Email
*
string
`json:"email"`
Email
*
string
`json:"email"`
Role
*
Role
Role
*
Role
...
...
server/auth.go
View file @
bc22f69a
...
@@ -27,6 +27,8 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
...
@@ -27,6 +27,8 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
}
}
if
user
==
nil
{
if
user
==
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusUnauthorized
,
fmt
.
Sprintf
(
"User not found with email %s"
,
login
.
Email
))
return
echo
.
NewHTTPError
(
http
.
StatusUnauthorized
,
fmt
.
Sprintf
(
"User not found with email %s"
,
login
.
Email
))
}
else
if
user
.
RowStatus
==
api
.
Archived
{
return
echo
.
NewHTTPError
(
http
.
StatusForbidden
,
fmt
.
Sprintf
(
"User has been archived with email %s"
,
login
.
Email
))
}
}
// Compare the stored hashed password, with the hashed version of the password that was received.
// Compare the stored hashed password, with the hashed version of the password that was received.
...
...
server/basic_auth.go
View file @
bc22f69a
...
@@ -85,6 +85,8 @@ func BasicAuthMiddleware(s *Server, next echo.HandlerFunc) echo.HandlerFunc {
...
@@ -85,6 +85,8 @@ func BasicAuthMiddleware(s *Server, next echo.HandlerFunc) echo.HandlerFunc {
}
}
if
user
==
nil
{
if
user
==
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusUnauthorized
,
fmt
.
Sprintf
(
"Not found user ID: %d"
,
userID
))
return
echo
.
NewHTTPError
(
http
.
StatusUnauthorized
,
fmt
.
Sprintf
(
"Not found user ID: %d"
,
userID
))
}
else
if
user
.
RowStatus
==
api
.
Archived
{
return
echo
.
NewHTTPError
(
http
.
StatusForbidden
,
fmt
.
Sprintf
(
"User has been archived with email %s"
,
user
.
Email
))
}
}
// Stores userID into context.
// Stores userID into context.
...
...
server/memo.go
View file @
bc22f69a
...
@@ -65,10 +65,16 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
...
@@ -65,10 +65,16 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
memoFind
:=
&
api
.
MemoFind
{
memoFind
:=
&
api
.
MemoFind
{
CreatorID
:
&
userID
,
CreatorID
:
&
userID
,
}
}
rowStatus
:=
c
.
QueryParam
(
"rowStatus"
)
rowStatus
:=
api
.
RowStatus
(
c
.
QueryParam
(
"rowStatus"
))
if
rowStatus
!=
""
{
if
rowStatus
!=
""
{
memoFind
.
RowStatus
=
&
rowStatus
memoFind
.
RowStatus
=
&
rowStatus
}
}
pinnedStr
:=
c
.
QueryParam
(
"pinned"
)
if
pinnedStr
!=
""
{
pinned
:=
pinnedStr
==
"true"
memoFind
.
Pinned
=
&
pinned
}
list
,
err
:=
s
.
Store
.
FindMemoList
(
memoFind
)
list
,
err
:=
s
.
Store
.
FindMemoList
(
memoFind
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -83,6 +89,45 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
...
@@ -83,6 +89,45 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
return
nil
return
nil
})
})
g
.
POST
(
"/memo/:memoId/organizer"
,
func
(
c
echo
.
Context
)
error
{
memoID
,
err
:=
strconv
.
Atoi
(
c
.
Param
(
"memoId"
))
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
fmt
.
Sprintf
(
"ID is not a number: %s"
,
c
.
Param
(
"memoId"
)))
.
SetInternal
(
err
)
}
userID
:=
c
.
Get
(
getUserIDContextKey
())
.
(
int
)
memoOrganizerUpsert
:=
&
api
.
MemoOrganizerUpsert
{
MemoID
:
memoID
,
UserID
:
userID
,
}
if
err
:=
json
.
NewDecoder
(
c
.
Request
()
.
Body
)
.
Decode
(
memoOrganizerUpsert
);
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
"Malformatted post memo organizer request"
)
.
SetInternal
(
err
)
}
err
=
s
.
Store
.
UpsertMemoOrganizer
(
memoOrganizerUpsert
)
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to upsert memo organizer"
)
.
SetInternal
(
err
)
}
memo
,
err
:=
s
.
Store
.
FindMemo
(
&
api
.
MemoFind
{
ID
:
&
memoID
,
})
if
err
!=
nil
{
if
common
.
ErrorCode
(
err
)
==
common
.
NotFound
{
return
echo
.
NewHTTPError
(
http
.
StatusNotFound
,
fmt
.
Sprintf
(
"Memo ID not found: %d"
,
memoID
))
.
SetInternal
(
err
)
}
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
fmt
.
Sprintf
(
"Failed to find memo by ID: %v"
,
memoID
))
.
SetInternal
(
err
)
}
c
.
Response
()
.
Header
()
.
Set
(
echo
.
HeaderContentType
,
echo
.
MIMEApplicationJSONCharsetUTF8
)
if
err
:=
json
.
NewEncoder
(
c
.
Response
()
.
Writer
)
.
Encode
(
composeResponse
(
memo
));
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to encode memo response"
)
.
SetInternal
(
err
)
}
return
nil
})
g
.
GET
(
"/memo/:memoId"
,
func
(
c
echo
.
Context
)
error
{
g
.
GET
(
"/memo/:memoId"
,
func
(
c
echo
.
Context
)
error
{
memoID
,
err
:=
strconv
.
Atoi
(
c
.
Param
(
"memoId"
))
memoID
,
err
:=
strconv
.
Atoi
(
c
.
Param
(
"memoId"
))
if
err
!=
nil
{
if
err
!=
nil
{
...
...
server/user.go
View file @
bc22f69a
...
@@ -6,6 +6,7 @@ import (
...
@@ -6,6 +6,7 @@ import (
"memos/api"
"memos/api"
"memos/common"
"memos/common"
"net/http"
"net/http"
"strconv"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4"
"golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/bcrypt"
...
@@ -84,19 +85,6 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
...
@@ -84,19 +85,6 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
"Malformatted patch user request"
)
.
SetInternal
(
err
)
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
"Malformatted patch user request"
)
.
SetInternal
(
err
)
}
}
if
userPatch
.
Email
!=
nil
{
userFind
:=
api
.
UserFind
{
Email
:
userPatch
.
Email
,
}
user
,
err
:=
s
.
Store
.
FindUser
(
&
userFind
)
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
fmt
.
Sprintf
(
"Failed to find user by email %s"
,
*
userPatch
.
Email
))
.
SetInternal
(
err
)
}
if
user
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
fmt
.
Sprintf
(
"User with email %s existed"
,
*
userPatch
.
Email
))
.
SetInternal
(
err
)
}
}
if
userPatch
.
Password
!=
nil
&&
*
userPatch
.
Password
!=
""
{
if
userPatch
.
Password
!=
nil
&&
*
userPatch
.
Password
!=
""
{
passwordHash
,
err
:=
bcrypt
.
GenerateFromPassword
([]
byte
(
*
userPatch
.
Password
),
bcrypt
.
DefaultCost
)
passwordHash
,
err
:=
bcrypt
.
GenerateFromPassword
([]
byte
(
*
userPatch
.
Password
),
bcrypt
.
DefaultCost
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -124,4 +112,53 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
...
@@ -124,4 +112,53 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
return
nil
return
nil
})
})
g
.
PATCH
(
"/user/:userId"
,
func
(
c
echo
.
Context
)
error
{
currentUserID
:=
c
.
Get
(
getUserIDContextKey
())
.
(
int
)
currentUser
,
err
:=
s
.
Store
.
FindUser
(
&
api
.
UserFind
{
ID
:
&
currentUserID
,
})
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to find user"
)
.
SetInternal
(
err
)
}
if
currentUser
==
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
fmt
.
Sprintf
(
"Current session user not found with ID: %d"
,
currentUserID
))
.
SetInternal
(
err
)
}
else
if
currentUser
.
Role
!=
api
.
Owner
{
return
echo
.
NewHTTPError
(
http
.
StatusForbidden
,
"Access forbidden for current session user"
)
.
SetInternal
(
err
)
}
userID
,
err
:=
strconv
.
Atoi
(
c
.
Param
(
"userId"
))
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
fmt
.
Sprintf
(
"ID is not a number: %s"
,
c
.
Param
(
"userId"
)))
.
SetInternal
(
err
)
}
userPatch
:=
&
api
.
UserPatch
{
ID
:
userID
,
}
if
err
:=
json
.
NewDecoder
(
c
.
Request
()
.
Body
)
.
Decode
(
userPatch
);
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
"Malformatted patch user request"
)
.
SetInternal
(
err
)
}
if
userPatch
.
Password
!=
nil
&&
*
userPatch
.
Password
!=
""
{
passwordHash
,
err
:=
bcrypt
.
GenerateFromPassword
([]
byte
(
*
userPatch
.
Password
),
bcrypt
.
DefaultCost
)
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to generate password hash"
)
.
SetInternal
(
err
)
}
passwordHashStr
:=
string
(
passwordHash
)
userPatch
.
PasswordHash
=
&
passwordHashStr
}
user
,
err
:=
s
.
Store
.
PatchUser
(
userPatch
)
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to patch user"
)
.
SetInternal
(
err
)
}
c
.
Response
()
.
Header
()
.
Set
(
echo
.
HeaderContentType
,
echo
.
MIMEApplicationJSONCharsetUTF8
)
if
err
:=
json
.
NewEncoder
(
c
.
Response
()
.
Writer
)
.
Encode
(
composeResponse
(
user
));
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to encode user response"
)
.
SetInternal
(
err
)
}
return
nil
})
}
}
server/webhook.go
View file @
bc22f69a
...
@@ -67,7 +67,7 @@ func (s *Server) registerWebhookRoutes(g *echo.Group) {
...
@@ -67,7 +67,7 @@ func (s *Server) registerWebhookRoutes(g *echo.Group) {
memoFind
:=
&
api
.
MemoFind
{
memoFind
:=
&
api
.
MemoFind
{
CreatorID
:
&
user
.
ID
,
CreatorID
:
&
user
.
ID
,
}
}
rowStatus
:=
c
.
QueryParam
(
"rowStatus"
)
rowStatus
:=
api
.
RowStatus
(
c
.
QueryParam
(
"rowStatus"
)
)
if
rowStatus
!=
""
{
if
rowStatus
!=
""
{
memoFind
.
RowStatus
=
&
rowStatus
memoFind
.
RowStatus
=
&
rowStatus
}
}
...
...
store/memo.go
View file @
bc22f69a
...
@@ -7,8 +7,45 @@ import (
...
@@ -7,8 +7,45 @@ import (
"strings"
"strings"
)
)
// memoRaw is the store model for an Memo.
// Fields have exactly the same meanings as Memo.
type
memoRaw
struct
{
ID
int
// Standard fields
RowStatus
api
.
RowStatus
CreatorID
int
CreatedTs
int64
UpdatedTs
int64
// Domain specific fields
Content
string
}
// toMemo creates an instance of Memo based on the memoRaw.
// This is intended to be called when we need to compose an Memo relationship.
func
(
raw
*
memoRaw
)
toMemo
()
*
api
.
Memo
{
return
&
api
.
Memo
{
ID
:
raw
.
ID
,
// Standard fields
RowStatus
:
raw
.
RowStatus
,
CreatorID
:
raw
.
CreatorID
,
CreatedTs
:
raw
.
CreatedTs
,
UpdatedTs
:
raw
.
UpdatedTs
,
// Domain specific fields
Content
:
raw
.
Content
,
}
}
func
(
s
*
Store
)
CreateMemo
(
create
*
api
.
MemoCreate
)
(
*
api
.
Memo
,
error
)
{
func
(
s
*
Store
)
CreateMemo
(
create
*
api
.
MemoCreate
)
(
*
api
.
Memo
,
error
)
{
memo
,
err
:=
createMemo
(
s
.
db
,
create
)
memoRaw
,
err
:=
createMemoRaw
(
s
.
db
,
create
)
if
err
!=
nil
{
return
nil
,
err
}
memo
,
err
:=
s
.
composeMemo
(
memoRaw
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -17,7 +54,12 @@ func (s *Store) CreateMemo(create *api.MemoCreate) (*api.Memo, error) {
...
@@ -17,7 +54,12 @@ func (s *Store) CreateMemo(create *api.MemoCreate) (*api.Memo, error) {
}
}
func
(
s
*
Store
)
PatchMemo
(
patch
*
api
.
MemoPatch
)
(
*
api
.
Memo
,
error
)
{
func
(
s
*
Store
)
PatchMemo
(
patch
*
api
.
MemoPatch
)
(
*
api
.
Memo
,
error
)
{
memo
,
err
:=
patchMemo
(
s
.
db
,
patch
)
memoRaw
,
err
:=
patchMemoRaw
(
s
.
db
,
patch
)
if
err
!=
nil
{
return
nil
,
err
}
memo
,
err
:=
s
.
composeMemo
(
memoRaw
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -26,16 +68,26 @@ func (s *Store) PatchMemo(patch *api.MemoPatch) (*api.Memo, error) {
...
@@ -26,16 +68,26 @@ func (s *Store) PatchMemo(patch *api.MemoPatch) (*api.Memo, error) {
}
}
func
(
s
*
Store
)
FindMemoList
(
find
*
api
.
MemoFind
)
([]
*
api
.
Memo
,
error
)
{
func
(
s
*
Store
)
FindMemoList
(
find
*
api
.
MemoFind
)
([]
*
api
.
Memo
,
error
)
{
list
,
err
:=
findMemo
List
(
s
.
db
,
find
)
memoRawList
,
err
:=
findMemoRaw
List
(
s
.
db
,
find
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
list
:=
[]
*
api
.
Memo
{}
for
_
,
raw
:=
range
memoRawList
{
memo
,
err
:=
s
.
composeMemo
(
raw
)
if
err
!=
nil
{
return
nil
,
err
}
list
=
append
(
list
,
memo
)
}
return
list
,
nil
return
list
,
nil
}
}
func
(
s
*
Store
)
FindMemo
(
find
*
api
.
MemoFind
)
(
*
api
.
Memo
,
error
)
{
func
(
s
*
Store
)
FindMemo
(
find
*
api
.
MemoFind
)
(
*
api
.
Memo
,
error
)
{
list
,
err
:=
findMemoList
(
s
.
db
,
find
)
list
,
err
:=
findMemo
Raw
List
(
s
.
db
,
find
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -44,7 +96,12 @@ func (s *Store) FindMemo(find *api.MemoFind) (*api.Memo, error) {
...
@@ -44,7 +96,12 @@ func (s *Store) FindMemo(find *api.MemoFind) (*api.Memo, error) {
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
}
}
return
list
[
0
],
nil
memo
,
err
:=
s
.
composeMemo
(
list
[
0
])
if
err
!=
nil
{
return
nil
,
err
}
return
memo
,
nil
}
}
func
(
s
*
Store
)
DeleteMemo
(
delete
*
api
.
MemoDelete
)
error
{
func
(
s
*
Store
)
DeleteMemo
(
delete
*
api
.
MemoDelete
)
error
{
...
@@ -56,7 +113,7 @@ func (s *Store) DeleteMemo(delete *api.MemoDelete) error {
...
@@ -56,7 +113,7 @@ func (s *Store) DeleteMemo(delete *api.MemoDelete) error {
return
nil
return
nil
}
}
func
createMemo
(
db
*
DB
,
create
*
api
.
MemoCreate
)
(
*
api
.
Memo
,
error
)
{
func
createMemo
Raw
(
db
*
DB
,
create
*
api
.
MemoCreate
)
(
*
memoRaw
,
error
)
{
set
:=
[]
string
{
"creator_id"
,
"content"
}
set
:=
[]
string
{
"creator_id"
,
"content"
}
placeholder
:=
[]
string
{
"?"
,
"?"
}
placeholder
:=
[]
string
{
"?"
,
"?"
}
args
:=
[]
interface
{}{
create
.
CreatorID
,
create
.
Content
}
args
:=
[]
interface
{}{
create
.
CreatorID
,
create
.
Content
}
...
@@ -79,26 +136,23 @@ func createMemo(db *DB, create *api.MemoCreate) (*api.Memo, error) {
...
@@ -79,26 +136,23 @@ func createMemo(db *DB, create *api.MemoCreate) (*api.Memo, error) {
}
}
defer
row
.
Close
()
defer
row
.
Close
()
if
!
row
.
Next
()
{
row
.
Next
()
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
var
memoRaw
memoRaw
}
var
memo
api
.
Memo
if
err
:=
row
.
Scan
(
if
err
:=
row
.
Scan
(
&
memo
.
ID
,
&
memo
Raw
.
ID
,
&
memo
.
CreatorID
,
&
memo
Raw
.
CreatorID
,
&
memo
.
CreatedTs
,
&
memo
Raw
.
CreatedTs
,
&
memo
.
UpdatedTs
,
&
memo
Raw
.
UpdatedTs
,
&
memo
.
Content
,
&
memo
Raw
.
Content
,
&
memo
.
RowStatus
,
&
memo
Raw
.
RowStatus
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
&
memo
,
nil
return
&
memo
Raw
,
nil
}
}
func
patchMemo
(
db
*
DB
,
patch
*
api
.
MemoPatch
)
(
*
api
.
Memo
,
error
)
{
func
patchMemo
Raw
(
db
*
DB
,
patch
*
api
.
MemoPatch
)
(
*
memoRaw
,
error
)
{
set
,
args
:=
[]
string
{},
[]
interface
{}{}
set
,
args
:=
[]
string
{},
[]
interface
{}{}
if
v
:=
patch
.
Content
;
v
!=
nil
{
if
v
:=
patch
.
Content
;
v
!=
nil
{
...
@@ -125,21 +179,21 @@ func patchMemo(db *DB, patch *api.MemoPatch) (*api.Memo, error) {
...
@@ -125,21 +179,21 @@ func patchMemo(db *DB, patch *api.MemoPatch) (*api.Memo, error) {
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
}
}
var
memo
api
.
Memo
var
memo
Raw
memoRaw
if
err
:=
row
.
Scan
(
if
err
:=
row
.
Scan
(
&
memo
.
ID
,
&
memo
Raw
.
ID
,
&
memo
.
CreatedTs
,
&
memo
Raw
.
CreatedTs
,
&
memo
.
UpdatedTs
,
&
memo
Raw
.
UpdatedTs
,
&
memo
.
Content
,
&
memo
Raw
.
Content
,
&
memo
.
RowStatus
,
&
memo
Raw
.
RowStatus
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
&
memo
,
nil
return
&
memo
Raw
,
nil
}
}
func
findMemo
List
(
db
*
DB
,
find
*
api
.
MemoFind
)
([]
*
api
.
Memo
,
error
)
{
func
findMemo
RawList
(
db
*
DB
,
find
*
api
.
MemoFind
)
([]
*
memoRaw
,
error
)
{
where
,
args
:=
[]
string
{
"1 = 1"
},
[]
interface
{}{}
where
,
args
:=
[]
string
{
"1 = 1"
},
[]
interface
{}{}
if
v
:=
find
.
ID
;
v
!=
nil
{
if
v
:=
find
.
ID
;
v
!=
nil
{
...
@@ -151,6 +205,9 @@ func findMemoList(db *DB, find *api.MemoFind) ([]*api.Memo, error) {
...
@@ -151,6 +205,9 @@ func findMemoList(db *DB, find *api.MemoFind) ([]*api.Memo, error) {
if
v
:=
find
.
RowStatus
;
v
!=
nil
{
if
v
:=
find
.
RowStatus
;
v
!=
nil
{
where
,
args
=
append
(
where
,
"row_status = ?"
),
append
(
args
,
*
v
)
where
,
args
=
append
(
where
,
"row_status = ?"
),
append
(
args
,
*
v
)
}
}
if
v
:=
find
.
Pinned
;
v
!=
nil
{
where
=
append
(
where
,
"id in (SELECT memo_id FROM memo_organizer WHERE pinned = 1 AND user_id = memo.creator_id )"
)
}
rows
,
err
:=
db
.
Db
.
Query
(
`
rows
,
err
:=
db
.
Db
.
Query
(
`
SELECT
SELECT
...
@@ -169,28 +226,28 @@ func findMemoList(db *DB, find *api.MemoFind) ([]*api.Memo, error) {
...
@@ -169,28 +226,28 @@ func findMemoList(db *DB, find *api.MemoFind) ([]*api.Memo, error) {
}
}
defer
rows
.
Close
()
defer
rows
.
Close
()
list
:=
make
([]
*
api
.
Memo
,
0
)
memoRawList
:=
make
([]
*
memoRaw
,
0
)
for
rows
.
Next
()
{
for
rows
.
Next
()
{
var
memo
api
.
Memo
var
memo
Raw
memoRaw
if
err
:=
rows
.
Scan
(
if
err
:=
rows
.
Scan
(
&
memo
.
ID
,
&
memo
Raw
.
ID
,
&
memo
.
CreatorID
,
&
memo
Raw
.
CreatorID
,
&
memo
.
CreatedTs
,
&
memo
Raw
.
CreatedTs
,
&
memo
.
UpdatedTs
,
&
memo
Raw
.
UpdatedTs
,
&
memo
.
Content
,
&
memo
Raw
.
Content
,
&
memo
.
RowStatus
,
&
memo
Raw
.
RowStatus
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
list
=
append
(
list
,
&
memo
)
memoRawList
=
append
(
memoRawList
,
&
memoRaw
)
}
}
if
err
:=
rows
.
Err
();
err
!=
nil
{
if
err
:=
rows
.
Err
();
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
l
ist
,
nil
return
memoRawL
ist
,
nil
}
}
func
deleteMemo
(
db
*
DB
,
delete
*
api
.
MemoDelete
)
error
{
func
deleteMemo
(
db
*
DB
,
delete
*
api
.
MemoDelete
)
error
{
...
@@ -206,3 +263,19 @@ func deleteMemo(db *DB, delete *api.MemoDelete) error {
...
@@ -206,3 +263,19 @@ func deleteMemo(db *DB, delete *api.MemoDelete) error {
return
nil
return
nil
}
}
func
(
s
*
Store
)
composeMemo
(
raw
*
memoRaw
)
(
*
api
.
Memo
,
error
)
{
memo
:=
raw
.
toMemo
()
memoOrganizer
,
err
:=
s
.
FindMemoOrganizer
(
&
api
.
MemoOrganizerFind
{
MemoID
:
memo
.
ID
,
UserID
:
memo
.
CreatorID
,
})
if
err
!=
nil
&&
common
.
ErrorCode
(
err
)
!=
common
.
NotFound
{
return
nil
,
err
}
else
if
memoOrganizer
!=
nil
{
memo
.
Pinned
=
memoOrganizer
.
Pinned
}
return
memo
,
nil
}
store/memo_organizer.go
0 → 100644
View file @
bc22f69a
package
store
import
(
"fmt"
"memos/api"
"memos/common"
)
// memoOrganizerRaw is the store model for an MemoOrganizer.
// Fields have exactly the same meanings as MemoOrganizer.
type
memoOrganizerRaw
struct
{
ID
int
// Domain specific fields
MemoID
int
UserID
int
Pinned
bool
}
func
(
raw
*
memoOrganizerRaw
)
toMemoOrganizer
()
*
api
.
MemoOrganizer
{
return
&
api
.
MemoOrganizer
{
ID
:
raw
.
ID
,
MemoID
:
raw
.
MemoID
,
UserID
:
raw
.
UserID
,
Pinned
:
raw
.
Pinned
,
}
}
func
(
s
*
Store
)
FindMemoOrganizer
(
find
*
api
.
MemoOrganizerFind
)
(
*
api
.
MemoOrganizer
,
error
)
{
memoOrganizerRaw
,
err
:=
findMemoOrganizer
(
s
.
db
,
find
)
if
err
!=
nil
{
return
nil
,
err
}
memoOrganizer
:=
memoOrganizerRaw
.
toMemoOrganizer
()
return
memoOrganizer
,
nil
}
func
(
s
*
Store
)
UpsertMemoOrganizer
(
upsert
*
api
.
MemoOrganizerUpsert
)
error
{
err
:=
upsertMemoOrganizer
(
s
.
db
,
upsert
)
if
err
!=
nil
{
return
err
}
return
nil
}
func
findMemoOrganizer
(
db
*
DB
,
find
*
api
.
MemoOrganizerFind
)
(
*
memoOrganizerRaw
,
error
)
{
row
,
err
:=
db
.
Db
.
Query
(
`
SELECT
id,
memo_id,
user_id,
pinned
FROM memo_organizer
WHERE memo_id = ? AND user_id = ?
`
,
find
.
MemoID
,
find
.
UserID
)
if
err
!=
nil
{
return
nil
,
FormatError
(
err
)
}
defer
row
.
Close
()
if
!
row
.
Next
()
{
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
}
var
memoOrganizerRaw
memoOrganizerRaw
if
err
:=
row
.
Scan
(
&
memoOrganizerRaw
.
ID
,
&
memoOrganizerRaw
.
MemoID
,
&
memoOrganizerRaw
.
UserID
,
&
memoOrganizerRaw
.
Pinned
,
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
}
return
&
memoOrganizerRaw
,
nil
}
func
upsertMemoOrganizer
(
db
*
DB
,
upsert
*
api
.
MemoOrganizerUpsert
)
error
{
row
,
err
:=
db
.
Db
.
Query
(
`
INSERT INTO memo_organizer (
memo_id,
user_id,
pinned
)
VALUES (?, ?, ?)
ON CONFLICT(memo_id, user_id) DO UPDATE
SET
pinned = EXCLUDED.pinned
RETURNING id, memo_id, user_id, pinned
`
,
upsert
.
MemoID
,
upsert
.
UserID
,
upsert
.
Pinned
,
)
if
err
!=
nil
{
return
FormatError
(
err
)
}
defer
row
.
Close
()
row
.
Next
()
var
memoOrganizer
api
.
MemoOrganizer
if
err
:=
row
.
Scan
(
&
memoOrganizer
.
ID
,
&
memoOrganizer
.
MemoID
,
&
memoOrganizer
.
UserID
,
&
memoOrganizer
.
Pinned
,
);
err
!=
nil
{
return
FormatError
(
err
)
}
return
nil
}
store/migration/10000__reset.sql
View file @
bc22f69a
DROP
TABLE
IF
EXISTS
`memo_organizer`
;
DROP
TABLE
IF
EXISTS
`memo`
;
DROP
TABLE
IF
EXISTS
`memo`
;
DROP
TABLE
IF
EXISTS
`shortcut`
;
DROP
TABLE
IF
EXISTS
`shortcut`
;
DROP
TABLE
IF
EXISTS
`resource`
;
DROP
TABLE
IF
EXISTS
`resource`
;
...
...
store/migration/10001__schema.sql
View file @
bc22f69a
...
@@ -3,6 +3,8 @@ CREATE TABLE user (
...
@@ -3,6 +3,8 @@ CREATE TABLE user (
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT
,
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT
,
created_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
created_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
updated_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
updated_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
-- allowed row status are 'NORMAL', 'ARCHIVED'.
row_status
TEXT
NOT
NULL
CHECK
(
row_status
IN
(
'NORMAL'
,
'ARCHIVED'
))
DEFAULT
'NORMAL'
,
email
TEXT
NOT
NULL
UNIQUE
,
email
TEXT
NOT
NULL
UNIQUE
,
role
TEXT
NOT
NULL
CHECK
(
role
IN
(
'OWNER'
,
'USER'
))
DEFAULT
'USER'
,
role
TEXT
NOT
NULL
CHECK
(
role
IN
(
'OWNER'
,
'USER'
))
DEFAULT
'USER'
,
name
TEXT
NOT
NULL
,
name
TEXT
NOT
NULL
,
...
@@ -33,10 +35,9 @@ CREATE TABLE memo (
...
@@ -33,10 +35,9 @@ CREATE TABLE memo (
creator_id
INTEGER
NOT
NULL
,
creator_id
INTEGER
NOT
NULL
,
created_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
created_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
updated_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
updated_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
-- allowed row status are 'NORMAL', 'ARCHIVED', 'HIDDEN'.
row_status
TEXT
NOT
NULL
CHECK
(
row_status
IN
(
'NORMAL'
,
'ARCHIVED'
))
DEFAULT
'NORMAL'
,
row_status
TEXT
NOT
NULL
DEFAULT
'NORMAL'
,
content
TEXT
NOT
NULL
DEFAULT
''
,
content
TEXT
NOT
NULL
DEFAULT
''
,
FOREIGN
KEY
(
creator_id
)
REFERENCES
user
s
(
id
)
FOREIGN
KEY
(
creator_id
)
REFERENCES
user
(
id
)
);
);
INSERT
INTO
INSERT
INTO
...
@@ -56,17 +57,32 @@ WHERE
...
@@ -56,17 +57,32 @@ WHERE
rowid
=
old
.
rowid
;
rowid
=
old
.
rowid
;
END
;
END
;
-- memo_organizer
CREATE
TABLE
memo_organizer
(
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT
,
memo_id
INTEGER
NOT
NULL
,
user_id
INTEGER
NOT
NULL
,
pinned
INTEGER
NOT
NULL
CHECK
(
pinned
IN
(
0
,
1
))
DEFAULT
0
,
FOREIGN
KEY
(
memo_id
)
REFERENCES
memo
(
id
),
FOREIGN
KEY
(
user_id
)
REFERENCES
user
(
id
),
UNIQUE
(
memo_id
,
user_id
)
);
INSERT
INTO
sqlite_sequence
(
name
,
seq
)
VALUES
(
'memo_organizer'
,
100
);
-- shortcut
-- shortcut
CREATE
TABLE
shortcut
(
CREATE
TABLE
shortcut
(
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT
,
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT
,
creator_id
INTEGER
NOT
NULL
,
creator_id
INTEGER
NOT
NULL
,
created_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
created_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
updated_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
updated_ts
BIGINT
NOT
NULL
DEFAULT
(
strftime
(
'%s'
,
'now'
)),
row_status
TEXT
NOT
NULL
CHECK
(
row_status
IN
(
'NORMAL'
,
'ARCHIVED'
))
DEFAULT
'NORMAL'
,
title
TEXT
NOT
NULL
DEFAULT
''
,
title
TEXT
NOT
NULL
DEFAULT
''
,
payload
TEXT
NOT
NULL
DEFAULT
'{}'
,
payload
TEXT
NOT
NULL
DEFAULT
'{}'
,
-- allowed row status are 'NORMAL', 'ARCHIVED'.
FOREIGN
KEY
(
creator_id
)
REFERENCES
user
(
id
)
row_status
TEXT
NOT
NULL
DEFAULT
'NORMAL'
,
FOREIGN
KEY
(
creator_id
)
REFERENCES
users
(
id
)
);
);
INSERT
INTO
INSERT
INTO
...
@@ -96,7 +112,7 @@ CREATE TABLE resource (
...
@@ -96,7 +112,7 @@ CREATE TABLE resource (
blob
BLOB
NOT
NULL
,
blob
BLOB
NOT
NULL
,
type
TEXT
NOT
NULL
DEFAULT
''
,
type
TEXT
NOT
NULL
DEFAULT
''
,
size
INTEGER
NOT
NULL
DEFAULT
0
,
size
INTEGER
NOT
NULL
DEFAULT
0
,
FOREIGN
KEY
(
creator_id
)
REFERENCES
user
s
(
id
)
FOREIGN
KEY
(
creator_id
)
REFERENCES
user
(
id
)
);
);
INSERT
INTO
INSERT
INTO
...
...
store/resource.go
View file @
bc22f69a
...
@@ -7,22 +7,63 @@ import (
...
@@ -7,22 +7,63 @@ import (
"strings"
"strings"
)
)
// resourceRaw is the store model for an Resource.
// Fields have exactly the same meanings as Resource.
type
resourceRaw
struct
{
ID
int
// Standard fields
CreatorID
int
CreatedTs
int64
UpdatedTs
int64
// Domain specific fields
Filename
string
Blob
[]
byte
Type
string
Size
int64
}
func
(
raw
*
resourceRaw
)
toResource
()
*
api
.
Resource
{
return
&
api
.
Resource
{
ID
:
raw
.
ID
,
// Standard fields
CreatorID
:
raw
.
CreatorID
,
CreatedTs
:
raw
.
CreatedTs
,
UpdatedTs
:
raw
.
UpdatedTs
,
// Domain specific fields
Filename
:
raw
.
Filename
,
Blob
:
raw
.
Blob
,
Type
:
raw
.
Type
,
Size
:
raw
.
Size
,
}
}
func
(
s
*
Store
)
CreateResource
(
create
*
api
.
ResourceCreate
)
(
*
api
.
Resource
,
error
)
{
func
(
s
*
Store
)
CreateResource
(
create
*
api
.
ResourceCreate
)
(
*
api
.
Resource
,
error
)
{
resource
,
err
:=
createResource
(
s
.
db
,
create
)
resource
Raw
,
err
:=
createResource
(
s
.
db
,
create
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
resource
:=
resourceRaw
.
toResource
()
return
resource
,
nil
return
resource
,
nil
}
}
func
(
s
*
Store
)
FindResourceList
(
find
*
api
.
ResourceFind
)
([]
*
api
.
Resource
,
error
)
{
func
(
s
*
Store
)
FindResourceList
(
find
*
api
.
ResourceFind
)
([]
*
api
.
Resource
,
error
)
{
l
ist
,
err
:=
findResourceList
(
s
.
db
,
find
)
resourceRawL
ist
,
err
:=
findResourceList
(
s
.
db
,
find
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
return
list
,
nil
resourceList
:=
[]
*
api
.
Resource
{}
for
_
,
raw
:=
range
resourceRawList
{
resourceList
=
append
(
resourceList
,
raw
.
toResource
())
}
return
resourceList
,
nil
}
}
func
(
s
*
Store
)
FindResource
(
find
*
api
.
ResourceFind
)
(
*
api
.
Resource
,
error
)
{
func
(
s
*
Store
)
FindResource
(
find
*
api
.
ResourceFind
)
(
*
api
.
Resource
,
error
)
{
...
@@ -35,7 +76,9 @@ func (s *Store) FindResource(find *api.ResourceFind) (*api.Resource, error) {
...
@@ -35,7 +76,9 @@ func (s *Store) FindResource(find *api.ResourceFind) (*api.Resource, error) {
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
}
}
return
list
[
0
],
nil
resource
:=
list
[
0
]
.
toResource
()
return
resource
,
nil
}
}
func
(
s
*
Store
)
DeleteResource
(
delete
*
api
.
ResourceDelete
)
error
{
func
(
s
*
Store
)
DeleteResource
(
delete
*
api
.
ResourceDelete
)
error
{
...
@@ -47,7 +90,7 @@ func (s *Store) DeleteResource(delete *api.ResourceDelete) error {
...
@@ -47,7 +90,7 @@ func (s *Store) DeleteResource(delete *api.ResourceDelete) error {
return
nil
return
nil
}
}
func
createResource
(
db
*
DB
,
create
*
api
.
ResourceCreate
)
(
*
api
.
Resource
,
error
)
{
func
createResource
(
db
*
DB
,
create
*
api
.
ResourceCreate
)
(
*
resourceRaw
,
error
)
{
row
,
err
:=
db
.
Db
.
Query
(
`
row
,
err
:=
db
.
Db
.
Query
(
`
INSERT INTO resource (
INSERT INTO resource (
filename,
filename,
...
@@ -70,27 +113,24 @@ func createResource(db *DB, create *api.ResourceCreate) (*api.Resource, error) {
...
@@ -70,27 +113,24 @@ func createResource(db *DB, create *api.ResourceCreate) (*api.Resource, error) {
}
}
defer
row
.
Close
()
defer
row
.
Close
()
if
!
row
.
Next
()
{
row
.
Next
()
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
var
resourceRaw
resourceRaw
}
var
resource
api
.
Resource
if
err
:=
row
.
Scan
(
if
err
:=
row
.
Scan
(
&
resource
.
ID
,
&
resource
Raw
.
ID
,
&
resource
.
Filename
,
&
resource
Raw
.
Filename
,
&
resource
.
Blob
,
&
resource
Raw
.
Blob
,
&
resource
.
Type
,
&
resource
Raw
.
Type
,
&
resource
.
Size
,
&
resource
Raw
.
Size
,
&
resource
.
CreatedTs
,
&
resource
Raw
.
CreatedTs
,
&
resource
.
UpdatedTs
,
&
resource
Raw
.
UpdatedTs
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
&
resource
,
nil
return
&
resource
Raw
,
nil
}
}
func
findResourceList
(
db
*
DB
,
find
*
api
.
ResourceFind
)
([]
*
api
.
Resource
,
error
)
{
func
findResourceList
(
db
*
DB
,
find
*
api
.
ResourceFind
)
([]
*
resourceRaw
,
error
)
{
where
,
args
:=
[]
string
{
"1 = 1"
},
[]
interface
{}{}
where
,
args
:=
[]
string
{
"1 = 1"
},
[]
interface
{}{}
if
v
:=
find
.
ID
;
v
!=
nil
{
if
v
:=
find
.
ID
;
v
!=
nil
{
...
@@ -121,29 +161,29 @@ func findResourceList(db *DB, find *api.ResourceFind) ([]*api.Resource, error) {
...
@@ -121,29 +161,29 @@ func findResourceList(db *DB, find *api.ResourceFind) ([]*api.Resource, error) {
}
}
defer
rows
.
Close
()
defer
rows
.
Close
()
list
:=
make
([]
*
api
.
Resource
,
0
)
resourceRawList
:=
make
([]
*
resourceRaw
,
0
)
for
rows
.
Next
()
{
for
rows
.
Next
()
{
var
resource
api
.
Resource
var
resource
Raw
resourceRaw
if
err
:=
rows
.
Scan
(
if
err
:=
rows
.
Scan
(
&
resource
.
ID
,
&
resource
Raw
.
ID
,
&
resource
.
Filename
,
&
resource
Raw
.
Filename
,
&
resource
.
Blob
,
&
resource
Raw
.
Blob
,
&
resource
.
Type
,
&
resource
Raw
.
Type
,
&
resource
.
Size
,
&
resource
Raw
.
Size
,
&
resource
.
CreatedTs
,
&
resource
Raw
.
CreatedTs
,
&
resource
.
UpdatedTs
,
&
resource
Raw
.
UpdatedTs
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
list
=
append
(
list
,
&
resource
)
resourceRawList
=
append
(
resourceRawList
,
&
resourceRaw
)
}
}
if
err
:=
rows
.
Err
();
err
!=
nil
{
if
err
:=
rows
.
Err
();
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
l
ist
,
nil
return
resourceRawL
ist
,
nil
}
}
func
deleteResource
(
db
*
DB
,
delete
*
api
.
ResourceDelete
)
error
{
func
deleteResource
(
db
*
DB
,
delete
*
api
.
ResourceDelete
)
error
{
...
...
store/seed/10000__reset.sql
View file @
bc22f69a
DELETE
FROM
memo_organizer
;
DELETE
FROM
resource
;
DELETE
FROM
resource
;
DELETE
FROM
shortcut
;
DELETE
FROM
shortcut
;
DELETE
FROM
memo
;
DELETE
FROM
memo
;
...
...
store/seed/10001__user.sql
View file @
bc22f69a
...
@@ -12,6 +12,6 @@ VALUES
...
@@ -12,6 +12,6 @@ VALUES
'guest'
,
'guest'
,
'guest@example.com'
,
'guest@example.com'
,
'guest_open_id'
,
'guest_open_id'
,
--
"secret"
--
raw password: secret
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
);
);
store/seed/10002__memo.sql
View file @
bc22f69a
INSERT
INTO
INSERT
INTO
memo
(
memo
(
`id`
,
`content`
,
`content`
,
`creator_id`
`creator_id`
)
)
VALUES
VALUES
(
(
101
,
'#memos 👋 Welcome to memos'
,
'#memos 👋 Welcome to memos'
,
101
101
);
);
INSERT
INTO
INSERT
INTO
memo
(
memo
(
`id`
,
`content`
,
`content`
,
`creator_id`
,
`creator_id`
`row_status`
)
)
VALUES
VALUES
(
(
102
,
'好好学习,天天向上。'
,
'好好学习,天天向上。'
,
101
,
101
'ARCHIVED'
);
);
store/seed/10003__memo_organizer.sql
0 → 100644
View file @
bc22f69a
INSERT
INTO
memo_organizer
(
`memo_id`
,
`user_id`
,
`pinned`
)
VALUES
(
102
,
101
,
1
);
store/seed/1000
2
__shortcut.sql
→
store/seed/1000
4
__shortcut.sql
View file @
bc22f69a
File moved
store/shortcut.go
View file @
bc22f69a
...
@@ -7,30 +7,69 @@ import (
...
@@ -7,30 +7,69 @@ import (
"strings"
"strings"
)
)
// shortcutRaw is the store model for an Shortcut.
// Fields have exactly the same meanings as Shortcut.
type
shortcutRaw
struct
{
ID
int
// Standard fields
RowStatus
api
.
RowStatus
CreatorID
int
CreatedTs
int64
UpdatedTs
int64
// Domain specific fields
Title
string
Payload
string
}
func
(
raw
*
shortcutRaw
)
toShortcut
()
*
api
.
Shortcut
{
return
&
api
.
Shortcut
{
ID
:
raw
.
ID
,
RowStatus
:
raw
.
RowStatus
,
CreatorID
:
raw
.
CreatorID
,
CreatedTs
:
raw
.
CreatedTs
,
UpdatedTs
:
raw
.
UpdatedTs
,
Title
:
raw
.
Title
,
Payload
:
raw
.
Payload
,
}
}
func
(
s
*
Store
)
CreateShortcut
(
create
*
api
.
ShortcutCreate
)
(
*
api
.
Shortcut
,
error
)
{
func
(
s
*
Store
)
CreateShortcut
(
create
*
api
.
ShortcutCreate
)
(
*
api
.
Shortcut
,
error
)
{
shortcut
,
err
:=
createShortcut
(
s
.
db
,
create
)
shortcut
Raw
,
err
:=
createShortcut
(
s
.
db
,
create
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
shortcut
:=
shortcutRaw
.
toShortcut
()
return
shortcut
,
nil
return
shortcut
,
nil
}
}
func
(
s
*
Store
)
PatchShortcut
(
patch
*
api
.
ShortcutPatch
)
(
*
api
.
Shortcut
,
error
)
{
func
(
s
*
Store
)
PatchShortcut
(
patch
*
api
.
ShortcutPatch
)
(
*
api
.
Shortcut
,
error
)
{
shortcut
,
err
:=
patchShortcut
(
s
.
db
,
patch
)
shortcut
Raw
,
err
:=
patchShortcut
(
s
.
db
,
patch
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
shortcut
:=
shortcutRaw
.
toShortcut
()
return
shortcut
,
nil
return
shortcut
,
nil
}
}
func
(
s
*
Store
)
FindShortcutList
(
find
*
api
.
ShortcutFind
)
([]
*
api
.
Shortcut
,
error
)
{
func
(
s
*
Store
)
FindShortcutList
(
find
*
api
.
ShortcutFind
)
([]
*
api
.
Shortcut
,
error
)
{
l
ist
,
err
:=
findShortcutList
(
s
.
db
,
find
)
shortcutRawL
ist
,
err
:=
findShortcutList
(
s
.
db
,
find
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
list
:=
[]
*
api
.
Shortcut
{}
for
_
,
raw
:=
range
shortcutRawList
{
list
=
append
(
list
,
raw
.
toShortcut
())
}
return
list
,
nil
return
list
,
nil
}
}
...
@@ -44,7 +83,9 @@ func (s *Store) FindShortcut(find *api.ShortcutFind) (*api.Shortcut, error) {
...
@@ -44,7 +83,9 @@ func (s *Store) FindShortcut(find *api.ShortcutFind) (*api.Shortcut, error) {
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
}
}
return
list
[
0
],
nil
shortcut
:=
list
[
0
]
.
toShortcut
()
return
shortcut
,
nil
}
}
func
(
s
*
Store
)
DeleteShortcut
(
delete
*
api
.
ShortcutDelete
)
error
{
func
(
s
*
Store
)
DeleteShortcut
(
delete
*
api
.
ShortcutDelete
)
error
{
...
@@ -56,7 +97,7 @@ func (s *Store) DeleteShortcut(delete *api.ShortcutDelete) error {
...
@@ -56,7 +97,7 @@ func (s *Store) DeleteShortcut(delete *api.ShortcutDelete) error {
return
nil
return
nil
}
}
func
createShortcut
(
db
*
DB
,
create
*
api
.
ShortcutCreate
)
(
*
api
.
Shortcut
,
error
)
{
func
createShortcut
(
db
*
DB
,
create
*
api
.
ShortcutCreate
)
(
*
shortcutRaw
,
error
)
{
row
,
err
:=
db
.
Db
.
Query
(
`
row
,
err
:=
db
.
Db
.
Query
(
`
INSERT INTO shortcut (
INSERT INTO shortcut (
title,
title,
...
@@ -70,30 +111,29 @@ func createShortcut(db *DB, create *api.ShortcutCreate) (*api.Shortcut, error) {
...
@@ -70,30 +111,29 @@ func createShortcut(db *DB, create *api.ShortcutCreate) (*api.Shortcut, error) {
create
.
Payload
,
create
.
Payload
,
create
.
CreatorID
,
create
.
CreatorID
,
)
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
defer
row
.
Close
()
defer
row
.
Close
()
row
.
Next
()
row
.
Next
()
var
shortcut
api
.
Shortcut
var
shortcut
Raw
shortcutRaw
if
err
:=
row
.
Scan
(
if
err
:=
row
.
Scan
(
&
shortcut
.
ID
,
&
shortcut
Raw
.
ID
,
&
shortcut
.
Title
,
&
shortcut
Raw
.
Title
,
&
shortcut
.
Payload
,
&
shortcut
Raw
.
Payload
,
&
shortcut
.
CreatorID
,
&
shortcut
Raw
.
CreatorID
,
&
shortcut
.
CreatedTs
,
&
shortcut
Raw
.
CreatedTs
,
&
shortcut
.
UpdatedTs
,
&
shortcut
Raw
.
UpdatedTs
,
&
shortcut
.
RowStatus
,
&
shortcut
Raw
.
RowStatus
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
&
shortcut
,
nil
return
&
shortcut
Raw
,
nil
}
}
func
patchShortcut
(
db
*
DB
,
patch
*
api
.
ShortcutPatch
)
(
*
api
.
Shortcut
,
error
)
{
func
patchShortcut
(
db
*
DB
,
patch
*
api
.
ShortcutPatch
)
(
*
shortcutRaw
,
error
)
{
set
,
args
:=
[]
string
{},
[]
interface
{}{}
set
,
args
:=
[]
string
{},
[]
interface
{}{}
if
v
:=
patch
.
Title
;
v
!=
nil
{
if
v
:=
patch
.
Title
;
v
!=
nil
{
...
@@ -123,22 +163,22 @@ func patchShortcut(db *DB, patch *api.ShortcutPatch) (*api.Shortcut, error) {
...
@@ -123,22 +163,22 @@ func patchShortcut(db *DB, patch *api.ShortcutPatch) (*api.Shortcut, error) {
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"not found"
)}
}
}
var
shortcut
api
.
Shortcut
var
shortcut
Raw
shortcutRaw
if
err
:=
row
.
Scan
(
if
err
:=
row
.
Scan
(
&
shortcut
.
ID
,
&
shortcut
Raw
.
ID
,
&
shortcut
.
Title
,
&
shortcut
Raw
.
Title
,
&
shortcut
.
Payload
,
&
shortcut
Raw
.
Payload
,
&
shortcut
.
CreatedTs
,
&
shortcut
Raw
.
CreatedTs
,
&
shortcut
.
UpdatedTs
,
&
shortcut
Raw
.
UpdatedTs
,
&
shortcut
.
RowStatus
,
&
shortcut
Raw
.
RowStatus
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
&
shortcut
,
nil
return
&
shortcut
Raw
,
nil
}
}
func
findShortcutList
(
db
*
DB
,
find
*
api
.
ShortcutFind
)
([]
*
api
.
Shortcut
,
error
)
{
func
findShortcutList
(
db
*
DB
,
find
*
api
.
ShortcutFind
)
([]
*
shortcutRaw
,
error
)
{
where
,
args
:=
[]
string
{
"1 = 1"
},
[]
interface
{}{}
where
,
args
:=
[]
string
{
"1 = 1"
},
[]
interface
{}{}
if
v
:=
find
.
ID
;
v
!=
nil
{
if
v
:=
find
.
ID
;
v
!=
nil
{
...
@@ -169,29 +209,29 @@ func findShortcutList(db *DB, find *api.ShortcutFind) ([]*api.Shortcut, error) {
...
@@ -169,29 +209,29 @@ func findShortcutList(db *DB, find *api.ShortcutFind) ([]*api.Shortcut, error) {
}
}
defer
rows
.
Close
()
defer
rows
.
Close
()
list
:=
make
([]
*
api
.
Shortcut
,
0
)
shortcutRawList
:=
make
([]
*
shortcutRaw
,
0
)
for
rows
.
Next
()
{
for
rows
.
Next
()
{
var
shortcut
api
.
Shortcut
var
shortcut
Raw
shortcutRaw
if
err
:=
rows
.
Scan
(
if
err
:=
rows
.
Scan
(
&
shortcut
.
ID
,
&
shortcut
Raw
.
ID
,
&
shortcut
.
Title
,
&
shortcut
Raw
.
Title
,
&
shortcut
.
Payload
,
&
shortcut
Raw
.
Payload
,
&
shortcut
.
CreatorID
,
&
shortcut
Raw
.
CreatorID
,
&
shortcut
.
CreatedTs
,
&
shortcut
Raw
.
CreatedTs
,
&
shortcut
.
UpdatedTs
,
&
shortcut
Raw
.
UpdatedTs
,
&
shortcut
.
RowStatus
,
&
shortcut
Raw
.
RowStatus
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
list
=
append
(
list
,
&
shortcut
)
shortcutRawList
=
append
(
shortcutRawList
,
&
shortcutRaw
)
}
}
if
err
:=
rows
.
Err
();
err
!=
nil
{
if
err
:=
rows
.
Err
();
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
l
ist
,
nil
return
shortcutRawL
ist
,
nil
}
}
func
deleteShortcut
(
db
*
DB
,
delete
*
api
.
ShortcutDelete
)
error
{
func
deleteShortcut
(
db
*
DB
,
delete
*
api
.
ShortcutDelete
)
error
{
...
...
store/user.go
View file @
bc22f69a
...
@@ -7,30 +7,73 @@ import (
...
@@ -7,30 +7,73 @@ import (
"strings"
"strings"
)
)
// userRaw is the store model for an User.
// Fields have exactly the same meanings as User.
type
userRaw
struct
{
ID
int
// Standard fields
RowStatus
api
.
RowStatus
CreatedTs
int64
UpdatedTs
int64
// Domain specific fields
Email
string
Role
api
.
Role
Name
string
PasswordHash
string
OpenID
string
}
func
(
raw
*
userRaw
)
toUser
()
*
api
.
User
{
return
&
api
.
User
{
ID
:
raw
.
ID
,
RowStatus
:
raw
.
RowStatus
,
CreatedTs
:
raw
.
CreatedTs
,
UpdatedTs
:
raw
.
UpdatedTs
,
Email
:
raw
.
Email
,
Role
:
raw
.
Role
,
Name
:
raw
.
Name
,
PasswordHash
:
raw
.
PasswordHash
,
OpenID
:
raw
.
OpenID
,
}
}
func
(
s
*
Store
)
CreateUser
(
create
*
api
.
UserCreate
)
(
*
api
.
User
,
error
)
{
func
(
s
*
Store
)
CreateUser
(
create
*
api
.
UserCreate
)
(
*
api
.
User
,
error
)
{
user
,
err
:=
createUser
(
s
.
db
,
create
)
user
Raw
,
err
:=
createUser
(
s
.
db
,
create
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
user
:=
userRaw
.
toUser
()
return
user
,
nil
return
user
,
nil
}
}
func
(
s
*
Store
)
PatchUser
(
patch
*
api
.
UserPatch
)
(
*
api
.
User
,
error
)
{
func
(
s
*
Store
)
PatchUser
(
patch
*
api
.
UserPatch
)
(
*
api
.
User
,
error
)
{
user
,
err
:=
patchUser
(
s
.
db
,
patch
)
user
Raw
,
err
:=
patchUser
(
s
.
db
,
patch
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
user
:=
userRaw
.
toUser
()
return
user
,
nil
return
user
,
nil
}
}
func
(
s
*
Store
)
FindUserList
(
find
*
api
.
UserFind
)
([]
*
api
.
User
,
error
)
{
func
(
s
*
Store
)
FindUserList
(
find
*
api
.
UserFind
)
([]
*
api
.
User
,
error
)
{
l
ist
,
err
:=
findUserList
(
s
.
db
,
find
)
userRawL
ist
,
err
:=
findUserList
(
s
.
db
,
find
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
list
:=
[]
*
api
.
User
{}
for
_
,
raw
:=
range
userRawList
{
list
=
append
(
list
,
raw
.
toUser
())
}
return
list
,
nil
return
list
,
nil
}
}
...
@@ -46,10 +89,12 @@ func (s *Store) FindUser(find *api.UserFind) (*api.User, error) {
...
@@ -46,10 +89,12 @@ func (s *Store) FindUser(find *api.UserFind) (*api.User, error) {
return
nil
,
&
common
.
Error
{
Code
:
common
.
Conflict
,
Err
:
fmt
.
Errorf
(
"found %d users with filter %+v, expect 1. "
,
len
(
list
),
find
)}
return
nil
,
&
common
.
Error
{
Code
:
common
.
Conflict
,
Err
:
fmt
.
Errorf
(
"found %d users with filter %+v, expect 1. "
,
len
(
list
),
find
)}
}
}
return
list
[
0
],
nil
user
:=
list
[
0
]
.
toUser
()
return
user
,
nil
}
}
func
createUser
(
db
*
DB
,
create
*
api
.
UserCreate
)
(
*
api
.
User
,
error
)
{
func
createUser
(
db
*
DB
,
create
*
api
.
UserCreate
)
(
*
userRaw
,
error
)
{
row
,
err
:=
db
.
Db
.
Query
(
`
row
,
err
:=
db
.
Db
.
Query
(
`
INSERT INTO user (
INSERT INTO user (
email,
email,
...
@@ -73,37 +118,40 @@ func createUser(db *DB, create *api.UserCreate) (*api.User, error) {
...
@@ -73,37 +118,40 @@ func createUser(db *DB, create *api.UserCreate) (*api.User, error) {
defer
row
.
Close
()
defer
row
.
Close
()
row
.
Next
()
row
.
Next
()
var
user
api
.
User
var
user
Raw
userRaw
if
err
:=
row
.
Scan
(
if
err
:=
row
.
Scan
(
&
user
.
ID
,
&
user
Raw
.
ID
,
&
user
.
Email
,
&
user
Raw
.
Email
,
&
user
.
Role
,
&
user
Raw
.
Role
,
&
user
.
Name
,
&
user
Raw
.
Name
,
&
user
.
PasswordHash
,
&
user
Raw
.
PasswordHash
,
&
user
.
OpenID
,
&
user
Raw
.
OpenID
,
&
user
.
CreatedTs
,
&
user
Raw
.
CreatedTs
,
&
user
.
UpdatedTs
,
&
user
Raw
.
UpdatedTs
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
&
user
,
nil
return
&
user
Raw
,
nil
}
}
func
patchUser
(
db
*
DB
,
patch
*
api
.
UserPatch
)
(
*
api
.
User
,
error
)
{
func
patchUser
(
db
*
DB
,
patch
*
api
.
UserPatch
)
(
*
userRaw
,
error
)
{
set
,
args
:=
[]
string
{},
[]
interface
{}{}
set
,
args
:=
[]
string
{},
[]
interface
{}{}
if
v
:=
patch
.
RowStatus
;
v
!=
nil
{
set
,
args
=
append
(
set
,
"row_status = ?"
),
append
(
args
,
*
v
)
}
if
v
:=
patch
.
Email
;
v
!=
nil
{
if
v
:=
patch
.
Email
;
v
!=
nil
{
set
,
args
=
append
(
set
,
"email = ?"
),
append
(
args
,
v
)
set
,
args
=
append
(
set
,
"email = ?"
),
append
(
args
,
*
v
)
}
}
if
v
:=
patch
.
Name
;
v
!=
nil
{
if
v
:=
patch
.
Name
;
v
!=
nil
{
set
,
args
=
append
(
set
,
"name = ?"
),
append
(
args
,
v
)
set
,
args
=
append
(
set
,
"name = ?"
),
append
(
args
,
*
v
)
}
}
if
v
:=
patch
.
PasswordHash
;
v
!=
nil
{
if
v
:=
patch
.
PasswordHash
;
v
!=
nil
{
set
,
args
=
append
(
set
,
"password_hash = ?"
),
append
(
args
,
v
)
set
,
args
=
append
(
set
,
"password_hash = ?"
),
append
(
args
,
*
v
)
}
}
if
v
:=
patch
.
OpenID
;
v
!=
nil
{
if
v
:=
patch
.
OpenID
;
v
!=
nil
{
set
,
args
=
append
(
set
,
"open_id = ?"
),
append
(
args
,
v
)
set
,
args
=
append
(
set
,
"open_id = ?"
),
append
(
args
,
*
v
)
}
}
args
=
append
(
args
,
patch
.
ID
)
args
=
append
(
args
,
patch
.
ID
)
...
@@ -120,27 +168,27 @@ func patchUser(db *DB, patch *api.UserPatch) (*api.User, error) {
...
@@ -120,27 +168,27 @@ func patchUser(db *DB, patch *api.UserPatch) (*api.User, error) {
defer
row
.
Close
()
defer
row
.
Close
()
if
row
.
Next
()
{
if
row
.
Next
()
{
var
user
api
.
User
var
user
Raw
userRaw
if
err
:=
row
.
Scan
(
if
err
:=
row
.
Scan
(
&
user
.
ID
,
&
user
Raw
.
ID
,
&
user
.
Email
,
&
user
Raw
.
Email
,
&
user
.
Role
,
&
user
Raw
.
Role
,
&
user
.
Name
,
&
user
Raw
.
Name
,
&
user
.
PasswordHash
,
&
user
Raw
.
PasswordHash
,
&
user
.
OpenID
,
&
user
Raw
.
OpenID
,
&
user
.
CreatedTs
,
&
user
Raw
.
CreatedTs
,
&
user
.
UpdatedTs
,
&
user
Raw
.
UpdatedTs
,
);
err
!=
nil
{
);
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
&
user
,
nil
return
&
user
Raw
,
nil
}
}
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"user ID not found: %d"
,
patch
.
ID
)}
return
nil
,
&
common
.
Error
{
Code
:
common
.
NotFound
,
Err
:
fmt
.
Errorf
(
"user ID not found: %d"
,
patch
.
ID
)}
}
}
func
findUserList
(
db
*
DB
,
find
*
api
.
UserFind
)
([]
*
api
.
User
,
error
)
{
func
findUserList
(
db
*
DB
,
find
*
api
.
UserFind
)
([]
*
userRaw
,
error
)
{
where
,
args
:=
[]
string
{
"1 = 1"
},
[]
interface
{}{}
where
,
args
:=
[]
string
{
"1 = 1"
},
[]
interface
{}{}
if
v
:=
find
.
ID
;
v
!=
nil
{
if
v
:=
find
.
ID
;
v
!=
nil
{
...
@@ -178,29 +226,29 @@ func findUserList(db *DB, find *api.UserFind) ([]*api.User, error) {
...
@@ -178,29 +226,29 @@ func findUserList(db *DB, find *api.UserFind) ([]*api.User, error) {
}
}
defer
rows
.
Close
()
defer
rows
.
Close
()
list
:=
make
([]
*
api
.
User
,
0
)
userRawList
:=
make
([]
*
userRaw
,
0
)
for
rows
.
Next
()
{
for
rows
.
Next
()
{
var
user
api
.
User
var
user
Raw
userRaw
if
err
:=
rows
.
Scan
(
if
err
:=
rows
.
Scan
(
&
user
.
ID
,
&
user
Raw
.
ID
,
&
user
.
Email
,
&
user
Raw
.
Email
,
&
user
.
Role
,
&
user
Raw
.
Role
,
&
user
.
Name
,
&
user
Raw
.
Name
,
&
user
.
PasswordHash
,
&
user
Raw
.
PasswordHash
,
&
user
.
OpenID
,
&
user
Raw
.
OpenID
,
&
user
.
CreatedTs
,
&
user
Raw
.
CreatedTs
,
&
user
.
UpdatedTs
,
&
user
Raw
.
UpdatedTs
,
);
err
!=
nil
{
);
err
!=
nil
{
fmt
.
Println
(
err
)
fmt
.
Println
(
err
)
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
list
=
append
(
list
,
&
user
)
userRawList
=
append
(
userRawList
,
&
userRaw
)
}
}
if
err
:=
rows
.
Err
();
err
!=
nil
{
if
err
:=
rows
.
Err
();
err
!=
nil
{
return
nil
,
FormatError
(
err
)
return
nil
,
FormatError
(
err
)
}
}
return
l
ist
,
nil
return
userRawL
ist
,
nil
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment