feat: add public visibility

This commit is contained in:
Steven 2022-09-14 23:08:24 +08:00
parent 5a79304153
commit 469c841713
9 changed files with 81 additions and 27 deletions

View File

@ -4,6 +4,8 @@ package api
type Visibility string
const (
// VisibilityPublic is the PUBLIC visibility.
VisibilityPublic Visibility = "PUBLIC"
// VisibilityWorkspace is the WORKSPACE visibility.
VisibilityWorkspace Visibility = "WORKSPACE"
// VisibilityPrivite is the PRIVATE visibility.
@ -12,6 +14,8 @@ const (
func (e Visibility) String() string {
switch e {
case VisibilityPublic:
return "PUBLIC"
case VisibilityWorkspace:
return "WORKSPACE"
case VisibilityPrivite:

View File

@ -60,7 +60,9 @@ func aclMiddleware(s *Server, next echo.HandlerFunc) echo.HandlerFunc {
return next(c)
}
if common.HasPrefixes(path, "/api/ping", "/api/status", "/api/user/:id") && c.Request().Method == http.MethodGet {
println("path", path)
if common.HasPrefixes(path, "/api/ping", "/api/status", "/api/user/:id", "/api/workspace/:workspaceName/shortcut/:shortcutName") && c.Request().Method == http.MethodGet {
return next(c)
}

View File

@ -92,11 +92,6 @@ func (s *Server) registerWorkspaceRoutes(g *echo.Group) {
g.GET("/workspace/:workspaceName/shortcut/:shortcutName", 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")
}
workspaceName := c.Param("workspaceName")
shortcutName := c.Param("shortcutName")
if workspaceName == "" || shortcutName == "" {
@ -113,6 +108,23 @@ func (s *Server) registerWorkspaceRoutes(g *echo.Group) {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to find workspace with name %s", workspaceName)).SetInternal(err)
}
shortcut, err := s.Store.FindShortcut(ctx, &api.ShortcutFind{
WorkspaceID: &workspace.ID,
Name: &shortcutName,
})
if err != nil {
if common.ErrorCode(err) == common.NotFound {
return echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("shortcut not found by name %s", shortcutName))
}
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to find shortcut with name %s", shortcutName)).SetInternal(err)
}
if shortcut.Visibility != api.VisibilityPublic {
userID, ok := c.Get(getUserIDContextKey()).(int)
if !ok {
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
}
workspaceUser, err := s.Store.FindWordspaceUser(ctx, &api.WorkspaceUserFind{
WorkspaceID: &workspace.ID,
UserID: &userID,
@ -126,16 +138,6 @@ func (s *Server) registerWorkspaceRoutes(g *echo.Group) {
if workspaceUser == nil {
return echo.NewHTTPError(http.StatusUnauthorized, "not workspace user")
}
shortcut, err := s.Store.FindShortcut(ctx, &api.ShortcutFind{
WorkspaceID: &workspace.ID,
Name: &shortcutName,
})
if err != nil {
if common.ErrorCode(err) == common.NotFound {
return echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("shortcut not found by name %s", shortcutName))
}
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to find shortcut with name %s", shortcutName)).SetInternal(err)
}
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)

View File

@ -116,7 +116,7 @@ CREATE TABLE shortcut (
name TEXT NOT NULL,
link TEXT NOT NULL DEFAULT '',
description TEXT NOT NULL DEFAULT '',
visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE')) DEFAULT 'PRIVATE',
visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE',
FOREIGN KEY(creator_id) REFERENCES user(id) ON DELETE CASCADE,
FOREIGN KEY(workspace_id) REFERENCES workspace(id) ON DELETE CASCADE
);

View File

@ -9,6 +9,6 @@ VALUES
(
11,
101,
'Demo',
'demo',
''
);

View File

@ -16,3 +16,22 @@ VALUES
'百度搜索',
'WORKSPACE'
);
INSERT INTO
shortcut (
`creator_id`,
`workspace_id`,
`name`,
`link`,
`description`,
`visibility`
)
VALUES
(
102,
11,
'bl',
'https://bilibili.com',
'B站',
'PUBLIC'
);

View File

@ -1,5 +1,5 @@
import { useEffect } from "react";
import { Route, Routes, useNavigate } from "react-router-dom";
import { Route, Routes, useLocation, useNavigate } from "react-router-dom";
import { userService, workspaceService } from "./services";
import useLoading from "./hooks/useLoading";
import Only from "./components/common/OnlyWhen";
@ -9,11 +9,27 @@ import WorkspaceDetail from "./pages/WorkspaceDetail";
import UserDetail from "./pages/UserDetail";
import ShortcutRedirector from "./pages/ShortcutRedirector";
const pathnameWhitelist = [/\/.+?\/go\/.+/];
function App() {
const navigate = useNavigate();
const location = useLocation();
const pageLoadingStatus = useLoading();
useEffect(() => {
let needAuth = true;
for (const regexp of pathnameWhitelist) {
if (regexp.test(location.pathname)) {
needAuth = false;
break;
}
}
if (!needAuth) {
pageLoadingStatus.setFinish();
return;
}
userService.initialState().finally(() => {
if (!userService.getState().user) {
pageLoadingStatus.setFinish();

View File

@ -148,7 +148,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
checked={state.shortcutCreate.visibility === "PRIVATE"}
/>
<label htmlFor="visibility-private" className="ml-1 mr-4">
Only for myself
Private
</label>
<input
type="radio"
@ -158,8 +158,19 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
onChange={handleVisibilityInputChange}
checked={state.shortcutCreate.visibility === "WORKSPACE"}
/>
<label htmlFor="visibility-workspace" className="ml-1">
Public in workspace
<label htmlFor="visibility-workspace" className="ml-1 mr-4">
Workspace
</label>
<input
type="radio"
name="visibility"
id="visibility-public"
value="PUBLIC"
onChange={handleVisibilityInputChange}
checked={state.shortcutCreate.visibility === "PUBLIC"}
/>
<label htmlFor="visibility-public" className="ml-1">
Public
</label>
</div>
</div>

View File

@ -1,6 +1,6 @@
type ShortcutId = number;
type Visibility = "PRIVATE" | "WORKSPACE";
type Visibility = "PRIVATE" | "WORKSPACE" | "PUBLIC";
interface Shortcut {
id: ShortcutId;