mirror of
https://github.com/usememos/memos.git
synced 2025-03-20 04:30:08 +01:00
fix: access control (#870)
This commit is contained in:
parent
f888c62840
commit
3556ae4e65
@ -46,7 +46,7 @@ type Memo struct {
|
|||||||
|
|
||||||
type MemoCreate struct {
|
type MemoCreate struct {
|
||||||
// Standard fields
|
// Standard fields
|
||||||
CreatorID int
|
CreatorID int `json:"-"`
|
||||||
|
|
||||||
// Domain specific fields
|
// Domain specific fields
|
||||||
Visibility Visibility `json:"visibility"`
|
Visibility Visibility `json:"visibility"`
|
||||||
@ -73,11 +73,11 @@ type MemoPatch struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MemoFind struct {
|
type MemoFind struct {
|
||||||
ID *int `json:"id"`
|
ID *int
|
||||||
|
|
||||||
// Standard fields
|
// Standard fields
|
||||||
RowStatus *RowStatus `json:"rowStatus"`
|
RowStatus *RowStatus
|
||||||
CreatorID *int `json:"creatorId"`
|
CreatorID *int
|
||||||
|
|
||||||
// Domain specific fields
|
// Domain specific fields
|
||||||
Pinned *bool
|
Pinned *bool
|
||||||
|
@ -9,17 +9,17 @@ type MemoOrganizer struct {
|
|||||||
Pinned bool
|
Pinned bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MemoOrganizerUpsert struct {
|
||||||
|
MemoID int `json:"-"`
|
||||||
|
UserID int `json:"-"`
|
||||||
|
Pinned bool `json:"pinned"`
|
||||||
|
}
|
||||||
|
|
||||||
type MemoOrganizerFind struct {
|
type MemoOrganizerFind struct {
|
||||||
MemoID int
|
MemoID int
|
||||||
UserID int
|
UserID int
|
||||||
}
|
}
|
||||||
|
|
||||||
type MemoOrganizerUpsert struct {
|
|
||||||
MemoID int
|
|
||||||
UserID int
|
|
||||||
Pinned bool `json:"pinned"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MemoOrganizerDelete struct {
|
type MemoOrganizerDelete struct {
|
||||||
MemoID *int
|
MemoID *int
|
||||||
UserID *int
|
UserID *int
|
||||||
|
@ -8,7 +8,7 @@ type MemoResource struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MemoResourceUpsert struct {
|
type MemoResourceUpsert struct {
|
||||||
MemoID int
|
MemoID int `json:"-"`
|
||||||
ResourceID int
|
ResourceID int
|
||||||
UpdatedTs *int64
|
UpdatedTs *int64
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ type Resource struct {
|
|||||||
|
|
||||||
type ResourceCreate struct {
|
type ResourceCreate struct {
|
||||||
// Standard fields
|
// Standard fields
|
||||||
CreatorID int
|
CreatorID int `json:"-"`
|
||||||
|
|
||||||
// Domain specific fields
|
// Domain specific fields
|
||||||
Filename string `json:"filename"`
|
Filename string `json:"filename"`
|
||||||
|
@ -16,7 +16,7 @@ type Shortcut struct {
|
|||||||
|
|
||||||
type ShortcutCreate struct {
|
type ShortcutCreate struct {
|
||||||
// Standard fields
|
// Standard fields
|
||||||
CreatorID int
|
CreatorID int `json:"-"`
|
||||||
|
|
||||||
// Domain specific fields
|
// Domain specific fields
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
@ -7,7 +7,7 @@ type Tag struct {
|
|||||||
|
|
||||||
type TagUpsert struct {
|
type TagUpsert struct {
|
||||||
Name string
|
Name string
|
||||||
CreatorID int
|
CreatorID int `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TagFind struct {
|
type TagFind struct {
|
||||||
|
@ -50,7 +50,7 @@ type UserSetting struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserSettingUpsert struct {
|
type UserSettingUpsert struct {
|
||||||
UserID int
|
UserID int `json:"-"`
|
||||||
Key UserSettingKey `json:"key"`
|
Key UserSettingKey `json:"key"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
|
||||||
}
|
}
|
||||||
if signup.Role == api.Host && hostUser != nil {
|
if signup.Role == api.Host && hostUser != nil {
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Site Host existed, please contact the site host to signin account firstly.").SetInternal(err)
|
return echo.NewHTTPError(http.StatusUnauthorized, "Site Host existed, please contact the site host to signin account firstly").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
systemSettingAllowSignUpName := api.SystemSettingAllowSignUpName
|
systemSettingAllowSignUpName := api.SystemSettingAllowSignUpName
|
||||||
@ -103,7 +103,7 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !allowSignUpSettingValue && hostUser != nil {
|
if !allowSignUpSettingValue && hostUser != nil {
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Site Host existed, please contact the site host to signin account firstly.").SetInternal(err)
|
return echo.NewHTTPError(http.StatusUnauthorized, "Site Host existed, please contact the site host to signin account firstly").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
userCreate := &api.UserCreate{
|
userCreate := &api.UserCreate{
|
||||||
@ -114,7 +114,7 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
OpenID: common.GenUUID(),
|
OpenID: common.GenUUID(),
|
||||||
}
|
}
|
||||||
if err := userCreate.Validate(); err != nil {
|
if err := userCreate.Validate(); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format.").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(signup.Password), bcrypt.DefaultCost)
|
passwordHash, err := bcrypt.GenerateFromPassword([]byte(signup.Password), bcrypt.DefaultCost)
|
||||||
|
363
server/memo.go
363
server/memo.go
@ -24,9 +24,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||||
}
|
}
|
||||||
|
|
||||||
memoCreate := &api.MemoCreate{
|
memoCreate := &api.MemoCreate{}
|
||||||
CreatorID: userID,
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(memoCreate); err != nil {
|
if err := json.NewDecoder(c.Request().Body).Decode(memoCreate); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post memo request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post memo request").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -57,6 +55,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memoCreate.CreatorID = userID
|
||||||
memo, err := s.Store.CreateMemo(ctx, memoCreate)
|
memo, err := s.Store.CreateMemo(ctx, memoCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create memo").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create memo").SetInternal(err)
|
||||||
@ -98,13 +97,15 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("memoId"))).SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("memoId"))).SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
memoFind := &api.MemoFind{
|
memo, err := s.Store.FindMemo(ctx, &api.MemoFind{
|
||||||
ID: &memoID,
|
ID: &memoID,
|
||||||
CreatorID: &userID,
|
})
|
||||||
}
|
if err != nil {
|
||||||
if _, err := s.Store.FindMemo(ctx, memoFind); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
if memo.CreatorID != userID {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
currentTs := time.Now().Unix()
|
currentTs := time.Now().Unix()
|
||||||
memoPatch := &api.MemoPatch{
|
memoPatch := &api.MemoPatch{
|
||||||
@ -115,7 +116,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch memo request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch memo request").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
memo, err := s.Store.PatchMemo(ctx, memoPatch)
|
memo, err = s.Store.PatchMemo(ctx, memoPatch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch memo").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch memo").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -173,7 +174,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
tag := c.QueryParam("tag")
|
tag := c.QueryParam("tag")
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
contentSearch := "#" + tag + " "
|
contentSearch := "#" + tag
|
||||||
memoFind.ContentSearch = &contentSearch
|
memoFind.ContentSearch = &contentSearch
|
||||||
}
|
}
|
||||||
visibilityListStr := c.QueryParam("visibility")
|
visibilityListStr := c.QueryParam("visibility")
|
||||||
@ -229,6 +230,141 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
g.GET("/memo/:memoId", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
memoFind := &api.MemoFind{
|
||||||
|
ID: &memoID,
|
||||||
|
}
|
||||||
|
memo, err := s.Store.FindMemo(ctx, memoFind)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if memo.Visibility == api.Private {
|
||||||
|
if !ok || memo.CreatorID != userID {
|
||||||
|
return echo.NewHTTPError(http.StatusForbidden, "this memo is private only")
|
||||||
|
}
|
||||||
|
} else if memo.Visibility == api.Protected {
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusForbidden, "this memo is protected, missing user in session")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.POST("/memo/:memoId/organizer", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
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, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||||
|
}
|
||||||
|
memoOrganizerUpsert := &api.MemoOrganizerUpsert{}
|
||||||
|
if err := json.NewDecoder(c.Request().Body).Decode(memoOrganizerUpsert); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post memo organizer request").SetInternal(err)
|
||||||
|
}
|
||||||
|
memoOrganizerUpsert.MemoID = memoID
|
||||||
|
memoOrganizerUpsert.UserID = userID
|
||||||
|
|
||||||
|
err = s.Store.UpsertMemoOrganizer(ctx, memoOrganizerUpsert)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert memo organizer").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
memo, err := s.Store.FindMemo(ctx, &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.POST("/memo/:memoId/resource", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTs := time.Now().Unix()
|
||||||
|
memoResourceUpsert := &api.MemoResourceUpsert{
|
||||||
|
UpdatedTs: ¤tTs,
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(c.Request().Body).Decode(memoResourceUpsert); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post memo resource request").SetInternal(err)
|
||||||
|
}
|
||||||
|
memoResourceUpsert.MemoID = memoID
|
||||||
|
|
||||||
|
if _, err := s.Store.UpsertMemoResource(ctx, memoResourceUpsert); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert memo resource").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceFind := &api.ResourceFind{
|
||||||
|
ID: &memoResourceUpsert.ResourceID,
|
||||||
|
}
|
||||||
|
resource, err := s.Store.FindResource(ctx, resourceFind)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
|
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource response").SetInternal(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
g.GET("/memo/:memoId/resource", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceFind := &api.ResourceFind{
|
||||||
|
MemoID: &memoID,
|
||||||
|
}
|
||||||
|
resourceList, err := s.Store.FindResourceList(ctx, resourceFind)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource list").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
|
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resourceList)); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource list response").SetInternal(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
g.GET("/memo/amount", func(c echo.Context) error {
|
g.GET("/memo/amount", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
normalRowStatus := api.Normal
|
normalRowStatus := api.Normal
|
||||||
@ -352,183 +488,26 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
g.GET("/memo/:memoId", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
memoFind := &api.MemoFind{
|
|
||||||
ID: &memoID,
|
|
||||||
}
|
|
||||||
memo, err := s.Store.FindMemo(ctx, memoFind)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
|
||||||
if memo.Visibility == api.Private {
|
|
||||||
if !ok || memo.CreatorID != userID {
|
|
||||||
return echo.NewHTTPError(http.StatusForbidden, "this memo is private only")
|
|
||||||
}
|
|
||||||
} else if memo.Visibility == api.Protected {
|
|
||||||
if !ok {
|
|
||||||
return echo.NewHTTPError(http.StatusForbidden, "this memo is protected, missing user in session")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.POST("/memo/:memoId/organizer", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
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, ok := c.Get(getUserIDContextKey()).(int)
|
|
||||||
if !ok {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
|
||||||
}
|
|
||||||
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(ctx, memoOrganizerUpsert)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert memo organizer").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
memo, err := s.Store.FindMemo(ctx, &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.POST("/memo/:memoId/resource", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentTs := time.Now().Unix()
|
|
||||||
memoResourceUpsert := &api.MemoResourceUpsert{
|
|
||||||
MemoID: memoID,
|
|
||||||
UpdatedTs: ¤tTs,
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(memoResourceUpsert); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post memo resource request").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := s.Store.UpsertMemoResource(ctx, memoResourceUpsert); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert memo resource").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceFind := &api.ResourceFind{
|
|
||||||
ID: &memoResourceUpsert.ResourceID,
|
|
||||||
}
|
|
||||||
resource, err := s.Store.FindResource(ctx, resourceFind)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
|
||||||
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource response").SetInternal(err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
g.GET("/memo/:memoId/resource", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceFind := &api.ResourceFind{
|
|
||||||
MemoID: &memoID,
|
|
||||||
}
|
|
||||||
resourceList, err := s.Store.FindResourceList(ctx, resourceFind)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource list").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
|
||||||
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resourceList)); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource list response").SetInternal(err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
g.DELETE("/memo/:memoId/resource/:resourceId", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
memoID, err := strconv.Atoi(c.Param("memoId"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Memo ID is not a number: %s", c.Param("memoId"))).SetInternal(err)
|
|
||||||
}
|
|
||||||
resourceID, err := strconv.Atoi(c.Param("resourceId"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Resource ID is not a number: %s", c.Param("resourceId"))).SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
memoResourceDelete := &api.MemoResourceDelete{
|
|
||||||
MemoID: &memoID,
|
|
||||||
ResourceID: &resourceID,
|
|
||||||
}
|
|
||||||
if err := s.Store.DeleteMemoResource(ctx, memoResourceDelete); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource list").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, true)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.DELETE("/memo/:memoId", func(c echo.Context) error {
|
g.DELETE("/memo/:memoId", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
if !ok {
|
if !ok {
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||||
}
|
}
|
||||||
|
|
||||||
memoID, err := strconv.Atoi(c.Param("memoId"))
|
memoID, err := strconv.Atoi(c.Param("memoId"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("memoId"))).SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("memoId"))).SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
memoFind := &api.MemoFind{
|
memo, err := s.Store.FindMemo(ctx, &api.MemoFind{
|
||||||
ID: &memoID,
|
ID: &memoID,
|
||||||
CreatorID: &userID,
|
})
|
||||||
}
|
if err != nil {
|
||||||
if _, err := s.Store.FindMemo(ctx, memoFind); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
if memo.CreatorID != userID {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
memoDelete := &api.MemoDelete{
|
memoDelete := &api.MemoDelete{
|
||||||
ID: memoID,
|
ID: memoID,
|
||||||
@ -542,4 +521,40 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
return c.JSON(http.StatusOK, true)
|
return c.JSON(http.StatusOK, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
g.DELETE("/memo/:memoId/resource/:resourceId", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||||
|
}
|
||||||
|
memoID, err := strconv.Atoi(c.Param("memoId"))
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Memo ID is not a number: %s", c.Param("memoId"))).SetInternal(err)
|
||||||
|
}
|
||||||
|
resourceID, err := strconv.Atoi(c.Param("resourceId"))
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Resource ID is not a number: %s", c.Param("resourceId"))).SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
memo, err := s.Store.FindMemo(ctx, &api.MemoFind{
|
||||||
|
ID: &memoID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo").SetInternal(err)
|
||||||
|
}
|
||||||
|
if memo.CreatorID != userID {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
memoResourceDelete := &api.MemoResourceDelete{
|
||||||
|
MemoID: &memoID,
|
||||||
|
ResourceID: &resourceID,
|
||||||
|
}
|
||||||
|
if err := s.Store.DeleteMemoResource(ctx, memoResourceDelete); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource list").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, true)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -56,13 +56,12 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resourceCreate := &api.ResourceCreate{
|
resourceCreate := &api.ResourceCreate{
|
||||||
|
CreatorID: userID,
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
Type: filetype,
|
Type: filetype,
|
||||||
Size: size,
|
Size: size,
|
||||||
Blob: fileBytes,
|
Blob: fileBytes,
|
||||||
CreatorID: userID,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource, err := s.Store.CreateResource(ctx, resourceCreate)
|
resource, err := s.Store.CreateResource(ctx, resourceCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
||||||
@ -158,6 +157,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
c.Response().Writer.WriteHeader(http.StatusOK)
|
c.Response().Writer.WriteHeader(http.StatusOK)
|
||||||
c.Response().Writer.Header().Set("Content-Type", resource.Type)
|
c.Response().Writer.Header().Set("Content-Type", resource.Type)
|
||||||
|
c.Response().Writer.Header().Set(echo.HeaderContentSecurityPolicy, "default-src 'self'")
|
||||||
if _, err := c.Response().Writer.Write(resource.Blob); err != nil {
|
if _, err := c.Response().Writer.Write(resource.Blob); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to write resource blob").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to write resource blob").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -177,23 +177,26 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resourceFind := &api.ResourceFind{
|
resourceFind := &api.ResourceFind{
|
||||||
ID: &resourceID,
|
ID: &resourceID,
|
||||||
CreatorID: &userID,
|
|
||||||
}
|
}
|
||||||
if _, err := s.Store.FindResource(ctx, resourceFind); err != nil {
|
resource, err := s.Store.FindResource(ctx, resourceFind)
|
||||||
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find resource").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find resource").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
if resource.CreatorID != userID {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
currentTs := time.Now().Unix()
|
currentTs := time.Now().Unix()
|
||||||
resourcePatch := &api.ResourcePatch{
|
resourcePatch := &api.ResourcePatch{
|
||||||
ID: resourceID,
|
|
||||||
UpdatedTs: ¤tTs,
|
UpdatedTs: ¤tTs,
|
||||||
}
|
}
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(resourcePatch); err != nil {
|
if err := json.NewDecoder(c.Request().Body).Decode(resourcePatch); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch resource request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch resource request").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resource, err := s.Store.PatchResource(ctx, resourcePatch)
|
resource.ID = resourceID
|
||||||
|
resource, err = s.Store.PatchResource(ctx, resourcePatch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch resource").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch resource").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -224,8 +227,8 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find resource").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find resource").SetInternal(err)
|
||||||
}
|
}
|
||||||
if resource == nil {
|
if resource.CreatorID != userID {
|
||||||
return echo.NewHTTPError(http.StatusNotFound, "Not find resource").SetInternal(err)
|
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceDelete := &api.ResourceDelete{
|
resourceDelete := &api.ResourceDelete{
|
||||||
|
@ -21,13 +21,12 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||||
}
|
}
|
||||||
shortcutCreate := &api.ShortcutCreate{
|
shortcutCreate := &api.ShortcutCreate{}
|
||||||
CreatorID: userID,
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(shortcutCreate); err != nil {
|
if err := json.NewDecoder(c.Request().Body).Decode(shortcutCreate); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post shortcut request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post shortcut request").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shortcutCreate.CreatorID = userID
|
||||||
shortcut, err := s.Store.CreateShortcut(ctx, shortcutCreate)
|
shortcut, err := s.Store.CreateShortcut(ctx, shortcutCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create shortcut").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create shortcut").SetInternal(err)
|
||||||
@ -45,21 +44,36 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
g.PATCH("/shortcut/:shortcutId", func(c echo.Context) error {
|
g.PATCH("/shortcut/:shortcutId", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||||
|
}
|
||||||
shortcutID, err := strconv.Atoi(c.Param("shortcutId"))
|
shortcutID, err := strconv.Atoi(c.Param("shortcutId"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("shortcutId"))).SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("shortcutId"))).SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shortcutFind := &api.ShortcutFind{
|
||||||
|
ID: &shortcutID,
|
||||||
|
}
|
||||||
|
shortcut, err := s.Store.FindShortcut(ctx, shortcutFind)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find shortcut").SetInternal(err)
|
||||||
|
}
|
||||||
|
if shortcut.CreatorID != userID {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
currentTs := time.Now().Unix()
|
currentTs := time.Now().Unix()
|
||||||
shortcutPatch := &api.ShortcutPatch{
|
shortcutPatch := &api.ShortcutPatch{
|
||||||
ID: shortcutID,
|
|
||||||
UpdatedTs: ¤tTs,
|
UpdatedTs: ¤tTs,
|
||||||
}
|
}
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(shortcutPatch); err != nil {
|
if err := json.NewDecoder(c.Request().Body).Decode(shortcutPatch); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch shortcut request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch shortcut request").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
shortcut, err := s.Store.PatchShortcut(ctx, shortcutPatch)
|
shortcutPatch.ID = shortcutID
|
||||||
|
shortcut, err = s.Store.PatchShortcut(ctx, shortcutPatch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch shortcut").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch shortcut").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -73,17 +87,12 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
g.GET("/shortcut", func(c echo.Context) error {
|
g.GET("/shortcut", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
shortcutFind := &api.ShortcutFind{}
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if !ok {
|
||||||
if userID, err := strconv.Atoi(c.QueryParam("creatorId")); err == nil {
|
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find shortcut")
|
||||||
shortcutFind.CreatorID = &userID
|
}
|
||||||
} else {
|
shortcutFind := &api.ShortcutFind{
|
||||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
CreatorID: &userID,
|
||||||
if !ok {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find shortcut")
|
|
||||||
}
|
|
||||||
|
|
||||||
shortcutFind.CreatorID = &userID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list, err := s.Store.FindShortcutList(ctx, shortcutFind)
|
list, err := s.Store.FindShortcutList(ctx, shortcutFind)
|
||||||
@ -122,11 +131,26 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
g.DELETE("/shortcut/:shortcutId", func(c echo.Context) error {
|
g.DELETE("/shortcut/:shortcutId", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||||
|
}
|
||||||
shortcutID, err := strconv.Atoi(c.Param("shortcutId"))
|
shortcutID, err := strconv.Atoi(c.Param("shortcutId"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("shortcutId"))).SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("shortcutId"))).SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shortcutFind := &api.ShortcutFind{
|
||||||
|
ID: &shortcutID,
|
||||||
|
}
|
||||||
|
shortcut, err := s.Store.FindShortcut(ctx, shortcutFind)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find shortcut").SetInternal(err)
|
||||||
|
}
|
||||||
|
if shortcut.CreatorID != userID {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
shortcutDelete := &api.ShortcutDelete{
|
shortcutDelete := &api.ShortcutDelete{
|
||||||
ID: &shortcutID,
|
ID: &shortcutID,
|
||||||
}
|
}
|
||||||
|
@ -76,13 +76,24 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
|
|||||||
systemStatus.AdditionalScript = value.(string)
|
systemStatus.AdditionalScript = value.(string)
|
||||||
} else if systemSetting.Name == api.SystemSettingCustomizedProfileName {
|
} else if systemSetting.Name == api.SystemSettingCustomizedProfileName {
|
||||||
valueMap := value.(map[string]interface{})
|
valueMap := value.(map[string]interface{})
|
||||||
systemStatus.CustomizedProfile = api.CustomizedProfile{
|
systemStatus.CustomizedProfile = api.CustomizedProfile{}
|
||||||
Name: valueMap["name"].(string),
|
if v := valueMap["name"]; v != nil {
|
||||||
LogoURL: valueMap["logoUrl"].(string),
|
systemStatus.CustomizedProfile.Name = v.(string)
|
||||||
Description: valueMap["description"].(string),
|
}
|
||||||
Locale: valueMap["locale"].(string),
|
if v := valueMap["logoUrl"]; v != nil {
|
||||||
Appearance: valueMap["appearance"].(string),
|
systemStatus.CustomizedProfile.LogoURL = v.(string)
|
||||||
ExternalURL: valueMap["externalUrl"].(string),
|
}
|
||||||
|
if v := valueMap["description"]; v != nil {
|
||||||
|
systemStatus.CustomizedProfile.Description = v.(string)
|
||||||
|
}
|
||||||
|
if v := valueMap["locale"]; v != nil {
|
||||||
|
systemStatus.CustomizedProfile.Locale = v.(string)
|
||||||
|
}
|
||||||
|
if v := valueMap["appearance"]; v != nil {
|
||||||
|
systemStatus.CustomizedProfile.Appearance = v.(string)
|
||||||
|
}
|
||||||
|
if v := valueMap["externalUrl"]; v != nil {
|
||||||
|
systemStatus.CustomizedProfile.ExternalURL = v.(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,9 +136,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
|
||||||
}
|
}
|
||||||
if user == nil {
|
if user == nil || user.Role != api.Host {
|
||||||
return echo.NewHTTPError(http.StatusNotFound, "Current signin user not found")
|
|
||||||
} else if user.Role != api.Host {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,7 @@ func (s *Server) registerTagRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||||
}
|
}
|
||||||
|
|
||||||
tagUpsert := &api.TagUpsert{
|
tagUpsert := &api.TagUpsert{}
|
||||||
CreatorID: userID,
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(tagUpsert); err != nil {
|
if err := json.NewDecoder(c.Request().Body).Decode(tagUpsert); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post tag request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post tag request").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -33,6 +31,7 @@ func (s *Server) registerTagRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusBadRequest, "Tag name shouldn't be empty")
|
return echo.NewHTTPError(http.StatusBadRequest, "Tag name shouldn't be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tagUpsert.CreatorID = userID
|
||||||
tag, err := s.Store.UpsertTag(ctx, tagUpsert)
|
tag, err := s.Store.UpsertTag(ctx, tagUpsert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert tag").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert tag").SetInternal(err)
|
||||||
@ -82,31 +81,18 @@ func (s *Server) registerTagRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
g.GET("/tag/suggestion", func(c echo.Context) error {
|
g.GET("/tag/suggestion", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Missing user session")
|
||||||
|
}
|
||||||
contentSearch := "#"
|
contentSearch := "#"
|
||||||
normalRowStatus := api.Normal
|
normalRowStatus := api.Normal
|
||||||
memoFind := api.MemoFind{
|
memoFind := api.MemoFind{
|
||||||
|
CreatorID: &userID,
|
||||||
ContentSearch: &contentSearch,
|
ContentSearch: &contentSearch,
|
||||||
RowStatus: &normalRowStatus,
|
RowStatus: &normalRowStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
if userID, err := strconv.Atoi(c.QueryParam("creatorId")); err == nil {
|
|
||||||
memoFind.CreatorID = &userID
|
|
||||||
}
|
|
||||||
|
|
||||||
currentUserID, ok := c.Get(getUserIDContextKey()).(int)
|
|
||||||
if !ok {
|
|
||||||
if memoFind.CreatorID == nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find memo")
|
|
||||||
}
|
|
||||||
memoFind.VisibilityList = []api.Visibility{api.Public}
|
|
||||||
} else {
|
|
||||||
if memoFind.CreatorID == nil {
|
|
||||||
memoFind.CreatorID = ¤tUserID
|
|
||||||
} else {
|
|
||||||
memoFind.VisibilityList = []api.Visibility{api.Public, api.Protected}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memoList, err := s.Store.FindMemoList(ctx, &memoFind)
|
memoList, err := s.Store.FindMemoList(ctx, &memoFind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo list").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo list").SetInternal(err)
|
||||||
|
@ -29,18 +29,20 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user by id").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user by id").SetInternal(err)
|
||||||
}
|
}
|
||||||
if currentUser.Role != api.Host {
|
if currentUser.Role != api.Host {
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Only Host user can create member.")
|
return echo.NewHTTPError(http.StatusUnauthorized, "Only Host user can create member")
|
||||||
}
|
}
|
||||||
|
|
||||||
userCreate := &api.UserCreate{
|
userCreate := &api.UserCreate{}
|
||||||
OpenID: common.GenUUID(),
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(userCreate); err != nil {
|
if err := json.NewDecoder(c.Request().Body).Decode(userCreate); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user request").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
if userCreate.Role == api.Host {
|
||||||
|
return echo.NewHTTPError(http.StatusForbidden, "Could not create host user")
|
||||||
|
}
|
||||||
|
userCreate.OpenID = common.GenUUID()
|
||||||
|
|
||||||
if err := userCreate.Validate(); err != nil {
|
if err := userCreate.Validate(); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format.").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(userCreate.Password), bcrypt.DefaultCost)
|
passwordHash, err := bcrypt.GenerateFromPassword([]byte(userCreate.Password), bcrypt.DefaultCost)
|
||||||
@ -74,6 +76,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
for _, user := range userList {
|
for _, user := range userList {
|
||||||
// data desensitize
|
// data desensitize
|
||||||
user.OpenID = ""
|
user.OpenID = ""
|
||||||
|
user.Email = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
@ -159,6 +162,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
if user != nil {
|
if user != nil {
|
||||||
// data desensitize
|
// data desensitize
|
||||||
user.OpenID = ""
|
user.OpenID = ""
|
||||||
|
user.Email = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
@ -192,14 +196,14 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
currentTs := time.Now().Unix()
|
currentTs := time.Now().Unix()
|
||||||
userPatch := &api.UserPatch{
|
userPatch := &api.UserPatch{
|
||||||
ID: userID,
|
|
||||||
UpdatedTs: ¤tTs,
|
UpdatedTs: ¤tTs,
|
||||||
}
|
}
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(userPatch); err != nil {
|
if err := json.NewDecoder(c.Request().Body).Decode(userPatch); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch user request").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch user request").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
userPatch.ID = userID
|
||||||
if err := userPatch.Validate(); err != nil {
|
if err := userPatch.Validate(); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user patch format.").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user patch format").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if userPatch.Password != nil && *userPatch.Password != "" {
|
if userPatch.Password != nil && *userPatch.Password != "" {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user