mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-18 21:19:44 +00:00
chore: remove workspace and workspace tables
This commit is contained in:
parent
c3ce03ffe5
commit
895cd8e38c
@ -39,12 +39,11 @@ type Shortcut struct {
|
|||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
|
|
||||||
// Standard fields
|
// Standard fields
|
||||||
CreatorID int `json:"creatorId"`
|
CreatorID int `json:"creatorId"`
|
||||||
Creator *User `json:"creator"`
|
Creator *User `json:"creator"`
|
||||||
CreatedTs int64 `json:"createdTs"`
|
CreatedTs int64 `json:"createdTs"`
|
||||||
UpdatedTs int64 `json:"updatedTs"`
|
UpdatedTs int64 `json:"updatedTs"`
|
||||||
WorkspaceID int `json:"workspaceId"`
|
RowStatus RowStatus `json:"rowStatus"`
|
||||||
RowStatus RowStatus `json:"rowStatus"`
|
|
||||||
|
|
||||||
// Domain specific fields
|
// Domain specific fields
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@ -54,7 +53,6 @@ type Shortcut struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CreateShortcutRequest struct {
|
type CreateShortcutRequest struct {
|
||||||
WorkspaceID int `json:"workspaceId"`
|
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Link string `json:"link"`
|
Link string `json:"link"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
@ -83,7 +81,6 @@ func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
shortcut, err := s.Store.CreateShortcut(ctx, &store.Shortcut{
|
shortcut, err := s.Store.CreateShortcut(ctx, &store.Shortcut{
|
||||||
CreatorID: userID,
|
CreatorID: userID,
|
||||||
WorkspaceID: create.WorkspaceID,
|
|
||||||
Name: create.Name,
|
Name: create.Name,
|
||||||
Link: create.Link,
|
Link: create.Link,
|
||||||
Description: create.Description,
|
Description: create.Description,
|
||||||
@ -113,17 +110,11 @@ func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find shortcut").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find shortcut").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
if shortcut == nil {
|
||||||
workspaceUser, err := s.Store.GetWorkspaceUser(ctx, &store.FindWorkspaceUser{
|
return echo.NewHTTPError(http.StatusNotFound, "Shortcut not found")
|
||||||
UserID: &userID,
|
|
||||||
WorkspaceID: &shortcut.WorkspaceID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace user").SetInternal(err)
|
|
||||||
}
|
}
|
||||||
|
if shortcut.CreatorID != userID {
|
||||||
if shortcut.CreatorID != userID && workspaceUser.Role != store.RoleAdmin {
|
return echo.NewHTTPError(http.StatusForbidden, "Shortcut does not belong to user")
|
||||||
return echo.NewHTTPError(http.StatusForbidden, "Forbidden to patch shortcut")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
patch := &PatchShortcutRequest{}
|
patch := &PatchShortcutRequest{}
|
||||||
@ -153,9 +144,6 @@ func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
find := &store.FindShortcut{}
|
find := &store.FindShortcut{}
|
||||||
if workspaceID, err := strconv.Atoi(c.QueryParam("workspaceId")); err == nil {
|
|
||||||
find.WorkspaceID = &workspaceID
|
|
||||||
}
|
|
||||||
if name := c.QueryParam("name"); name != "" {
|
if name := c.QueryParam("name"); name != "" {
|
||||||
find.Name = &name
|
find.Name = &name
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,5 @@ func (s *APIV1Service) Start(apiV1Group *echo.Group, secret string) {
|
|||||||
s.registerSystemRoutes(apiV1Group)
|
s.registerSystemRoutes(apiV1Group)
|
||||||
s.registerAuthRoutes(apiV1Group, secret)
|
s.registerAuthRoutes(apiV1Group, secret)
|
||||||
s.registerUserRoutes(apiV1Group)
|
s.registerUserRoutes(apiV1Group)
|
||||||
s.registerWorkspaceRoutes(apiV1Group)
|
|
||||||
s.registerWorkspaceUserRoutes(apiV1Group)
|
|
||||||
s.registerShortcutRoutes(apiV1Group)
|
s.registerShortcutRoutes(apiV1Group)
|
||||||
}
|
}
|
||||||
|
@ -1,189 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/boojack/shortify/store"
|
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Workspace struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
|
|
||||||
// Standard fields
|
|
||||||
CreatorID int `json:"creatorId"`
|
|
||||||
CreatedTs int64 `json:"createdTs"`
|
|
||||||
UpdatedTs int64 `json:"updatedTs"`
|
|
||||||
RowStatus RowStatus `json:"rowStatus"`
|
|
||||||
|
|
||||||
// Domain specific fields
|
|
||||||
Name string `json:"name"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateWorkspaceRequest struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PatchWorkspaceRequest struct {
|
|
||||||
RowStatus *RowStatus `json:"rowStatus"`
|
|
||||||
Name *string `json:"name"`
|
|
||||||
Title *string `json:"title"`
|
|
||||||
Description *string `json:"description"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type WorkspaceFind struct {
|
|
||||||
ID *int `json:"id"`
|
|
||||||
|
|
||||||
// Standard fields
|
|
||||||
RowStatus *RowStatus `json:"rowStatus"`
|
|
||||||
|
|
||||||
// Domain specific fields
|
|
||||||
Name *string `json:"name"`
|
|
||||||
|
|
||||||
// Related fields
|
|
||||||
MemberID *int
|
|
||||||
}
|
|
||||||
|
|
||||||
type WorkspaceDelete struct {
|
|
||||||
ID int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *APIV1Service) registerWorkspaceRoutes(g *echo.Group) {
|
|
||||||
g.POST("/workspace", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
|
||||||
if !ok {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
|
|
||||||
}
|
|
||||||
|
|
||||||
create := &CreateWorkspaceRequest{}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(create); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post workspace request").SetInternal(err)
|
|
||||||
}
|
|
||||||
if len(create.Name) > 24 {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Workspace name length should be less than 24")
|
|
||||||
}
|
|
||||||
|
|
||||||
workspace, err := s.Store.CreateWorkspace(ctx, &store.Workspace{
|
|
||||||
ResourceID: create.Name,
|
|
||||||
Title: create.Title,
|
|
||||||
Description: create.Description,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create workspace").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = s.Store.UpsertWorkspaceUser(ctx, &store.WorkspaceUser{
|
|
||||||
WorkspaceID: workspace.ID,
|
|
||||||
UserID: userID,
|
|
||||||
Role: store.RoleAdmin,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, workspace)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.GET("/workspace/:id", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted workspace id").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspace, err := s.Store.GetWorkspace(ctx, &store.FindWorkspace{
|
|
||||||
ID: &id,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, workspace)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.PATCH("/workspace/:id", 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")
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceID, err := strconv.Atoi(c.Param("id"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("id"))).SetInternal(err)
|
|
||||||
}
|
|
||||||
workspaceUser, err := s.Store.GetWorkspaceUser(ctx, &store.FindWorkspaceUser{
|
|
||||||
WorkspaceID: &workspaceID,
|
|
||||||
UserID: &userID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
if workspaceUser == nil {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Current user is not a member of the workspace")
|
|
||||||
}
|
|
||||||
if workspaceUser.Role != store.RoleAdmin {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Current user is not an admin of the workspace")
|
|
||||||
}
|
|
||||||
|
|
||||||
patch := &PatchWorkspaceRequest{}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(patch); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch workspace request").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspace, err := s.Store.UpdateWorkspace(ctx, &store.UpdateWorkspace{
|
|
||||||
ID: workspaceID,
|
|
||||||
RowStatus: (*store.RowStatus)(patch.RowStatus),
|
|
||||||
ResourceID: patch.Name,
|
|
||||||
Title: patch.Title,
|
|
||||||
Description: patch.Description,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch workspace").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, workspace)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.DELETE("/workspace/:id", 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")
|
|
||||||
}
|
|
||||||
workspaceID, err := strconv.Atoi(c.Param("id"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("id"))).SetInternal(err)
|
|
||||||
}
|
|
||||||
workspaceUser, err := s.Store.GetWorkspaceUser(ctx, &store.FindWorkspaceUser{
|
|
||||||
WorkspaceID: &workspaceID,
|
|
||||||
UserID: &userID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
if workspaceUser == nil {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "not workspace user")
|
|
||||||
}
|
|
||||||
if workspaceUser.Role != store.RoleAdmin {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "not workspace admin")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.Store.DeleteWorkspace(ctx, &store.DeleteWorkspace{
|
|
||||||
ID: workspaceID,
|
|
||||||
}); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to delete user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, true)
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,213 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/boojack/shortify/store"
|
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
type WorkspaceUser struct {
|
|
||||||
WorkspaceID int `json:"workspaceId"`
|
|
||||||
UserID int `json:"userId"`
|
|
||||||
Role Role `json:"role"`
|
|
||||||
|
|
||||||
// Related fields
|
|
||||||
Username string `json:"username"`
|
|
||||||
Nickname string `json:"nickname"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpsertWorkspaceUserRequest struct {
|
|
||||||
WorkspaceID int `json:"workspaceId"`
|
|
||||||
UserID int `json:"userId"`
|
|
||||||
Role Role `json:"role"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *APIV1Service) registerWorkspaceUserRoutes(g *echo.Group) {
|
|
||||||
g.POST("/workspace/:id/user", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
|
||||||
if !ok {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceID, err := strconv.Atoi(c.Param("id"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted workspace id").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentWorkspaceUser, err := s.Store.GetWorkspaceUser(ctx, &store.FindWorkspaceUser{
|
|
||||||
WorkspaceID: &workspaceID,
|
|
||||||
UserID: &userID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
if currentWorkspaceUser.Role != store.RoleAdmin {
|
|
||||||
return echo.NewHTTPError(http.StatusForbidden, "Access forbidden to add workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
upsert := &UpsertWorkspaceUserRequest{
|
|
||||||
WorkspaceID: workspaceID,
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(upsert); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post workspace user request").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceUser, err := s.Store.UpsertWorkspaceUser(ctx, &store.WorkspaceUser{
|
|
||||||
WorkspaceID: upsert.WorkspaceID,
|
|
||||||
UserID: upsert.UserID,
|
|
||||||
Role: convertRoleToStore(upsert.Role),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
composedWorkspaceUser, err := s.composeWorkspaceUser(ctx, workspaceUser)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, composedWorkspaceUser)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.GET("/workspace/:id/user", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
workspaceID, err := strconv.Atoi(c.Param("id"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted workspace id").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceUserList, err := s.Store.ListWorkspaceUsers(ctx, &store.FindWorkspaceUser{
|
|
||||||
WorkspaceID: &workspaceID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace user list").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
composedList := make([]*WorkspaceUser, 0, len(workspaceUserList))
|
|
||||||
for _, workspaceUser := range workspaceUserList {
|
|
||||||
composedWorkspaceUser, err := s.composeWorkspaceUser(ctx, workspaceUser)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
composedList = append(composedList, composedWorkspaceUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, composedList)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.GET("/workspace/:workspaceId/user/:userId", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
workspaceID, err := strconv.Atoi(c.Param("workspaceId"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted workspace id").SetInternal(err)
|
|
||||||
}
|
|
||||||
userID, err := strconv.Atoi(c.Param("userId"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted user id").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceUser, err := s.Store.GetWorkspaceUser(ctx, &store.FindWorkspaceUser{
|
|
||||||
WorkspaceID: &workspaceID,
|
|
||||||
UserID: &userID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
composedWorkspaceUser, err := s.composeWorkspaceUser(ctx, workspaceUser)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, composedWorkspaceUser)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.DELETE("/workspace/:workspaceId/user/:userId", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
currentUserID, ok := c.Get(getUserIDContextKey()).(int)
|
|
||||||
if !ok {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceID, err := strconv.Atoi(c.Param("workspaceId"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted workspace id").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, err := strconv.Atoi(c.Param("userId"))
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted user id").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentWorkspaceUser, err := s.Store.GetWorkspaceUser(ctx, &store.FindWorkspaceUser{
|
|
||||||
WorkspaceID: &workspaceID,
|
|
||||||
UserID: ¤tUserID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
if currentUserID != userID && currentWorkspaceUser.Role != store.RoleAdmin {
|
|
||||||
return echo.NewHTTPError(http.StatusForbidden, "Access forbidden to delete workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.Store.DeleteWorkspaceUser(ctx, &store.DeleteWorkspaceUser{
|
|
||||||
WorkspaceID: workspaceID,
|
|
||||||
UserID: userID,
|
|
||||||
}); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to delete workspace user").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertRoleToStore(role Role) store.Role {
|
|
||||||
switch role {
|
|
||||||
case RoleAdmin:
|
|
||||||
return store.RoleAdmin
|
|
||||||
case RoleUser:
|
|
||||||
return store.RoleUser
|
|
||||||
default:
|
|
||||||
return store.RoleUser
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertRoleFromStore(role store.Role) Role {
|
|
||||||
switch role {
|
|
||||||
case store.RoleAdmin:
|
|
||||||
return RoleAdmin
|
|
||||||
case store.RoleUser:
|
|
||||||
return RoleUser
|
|
||||||
default:
|
|
||||||
return RoleUser
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *APIV1Service) composeWorkspaceUser(ctx context.Context, workspaceUser *store.WorkspaceUser) (*WorkspaceUser, error) {
|
|
||||||
user, err := s.Store.GetUser(ctx, &store.FindUser{
|
|
||||||
ID: &workspaceUser.UserID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if user == nil {
|
|
||||||
return nil, fmt.Errorf("Failed to find user %d", workspaceUser.UserID)
|
|
||||||
}
|
|
||||||
|
|
||||||
composedWorkspaceUser := &WorkspaceUser{
|
|
||||||
WorkspaceID: workspaceUser.WorkspaceID,
|
|
||||||
UserID: workspaceUser.UserID,
|
|
||||||
Role: convertRoleFromStore(workspaceUser.Role),
|
|
||||||
Username: user.Username,
|
|
||||||
Nickname: user.Nickname,
|
|
||||||
}
|
|
||||||
|
|
||||||
return composedWorkspaceUser, nil
|
|
||||||
}
|
|
@ -4,28 +4,10 @@ CREATE TABLE migration_history (
|
|||||||
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now'))
|
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now'))
|
||||||
);
|
);
|
||||||
|
|
||||||
-- workspace
|
|
||||||
CREATE TABLE workspace (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
created_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',
|
|
||||||
resource_id TEXT NOT NULL UNIQUE,
|
|
||||||
title TEXT NOT NULL,
|
|
||||||
description TEXT NOT NULL DEFAULT ''
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
sqlite_sequence (name, seq)
|
|
||||||
VALUES
|
|
||||||
('workspace', 1);
|
|
||||||
|
|
||||||
-- workspace_setting
|
-- workspace_setting
|
||||||
CREATE TABLE workspace_setting (
|
CREATE TABLE workspace_setting (
|
||||||
workspace_id INTEGER NOT NULL,
|
key TEXT NOT NULL UNIQUE,
|
||||||
key TEXT NOT NULL,
|
value TEXT NOT NULL
|
||||||
value TEXT NOT NULL,
|
|
||||||
UNIQUE(workspace_id, key)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
-- user
|
-- user
|
||||||
@ -41,11 +23,6 @@ CREATE TABLE user (
|
|||||||
role TEXT NOT NULL CHECK (role IN ('ADMIN', 'USER')) DEFAULT 'USER'
|
role TEXT NOT NULL CHECK (role IN ('ADMIN', 'USER')) DEFAULT 'USER'
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
sqlite_sequence (name, seq)
|
|
||||||
VALUES
|
|
||||||
('user', 10);
|
|
||||||
|
|
||||||
-- user_setting
|
-- user_setting
|
||||||
CREATE TABLE user_setting (
|
CREATE TABLE user_setting (
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
@ -54,14 +31,6 @@ CREATE TABLE user_setting (
|
|||||||
UNIQUE(user_id, key)
|
UNIQUE(user_id, key)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- workspace_user
|
|
||||||
CREATE TABLE workspace_user (
|
|
||||||
workspace_id INTEGER NOT NULL,
|
|
||||||
user_id INTEGER NOT NULL,
|
|
||||||
role TEXT NOT NULL CHECK (role IN ('ADMIN', 'USER')) DEFAULT 'USER',
|
|
||||||
UNIQUE(workspace_id, user_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- shortcut
|
-- shortcut
|
||||||
CREATE TABLE shortcut (
|
CREATE TABLE shortcut (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@ -69,15 +38,8 @@ CREATE TABLE shortcut (
|
|||||||
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',
|
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
|
||||||
workspace_id INTEGER NOT NULL,
|
name TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
|
||||||
link TEXT NOT NULL,
|
link TEXT NOT NULL,
|
||||||
description TEXT NOT NULL DEFAULT '',
|
description TEXT NOT NULL DEFAULT '',
|
||||||
visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE',
|
visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE'
|
||||||
UNIQUE(workspace_id, name)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
sqlite_sequence (name, seq)
|
|
||||||
VALUES
|
|
||||||
('shortcut', 100);
|
|
||||||
|
@ -4,28 +4,10 @@ CREATE TABLE migration_history (
|
|||||||
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now'))
|
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now'))
|
||||||
);
|
);
|
||||||
|
|
||||||
-- workspace
|
|
||||||
CREATE TABLE workspace (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
created_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',
|
|
||||||
resource_id TEXT NOT NULL UNIQUE,
|
|
||||||
title TEXT NOT NULL,
|
|
||||||
description TEXT NOT NULL DEFAULT ''
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
sqlite_sequence (name, seq)
|
|
||||||
VALUES
|
|
||||||
('workspace', 1);
|
|
||||||
|
|
||||||
-- workspace_setting
|
-- workspace_setting
|
||||||
CREATE TABLE workspace_setting (
|
CREATE TABLE workspace_setting (
|
||||||
workspace_id INTEGER NOT NULL,
|
key TEXT NOT NULL UNIQUE,
|
||||||
key TEXT NOT NULL,
|
value TEXT NOT NULL
|
||||||
value TEXT NOT NULL,
|
|
||||||
UNIQUE(workspace_id, key)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
-- user
|
-- user
|
||||||
@ -41,11 +23,6 @@ CREATE TABLE user (
|
|||||||
role TEXT NOT NULL CHECK (role IN ('ADMIN', 'USER')) DEFAULT 'USER'
|
role TEXT NOT NULL CHECK (role IN ('ADMIN', 'USER')) DEFAULT 'USER'
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
sqlite_sequence (name, seq)
|
|
||||||
VALUES
|
|
||||||
('user', 10);
|
|
||||||
|
|
||||||
-- user_setting
|
-- user_setting
|
||||||
CREATE TABLE user_setting (
|
CREATE TABLE user_setting (
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
@ -54,14 +31,6 @@ CREATE TABLE user_setting (
|
|||||||
UNIQUE(user_id, key)
|
UNIQUE(user_id, key)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- workspace_user
|
|
||||||
CREATE TABLE workspace_user (
|
|
||||||
workspace_id INTEGER NOT NULL,
|
|
||||||
user_id INTEGER NOT NULL,
|
|
||||||
role TEXT NOT NULL CHECK (role IN ('ADMIN', 'USER')) DEFAULT 'USER',
|
|
||||||
UNIQUE(workspace_id, user_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- shortcut
|
-- shortcut
|
||||||
CREATE TABLE shortcut (
|
CREATE TABLE shortcut (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@ -69,15 +38,8 @@ CREATE TABLE shortcut (
|
|||||||
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',
|
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
|
||||||
workspace_id INTEGER NOT NULL,
|
name TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
|
||||||
link TEXT NOT NULL,
|
link TEXT NOT NULL,
|
||||||
description TEXT NOT NULL DEFAULT '',
|
description TEXT NOT NULL DEFAULT '',
|
||||||
visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE',
|
visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE'
|
||||||
UNIQUE(workspace_id, name)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
sqlite_sequence (name, seq)
|
|
||||||
VALUES
|
|
||||||
('shortcut', 100);
|
|
||||||
|
@ -41,7 +41,6 @@ type Shortcut struct {
|
|||||||
RowStatus RowStatus
|
RowStatus RowStatus
|
||||||
|
|
||||||
// Domain specific fields
|
// Domain specific fields
|
||||||
WorkspaceID int
|
|
||||||
Name string
|
Name string
|
||||||
Link string
|
Link string
|
||||||
Description string
|
Description string
|
||||||
@ -62,7 +61,6 @@ type FindShortcut struct {
|
|||||||
ID *int
|
ID *int
|
||||||
CreatorID *int
|
CreatorID *int
|
||||||
RowStatus *RowStatus
|
RowStatus *RowStatus
|
||||||
WorkspaceID *int
|
|
||||||
Name *string
|
Name *string
|
||||||
VisibilityList []Visibility
|
VisibilityList []Visibility
|
||||||
}
|
}
|
||||||
@ -78,9 +76,9 @@ func (s *Store) CreateShortcut(ctx context.Context, create *Shortcut) (*Shortcut
|
|||||||
}
|
}
|
||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
|
|
||||||
set := []string{"creator_id", "workspace_id", "name", "link", "description", "visibility"}
|
set := []string{"creator_id", "name", "link", "description", "visibility"}
|
||||||
args := []any{create.CreatorID, create.WorkspaceID, create.Name, create.Link, create.Description, create.Visibility}
|
args := []any{create.CreatorID, create.Name, create.Link, create.Description, create.Visibility}
|
||||||
placeholder := []string{"?", "?", "?", "?", "?", "?"}
|
placeholder := []string{"?", "?", "?", "?", "?"}
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
INSERT INTO shortcut (
|
INSERT INTO shortcut (
|
||||||
@ -140,7 +138,7 @@ func (s *Store) UpdateShortcut(ctx context.Context, update *UpdateShortcut) (*Sh
|
|||||||
` + strings.Join(set, ", ") + `
|
` + strings.Join(set, ", ") + `
|
||||||
WHERE
|
WHERE
|
||||||
id = ?
|
id = ?
|
||||||
RETURNING id, creator_id, created_ts, updated_ts, workspace_id, row_status, name, link, description, visibility
|
RETURNING id, creator_id, created_ts, updated_ts, row_status, name, link, description, visibility
|
||||||
`
|
`
|
||||||
var shortcut Shortcut
|
var shortcut Shortcut
|
||||||
if err := tx.QueryRowContext(ctx, query, args...).Scan(
|
if err := tx.QueryRowContext(ctx, query, args...).Scan(
|
||||||
@ -148,7 +146,6 @@ func (s *Store) UpdateShortcut(ctx context.Context, update *UpdateShortcut) (*Sh
|
|||||||
&shortcut.CreatorID,
|
&shortcut.CreatorID,
|
||||||
&shortcut.CreatedTs,
|
&shortcut.CreatedTs,
|
||||||
&shortcut.UpdatedTs,
|
&shortcut.UpdatedTs,
|
||||||
&shortcut.WorkspaceID,
|
|
||||||
&shortcut.RowStatus,
|
&shortcut.RowStatus,
|
||||||
&shortcut.Name,
|
&shortcut.Name,
|
||||||
&shortcut.Link,
|
&shortcut.Link,
|
||||||
@ -239,9 +236,6 @@ func listShortcuts(ctx context.Context, tx *sql.Tx, find *FindShortcut) ([]*Shor
|
|||||||
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.WorkspaceID; v != nil {
|
|
||||||
where, args = append(where, "workspace_id = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
if v := find.Name; v != nil {
|
if v := find.Name; v != nil {
|
||||||
where, args = append(where, "name = ?"), append(args, *v)
|
where, args = append(where, "name = ?"), append(args, *v)
|
||||||
}
|
}
|
||||||
@ -261,7 +255,6 @@ func listShortcuts(ctx context.Context, tx *sql.Tx, find *FindShortcut) ([]*Shor
|
|||||||
created_ts,
|
created_ts,
|
||||||
updated_ts,
|
updated_ts,
|
||||||
row_status,
|
row_status,
|
||||||
workspace_id,
|
|
||||||
name,
|
name,
|
||||||
link,
|
link,
|
||||||
description,
|
description,
|
||||||
@ -284,7 +277,6 @@ func listShortcuts(ctx context.Context, tx *sql.Tx, find *FindShortcut) ([]*Shor
|
|||||||
&shortcut.CreatorID,
|
&shortcut.CreatorID,
|
||||||
&shortcut.CreatedTs,
|
&shortcut.CreatedTs,
|
||||||
&shortcut.UpdatedTs,
|
&shortcut.UpdatedTs,
|
||||||
&shortcut.WorkspaceID,
|
|
||||||
&shortcut.RowStatus,
|
&shortcut.RowStatus,
|
||||||
&shortcut.Name,
|
&shortcut.Name,
|
||||||
&shortcut.Link,
|
&shortcut.Link,
|
||||||
|
@ -7,6 +7,16 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Role is the type of a role.
|
||||||
|
type Role string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RoleAdmin is the ADMIN role.
|
||||||
|
RoleAdmin Role = "ADMIN"
|
||||||
|
// RoleUser is the USER role.
|
||||||
|
RoleUser Role = "USER"
|
||||||
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int
|
ID int
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
package store
|
|
@ -1,254 +0,0 @@
|
|||||||
package store
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Workspace struct {
|
|
||||||
ID int
|
|
||||||
|
|
||||||
// Standard fields
|
|
||||||
CreatedTs int64
|
|
||||||
UpdatedTs int64
|
|
||||||
RowStatus RowStatus
|
|
||||||
|
|
||||||
// Domain specific fields
|
|
||||||
ResourceID string
|
|
||||||
Title string
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateWorkspace struct {
|
|
||||||
ID int
|
|
||||||
|
|
||||||
// Standard fields
|
|
||||||
RowStatus *RowStatus
|
|
||||||
|
|
||||||
// Domain specific fields
|
|
||||||
ResourceID *string
|
|
||||||
Title *string
|
|
||||||
Description *string
|
|
||||||
}
|
|
||||||
|
|
||||||
type FindWorkspace struct {
|
|
||||||
ID *int
|
|
||||||
RowStatus *RowStatus
|
|
||||||
ResourceID *string
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteWorkspace struct {
|
|
||||||
ID int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) CreateWorkspace(ctx context.Context, create *Workspace) (*Workspace, error) {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
query := `
|
|
||||||
INSERT INTO workspace (
|
|
||||||
resource_id,
|
|
||||||
title,
|
|
||||||
description
|
|
||||||
)
|
|
||||||
VALUES (?, ?, ?)
|
|
||||||
RETURNING id, created_ts, updated_ts, row_status
|
|
||||||
`
|
|
||||||
if err := tx.QueryRowContext(ctx, query,
|
|
||||||
create.ResourceID,
|
|
||||||
create.Title,
|
|
||||||
create.Description,
|
|
||||||
).Scan(
|
|
||||||
&create.ID,
|
|
||||||
&create.CreatedTs,
|
|
||||||
&create.UpdatedTs,
|
|
||||||
&create.RowStatus,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
workspace := create
|
|
||||||
return workspace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) UpdateWorkspace(ctx context.Context, update *UpdateWorkspace) (*Workspace, error) {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
set, args := []string{}, []any{}
|
|
||||||
|
|
||||||
if v := update.RowStatus; v != nil {
|
|
||||||
set, args = append(set, "row_status = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
if v := update.ResourceID; v != nil {
|
|
||||||
set, args = append(set, "resource_id = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
if v := update.Title; v != nil {
|
|
||||||
set, args = append(set, "title = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
if v := update.Description; v != nil {
|
|
||||||
set, args = append(set, "description = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
args = append(args, update.ID)
|
|
||||||
|
|
||||||
query := `
|
|
||||||
UPDATE workspace
|
|
||||||
SET ` + strings.Join(set, ", ") + `
|
|
||||||
WHERE id = ?
|
|
||||||
RETURNING id, created_ts, updated_ts, row_status, resource_id, title, description
|
|
||||||
`
|
|
||||||
row, err := tx.QueryContext(ctx, query, args...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer row.Close()
|
|
||||||
|
|
||||||
if !row.Next() {
|
|
||||||
return nil, errors.New(fmt.Sprint("workspace ID not found: ", update.ID))
|
|
||||||
}
|
|
||||||
workspace := &Workspace{}
|
|
||||||
if err := row.Scan(
|
|
||||||
&workspace.ID,
|
|
||||||
&workspace.CreatedTs,
|
|
||||||
&workspace.UpdatedTs,
|
|
||||||
&workspace.RowStatus,
|
|
||||||
&workspace.ResourceID,
|
|
||||||
&workspace.Title,
|
|
||||||
&workspace.Description,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := row.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return workspace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) ListWorkspaces(ctx context.Context, find *FindWorkspace) ([]*Workspace, error) {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
list, err := listWorkspaces(ctx, tx, find)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetWorkspace(ctx context.Context, find *FindWorkspace) (*Workspace, error) {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
list, err := listWorkspaces(ctx, tx, find)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(list) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return list[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) DeleteWorkspace(ctx context.Context, delete *DeleteWorkspace) error {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
if _, err := tx.ExecContext(ctx, `
|
|
||||||
DELETE FROM workspace WHERE id = ?
|
|
||||||
`, delete.ID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
// do nothing here to prevent linter warning.
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listWorkspaces(ctx context.Context, tx *sql.Tx, find *FindWorkspace) ([]*Workspace, error) {
|
|
||||||
where, args := []string{"1 = 1"}, []any{}
|
|
||||||
|
|
||||||
if v := find.ID; v != nil {
|
|
||||||
where, args = append(where, "id = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
if v := find.RowStatus; v != nil {
|
|
||||||
where, args = append(where, "row_status = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
if v := find.ResourceID; v != nil {
|
|
||||||
where, args = append(where, "resource_id = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
|
|
||||||
query := `
|
|
||||||
SELECT
|
|
||||||
id,
|
|
||||||
created_ts,
|
|
||||||
updated_ts,
|
|
||||||
row_status,
|
|
||||||
resource_id,
|
|
||||||
title,
|
|
||||||
description
|
|
||||||
FROM workspace
|
|
||||||
WHERE ` + strings.Join(where, " AND ") + `
|
|
||||||
ORDER BY created_ts DESC, row_status DESC
|
|
||||||
`
|
|
||||||
rows, err := tx.QueryContext(ctx, query, args...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
list := make([]*Workspace, 0)
|
|
||||||
for rows.Next() {
|
|
||||||
var workspace Workspace
|
|
||||||
if err := rows.Scan(
|
|
||||||
&workspace.ID,
|
|
||||||
&workspace.CreatedTs,
|
|
||||||
&workspace.UpdatedTs,
|
|
||||||
&workspace.RowStatus,
|
|
||||||
&workspace.ResourceID,
|
|
||||||
&workspace.Title,
|
|
||||||
&workspace.Description,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
list = append(list, &workspace)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return list, nil
|
|
||||||
}
|
|
116
store/workspace_setting.go
Normal file
116
store/workspace_setting.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package store
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WorkspaceSetting struct {
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
type FindWorkspaceSetting struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) UpsertWorkspaceSetting(ctx context.Context, upsert *WorkspaceSetting) (*WorkspaceSetting, error) {
|
||||||
|
tx, err := s.db.BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
query := `
|
||||||
|
INSERT INTO workspace_setting (
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
VALUES (?, ?)
|
||||||
|
ON CONFLICT(key) DO UPDATE
|
||||||
|
SET value = EXCLUDED.value
|
||||||
|
`
|
||||||
|
if _, err := tx.ExecContext(ctx, query, upsert.Key, upsert.Value); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaceSetting := upsert
|
||||||
|
return workspaceSetting, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) ListWorkspaceSettings(ctx context.Context, find *FindWorkspaceSetting) ([]*WorkspaceSetting, error) {
|
||||||
|
tx, err := s.db.BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
list, err := listWorkspaceSettings(ctx, tx, find)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetWorkspaceSetting(ctx context.Context, find *FindWorkspaceSetting) (*WorkspaceSetting, error) {
|
||||||
|
tx, err := s.db.BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
list, err := listWorkspaceSettings(ctx, tx, find)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(list) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaceSetting := list[0]
|
||||||
|
return workspaceSetting, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func listWorkspaceSettings(ctx context.Context, tx *sql.Tx, find *FindWorkspaceSetting) ([]*WorkspaceSetting, error) {
|
||||||
|
where, args := []string{"1 = 1"}, []any{}
|
||||||
|
if find.Key != "" {
|
||||||
|
where, args = append(where, "key = ?"), append(args, find.Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
query := `
|
||||||
|
SELECT
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
FROM workspace_setting
|
||||||
|
WHERE ` + strings.Join(where, " AND ")
|
||||||
|
|
||||||
|
rows, err := tx.QueryContext(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
list := []*WorkspaceSetting{}
|
||||||
|
for rows.Next() {
|
||||||
|
workspaceSetting := &WorkspaceSetting{}
|
||||||
|
if err := rows.Scan(
|
||||||
|
&workspaceSetting.Key,
|
||||||
|
&workspaceSetting.Value,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
list = append(list, workspaceSetting)
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
@ -1,172 +0,0 @@
|
|||||||
package store
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Role is the type of a role.
|
|
||||||
type Role string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// RoleAdmin is the ADMIN role.
|
|
||||||
RoleAdmin Role = "ADMIN"
|
|
||||||
// RoleUser is the USER role.
|
|
||||||
RoleUser Role = "USER"
|
|
||||||
)
|
|
||||||
|
|
||||||
type WorkspaceUser struct {
|
|
||||||
WorkspaceID int
|
|
||||||
UserID int
|
|
||||||
Role Role
|
|
||||||
}
|
|
||||||
|
|
||||||
type FindWorkspaceUser struct {
|
|
||||||
WorkspaceID *int
|
|
||||||
UserID *int
|
|
||||||
Role *Role
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteWorkspaceUser struct {
|
|
||||||
WorkspaceID int
|
|
||||||
UserID int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) UpsertWorkspaceUser(ctx context.Context, upsert *WorkspaceUser) (*WorkspaceUser, error) {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
set := []string{"workspace_id", "user_id", "role"}
|
|
||||||
args := []any{upsert.WorkspaceID, upsert.UserID, upsert.Role}
|
|
||||||
placeholder := []string{"?", "?", "?"}
|
|
||||||
|
|
||||||
query := `
|
|
||||||
INSERT INTO workspace_user (
|
|
||||||
` + strings.Join(set, ", ") + `
|
|
||||||
)
|
|
||||||
VALUES (` + strings.Join(placeholder, ",") + `)
|
|
||||||
ON CONFLICT(workspace_id, user_id) DO UPDATE
|
|
||||||
SET
|
|
||||||
role = EXCLUDED.role
|
|
||||||
`
|
|
||||||
if _, err := tx.ExecContext(ctx, query, args...); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceUser := upsert
|
|
||||||
return workspaceUser, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) ListWorkspaceUsers(ctx context.Context, find *FindWorkspaceUser) ([]*WorkspaceUser, error) {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
list, err := listWorkspaceUsers(ctx, tx, find)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetWorkspaceUser(ctx context.Context, find *FindWorkspaceUser) (*WorkspaceUser, error) {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
list, err := listWorkspaceUsers(ctx, tx, find)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(list) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
workspaceUser := list[0]
|
|
||||||
return workspaceUser, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) DeleteWorkspaceUser(ctx context.Context, delete *DeleteWorkspaceUser) error {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
if _, err := tx.ExecContext(ctx, `
|
|
||||||
DELETE FROM workspace_user WHERE workspace_id = ? AND user_id = ?
|
|
||||||
`, delete.WorkspaceID, delete.UserID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
// do nothing here to prevent linter warning.
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func listWorkspaceUsers(ctx context.Context, tx *sql.Tx, find *FindWorkspaceUser) ([]*WorkspaceUser, error) {
|
|
||||||
where, args := []string{"1 = 1"}, []any{}
|
|
||||||
|
|
||||||
if v := find.WorkspaceID; v != nil {
|
|
||||||
where, args = append(where, "workspace_id = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
if v := find.UserID; v != nil {
|
|
||||||
where, args = append(where, "user_id = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
if v := find.Role; v != nil {
|
|
||||||
where, args = append(where, "role = ?"), append(args, *v)
|
|
||||||
}
|
|
||||||
|
|
||||||
query := `
|
|
||||||
SELECT
|
|
||||||
workspace_id,
|
|
||||||
user_id,
|
|
||||||
role
|
|
||||||
FROM workspace_user
|
|
||||||
WHERE ` + strings.Join(where, " AND ")
|
|
||||||
rows, err := tx.QueryContext(ctx, query, args...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
list := make([]*WorkspaceUser, 0)
|
|
||||||
for rows.Next() {
|
|
||||||
var workspaceUser WorkspaceUser
|
|
||||||
if err := rows.Scan(
|
|
||||||
&workspaceUser.WorkspaceID,
|
|
||||||
&workspaceUser.UserID,
|
|
||||||
&workspaceUser.Role,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
list = append(list, &workspaceUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return list, nil
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user