mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-16 12:23:12 +00:00
feat: support multiple type shortcuts link
This commit is contained in:
parent
fbf958cf3e
commit
fc27490766
@ -3,6 +3,7 @@ package v1
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/boojack/shortify/store"
|
||||
"github.com/labstack/echo/v4"
|
||||
@ -39,7 +40,10 @@ func (s *APIV1Service) registerRedirectorRoutes(g *echo.Group) {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err)
|
||||
}
|
||||
|
||||
return c.Redirect(http.StatusSeeOther, shortcut.Link)
|
||||
if isValidURLString(shortcut.Link) {
|
||||
return c.Redirect(http.StatusSeeOther, shortcut.Link)
|
||||
}
|
||||
return c.String(http.StatusOK, shortcut.Link)
|
||||
})
|
||||
}
|
||||
|
||||
@ -66,3 +70,8 @@ func (s *APIV1Service) createShortcutViewActivity(c echo.Context, shortcut *stor
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isValidURLString(s string) bool {
|
||||
_, err := url.ParseRequestURI(s)
|
||||
return err == nil
|
||||
}
|
||||
|
33
api/v1/redirector_test.go
Normal file
33
api/v1/redirector_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package v1
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIsValidURLString(t *testing.T) {
|
||||
tests := []struct {
|
||||
link string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
link: "https://google.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
link: "http://google.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
link: "google.com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
link: "mailto:email@example.com",
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if isValidURLString(test.link) != test.expected {
|
||||
t.Errorf("isValidURLString(%s) = %v, expected %v", test.link, !test.expected, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/boojack/shortify/internal/util"
|
||||
"github.com/boojack/shortify/store"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
@ -86,9 +85,6 @@ func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
|
||||
if err := json.NewDecoder(c.Request().Body).Decode(create); err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post shortcut request").SetInternal(err)
|
||||
}
|
||||
if !validateLink(create.Link) {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid link: %s", create.Link))
|
||||
}
|
||||
|
||||
shortcut, err := s.Store.CreateShortcut(ctx, &store.Shortcut{
|
||||
CreatorID: userID,
|
||||
@ -151,9 +147,6 @@ func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
|
||||
name := strings.ToLower(*patch.Name)
|
||||
patch.Name = &name
|
||||
}
|
||||
if patch.Link != nil && !validateLink(*patch.Link) {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid link: %s", *patch.Link))
|
||||
}
|
||||
|
||||
shortcutUpdate := &store.UpdateShortcut{
|
||||
ID: shortcutID,
|
||||
@ -369,7 +362,3 @@ func convertShortcutFromStore(shortcut *store.Shortcut) *Shortcut {
|
||||
Tags: tags,
|
||||
}
|
||||
}
|
||||
|
||||
func validateLink(link string) bool {
|
||||
return util.HasPrefixes(link, "http://", "https://")
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ const ShortcutView = (props: Props) => {
|
||||
const faviconStore = useFaviconStore();
|
||||
const [favicon, setFavicon] = useState<string | undefined>(undefined);
|
||||
const havePermission = user.role === "ADMIN" || shortcut.creatorId === user.id;
|
||||
const shortifyLink = absolutifyLink(`/s/${shortcut.name}`);
|
||||
|
||||
useEffect(() => {
|
||||
faviconStore.getOrFetchUrlFavicon(shortcut.link).then((url) => {
|
||||
@ -33,8 +34,8 @@ const ShortcutView = (props: Props) => {
|
||||
});
|
||||
}, [shortcut.link]);
|
||||
|
||||
const handleCopyButtonClick = (shortcut: Shortcut) => {
|
||||
copy(absolutifyLink(`/s/${shortcut.name}`));
|
||||
const handleCopyButtonClick = () => {
|
||||
copy(shortifyLink);
|
||||
toast.success("Shortcut link copied to clipboard.");
|
||||
};
|
||||
|
||||
@ -60,11 +61,11 @@ const ShortcutView = (props: Props) => {
|
||||
<Icon.Globe2 className="w-5 h-auto text-gray-500" />
|
||||
)}
|
||||
</div>
|
||||
<button className="items-center cursor-pointer hover:opacity-80" onClick={() => handleCopyButtonClick(shortcut)}>
|
||||
<button className="items-center cursor-pointer hover:opacity-80" onClick={() => handleCopyButtonClick()}>
|
||||
<span className="text-gray-400">s/</span>
|
||||
{shortcut.name}
|
||||
</button>
|
||||
<a className="hidden group-hover:block ml-1 cursor-pointer hover:opacity-80" target="_blank" href={shortcut.link}>
|
||||
<a className="hidden group-hover:block ml-1 cursor-pointer hover:opacity-80" target="_blank" href={shortifyLink}>
|
||||
<Icon.ExternalLink className="w-4 h-auto text-gray-500" />
|
||||
</a>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user