Unverified Commit 3556ae4e authored by boojack's avatar boojack Committed by GitHub

fix: access control (#870)

parent f888c628
......@@ -46,7 +46,7 @@ type Memo struct {
type MemoCreate struct {
// Standard fields
CreatorID int
CreatorID int `json:"-"`
// Domain specific fields
Visibility Visibility `json:"visibility"`
......@@ -73,11 +73,11 @@ type MemoPatch struct {
}
type MemoFind struct {
ID *int `json:"id"`
ID *int
// Standard fields
RowStatus *RowStatus `json:"rowStatus"`
CreatorID *int `json:"creatorId"`
RowStatus *RowStatus
CreatorID *int
// Domain specific fields
Pinned *bool
......
......@@ -9,15 +9,15 @@ type MemoOrganizer struct {
Pinned bool
}
type MemoOrganizerFind struct {
MemoID int
UserID int
type MemoOrganizerUpsert struct {
MemoID int `json:"-"`
UserID int `json:"-"`
Pinned bool `json:"pinned"`
}
type MemoOrganizerUpsert struct {
type MemoOrganizerFind struct {
MemoID int
UserID int
Pinned bool `json:"pinned"`
}
type MemoOrganizerDelete struct {
......
......@@ -8,7 +8,7 @@ type MemoResource struct {
}
type MemoResourceUpsert struct {
MemoID int
MemoID int `json:"-"`
ResourceID int
UpdatedTs *int64
}
......
......@@ -20,7 +20,7 @@ type Resource struct {
type ResourceCreate struct {
// Standard fields
CreatorID int
CreatorID int `json:"-"`
// Domain specific fields
Filename string `json:"filename"`
......
......@@ -16,7 +16,7 @@ type Shortcut struct {
type ShortcutCreate struct {
// Standard fields
CreatorID int
CreatorID int `json:"-"`
// Domain specific fields
Title string `json:"title"`
......
......@@ -7,7 +7,7 @@ type Tag struct {
type TagUpsert struct {
Name string
CreatorID int
CreatorID int `json:"-"`
}
type TagFind struct {
......
......@@ -50,7 +50,7 @@ type UserSetting struct {
}
type UserSettingUpsert struct {
UserID int
UserID int `json:"-"`
Key UserSettingKey `json:"key"`
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)
}
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
......@@ -103,7 +103,7 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
}
}
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{
......@@ -114,7 +114,7 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
OpenID: common.GenUUID(),
}
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)
......
This diff is collapsed.
......@@ -56,13 +56,12 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
}
resourceCreate := &api.ResourceCreate{
CreatorID: userID,
Filename: filename,
Type: filetype,
Size: size,
Blob: fileBytes,
CreatorID: userID,
}
resource, err := s.Store.CreateResource(ctx, resourceCreate)
if err != nil {
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.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 {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to write resource blob").SetInternal(err)
}
......@@ -178,22 +178,25 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
resourceFind := &api.ResourceFind{
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)
}
if resource.CreatorID != userID {
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
}
currentTs := time.Now().Unix()
resourcePatch := &api.ResourcePatch{
ID: resourceID,
UpdatedTs: &currentTs,
}
if err := json.NewDecoder(c.Request().Body).Decode(resourcePatch); err != nil {
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 {
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 {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find resource").SetInternal(err)
}
if resource == nil {
return echo.NewHTTPError(http.StatusNotFound, "Not find resource").SetInternal(err)
if resource.CreatorID != userID {
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
}
resourceDelete := &api.ResourceDelete{
......
......@@ -21,13 +21,12 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) {
if !ok {
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
}
shortcutCreate := &api.ShortcutCreate{
CreatorID: userID,
}
shortcutCreate := &api.ShortcutCreate{}
if err := json.NewDecoder(c.Request().Body).Decode(shortcutCreate); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post shortcut request").SetInternal(err)
}
shortcutCreate.CreatorID = userID
shortcut, err := s.Store.CreateShortcut(ctx, shortcutCreate)
if err != nil {
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 {
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"))
if err != nil {
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()
shortcutPatch := &api.ShortcutPatch{
ID: shortcutID,
UpdatedTs: &currentTs,
}
if err := json.NewDecoder(c.Request().Body).Decode(shortcutPatch); err != nil {
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 {
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 {
ctx := c.Request().Context()
shortcutFind := &api.ShortcutFind{}
if userID, err := strconv.Atoi(c.QueryParam("creatorId")); err == nil {
shortcutFind.CreatorID = &userID
} else {
userID, ok := c.Get(getUserIDContextKey()).(int)
if !ok {
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find shortcut")
}
shortcutFind.CreatorID = &userID
shortcutFind := &api.ShortcutFind{
CreatorID: &userID,
}
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 {
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"))
if err != nil {
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{
ID: &shortcutID,
}
......
......@@ -76,13 +76,24 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
systemStatus.AdditionalScript = value.(string)
} else if systemSetting.Name == api.SystemSettingCustomizedProfileName {
valueMap := value.(map[string]interface{})
systemStatus.CustomizedProfile = api.CustomizedProfile{
Name: valueMap["name"].(string),
LogoURL: valueMap["logoUrl"].(string),
Description: valueMap["description"].(string),
Locale: valueMap["locale"].(string),
Appearance: valueMap["appearance"].(string),
ExternalURL: valueMap["externalUrl"].(string),
systemStatus.CustomizedProfile = api.CustomizedProfile{}
if v := valueMap["name"]; v != nil {
systemStatus.CustomizedProfile.Name = v.(string)
}
if v := valueMap["logoUrl"]; v != nil {
systemStatus.CustomizedProfile.LogoURL = v.(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 {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
}
if user == nil {
return echo.NewHTTPError(http.StatusNotFound, "Current signin user not found")
} else if user.Role != api.Host {
if user == nil || user.Role != api.Host {
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")
}
tagUpsert := &api.TagUpsert{
CreatorID: userID,
}
tagUpsert := &api.TagUpsert{}
if err := json.NewDecoder(c.Request().Body).Decode(tagUpsert); err != nil {
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")
}
tagUpsert.CreatorID = userID
tag, err := s.Store.UpsertTag(ctx, tagUpsert)
if err != nil {
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 {
ctx := c.Request().Context()
userID, ok := c.Get(getUserIDContextKey()).(int)
if !ok {
return echo.NewHTTPError(http.StatusBadRequest, "Missing user session")
}
contentSearch := "#"
normalRowStatus := api.Normal
memoFind := api.MemoFind{
CreatorID: &userID,
ContentSearch: &contentSearch,
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 = &currentUserID
} else {
memoFind.VisibilityList = []api.Visibility{api.Public, api.Protected}
}
}
memoList, err := s.Store.FindMemoList(ctx, &memoFind)
if err != nil {
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)
}
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{
OpenID: common.GenUUID(),
}
userCreate := &api.UserCreate{}
if err := json.NewDecoder(c.Request().Body).Decode(userCreate); err != nil {
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 {
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)
......@@ -74,6 +76,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
for _, user := range userList {
// data desensitize
user.OpenID = ""
user.Email = ""
}
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
......@@ -159,6 +162,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
if user != nil {
// data desensitize
user.OpenID = ""
user.Email = ""
}
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
......@@ -192,14 +196,14 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
currentTs := time.Now().Unix()
userPatch := &api.UserPatch{
ID: userID,
UpdatedTs: &currentTs,
}
if err := json.NewDecoder(c.Request().Body).Decode(userPatch); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch user request").SetInternal(err)
}
userPatch.ID = userID
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 != "" {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment