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
b7339e00
Commit
b7339e00
authored
Jul 26, 2022
by
boojack
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: update finding memo with visibility
parent
58e68f8f
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
133 additions
and
79 deletions
+133
-79
auth.go
api/auth.go
+4
-0
memo.go
api/memo.go
+7
-3
basic_auth.go
server/basic_auth.go
+43
-43
memo.go
server/memo.go
+22
-15
tag.go
server/tag.go
+12
-12
user.go
server/user.go
+30
-0
10002__memo.sql
store/db/seed/10002__memo.sql
+8
-4
memo.go
store/memo.go
+7
-2
No files found.
api/auth.go
View file @
b7339e00
package
api
package
api
var
(
UNKNOWN_ID
=
0
)
type
Signin
struct
{
type
Signin
struct
{
Email
string
`json:"email"`
Email
string
`json:"email"`
Password
string
`json:"password"`
Password
string
`json:"password"`
...
...
api/memo.go
View file @
b7339e00
...
@@ -6,6 +6,8 @@ type Visibility string
...
@@ -6,6 +6,8 @@ type Visibility string
const
(
const
(
// Public is the PUBLIC visibility.
// Public is the PUBLIC visibility.
Public
Visibility
=
"PUBLIC"
Public
Visibility
=
"PUBLIC"
// Protected is the PROTECTED visibility.
Protected
Visibility
=
"PROTECTED"
// Privite is the PRIVATE visibility.
// Privite is the PRIVATE visibility.
Privite
Visibility
=
"PRIVATE"
Privite
Visibility
=
"PRIVATE"
)
)
...
@@ -14,6 +16,8 @@ func (e Visibility) String() string {
...
@@ -14,6 +16,8 @@ func (e Visibility) String() string {
switch
e
{
switch
e
{
case
Public
:
case
Public
:
return
"PUBLIC"
return
"PUBLIC"
case
Protected
:
return
"PROTECTED"
case
Privite
:
case
Privite
:
return
"PRIVATE"
return
"PRIVATE"
}
}
...
@@ -65,9 +69,9 @@ type MemoFind struct {
...
@@ -65,9 +69,9 @@ type MemoFind struct {
CreatorID
*
int
`json:"creatorId"`
CreatorID
*
int
`json:"creatorId"`
// Domain specific fields
// Domain specific fields
Pinned
*
bool
Pinned
*
bool
ContentSearch
*
string
ContentSearch
*
string
Visibility
*
Visibility
Visibility
List
[]
Visibility
// Pagination
// Pagination
Limit
int
Limit
int
...
...
server/basic_auth.go
View file @
b7339e00
...
@@ -21,30 +21,30 @@ func getUserIDContextKey() string {
...
@@ -21,30 +21,30 @@ func getUserIDContextKey() string {
return
userIDContextKey
return
userIDContextKey
}
}
func
setUserSession
(
c
echo
.
Context
,
user
*
api
.
User
)
error
{
func
setUserSession
(
c
tx
echo
.
Context
,
user
*
api
.
User
)
error
{
sess
,
_
:=
session
.
Get
(
"session"
,
c
)
sess
,
_
:=
session
.
Get
(
"session"
,
c
tx
)
sess
.
Options
=
&
sessions
.
Options
{
sess
.
Options
=
&
sessions
.
Options
{
Path
:
"/"
,
Path
:
"/"
,
MaxAge
:
1000
*
3600
*
24
*
30
,
MaxAge
:
1000
*
3600
*
24
*
30
,
HttpOnly
:
true
,
HttpOnly
:
true
,
}
}
sess
.
Values
[
userIDContextKey
]
=
user
.
ID
sess
.
Values
[
userIDContextKey
]
=
user
.
ID
err
:=
sess
.
Save
(
c
.
Request
(),
c
.
Response
())
err
:=
sess
.
Save
(
c
tx
.
Request
(),
ctx
.
Response
())
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to set session, err: %w"
,
err
)
return
fmt
.
Errorf
(
"failed to set session, err: %w"
,
err
)
}
}
return
nil
return
nil
}
}
func
removeUserSession
(
c
echo
.
Context
)
error
{
func
removeUserSession
(
c
tx
echo
.
Context
)
error
{
sess
,
_
:=
session
.
Get
(
"session"
,
c
)
sess
,
_
:=
session
.
Get
(
"session"
,
c
tx
)
sess
.
Options
=
&
sessions
.
Options
{
sess
.
Options
=
&
sessions
.
Options
{
Path
:
"/"
,
Path
:
"/"
,
MaxAge
:
0
,
MaxAge
:
0
,
HttpOnly
:
true
,
HttpOnly
:
true
,
}
}
sess
.
Values
[
userIDContextKey
]
=
nil
sess
.
Values
[
userIDContextKey
]
=
nil
err
:=
sess
.
Save
(
c
.
Request
(),
c
.
Response
())
err
:=
sess
.
Save
(
c
tx
.
Request
(),
ctx
.
Response
())
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to set session, err: %w"
,
err
)
return
fmt
.
Errorf
(
"failed to set session, err: %w"
,
err
)
}
}
...
@@ -53,14 +53,14 @@ func removeUserSession(c echo.Context) error {
...
@@ -53,14 +53,14 @@ func removeUserSession(c echo.Context) error {
// Use session to store user.id.
// Use session to store user.id.
func
BasicAuthMiddleware
(
s
*
Server
,
next
echo
.
HandlerFunc
)
echo
.
HandlerFunc
{
func
BasicAuthMiddleware
(
s
*
Server
,
next
echo
.
HandlerFunc
)
echo
.
HandlerFunc
{
return
func
(
c
echo
.
Context
)
error
{
return
func
(
c
tx
echo
.
Context
)
error
{
// Skip auth for some paths.
// Skip auth for some paths.
if
common
.
HasPrefixes
(
c
.
Path
(),
"/api/auth"
,
"/api/ping"
,
"/api/status"
,
"/api/user/:userId"
)
{
if
common
.
HasPrefixes
(
c
tx
.
Path
(),
"/api/auth"
,
"/api/ping"
,
"/api/status"
,
"/api/user/:userId"
)
{
return
next
(
c
)
return
next
(
c
tx
)
}
}
// If there is openId in query string and related user is found, then skip auth.
// If there is openId in query string and related user is found, then skip auth.
openID
:=
c
.
QueryParam
(
"openId"
)
openID
:=
c
tx
.
QueryParam
(
"openId"
)
if
openID
!=
""
{
if
openID
!=
""
{
userFind
:=
&
api
.
UserFind
{
userFind
:=
&
api
.
UserFind
{
OpenID
:
&
openID
,
OpenID
:
&
openID
,
...
@@ -71,49 +71,49 @@ func BasicAuthMiddleware(s *Server, next echo.HandlerFunc) echo.HandlerFunc {
...
@@ -71,49 +71,49 @@ func BasicAuthMiddleware(s *Server, next echo.HandlerFunc) echo.HandlerFunc {
}
}
if
user
!=
nil
{
if
user
!=
nil
{
// Stores userID into context.
// Stores userID into context.
c
.
Set
(
getUserIDContextKey
(),
user
.
ID
)
c
tx
.
Set
(
getUserIDContextKey
(),
user
.
ID
)
return
next
(
c
)
return
next
(
c
tx
)
}
}
}
}
if
common
.
HasPrefixes
(
c
.
Path
(),
"/api/memo"
,
"/api/tag"
,
"/api/shortcut"
)
&&
c
.
Request
()
.
Method
==
http
.
MethodGet
{
needAuth
:=
true
if
_
,
err
:=
strconv
.
Atoi
(
c
.
QueryParam
(
"creatorId"
));
err
==
nil
{
if
common
.
HasPrefixes
(
ctx
.
Path
(),
"/api/memo"
,
"/api/tag"
,
"/api/shortcut"
)
&&
ctx
.
Request
()
.
Method
==
http
.
MethodGet
{
return
next
(
c
)
if
_
,
err
:=
strconv
.
Atoi
(
ctx
.
QueryParam
(
"creatorId"
));
err
==
nil
{
needAuth
=
false
}
}
}
}
sess
,
err
:=
session
.
Get
(
"session"
,
c
)
{
if
err
!=
nil
{
sess
,
_
:=
session
.
Get
(
"session"
,
ctx
)
return
echo
.
NewHTTPError
(
http
.
StatusUnauthorized
,
"Missing session"
)
.
SetInternal
(
err
)
userIDValue
:=
sess
.
Values
[
userIDContextKey
]
}
if
userIDValue
==
nil
&&
needAuth
{
return
echo
.
NewHTTPError
(
http
.
StatusUnauthorized
,
"Missing userID in session"
)
}
userIDValue
:=
sess
.
Values
[
userIDContextKey
]
userID
,
err
:=
strconv
.
Atoi
(
fmt
.
Sprintf
(
"%v"
,
userIDValue
))
if
userIDValue
==
nil
{
if
err
!=
nil
&&
needAuth
{
return
echo
.
NewHTTPError
(
http
.
StatusUnauthorized
,
"Missing userID in session"
)
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to malformatted user id in the session."
)
.
SetInternal
(
err
)
}
}
userID
,
err
:=
strconv
.
Atoi
(
fmt
.
Sprintf
(
"%v"
,
userIDValue
))
userFind
:=
&
api
.
UserFind
{
if
err
!=
nil
{
ID
:
&
userID
,
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to malformatted user id in the session."
)
.
SetInternal
(
err
)
}
}
user
,
err
:=
s
.
Store
.
FindUser
(
userFind
)
if
err
!=
nil
&&
needAuth
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
fmt
.
Sprintf
(
"Failed to find user by ID: %d"
,
userID
))
.
SetInternal
(
err
)
}
if
needAuth
{
if
user
==
nil
{
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
))
}
}
// Even if there is no error, we still need to make sure the user still exists.
// Save userID into context.
userFind
:=
&
api
.
UserFind
{
ctx
.
Set
(
getUserIDContextKey
(),
userID
)
ID
:
&
userID
,
}
}
user
,
err
:=
s
.
Store
.
FindUser
(
userFind
)
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
fmt
.
Sprintf
(
"Failed to find user by ID: %d"
,
userID
))
.
SetInternal
(
err
)
}
if
user
==
nil
{
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.
c
.
Set
(
getUserIDContextKey
(),
userID
)
return
next
(
c
)
return
next
(
c
tx
)
}
}
}
}
server/memo.go
View file @
b7339e00
...
@@ -5,6 +5,7 @@ import (
...
@@ -5,6 +5,7 @@ import (
"fmt"
"fmt"
"net/http"
"net/http"
"strconv"
"strconv"
"strings"
"github.com/usememos/memos/api"
"github.com/usememos/memos/api"
"github.com/usememos/memos/common"
"github.com/usememos/memos/common"
...
@@ -68,21 +69,21 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
...
@@ -68,21 +69,21 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
memoFind
:=
&
api
.
MemoFind
{}
memoFind
:=
&
api
.
MemoFind
{}
if
userID
,
err
:=
strconv
.
Atoi
(
c
.
QueryParam
(
"creatorId"
));
err
==
nil
{
if
userID
,
err
:=
strconv
.
Atoi
(
c
.
QueryParam
(
"creatorId"
));
err
==
nil
{
memoFind
.
CreatorID
=
&
userID
}
else
{
userID
,
ok
:=
c
.
Get
(
getUserIDContextKey
())
.
(
int
)
if
!
ok
{
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
"Missing user id to find memo"
)
}
memoFind
.
CreatorID
=
&
userID
memoFind
.
CreatorID
=
&
userID
}
}
// Only can get PUBLIC memos in visitor mode
currentUserID
:=
c
.
Get
(
getUserIDContextKey
())
.
(
int
)
_
,
ok
:=
c
.
Get
(
getUserIDContextKey
())
.
(
int
)
if
currentUserID
==
api
.
UNKNOWN_ID
{
if
!
ok
{
if
memoFind
.
CreatorID
==
nil
{
publicVisibility
:=
api
.
Public
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
"Missing user id to find memo"
)
memoFind
.
Visibility
=
&
publicVisibility
}
memoFind
.
VisibilityList
=
[]
api
.
Visibility
{
api
.
Public
}
}
else
{
if
memoFind
.
CreatorID
==
nil
{
memoFind
.
CreatorID
=
&
currentUserID
}
else
{
memoFind
.
VisibilityList
=
[]
api
.
Visibility
{
api
.
Public
,
api
.
Protected
}
}
}
}
rowStatus
:=
api
.
RowStatus
(
c
.
QueryParam
(
"rowStatus"
))
rowStatus
:=
api
.
RowStatus
(
c
.
QueryParam
(
"rowStatus"
))
...
@@ -99,6 +100,14 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
...
@@ -99,6 +100,14 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
contentSearch
:=
"#"
+
tag
+
" "
contentSearch
:=
"#"
+
tag
+
" "
memoFind
.
ContentSearch
=
&
contentSearch
memoFind
.
ContentSearch
=
&
contentSearch
}
}
visibilitListStr
:=
c
.
QueryParam
(
"visibility"
)
if
visibilitListStr
!=
""
{
visibilityList
:=
[]
api
.
Visibility
{}
for
_
,
visibility
:=
range
strings
.
Split
(
visibilitListStr
,
","
)
{
visibilityList
=
append
(
visibilityList
,
api
.
Visibility
(
visibility
))
}
memoFind
.
VisibilityList
=
visibilityList
}
if
limit
,
err
:=
strconv
.
Atoi
(
c
.
QueryParam
(
"limit"
));
err
==
nil
{
if
limit
,
err
:=
strconv
.
Atoi
(
c
.
QueryParam
(
"limit"
));
err
==
nil
{
memoFind
.
Limit
=
limit
memoFind
.
Limit
=
limit
}
}
...
@@ -190,9 +199,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
...
@@ -190,9 +199,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
memoDelete
:=
&
api
.
MemoDelete
{
memoDelete
:=
&
api
.
MemoDelete
{
ID
:
memoID
,
ID
:
memoID
,
}
}
if
err
:=
s
.
Store
.
DeleteMemo
(
memoDelete
);
err
!=
nil
{
err
=
s
.
Store
.
DeleteMemo
(
memoDelete
)
if
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
fmt
.
Sprintf
(
"Failed to delete memo ID: %v"
,
memoID
))
.
SetInternal
(
err
)
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
fmt
.
Sprintf
(
"Failed to delete memo ID: %v"
,
memoID
))
.
SetInternal
(
err
)
}
}
...
...
server/tag.go
View file @
b7339e00
...
@@ -22,21 +22,21 @@ func (s *Server) registerTagRoutes(g *echo.Group) {
...
@@ -22,21 +22,21 @@ func (s *Server) registerTagRoutes(g *echo.Group) {
}
}
if
userID
,
err
:=
strconv
.
Atoi
(
c
.
QueryParam
(
"creatorId"
));
err
==
nil
{
if
userID
,
err
:=
strconv
.
Atoi
(
c
.
QueryParam
(
"creatorId"
));
err
==
nil
{
memoFind
.
CreatorID
=
&
userID
}
else
{
userID
,
ok
:=
c
.
Get
(
getUserIDContextKey
())
.
(
int
)
if
!
ok
{
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
"Missing user id to find tag"
)
}
memoFind
.
CreatorID
=
&
userID
memoFind
.
CreatorID
=
&
userID
}
}
// Only can get PUBLIC memos in visitor mode
currentUserID
:=
c
.
Get
(
getUserIDContextKey
())
.
(
int
)
_
,
ok
:=
c
.
Get
(
getUserIDContextKey
())
.
(
int
)
if
currentUserID
==
api
.
UNKNOWN_ID
{
if
!
ok
{
if
memoFind
.
CreatorID
==
nil
{
publicVisibility
:=
api
.
Public
return
echo
.
NewHTTPError
(
http
.
StatusBadRequest
,
"Missing user id to find memo"
)
memoFind
.
Visibility
=
&
publicVisibility
}
memoFind
.
VisibilityList
=
[]
api
.
Visibility
{
api
.
Public
}
}
else
{
if
memoFind
.
CreatorID
==
nil
{
memoFind
.
CreatorID
=
&
currentUserID
}
else
{
memoFind
.
VisibilityList
=
[]
api
.
Visibility
{
api
.
Public
,
api
.
Protected
}
}
}
}
memoList
,
err
:=
s
.
Store
.
FindMemoList
(
&
memoFind
)
memoList
,
err
:=
s
.
Store
.
FindMemoList
(
&
memoFind
)
...
...
server/user.go
View file @
b7339e00
...
@@ -182,4 +182,34 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
...
@@ -182,4 +182,34 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
}
}
return
nil
return
nil
})
})
g
.
DELETE
(
"/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
.
Host
{
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
)
}
userDelete
:=
&
api
.
UserDelete
{
ID
:
userID
,
}
if
err
:=
s
.
Store
.
DeleteUser
(
userDelete
);
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to delete user"
)
.
SetInternal
(
err
)
}
return
c
.
JSON
(
http
.
StatusOK
,
true
)
})
}
}
store/db/seed/10002__memo.sql
View file @
b7339e00
...
@@ -16,7 +16,8 @@ INSERT INTO
...
@@ -16,7 +16,8 @@ INSERT INTO
memo
(
memo
(
`id`
,
`id`
,
`content`
,
`content`
,
`creator_id`
`creator_id`
,
`visibility`
)
)
VALUES
VALUES
(
(
...
@@ -26,7 +27,8 @@ VALUES
...
@@ -26,7 +27,8 @@ VALUES
- [x] Clean the room;
- [x] Clean the room;
- [x] Read *📖 The Little Prince*;
- [x] Read *📖 The Little Prince*;
(👆 click to toggle status)'
,
(👆 click to toggle status)'
,
101
101
,
'PROTECTED'
);
);
INSERT
INTO
INSERT
INTO
...
@@ -48,7 +50,8 @@ INSERT INTO
...
@@ -48,7 +50,8 @@ INSERT INTO
memo
(
memo
(
`id`
,
`id`
,
`content`
,
`content`
,
`creator_id`
`creator_id`
,
`visibility`
)
)
VALUES
VALUES
(
(
...
@@ -59,7 +62,8 @@ VALUES
...
@@ -59,7 +62,8 @@ VALUES
- [ ] Watch *👦 The Boys*;
- [ ] Watch *👦 The Boys*;
(👆 click to toggle status)
(👆 click to toggle status)
'
,
'
,
102
102
,
'PROTECTED'
);
);
INSERT
INTO
INSERT
INTO
...
...
store/memo.go
View file @
b7339e00
...
@@ -222,8 +222,13 @@ func findMemoRawList(db *sql.DB, find *api.MemoFind) ([]*memoRaw, error) {
...
@@ -222,8 +222,13 @@ func findMemoRawList(db *sql.DB, find *api.MemoFind) ([]*memoRaw, error) {
if
v
:=
find
.
ContentSearch
;
v
!=
nil
{
if
v
:=
find
.
ContentSearch
;
v
!=
nil
{
where
,
args
=
append
(
where
,
"content LIKE ?"
),
append
(
args
,
"%"
+*
v
+
"%"
)
where
,
args
=
append
(
where
,
"content LIKE ?"
),
append
(
args
,
"%"
+*
v
+
"%"
)
}
}
if
v
:=
find
.
Visibility
;
v
!=
nil
{
if
v
:=
find
.
VisibilityList
;
len
(
v
)
!=
0
{
where
,
args
=
append
(
where
,
"visibility = ?"
),
append
(
args
,
*
v
)
list
:=
[]
string
{}
for
_
,
visibility
:=
range
v
{
list
=
append
(
list
,
fmt
.
Sprintf
(
"$%d"
,
len
(
args
)
+
1
))
args
=
append
(
args
,
visibility
)
}
where
=
append
(
where
,
fmt
.
Sprintf
(
"visibility in (%s)"
,
strings
.
Join
(
list
,
","
)))
}
}
pagination
:=
""
pagination
:=
""
...
...
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